Tagging module util-vserver - util-vserver-0.30.215-6
[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 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 }