#include #include #include #include #include #include #include #include #include #include #include #include static void * ifioctl(void *arg) { const char *name = arg; struct ifreq ifr; size_t len; int s; len = strlen(name); if (len >= sizeof(ifr.ifr_name)) errx(1, "interface name is too long"); s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) err(1, "%s socket", __func__); for (;;) { memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, name, len); if (ioctl(s, SIOCIFCREATE, &ifr) == -1) warn("SIOCIFCREATE %s", name); memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, name, len); if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) warn("SIOCIFDESTROY %s", name); } return (NULL); } static void * dvthing(void *arg) { const char *name = arg; int fd; unsigned int yay = 0, nay = 0; ssize_t rv; uint8_t buf[65536]; for (;;) { fd = open(name, O_RDWR); if (fd == -1) { nay++; if (errno != ECANCELED || (nay % 1000) == 0) { warn("open %s (yay %u vs nay %u)", name, yay, nay); } continue; } yay++; pain: rv = read(fd, buf, sizeof(buf)); if (rv == -1) { warn("read"); if (errno == EIO) { int nfd = open(name, O_RDWR); if (nfd == -1) warn("open new %s", name); else { close(fd); fd = nfd; goto pain; } } } close(fd); } return (NULL); } __dead static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s ifname\n", __progname); exit(1); } int main(int argc, char *argv[]) { int ecode; pthread_t if_tid, dv_tid; void *ret; if (argc != 2) usage(); if (chdir("/dev") == -1) err(1, "/dev"); ecode = pthread_create(&if_tid, NULL, ifioctl, argv[1]); if (ecode != 0) errc(1, ecode, "create ifioctl thread"); ecode = pthread_create(&dv_tid, NULL, dvthing, argv[1]); if (ecode != 0) errc(1, ecode, "create dvthing thread"); ecode = pthread_join(if_tid, &ret); if (ecode != 0) errc(1, ecode, "join ifioctl thread"); ecode = pthread_join(dv_tid, &ret); if (ecode != 0) errc(1, ecode, "join dvthing thread"); exit(0); }