blob: 3a0870eb5d7210393957334d20eeca0f6d67c306
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 | |
13 | //usage:#define tunctl_trivial_usage |
14 | //usage: "[-f device] ([-t name] | -d name)" IF_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]") |
15 | //usage:#define tunctl_full_usage "\n\n" |
16 | //usage: "Create or delete tun interfaces\n" |
17 | //usage: "\n -f name tun device (/dev/net/tun)" |
18 | //usage: "\n -t name Create iface 'name'" |
19 | //usage: "\n -d name Delete iface 'name'" |
20 | //usage: IF_FEATURE_TUNCTL_UG( |
21 | //usage: "\n -u owner Set iface owner" |
22 | //usage: "\n -g group Set iface group" |
23 | //usage: "\n -b Brief output" |
24 | //usage: ) |
25 | //usage: |
26 | //usage:#define tunctl_example_usage |
27 | //usage: "# tunctl\n" |
28 | //usage: "# tunctl -d tun0\n" |
29 | |
30 | #include <netinet/in.h> |
31 | #include <net/if.h> |
32 | #include <linux/if_tun.h> |
33 | #include "libbb.h" |
34 | |
35 | /* TUNSETGROUP appeared in 2.6.23 */ |
36 | #ifndef TUNSETGROUP |
37 | #define TUNSETGROUP _IOW('T', 206, int) |
38 | #endif |
39 | |
40 | #define IOCTL(a, b, c) ioctl_or_perror_and_die(a, b, c, NULL) |
41 | |
42 | #if 1 |
43 | |
44 | int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
45 | int tunctl_main(int argc UNUSED_PARAM, char **argv) |
46 | { |
47 | struct ifreq ifr; |
48 | int fd; |
49 | const char *opt_name = "tap%d"; |
50 | const char *opt_device = "/dev/net/tun"; |
51 | #if ENABLE_FEATURE_TUNCTL_UG |
52 | const char *opt_user, *opt_group; |
53 | long user = -1, group = -1; |
54 | #endif |
55 | unsigned opts; |
56 | |
57 | enum { |
58 | OPT_f = 1 << 0, // control device name (/dev/net/tun) |
59 | OPT_t = 1 << 1, // create named interface |
60 | OPT_d = 1 << 2, // delete named interface |
61 | #if ENABLE_FEATURE_TUNCTL_UG |
62 | OPT_u = 1 << 3, // set new interface owner |
63 | OPT_g = 1 << 4, // set new interface group |
64 | OPT_b = 1 << 5, // brief output |
65 | #endif |
66 | }; |
67 | |
68 | opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d |
69 | opts = getopt32(argv, "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b"), |
70 | &opt_device, &opt_name, &opt_name |
71 | IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)); |
72 | |
73 | // select device |
74 | memset(&ifr, 0, sizeof(ifr)); |
75 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
76 | strncpy_IFNAMSIZ(ifr.ifr_name, opt_name); |
77 | |
78 | // open device |
79 | fd = xopen(opt_device, O_RDWR); |
80 | IOCTL(fd, TUNSETIFF, (void *)&ifr); |
81 | |
82 | // delete? |
83 | if (opts & OPT_d) { |
84 | IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0); |
85 | bb_info_msg("Set '%s' %spersistent", ifr.ifr_name, "non"); |
86 | return EXIT_SUCCESS; |
87 | } |
88 | |
89 | // create |
90 | #if ENABLE_FEATURE_TUNCTL_UG |
91 | if (opts & OPT_g) { |
92 | group = xgroup2gid(opt_group); |
93 | IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group); |
94 | } else |
95 | user = geteuid(); |
96 | if (opts & OPT_u) |
97 | user = xuname2uid(opt_user); |
98 | IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user); |
99 | #endif |
100 | IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1); |
101 | |
102 | // show info |
103 | #if ENABLE_FEATURE_TUNCTL_UG |
104 | if (opts & OPT_b) { |
105 | puts(ifr.ifr_name); |
106 | } else { |
107 | printf("Set '%s' %spersistent", ifr.ifr_name, ""); |
108 | printf(" and owned by uid %ld", user); |
109 | if (group != -1) |
110 | printf(" gid %ld", group); |
111 | bb_putchar('\n'); |
112 | } |
113 | #else |
114 | puts(ifr.ifr_name); |
115 | #endif |
116 | return EXIT_SUCCESS; |
117 | } |
118 | |
119 | #else |
120 | |
121 | /* -210 bytes: */ |
122 | |
123 | int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
124 | int tunctl_main(int argc UNUSED_PARAM, char **argv) |
125 | { |
126 | struct ifreq ifr; |
127 | int fd; |
128 | const char *opt_name = "tap%d"; |
129 | const char *opt_device = "/dev/net/tun"; |
130 | unsigned opts; |
131 | |
132 | enum { |
133 | OPT_f = 1 << 0, // control device name (/dev/net/tun) |
134 | OPT_t = 1 << 1, // create named interface |
135 | OPT_d = 1 << 2, // delete named interface |
136 | }; |
137 | |
138 | opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d |
139 | opts = getopt32(argv, "f:t:d:u:g:b", // u, g, b accepted and ignored |
140 | &opt_device, &opt_name, &opt_name, NULL, NULL); |
141 | |
142 | // set interface name |
143 | memset(&ifr, 0, sizeof(ifr)); |
144 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
145 | strncpy_IFNAMSIZ(ifr.ifr_name, opt_name); |
146 | |
147 | // open device |
148 | fd = xopen(opt_device, O_RDWR); |
149 | IOCTL(fd, TUNSETIFF, (void *)&ifr); |
150 | |
151 | // create or delete interface |
152 | IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d))); |
153 | |
154 | return EXIT_SUCCESS; |
155 | } |
156 | |
157 | #endif |
158 |