#include #include #include #include #include #include #include #include #include #include #include #include #include #define PERROR_L(s) \ fprintf(stderr, "(line %d) %s: %s\n", __LINE__, s, strerror(errno)) static int tun_alloc(const char *dev) { struct ifreq ifr; int fd, err; if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { PERROR_L("open"); return fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP|IFF_NO_PI; strncpy(ifr.ifr_name, dev, IFNAMSIZ); if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { PERROR_L("ioctl"); close(fd); return err; } return fd; } static int ifup(const char *dev) { struct ifreq ifr; int fd, err; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { PERROR_L("socket"); return fd; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, dev, IFNAMSIZ); if ((err = ioctl(fd, SIOCGIFFLAGS, (void *)&ifr)) < 0) { PERROR_L("ioctl"); goto out; } ifr.ifr_flags |= IFF_UP|IFF_RUNNING; if ((err = ioctl(fd, SIOCSIFFLAGS, (void *)&ifr)) < 0) { PERROR_L("ioctl"); goto out; } out: close(fd); return err; } static void hexdump(const ssize_t size, const unsigned char *buf) { int i; time_t t = time(NULL); printf("\n--- %s", ctime(&t)); for (i = 0; i < size; i++) { if (i % 16 == 0) printf("\n 0x%04x: ", i); printf("%02x", buf[i]); if (i % 2) printf(" "); } printf("\n"); } static void mainloop(const int fd) { fd_set fds; int ret; struct timeval tv; ssize_t size; unsigned char buf[65535]; while (1) { memset(&tv, 0, sizeof(tv)); tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(fd, &fds); ret = select(fd+1, &fds, NULL, NULL, &tv); if (ret < 0) { if (errno == EINTR) continue; PERROR_L("select"); return; } else if (ret == 0) continue; memset(buf, 0, sizeof(buf)); size = read(fd, buf, sizeof(buf)); if (size < 0) { if (errno == EINTR) continue; PERROR_L("read"); return; } else if (size == 0) break; hexdump(size, buf); } } int main(int argc, char **argv) { int fd, ret; if (argc != 2) { fprintf(stderr, "Syntax: %s DEVNAME\n", argv[0]); return 1; } if (IFNAMSIZ <= strlen(argv[1])) { fprintf(stderr, "DEVNAME is too long\n"); return 2; } if ((fd = tun_alloc(argv[1])) < 0) return 3; if ((ret = ifup(argv[1])) < 0) goto out; mainloop(fd); out: close(fd); return ret; }