I am trying to write a tunneling program in C that will take UDP packets from the TUNTAP interface and send them to the serial interface.
What I do is select the interface from the clone device / dev / net / tun, enable it and give it an IP address:
int tun_setup(char *dev, int flags) { struct sockaddr_in my_addr; struct ifreq ifr; int fd, err; string clonedev = "/dev/net/tun"; // Open clone device file descriptor if( (fd = open(clonedev.c_str() , O_RDWR)) < 0 ) { perror("Opening /dev/net/tun"); return fd; } // Initialise interface parameters structure memset(&ifr, 0, sizeof(ifr)); // Set up flags ifr.ifr_flags = flags; // Set up interface name if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } // Put interface in TUN mode if( (err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0 ) { perror("ioctl(TUNSETIFF)"); close(fd); return err; } strcpy(dev, ifr.ifr_name); // Create a socket if ( (s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } // Get interface flags if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { perror("cannot get interface flags"); exit(1); } // Turn on interface ifr.ifr_flags |= IFF_UP; if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { fprintf(stderr, "ifup: failed "); perror(ifr.ifr_name); exit(1); } // Set interface address bzero((char *) &my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(inet_network("192.168.2.1")); memcpy(&ifr.ifr_addr, &my_addr, sizeof(struct sockaddr)); if (ioctl(s, SIOCSIFADDR, &ifr) < 0) { fprintf(stderr, "Cannot set IP address. "); perror(ifr.ifr_name); exit(1); } // Return interface file descriptor return fd; }
Then I create a stream that will poll () in the file descriptor of the created interface and will read () + some other things when an event occurs.
void* tun_readThreadProc (void* param) { struct pollfd fds[1]; int nread; unsigned char buffer[BUFFERSIZE]; fds[0].fd = tun_fd; fds[0].events = POLLIN; printf("%s : Entered. tun_fd = %d \n",__FUNCTION__,tun_fd); for(;;) { printf("%s : Entered loop\n",__FUNCTION__); if((poll(fds, 1, -1)) == -1) { perror("poll"); exit(1); } printf("%s : Poll sensed something\n",__FUNCTION__); if((nread = read(tun_fd, buffer, BUFFERSIZE)) < 0) { perror("read"); close(tun_fd); exit(1); } printf("%s : Read something : %d bytes\n",__FUNCTION__,nread); } return 0; }
In another part of the program, I bind a UDP socket to the IP address of this TUNTAP interface.
void socketInit( void ) { int on = 1; struct sockaddr_in my_addr; unsigned short DefaultPort = 47808; // Create a socket if ( (s1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } // Bind to it bzero((char *) &my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(inet_network("192.168.2.1")); my_addr.sin_port = htons(DefaultPort); if ( (bind(s, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) ) { perror("bind"); } // Allow it to broadcast if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) { perror("setsockopt"); } }
In another function, I use sendto () to send packets with this socket. I have to capture these packets with poll () + read () and then send them to the serial port, but poll () never captures events on the TUNTAP interface.
I can ping through this interface using ping -I tun0 [some destination] (tun0 = TUNTAP interface name)
But if I use ping -I 192.168.2.1 [some destination] (192.168.2.1 = TUNTAP interface address), it goes through the default interface (eth0, physical network adapter).
I was able to verify this with Wireshark.
This is most likely an ip route configuration problem ...
I would be very happy if anyone can help me.