util-vserver 0.30.215.
[util-vserver.git] / src / tunctl.c
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 TUNSETGROUP
37 #  define TUNSETGROUP           _IOW('T', 206, int)
38 #endif
39 #ifndef TUNSETNID
40 #  define TUNSETNID             _IOW('T', 215, int)
41 #endif
42
43 #define ENSC_WRAPPERS_PREFIX    "tunctl: "
44 #define ENSC_WRAPPERS_UNISTD    1
45 #define ENSC_WRAPPERS_VSERVER   1
46 #define ENSC_WRAPPERS_FCNTL     1
47 #define ENSC_WRAPPERS_IOCTL     1
48 #include <wrappers.h>
49
50
51 #define CMD_HELP                0x1000
52 #define CMD_VERSION             0x1001
53 #define CMD_NID                 0x0001
54 #define CMD_DEVICE              0x0002
55 #define CMD_PERSIST             0x0004
56 #define CMD_NOPERSIST           0x0008
57 #define CMD_CSUM                0x0010
58 #define CMD_NOCSUM              0x0020
59 #define CMD_UID                 0x0040
60 #define CMD_GID                 0x0080
61 #define CMD_LINKTYPE            0x0100
62 #define CMD_TUN                 0x0200
63 #define CMD_TAP                 0x0400
64 #define CMD_NID_FAILURE_OK      (0x0800 | CMD_NID)
65
66 int             wrapper_exit_code  =  255;
67
68 struct option const
69 CMDLINE_OPTIONS[] = {
70   { "help",           no_argument,       0, CMD_HELP },
71   { "version",        no_argument,       0, CMD_VERSION },
72   { "nid",            required_argument, 0, CMD_NID },
73   { "device",         required_argument, 0, CMD_DEVICE },
74   { "persist",        no_argument,       0, CMD_PERSIST },
75   { "~persist",       no_argument,       0, CMD_NOPERSIST },
76   { "checksum",       no_argument,       0, CMD_CSUM },
77   { "~checksum",      no_argument,       0, CMD_NOCSUM },
78   { "uid",            required_argument, 0, CMD_UID },
79   { "gid",            required_argument, 0, CMD_GID },
80   { "linktype",       required_argument, 0, CMD_LINKTYPE },
81   { "tun",            no_argument,       0, CMD_TUN },
82   { "tap",            no_argument,       0, CMD_TAP },
83   { "nid-failure-ok", required_argument, 0, CMD_NID_FAILURE_OK },
84   {0,0,0,0}
85 };
86
87 struct Arguments {
88   unsigned int set;
89   nid_t nid;
90   char *device;
91   unsigned persist : 1;
92   unsigned checksum : 1;
93   uid_t uid;
94   gid_t gid;
95   int linktype;
96   int type;
97 };
98
99 static void
100 showHelp(int fd, char const *cmd, int res)
101 {
102   WRITE_MSG(fd, "Usage: ");
103   WRITE_STR(fd, cmd);
104   WRITE_MSG(fd,
105             " {--tun|--tap}\n"
106             "    [--persist|--~persist] [--checksum|--~checksum]\n"
107             "    [--nid <nid>] [--uid <uid>] [--gid <gid>] [--linktype <link type>]\n"
108             "    <interface(s)>...\n"
109             "\n"
110             "Please report bugs to " PACKAGE_BUGREPORT "\n");
111
112   exit(res);
113 }
114
115 static void
116 showVersion()
117 {
118   WRITE_MSG(1,
119             "tunctl " VERSION " -- controls TUN/TAP devices\n"
120             "This program is part of " PACKAGE_STRING "\n\n"
121             "Copyright (C) 2008 Daniel Hokka Zakrisson\n"
122             VERSION_COPYRIGHT_DISCLAIMER);
123   exit(0);
124 }
125
126 static void
127 doTunctl(struct Arguments *args, char *interface)
128 {
129   int fd;
130   struct ifreq ifr;
131
132   fd = EopenD(args->device, O_RDWR, 0);
133
134   strncpy(ifr.ifr_name, interface, IFNAMSIZ);
135   ifr.ifr_name[IFNAMSIZ-1] = '\0';
136   ifr.ifr_flags = args->type;
137   EioctlD(fd, TUNSETIFF, &ifr);
138
139   if (args->set & (CMD_CSUM|CMD_NOCSUM))
140     EioctlD(fd, TUNSETNOCSUM, (void *) (long) !args->checksum);
141   if (args->set & CMD_UID)
142     EioctlD(fd, TUNSETOWNER, (void *) (long) args->uid);
143   if (args->set & CMD_GID)
144     EioctlD(fd, TUNSETGROUP, (void *) (long) args->gid);
145   if (args->set & CMD_NID) {
146     if (args->set & CMD_NID_FAILURE_OK)
147       ioctl(fd, TUNSETNID, (void *) (long) args->nid);
148     else
149       EioctlD(fd, TUNSETNID, (void *) (long) args->nid);
150   }
151   if (args->set & CMD_LINKTYPE)
152     EioctlD(fd, TUNSETLINK, (void *) (long) args->linktype);
153   if (args->set & (CMD_PERSIST|CMD_NOPERSIST))
154     EioctlD(fd, TUNSETPERSIST, (void *) (long) args->persist);
155
156   close(fd);
157 }
158
159 int main(int argc, char *argv[])
160 {
161   struct Arguments args = {
162     .set = 0,
163     .nid = VC_NOCTX,
164     .device = "/dev/net/tun",
165     .persist = 0,
166     .checksum = 0,
167     .uid = -1,
168     .gid = -1,
169     .linktype = -1,
170     .type = IFF_TUN,
171   };
172   char **interface;
173   
174   while (1) {
175     int         c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
176     signed long tmp = 0;
177     if (c==-1) break;
178
179     switch (c) {
180       case CMD_HELP     :  showHelp(1, argv[0], 0);
181       case CMD_VERSION  :  showVersion();
182
183       case CMD_NID_FAILURE_OK:
184       case CMD_NID      :  args.nid = Evc_nidopt2nid(optarg, true);     break;
185       case CMD_DEVICE   :  args.device = optarg;                        break;
186       case CMD_PERSIST  :  args.persist = 1;                            break;
187       case CMD_NOPERSIST:  args.persist = 0;                            break;
188       case CMD_CSUM     :  args.checksum = 1;                           break;
189       case CMD_NOCSUM   :  args.checksum = 0;                           break;
190       case CMD_TUN      :  args.type = IFF_TUN;                         break;
191       case CMD_TAP      :  args.type = IFF_TAP;                         break;
192       case CMD_UID      :
193         if (!isNumber(optarg, &tmp, true)) {
194           WRITE_MSG(2, "Uid '");
195           WRITE_STR(2, optarg);
196           WRITE_MSG(2, "' is not an integer.\n");
197         }
198         args.uid = (uid_t) tmp;
199         break;
200       case CMD_GID      :
201         if (!isNumber(optarg, &tmp, true)) {
202           WRITE_MSG(2, "Gid '");
203           WRITE_STR(2, optarg);
204           WRITE_MSG(2, "' is not an integer.\n");
205         }
206         args.gid = (gid_t) tmp;
207         break;
208       case CMD_LINKTYPE :
209         if (!isNumber(optarg, &tmp, true)) {
210           WRITE_MSG(2, "Link-type '");
211           WRITE_STR(2, optarg);
212           WRITE_STR(2, "' is not an integer.\n");
213         }
214         args.linktype = (int) tmp;
215         break;
216
217       default           :
218         WRITE_MSG(2, "Try '");
219         WRITE_STR(2, argv[0]);
220         WRITE_MSG(2, " --help' for more information.\n");
221         return 255;
222         break;
223     }
224
225     args.set |= c;
226   }
227
228   for (interface = argv + optind; *interface; interface++) {
229     doTunctl(&args, *interface);
230   }
231
232   return EXIT_SUCCESS;
233 }