xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-devtools/qemu/qemu-helper/tunctl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* Copyright 2002 Jeff Dike
2  * Licensed under the GPL
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <pwd.h>
12 #include <grp.h>
13 #include <net/if.h>
14 #include <sys/ioctl.h>
15 #include <linux/if_tun.h>
16 
17 /* TUNSETGROUP appeared in 2.6.23 */
18 #ifndef TUNSETGROUP
19 #define TUNSETGROUP   _IOW('T', 206, int)
20 #endif
21 
Usage(char * name,int status)22 static void Usage(char *name, int status)
23 {
24   fprintf(stderr, "Create: %s [-b] [-u owner] [-g group] [-t device-name] "
25 	  "[-f tun-clone-device]\n", name);
26   fprintf(stderr, "Delete: %s -d device-name [-f tun-clone-device]\n\n",
27 	  name);
28   fprintf(stderr, "The default tun clone device is /dev/net/tun - some systems"
29 	  " use\n/dev/misc/net/tun instead\n\n");
30   fprintf(stderr, "-b will result in brief output (just the device name)\n");
31   exit(status);
32 }
33 
main(int argc,char ** argv)34 int main(int argc, char **argv)
35 {
36   struct ifreq ifr;
37   struct passwd *pw;
38   struct group *gr;
39   uid_t owner = -1;
40   gid_t group = -1;
41   int tap_fd, opt, delete = 0, brief = 0;
42   char *tun = "", *file = "/dev/net/tun", *name = argv[0], *end;
43 
44   while((opt = getopt(argc, argv, "bd:f:t:u:g:h")) > 0){
45     switch(opt) {
46       case 'b':
47         brief = 1;
48         break;
49       case 'd':
50         delete = 1;
51 	tun = optarg;
52         break;
53       case 'f':
54 	file = optarg;
55 	break;
56       case 'u':
57 	pw = getpwnam(optarg);
58 	if(pw != NULL){
59 	  owner = pw->pw_uid;
60 	  break;
61 	}
62         owner = strtol(optarg, &end, 0);
63 	if(*end != '\0'){
64 	  fprintf(stderr, "'%s' is neither a username nor a numeric uid.\n",
65 		  optarg);
66 	  Usage(name, 1);
67 	}
68         break;
69       case 'g':
70 	gr = getgrnam(optarg);
71 	if(gr != NULL){
72 	  group = gr->gr_gid;
73 	  break;
74 	}
75         group = strtol(optarg, &end, 0);
76 	if(*end != '\0'){
77 	  fprintf(stderr, "'%s' is neither a groupname nor a numeric group.\n",
78 		  optarg);
79 	  Usage(name, 1);
80 	}
81         break;
82 
83       case 't':
84         tun = optarg;
85         break;
86       case 'h':
87         Usage(name, 0);
88         break;
89       default:
90         Usage(name, 1);
91     }
92   }
93 
94   argv += optind;
95   argc -= optind;
96 
97   if(argc > 0)
98     Usage(name, 1);
99 
100   if((tap_fd = open(file, O_RDWR)) < 0){
101     fprintf(stderr, "Failed to open '%s' : ", file);
102     perror("");
103     exit(1);
104   }
105 
106   memset(&ifr, 0, sizeof(ifr));
107 
108   ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
109   strncpy(ifr.ifr_name, tun, sizeof(ifr.ifr_name) - 1);
110   if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){
111     perror("TUNSETIFF");
112     exit(1);
113   }
114 
115   if(delete){
116     if(ioctl(tap_fd, TUNSETPERSIST, 0) < 0){
117       perror("disabling TUNSETPERSIST");
118       exit(1);
119     }
120     printf("Set '%s' nonpersistent\n", ifr.ifr_name);
121   }
122   else {
123     /* emulate behaviour prior to TUNSETGROUP */
124     if(owner == -1 && group == -1) {
125       owner = geteuid();
126     }
127 
128     if(owner != -1) {
129       if(ioctl(tap_fd, TUNSETOWNER, owner) < 0){
130       	perror("TUNSETOWNER");
131       	exit(1);
132       }
133     }
134     if(group != -1) {
135       if(ioctl(tap_fd, TUNSETGROUP, group) < 0){
136       	perror("TUNSETGROUP");
137       	exit(1);
138       }
139     }
140 
141     if(ioctl(tap_fd, TUNSETPERSIST, 1) < 0){
142       perror("enabling TUNSETPERSIST");
143       exit(1);
144     }
145 
146     if(brief)
147       printf("%s\n", ifr.ifr_name);
148     else {
149       printf("Set '%s' persistent and owned by", ifr.ifr_name);
150       if(owner != -1)
151           printf(" uid %d", owner);
152       if(group != -1)
153           printf(" gid %d", group);
154       printf("\n");
155     }
156   }
157   return(0);
158 }
159