Add build-dep on scratchbox-core
[qemu] / debian / tundev.c
1 /*
2  * $Id: tundev.c 325 2008-08-09 21:39:16Z aurel32 $
3  */
4
5 #define _GNU_SOURCE /* asprintf */
6 #include <stdio.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <pwd.h>
10 #include <grp.h>
11 #include <sys/stat.h>
12 #include <sys/ioctl.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <net/if.h>
17 #include <linux/if_tun.h>
18
19 /* Tiny code to open tap/tun device, and hand the fd to qemu.
20    Run as root, drops to given user. */
21 int main(int argc, char *argv[])
22 {
23         struct ifreq ifr;
24         struct passwd *p;
25         unsigned int i;
26         char *newargs[argc + 1];
27         int fd;
28
29         if (argc < 4) {
30                 fprintf(stderr,
31                         "Usage: tundev user logfile qemu <qemu options>...\n");
32                 exit(1);
33         }
34
35         fd = open("/dev/net/tun", O_RDWR);
36         if (fd < 0) {
37                 perror("Could not open /dev/net/tun");
38                 exit(1);
39         }
40
41         memset(&ifr, 0, sizeof(ifr));
42         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
43         strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ);
44         if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
45                 perror("Could not get tun device");
46                 exit(1);
47         }
48
49         /* Set userid. */
50         p = getpwnam(argv[1]);
51         if (!p) {
52                 fprintf(stderr, "No user '%s'\n", argv[1]);
53                 exit(1);
54         }
55         setgroups(0, NULL);
56         setgid(p->pw_gid);
57         if (setuid(p->pw_uid) != 0) {
58                 perror("setting uid");
59                 exit(1);
60         }
61
62         /* Insert -tun-fd */
63         newargs[0] = argv[3];
64         newargs[1] = "-tun-fd";
65         asprintf(&newargs[2], "%d", fd);
66         for (i = 4; i <= argc; i++)
67                 newargs[i-1] = argv[i];
68
69         if (strcmp(argv[2], "-") == 0) {
70                 execvp(newargs[0], newargs);
71                 exit(1);
72         }
73
74         switch (fork()) {
75         case 0: {
76                 close(1);
77                 close(2);
78                 open(argv[2], O_WRONLY|O_APPEND);
79                 open(argv[2], O_WRONLY|O_APPEND);
80                 close(0);
81                 execvp(newargs[0], newargs);
82                 exit(1);
83         }
84         case -1:
85                 perror("fork failed");
86                 exit(1);
87         }
88         printf("%s\n", ifr.ifr_name);
89         exit(0);
90 }