tunctl.c (6641B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2008 Daniel Hokka Zakrisson 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; version 2 of the License. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 #include "util.h" 24 25 #include <vserver.h> 26 27 #include <getopt.h> 28 #include <errno.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <sys/ioctl.h> 32 #include <linux/if.h> 33 #include <linux/if_tun.h> 34 35 /* Make sure we have the necessary ioctls */ 36 #ifndef TUNSETNOCSUM 37 # define TUNSETNOCSUM _IOW('T', 200, int) 38 #endif 39 #ifndef TUNSETIFF 40 # define TUNSETIFF _IOW('T', 202, int) 41 #endif 42 #ifndef TUNSETPERSIST 43 # define TUNSETPERSIST _IOW('T', 203, int) 44 #endif 45 #ifndef TUNSETOWNER 46 # define TUNSETOWNER _IOW('T', 204, int) 47 #endif 48 #ifndef TUNSETLINK 49 # define TUNSETLINK _IOW('T', 205, int) 50 #endif 51 #ifndef TUNSETGROUP 52 # define TUNSETGROUP _IOW('T', 206, int) 53 #endif 54 #ifndef TUNSETNID 55 # define TUNSETNID _IOW('T', 215, int) 56 #endif 57 58 #define ENSC_WRAPPERS_PREFIX "tunctl: " 59 #define ENSC_WRAPPERS_UNISTD 1 60 #define ENSC_WRAPPERS_VSERVER 1 61 #define ENSC_WRAPPERS_FCNTL 1 62 #define ENSC_WRAPPERS_IOCTL 1 63 #include <wrappers.h> 64 65 66 #define CMD_HELP 0x1000 67 #define CMD_VERSION 0x1001 68 #define CMD_NID 0x0001 69 #define CMD_DEVICE 0x0002 70 #define CMD_PERSIST 0x0004 71 #define CMD_NOPERSIST 0x0008 72 #define CMD_CSUM 0x0010 73 #define CMD_NOCSUM 0x0020 74 #define CMD_UID 0x0040 75 #define CMD_GID 0x0080 76 #define CMD_LINKTYPE 0x0100 77 #define CMD_TUN 0x0200 78 #define CMD_TAP 0x0400 79 #define CMD_NID_FAILURE_OK (0x0800 | CMD_NID) 80 81 int wrapper_exit_code = 255; 82 83 struct option const 84 CMDLINE_OPTIONS[] = { 85 { "help", no_argument, 0, CMD_HELP }, 86 { "version", no_argument, 0, CMD_VERSION }, 87 { "nid", required_argument, 0, CMD_NID }, 88 { "device", required_argument, 0, CMD_DEVICE }, 89 { "persist", no_argument, 0, CMD_PERSIST }, 90 { "~persist", no_argument, 0, CMD_NOPERSIST }, 91 { "checksum", no_argument, 0, CMD_CSUM }, 92 { "~checksum", no_argument, 0, CMD_NOCSUM }, 93 { "uid", required_argument, 0, CMD_UID }, 94 { "gid", required_argument, 0, CMD_GID }, 95 { "linktype", required_argument, 0, CMD_LINKTYPE }, 96 { "tun", no_argument, 0, CMD_TUN }, 97 { "tap", no_argument, 0, CMD_TAP }, 98 { "nid-failure-ok", required_argument, 0, CMD_NID_FAILURE_OK }, 99 {0,0,0,0} 100 }; 101 102 struct Arguments { 103 unsigned int set; 104 nid_t nid; 105 char *device; 106 unsigned persist : 1; 107 unsigned checksum : 1; 108 uid_t uid; 109 gid_t gid; 110 int linktype; 111 int type; 112 }; 113 114 static void 115 showHelp(int fd, char const *cmd, int res) 116 { 117 WRITE_MSG(fd, "Usage: "); 118 WRITE_STR(fd, cmd); 119 WRITE_MSG(fd, 120 " {--tun|--tap}\n" 121 " [--persist|--~persist] [--checksum|--~checksum]\n" 122 " [--nid <nid>] [--uid <uid>] [--gid <gid>] [--linktype <link type>]\n" 123 " <interface(s)>...\n" 124 "\n" 125 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 126 127 exit(res); 128 } 129 130 static void 131 showVersion() 132 { 133 WRITE_MSG(1, 134 "tunctl " VERSION " -- controls TUN/TAP devices\n" 135 "This program is part of " PACKAGE_STRING "\n\n" 136 "Copyright (C) 2008 Daniel Hokka Zakrisson\n" 137 VERSION_COPYRIGHT_DISCLAIMER); 138 exit(0); 139 } 140 141 static void 142 doTunctl(struct Arguments *args, char *interface) 143 { 144 int fd; 145 struct ifreq ifr; 146 147 fd = EopenD(args->device, O_RDWR, 0); 148 149 strncpy(ifr.ifr_name, interface, IFNAMSIZ); 150 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 151 ifr.ifr_flags = args->type; 152 EioctlD(fd, TUNSETIFF, &ifr); 153 154 if (args->set & (CMD_CSUM|CMD_NOCSUM)) 155 EioctlD(fd, TUNSETNOCSUM, (void *) (long) !args->checksum); 156 if (args->set & CMD_UID) 157 EioctlD(fd, TUNSETOWNER, (void *) (long) args->uid); 158 if (args->set & CMD_GID) 159 EioctlD(fd, TUNSETGROUP, (void *) (long) args->gid); 160 if (args->set & CMD_NID) { 161 if (args->set & CMD_NID_FAILURE_OK) 162 ioctl(fd, TUNSETNID, (void *) (long) args->nid); 163 else 164 EioctlD(fd, TUNSETNID, (void *) (long) args->nid); 165 } 166 if (args->set & CMD_LINKTYPE) 167 EioctlD(fd, TUNSETLINK, (void *) (long) args->linktype); 168 if (args->set & (CMD_PERSIST|CMD_NOPERSIST)) 169 EioctlD(fd, TUNSETPERSIST, (void *) (long) args->persist); 170 171 close(fd); 172 } 173 174 int main(int argc, char *argv[]) 175 { 176 struct Arguments args = { 177 .set = 0, 178 .nid = VC_NOCTX, 179 .device = "/dev/net/tun", 180 .persist = 0, 181 .checksum = 0, 182 .uid = -1, 183 .gid = -1, 184 .linktype = -1, 185 .type = IFF_TUN, 186 }; 187 char **interface; 188 189 while (1) { 190 int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); 191 signed long tmp = 0; 192 if (c==-1) break; 193 194 switch (c) { 195 case CMD_HELP : showHelp(1, argv[0], 0); 196 case CMD_VERSION : showVersion(); 197 198 case CMD_NID_FAILURE_OK: 199 case CMD_NID : args.nid = Evc_nidopt2nid(optarg, true); break; 200 case CMD_DEVICE : args.device = optarg; break; 201 case CMD_PERSIST : args.persist = 1; break; 202 case CMD_NOPERSIST: args.persist = 0; break; 203 case CMD_CSUM : args.checksum = 1; break; 204 case CMD_NOCSUM : args.checksum = 0; break; 205 case CMD_TUN : args.type = IFF_TUN; break; 206 case CMD_TAP : args.type = IFF_TAP; break; 207 case CMD_UID : 208 if (!isNumber(optarg, &tmp, true)) { 209 WRITE_MSG(2, "Uid '"); 210 WRITE_STR(2, optarg); 211 WRITE_MSG(2, "' is not an integer.\n"); 212 } 213 args.uid = (uid_t) tmp; 214 break; 215 case CMD_GID : 216 if (!isNumber(optarg, &tmp, true)) { 217 WRITE_MSG(2, "Gid '"); 218 WRITE_STR(2, optarg); 219 WRITE_MSG(2, "' is not an integer.\n"); 220 } 221 args.gid = (gid_t) tmp; 222 break; 223 case CMD_LINKTYPE : 224 if (!isNumber(optarg, &tmp, true)) { 225 WRITE_MSG(2, "Link-type '"); 226 WRITE_STR(2, optarg); 227 WRITE_STR(2, "' is not an integer.\n"); 228 } 229 args.linktype = (int) tmp; 230 break; 231 232 default : 233 WRITE_MSG(2, "Try '"); 234 WRITE_STR(2, argv[0]); 235 WRITE_MSG(2, " --help' for more information.\n"); 236 return 255; 237 break; 238 } 239 240 args.set |= c; 241 } 242 243 for (interface = argv + optind; *interface; interface++) { 244 doTunctl(&args, *interface); 245 } 246 247 return EXIT_SUCCESS; 248 }