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 opt_complementary = "=0:t--d:d--t";
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
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
97 fd = xopen(opt_device, O_RDWR);
98 IOCTL(fd, TUNSETIFF, (void *)&ifr);
99
100
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
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
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
140
141int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
142int 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,
152 OPT_t = 1 << 1,
153 OPT_d = 1 << 2,
154 };
155
156 opt_complementary = "=0:t--d:d--t";
157 opts = getopt32(argv, "f:t:d:u:g:b",
158 &opt_device, &opt_name, &opt_name, NULL, NULL);
159
160
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
166 fd = xopen(opt_device, O_RDWR);
167 IOCTL(fd, TUNSETIFF, (void *)&ifr);
168
169
170 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
171
172 return EXIT_SUCCESS;
173}
174
175#endif
176