blob: 97ee1961b2ade2c14979f504823b4650eaf7fdac [file] [log] [blame]
Denis Vlasenko39b68132009-01-23 02:07:14 +00001/* 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 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +020010 * Licensed under GPLv2, see file LICENSE in this source tree.
Denis Vlasenko39b68132009-01-23 02:07:14 +000011 */
Denys Vlasenko47367e12016-11-23 09:05:14 +010012//config:config TUNCTL
Denys Vlasenko4eed2c62017-07-18 22:01:24 +020013//config: bool "tunctl (6.4 kb)"
Denys Vlasenko47367e12016-11-23 09:05:14 +010014//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
Pere Orga5bc8c002011-04-11 03:29:49 +020030
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"
Pere Orga5bc8c002011-04-11 03:29:49 +020035//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
Denis Vlasenko39b68132009-01-23 02:07:14 +000048#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
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, // 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
Denis Vlasenko5e34ff22009-04-21 11:09:40 +000087 opts = getopt32(argv, "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b"),
Denis Vlasenko39b68132009-01-23 02:07:14 +000088 &opt_device, &opt_name, &opt_name
Denis Vlasenko5e34ff22009-04-21 11:09:40 +000089 IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group));
Denis Vlasenko39b68132009-01-23 02:07:14 +000090
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);
Denys Vlasenko066e76b2016-03-30 16:20:28 +0200103 printf("Set '%s' nonpersistent\n", ifr.ifr_name);
Denis Vlasenko39b68132009-01-23 02:07:14 +0000104 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
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, // 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