1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#include <netinet/in.h>
48#include <net/if.h>
49#include <linux/if_tun.h>
50#include "libbb.h"
51
52
53#ifndef TUNSETGROUP
54#define TUNSETGROUP _IOW('T', 206, int)
55#endif
56
57#define IOCTL(a, b, c) ioctl_or_perror_and_die(a, b, c, NULL)
58
59#if 1
60
61int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
62int tunctl_main(int argc UNUSED_PARAM, char **argv)
63{
64 struct ifreq ifr;
65 int fd;
66 const char *opt_name = "tap%d";
67 const char *opt_device = "/dev/net/tun";
68#if ENABLE_FEATURE_TUNCTL_UG
69 const char *opt_user, *opt_group;
70 long user = -1, group = -1;
71#endif
72 unsigned opts;
73
74 enum {
75 OPT_f = 1 << 0,
76 OPT_t = 1 << 1,
77 OPT_d = 1 << 2,
78#if ENABLE_FEATURE_TUNCTL_UG
79 OPT_u = 1 << 3,
80 OPT_g = 1 << 4,
81 OPT_b = 1 << 5,
82#endif
83 };
84
85 opts = getopt32(argv, "^"
86 "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b")
87 "\0"
88 "=0:t--d:d--t",
89 &opt_device, &opt_name, &opt_name
90 IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)
91 );
92
93
94 memset(&ifr, 0, sizeof(ifr));
95 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
96 strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
97
98
99 fd = xopen(opt_device, O_RDWR);
100 IOCTL(fd, TUNSETIFF, (void *)&ifr);
101
102
103 if (opts & OPT_d) {
104 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
105 printf("Set '%s' nonpersistent\n", ifr.ifr_name);
106 return EXIT_SUCCESS;
107 }
108
109
110#if ENABLE_FEATURE_TUNCTL_UG
111 if (opts & OPT_g) {
112 group = xgroup2gid(opt_group);
113 IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group);
114 } else
115 user = geteuid();
116 if (opts & OPT_u)
117 user = xuname2uid(opt_user);
118 IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user);
119#endif
120 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1);
121
122
123#if ENABLE_FEATURE_TUNCTL_UG
124 if (opts & OPT_b) {
125 puts(ifr.ifr_name);
126 } else {
127 printf("Set '%s' %spersistent", ifr.ifr_name, "");
128 printf(" and owned by uid %ld", user);
129 if (group != -1)
130 printf(" gid %ld", group);
131 bb_putchar('\n');
132 }
133#else
134 puts(ifr.ifr_name);
135#endif
136 return EXIT_SUCCESS;
137}
138
139#else
140
141
142
143int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
144int tunctl_main(int argc UNUSED_PARAM, char **argv)
145{
146 struct ifreq ifr;
147 int fd;
148 const char *opt_name = "tap%d";
149 const char *opt_device = "/dev/net/tun";
150 unsigned opts;
151
152 enum {
153 OPT_f = 1 << 0,
154 OPT_t = 1 << 1,
155 OPT_d = 1 << 2,
156 };
157
158 opts = getopt32(argv, "^"
159 "f:t:d:u:g:b"
160 "\0"
161 "=0:t--d:d--t",
162 &opt_device, &opt_name, &opt_name, NULL, NULL
163 );
164
165
166 memset(&ifr, 0, sizeof(ifr));
167 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
168 strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
169
170
171 fd = xopen(opt_device, O_RDWR);
172 IOCTL(fd, TUNSETIFF, (void *)&ifr);
173
174
175 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
176
177 return EXIT_SUCCESS;
178}
179
180#endif
181