| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 |  | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 22 | static void Usage(char *name, int status) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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"); | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 31 |   exit(status); | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 32 | } | 
 | 33 |  | 
 | 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 |  | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 44 |   while((opt = getopt(argc, argv, "bd:f:t:u:g:h")) > 0){ | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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); | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 66 | 	  Usage(name, 1); | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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); | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 79 | 	  Usage(name, 1); | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 80 | 	} | 
 | 81 |         break; | 
 | 82 |  | 
 | 83 |       case 't': | 
 | 84 |         tun = optarg; | 
 | 85 |         break; | 
 | 86 |       case 'h': | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 87 |         Usage(name, 0); | 
 | 88 |         break; | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 89 |       default: | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 90 |         Usage(name, 1); | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 91 |     } | 
 | 92 |   } | 
 | 93 |  | 
 | 94 |   argv += optind; | 
 | 95 |   argc -= optind; | 
 | 96 |  | 
 | 97 |   if(argc > 0) | 
| Brad Bishop | 64c979e | 2019-11-04 13:55:29 -0500 | [diff] [blame] | 98 |     Usage(name, 1); | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 | } |