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