Hi, it looks like I stirred up some change by asking about tun and tap. (and definately it's important to know that "tun" is a tap device!)
In case anyone's interested, here is a tapdev2.c that I put together to make use of two virtual nics as tap devices. Maybe also the script setup will interest people for the regular tapdev.c. Apologies for the clumsy way I use perl. #define _GNU_SOURCE /* asprintf */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <net/if.h> #include <linux/if_tun.h> /* Tiny code to open two tap devices, and hand the fds to qemu. Run as root, drops to given user. Based on tundev.c freely distributed at in http://fabrice.bellard.free.fr/qemu/tetrinet.tar.gz Assuming that code is available under BSD or GPL license, these modifications are under GPL. Linux usage: DEVS=`./tapdev2 root log /usr/bin/qemu ... &` DEV1=`echo $DEVS | perl -pe 's/^([^ ]*) *([^ ]*)/$1/'` DEV2=`echo $DEVS | perl -pe 's/^([^ ]*) *([^ ]*)/$2/'` /sbin/ifconfig $DEV1 0.0.0.0 promisc up /sbin/ifconfig $DEV2 0.0.0.0 promisc up /sbin/ifconfig br0 >& /dev/null || (/usr/sbin/brctl addbr br0 && /sbin/ifconfig br0 up) /usr/sbin/brctl addif br0 $DEV1 echo br0 device $DEV1 other device $DEV2 */ int main(int argc, char *argv[]) { struct ifreq ifr1; struct ifreq ifr2; struct passwd *p; unsigned int i; char *newargs[argc]; int fd1, fd2; #define JUNKARGS 3 #define TWONICS 2 #define TAPFD 2 if (argc < 4) { fprintf(stderr, "Usage: tapdev2 switchuser logfile qemu <qemu options>...\n"); exit(1); } fd1 = open("/dev/net/tun", O_RDWR); if (fd1 < 0) { perror("1 Could not open /dev/net/tun"); exit(1); } fd2 = open("/dev/net/tun", O_RDWR); if (fd2 < 0) { perror("2 Could not open /dev/net/tun"); exit(1); } memset(&ifr1, 0, sizeof(ifr1)); ifr1.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr1.ifr_name, "tap%d", IFNAMSIZ); memset(&ifr2, 0, sizeof(ifr2)); ifr2.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr2.ifr_name, "tap%d", IFNAMSIZ); if (ioctl(fd1, TUNSETIFF, (void *) &ifr1) != 0) { perror("1 Could not get tun device"); exit(1); } if (ioctl(fd2, TUNSETIFF, (void *) &ifr2) != 0) { perror("2 Could not get tun device"); exit(1); } /* Set userid. */ p = getpwnam(argv[JUNKARGS-2]); if (!p) { fprintf(stderr, "No user '%s'\n", argv[JUNKARGS-2]); exit(1); } setgroups(0, NULL); setgid(p->pw_gid); if (setuid(p->pw_uid) != 0) { perror("setting uid"); exit(1); } /* arg# 0 1 2 3 4 5 6 7 8 old: tapdev2 user - qemu -hda blah ... new: qemu -nics 2 -tun-fd x -tun-fd x -hda blah ... */ /* Insert -nics 2 -tun-fd, delete other args */ newargs[0] = argv[0+JUNKARGS]; asprintf(&newargs[1], "-nics"); asprintf(&newargs[2], "2"); asprintf(&newargs[TWONICS+1], "-tun-fd"); asprintf(&newargs[TWONICS+2], "%d", fd1); asprintf(&newargs[TWONICS+TAPFD+1], "-tun-fd"); asprintf(&newargs[TWONICS+TAPFD+2], "%d", fd2); for (i = JUNKARGS+1; i <= argc; i++) newargs[i-JUNKARGS+TWONICS+TAPFD+TAPFD] = argv[i]; if (strcmp(argv[JUNKARGS-1], "-") == 0) { printf("%s %s\n", ifr1.ifr_name, ifr2.ifr_name); execvp(newargs[0], newargs); exit(1); } switch (fork()) { case 0: { close(1); close(2); open(argv[JUNKARGS-1], O_WRONLY|O_APPEND); open(argv[JUNKARGS-1], O_WRONLY|O_APPEND); close(0); execvp(newargs[0], newargs); exit(1); } case -1: perror("fork failed"); exit(1); } printf("%s %s\n", ifr1.ifr_name, ifr2.ifr_name); exit(0); } _______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel