ftpd: handle restarts past 2147483647 bytes. closes 10741
[oweals/busybox.git] / networking / tunctl.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * tun devices controller
4  *
5  * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
6  *
7  * Original code:
8  *      Jeff Dike
9  *
10  * Licensed under GPLv2, see file LICENSE in this source tree.
11  */
12 //config:config TUNCTL
13 //config:       bool "tunctl (6.4 kb)"
14 //config:       default y
15 //config:       select PLATFORM_LINUX
16 //config:       help
17 //config:       tunctl creates or deletes tun devices.
18 //config:
19 //config:config FEATURE_TUNCTL_UG
20 //config:       bool "Support owner:group assignment"
21 //config:       default y
22 //config:       depends on TUNCTL
23 //config:       help
24 //config:       Allow to specify owner and group of newly created interface.
25 //config:       340 bytes of pure bloat. Say no here.
26
27 //applet:IF_TUNCTL(APPLET_NOEXEC(tunctl, tunctl, BB_DIR_SBIN, BB_SUID_DROP, tunctl))
28
29 //kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o
30
31 //usage:#define tunctl_trivial_usage
32 //usage:       "[-f device] ([-t name] | -d name)" IF_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]")
33 //usage:#define tunctl_full_usage "\n\n"
34 //usage:       "Create or delete tun interfaces\n"
35 //usage:     "\n        -f name         tun device (/dev/net/tun)"
36 //usage:     "\n        -t name         Create iface 'name'"
37 //usage:     "\n        -d name         Delete iface 'name'"
38 //usage:        IF_FEATURE_TUNCTL_UG(
39 //usage:     "\n        -u owner        Set iface owner"
40 //usage:     "\n        -g group        Set iface group"
41 //usage:     "\n        -b              Brief output"
42 //usage:        )
43 //usage:
44 //usage:#define tunctl_example_usage
45 //usage:       "# tunctl\n"
46 //usage:       "# tunctl -d tun0\n"
47
48 #include <netinet/in.h>
49 #include <net/if.h>
50 #include <linux/if_tun.h>
51 #include "libbb.h"
52
53 /* TUNSETGROUP appeared in 2.6.23 */
54 #ifndef TUNSETGROUP
55 #define TUNSETGROUP _IOW('T', 206, int)
56 #endif
57
58 #define IOCTL(a, b, c) ioctl_or_perror_and_die(a, b, c, NULL)
59
60 #if 1
61
62 int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
63 int tunctl_main(int argc UNUSED_PARAM, char **argv)
64 {
65         struct ifreq ifr;
66         int fd;
67         const char *opt_name = "tap%d";
68         const char *opt_device = "/dev/net/tun";
69 #if ENABLE_FEATURE_TUNCTL_UG
70         const char *opt_user, *opt_group;
71         long user = -1, group = -1;
72 #endif
73         unsigned opts;
74
75         enum {
76                 OPT_f = 1 << 0, // control device name (/dev/net/tun)
77                 OPT_t = 1 << 1, // create named interface
78                 OPT_d = 1 << 2, // delete named interface
79 #if ENABLE_FEATURE_TUNCTL_UG
80                 OPT_u = 1 << 3, // set new interface owner
81                 OPT_g = 1 << 4, // set new interface group
82                 OPT_b = 1 << 5, // brief output
83 #endif
84         };
85
86         opts = getopt32(argv, "^"
87                         "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b")
88                         "\0"
89                         "=0:t--d:d--t", // no arguments; t ^ d
90                         &opt_device, &opt_name, &opt_name
91                         IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)
92         );
93
94         // select device
95         memset(&ifr, 0, sizeof(ifr));
96         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
97         strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
98
99         // open device
100         fd = xopen(opt_device, O_RDWR);
101         IOCTL(fd, TUNSETIFF, (void *)&ifr);
102
103         // delete?
104         if (opts & OPT_d) {
105                 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
106                 printf("Set '%s' nonpersistent\n", ifr.ifr_name);
107                 return EXIT_SUCCESS;
108         }
109
110         // create
111 #if ENABLE_FEATURE_TUNCTL_UG
112         if (opts & OPT_g) {
113                 group = xgroup2gid(opt_group);
114                 IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group);
115         } else
116                 user = geteuid();
117         if (opts & OPT_u)
118                 user = xuname2uid(opt_user);
119         IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user);
120 #endif
121         IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1);
122
123         // show info
124 #if ENABLE_FEATURE_TUNCTL_UG
125         if (opts & OPT_b) {
126                 puts(ifr.ifr_name);
127         } else {
128                 printf("Set '%s' %spersistent", ifr.ifr_name, "");
129                 printf(" and owned by uid %ld", user);
130                 if (group != -1)
131                         printf(" gid %ld", group);
132                 bb_putchar('\n');
133         }
134 #else
135         puts(ifr.ifr_name);
136 #endif
137         return EXIT_SUCCESS;
138 }
139
140 #else
141
142 /* -210 bytes: */
143
144 int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
145 int tunctl_main(int argc UNUSED_PARAM, char **argv)
146 {
147         struct ifreq ifr;
148         int fd;
149         const char *opt_name = "tap%d";
150         const char *opt_device = "/dev/net/tun";
151         unsigned opts;
152
153         enum {
154                 OPT_f = 1 << 0, // control device name (/dev/net/tun)
155                 OPT_t = 1 << 1, // create named interface
156                 OPT_d = 1 << 2, // delete named interface
157         };
158
159         opts = getopt32(argv, "^"
160                         "f:t:d:u:g:b" // u, g, b accepted and ignored
161                         "\0"
162                         "=0:t--d:d--t", // no arguments; t ^ d
163                         &opt_device, &opt_name, &opt_name, NULL, NULL
164         );
165
166         // set interface name
167         memset(&ifr, 0, sizeof(ifr));
168         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
169         strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
170
171         // open device
172         fd = xopen(opt_device, O_RDWR);
173         IOCTL(fd, TUNSETIFF, (void *)&ifr);
174
175         // create or delete interface
176         IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
177
178         return EXIT_SUCCESS;
179 }
180
181 #endif