config: deindent all help texts
[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(tunctl, BB_DIR_SBIN, BB_SUID_DROP))
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         opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d
87         opts = getopt32(argv, "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b"),
88                         &opt_device, &opt_name, &opt_name
89                         IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group));
90
91         // select device
92         memset(&ifr, 0, sizeof(ifr));
93         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
94         strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
95
96         // open device
97         fd = xopen(opt_device, O_RDWR);
98         IOCTL(fd, TUNSETIFF, (void *)&ifr);
99
100         // delete?
101         if (opts & OPT_d) {
102                 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
103                 printf("Set '%s' nonpersistent\n", ifr.ifr_name);
104                 return EXIT_SUCCESS;
105         }
106
107         // create
108 #if ENABLE_FEATURE_TUNCTL_UG
109         if (opts & OPT_g) {
110                 group = xgroup2gid(opt_group);
111                 IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group);
112         } else
113                 user = geteuid();
114         if (opts & OPT_u)
115                 user = xuname2uid(opt_user);
116         IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user);
117 #endif
118         IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1);
119
120         // show info
121 #if ENABLE_FEATURE_TUNCTL_UG
122         if (opts & OPT_b) {
123                 puts(ifr.ifr_name);
124         } else {
125                 printf("Set '%s' %spersistent", ifr.ifr_name, "");
126                 printf(" and owned by uid %ld", user);
127                 if (group != -1)
128                         printf(" gid %ld", group);
129                 bb_putchar('\n');
130         }
131 #else
132         puts(ifr.ifr_name);
133 #endif
134         return EXIT_SUCCESS;
135 }
136
137 #else
138
139 /* -210 bytes: */
140
141 int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
142 int tunctl_main(int argc UNUSED_PARAM, char **argv)
143 {
144         struct ifreq ifr;
145         int fd;
146         const char *opt_name = "tap%d";
147         const char *opt_device = "/dev/net/tun";
148         unsigned opts;
149
150         enum {
151                 OPT_f = 1 << 0, // control device name (/dev/net/tun)
152                 OPT_t = 1 << 1, // create named interface
153                 OPT_d = 1 << 2, // delete named interface
154         };
155
156         opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d
157         opts = getopt32(argv, "f:t:d:u:g:b", // u, g, b accepted and ignored
158                         &opt_device, &opt_name, &opt_name, NULL, NULL);
159
160         // set interface name
161         memset(&ifr, 0, sizeof(ifr));
162         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
163         strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
164
165         // open device
166         fd = xopen(opt_device, O_RDWR);
167         IOCTL(fd, TUNSETIFF, (void *)&ifr);
168
169         // create or delete interface
170         IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
171
172         return EXIT_SUCCESS;
173 }
174
175 #endif