qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] tap device and two nics


From: Don Kitchen
Subject: [Qemu-devel] tap device and two nics
Date: Tue, 4 Oct 2005 14:27:56 -0700 (PDT)

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);
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]