diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-01-23 05:07:14 +0300 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-01-23 05:07:14 +0300 |
commit | 39b681343bee81fb7c31fd06e4dc5343bcef1292 (patch) | |
tree | 9f5896b38ed4c9069da747e1987eb5220677ade5 /networking/tunctl.c | |
parent | f6107c7e885da0f952569252798b7fc6b4d46411 (diff) |
tunctl: new applet by Vladimir
function old new delta
tunctl_main - 371 +371
packed_usage 25669 25799 +130
applet_names 1981 1988 +7
applet_main 1192 1196 +4
applet_nameofs 596 598 +2
applet_install_loc 149 150 +1
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 5/0 up/down: 515/0) Total: 515 bytes
Diffstat (limited to 'networking/tunctl.c')
-rw-r--r-- | networking/tunctl.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/networking/tunctl.c b/networking/tunctl.c new file mode 100644 index 000000000..a8e5270ad --- /dev/null +++ b/networking/tunctl.c @@ -0,0 +1,139 @@ +/* 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 tarball for details. + */ +#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 + }; + + opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d + opts = getopt32(argv, "f:t:d:" USE_FEATURE_TUNCTL_UG("u:g:b"), + &opt_device, &opt_name, &opt_name + USE_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); + bb_info_msg("Set '%s' %spersistent", ifr.ifr_name, "non"); + 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 + }; + + opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d + opts = getopt32(argv, "f:t:d:u:g:b", // u, g, b accepted and ignored + &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 |