#include #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { struct ifreq ifr; pid_t pid, ppid = getpid(); int fd; fd = open("/dev/net/tun", O_RDWR); if (fd < 0) { perror("open tun"); exit(1); } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = (IFF_TUN | IFF_NO_PI); if (ioctl(fd, TUNSETIFF, &ifr) < 0) { perror("TUNSETIFF"); exit(1); } pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (!pid) { char *cmd; close(fd); if (unshare(CLONE_NEWNET) < 0) { perror("unshare"); exit(1); } /* Wait for the tun device to be given to us... */ sleep(2); fd = open("/dev/net/tun", O_RDWR); if (fd < 0) { perror("open tun"); exit(1); } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = (IFF_TUN | IFF_NO_PI); if (ioctl(fd, TUNSETIFF, &ifr) < 0) { perror("TUNSETIFF"); exit(1); } printf("Open %s in child\n", ifr.ifr_name); if (asprintf(&cmd, "/sbin/ip link set %s netns %d", ifr.ifr_name, ppid) < 0) { perror("asprintf"); exit(1); } printf("%s\n", cmd); if (system(cmd)) { perror("give tun to parent"); exit(1); } sleep(1); printf("child bye\n"); exit(0); } else { /* Wait for the unshare() */ char *cmd; if (asprintf(&cmd, "/sbin/ip link set %s netns %d", ifr.ifr_name, pid) < 0) { perror("asprintf"); exit(1); } sleep(1); printf("%s\n", cmd); if (system(cmd)) { perror("give tun to child"); exit(1); } free(cmd); sleep(1); /* Yeah, too lazy to pass the real name back */ printf("del tun1\n"); sleep(1); system("/sbin/ip link del tun1"); close(fd); } return 0; }