| 12
 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
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 
 | /* vi: set sw=4 ts=4: */
/*
 * tun devices controller
 *
 * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
 *
 * Original code:
 *      Jeff Dike
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */
//config:config TUNCTL
//config:	bool "tunctl (6.2 kb)"
//config:	default y
//config:	depends on PLATFORM_LINUX
//config:	help
//config:	tunctl creates or deletes tun devices.
//config:
//config:config FEATURE_TUNCTL_UG
//config:	bool "Support owner:group assignment"
//config:	default y
//config:	depends on TUNCTL
//config:	help
//config:	Allow to specify owner and group of newly created interface.
//config:	340 bytes of pure bloat. Say no here.
//applet:IF_TUNCTL(APPLET_NOEXEC(tunctl, tunctl, BB_DIR_SBIN, BB_SUID_DROP, tunctl))
//kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o
//usage:#define tunctl_trivial_usage
//usage:       "[-f DEVICE] [-t NAME | -d NAME]" IF_FEATURE_TUNCTL_UG(" [-u USER] [-g GRP] [-b]")
//usage:#define tunctl_full_usage "\n\n"
//usage:       "Create or delete TUN/TAP interfaces\n"
//usage:     "\n	-f DEV	TUN device (default /dev/net/tun)"
//usage:     "\n	-t NAME	Create iface (default: tapN)"
//usage:     "\n	-d NAME	Delete iface"
//usage:	IF_FEATURE_TUNCTL_UG(
//usage:     "\n	-u USER	Set iface owner"
//usage:     "\n	-g GRP	Set iface group"
//usage:     "\n	-b	Brief output"
//usage:	)
//usage:
//usage:#define tunctl_example_usage
//usage:       "# tunctl\n"
//usage:       "# tunctl -d tun0\n"
#include <netinet/in.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include "libbb.h"
/* TUNSETGROUP appeared in 2.6.23 */
#ifndef TUNSETGROUP
#define TUNSETGROUP _IOW('T', 206, int)
#endif
#define IOCTL(a, b, c) ioctl_or_perror_and_die(a, b, c, NULL)
#if 1
int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tunctl_main(int argc UNUSED_PARAM, char **argv)
{
	struct ifreq ifr;
	int fd;
	const char *opt_name = "tap%d";
	const char *opt_device = "/dev/net/tun";
#if ENABLE_FEATURE_TUNCTL_UG
	const char *opt_user, *opt_group;
	long user = -1, group = -1;
#endif
	unsigned opts;
	enum {
		OPT_f = 1 << 0, // control device name (/dev/net/tun)
		OPT_t = 1 << 1, // create named interface
		OPT_d = 1 << 2, // delete named interface
#if ENABLE_FEATURE_TUNCTL_UG
		OPT_u = 1 << 3, // set new interface owner
		OPT_g = 1 << 4, // set new interface group
		OPT_b = 1 << 5, // brief output
#endif
	};
	opts = getopt32(argv, "^"
			"f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b")
			"\0"
			"=0:t--d:d--t", // no arguments; t ^ d
			&opt_device, &opt_name, &opt_name
			IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)
	);
	// select device
	memset(&ifr, 0, sizeof(ifr));
	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
	strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
	// open device
	fd = xopen(opt_device, O_RDWR);
	IOCTL(fd, TUNSETIFF, (void *)&ifr);
	// delete?
	if (opts & OPT_d) {
		IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
		printf("Set '%s' nonpersistent\n", ifr.ifr_name);
		return EXIT_SUCCESS;
	}
	// create
#if ENABLE_FEATURE_TUNCTL_UG
	if (opts & OPT_g) {
		group = xgroup2gid(opt_group);
		IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group);
	} else
		user = geteuid();
	if (opts & OPT_u)
		user = xuname2uid(opt_user);
	IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user);
#endif
	IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1);
	// show info
#if ENABLE_FEATURE_TUNCTL_UG
	if (opts & OPT_b) {
		puts(ifr.ifr_name);
	} else {
		printf("Set '%s' %spersistent", ifr.ifr_name, "");
		printf(" and owned by uid %ld", user);
		if (group != -1)
			printf(" gid %ld", group);
		bb_putchar('\n');
	}
#else
	puts(ifr.ifr_name);
#endif
	return EXIT_SUCCESS;
}
#else
/* -210 bytes: */
int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tunctl_main(int argc UNUSED_PARAM, char **argv)
{
	struct ifreq ifr;
	int fd;
	const char *opt_name = "tap%d";
	const char *opt_device = "/dev/net/tun";
	unsigned opts;
	enum {
		OPT_f = 1 << 0, // control device name (/dev/net/tun)
		OPT_t = 1 << 1, // create named interface
		OPT_d = 1 << 2, // delete named interface
	};
	opts = getopt32(argv, "^"
			"f:t:d:u:g:b" // u, g, b accepted and ignored
			"\0"
			"=0:t--d:d--t", // no arguments; t ^ d
			&opt_device, &opt_name, &opt_name, NULL, NULL
	);
	// set interface name
	memset(&ifr, 0, sizeof(ifr));
	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
	strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
	// open device
	fd = xopen(opt_device, O_RDWR);
	IOCTL(fd, TUNSETIFF, (void *)&ifr);
	// create or delete interface
	IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
	return EXIT_SUCCESS;
}
#endif
 |