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
48#include <netinet/in.h>
49#include <net/if.h>
50#include <linux/if_tun.h>
51#include "libbb.h"
52
53
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
62int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
63int 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,
77 OPT_t = 1 << 1,
78 OPT_d = 1 << 2,
79#if ENABLE_FEATURE_TUNCTL_UG
80 OPT_u = 1 << 3,
81 OPT_g = 1 << 4,
82 OPT_b = 1 << 5,
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",
90 &opt_device, &opt_name, &opt_name
91 IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)
92 );
93
94
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
100 fd = xopen(opt_device, O_RDWR);
101 IOCTL(fd, TUNSETIFF, (void *)&ifr);
102
103
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
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
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
143
144int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
145int 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,
155 OPT_t = 1 << 1,
156 OPT_d = 1 << 2,
157 };
158
159 opts = getopt32(argv, "^"
160 "f:t:d:u:g:b"
161 "\0"
162 "=0:t--d:d--t",
163 &opt_device, &opt_name, &opt_name, NULL, NULL
164 );
165
166
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
172 fd = xopen(opt_device, O_RDWR);
173 IOCTL(fd, TUNSETIFF, (void *)&ifr);
174
175
176 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
177
178 return EXIT_SUCCESS;
179}
180
181#endif
182