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:       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_NOEXEC(tunctl, tunctl, BB_DIR_SBIN, BB_SUID_DROP, tunctl))
  28
  29//kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o
  30
  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"
  35//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
  48#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        opts = getopt32(argv, "^"
  87                        "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b")
  88                        "\0"
  89                        "=0:t--d:d--t", // no arguments; t ^ d
  90                        &opt_device, &opt_name, &opt_name
  91                        IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)
  92        );
  93
  94        // select device
  95        memset(&ifr, 0, sizeof(ifr));
  96        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  97        strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
  98
  99        // open device
 100        fd = xopen(opt_device, O_RDWR);
 101        IOCTL(fd, TUNSETIFF, (void *)&ifr);
 102
 103        // delete?
 104        if (opts & OPT_d) {
 105                IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
 106                printf("Set '%s' nonpersistent\n", ifr.ifr_name);
 107                return EXIT_SUCCESS;
 108        }
 109
 110        // create
 111#if ENABLE_FEATURE_TUNCTL_UG
 112        if (opts & OPT_g) {
 113                group = xgroup2gid(opt_group);
 114                IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group);
 115        } else
 116                user = geteuid();
 117        if (opts & OPT_u)
 118                user = xuname2uid(opt_user);
 119        IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user);
 120#endif
 121        IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1);
 122
 123        // show info
 124#if ENABLE_FEATURE_TUNCTL_UG
 125        if (opts & OPT_b) {
 126                puts(ifr.ifr_name);
 127        } else {
 128                printf("Set '%s' %spersistent", ifr.ifr_name, "");
 129                printf(" and owned by uid %ld", user);
 130                if (group != -1)
 131                        printf(" gid %ld", group);
 132                bb_putchar('\n');
 133        }
 134#else
 135        puts(ifr.ifr_name);
 136#endif
 137        return EXIT_SUCCESS;
 138}
 139
 140#else
 141
 142/* -210 bytes: */
 143
 144int tunctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 145int tunctl_main(int argc UNUSED_PARAM, char **argv)
 146{
 147        struct ifreq ifr;
 148        int fd;
 149        const char *opt_name = "tap%d";
 150        const char *opt_device = "/dev/net/tun";
 151        unsigned opts;
 152
 153        enum {
 154                OPT_f = 1 << 0, // control device name (/dev/net/tun)
 155                OPT_t = 1 << 1, // create named interface
 156                OPT_d = 1 << 2, // delete named interface
 157        };
 158
 159        opts = getopt32(argv, "^"
 160                        "f:t:d:u:g:b" // u, g, b accepted and ignored
 161                        "\0"
 162                        "=0:t--d:d--t", // no arguments; t ^ d
 163                        &opt_device, &opt_name, &opt_name, NULL, NULL
 164        );
 165
 166        // set interface name
 167        memset(&ifr, 0, sizeof(ifr));
 168        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 169        strncpy_IFNAMSIZ(ifr.ifr_name, opt_name);
 170
 171        // open device
 172        fd = xopen(opt_device, O_RDWR);
 173        IOCTL(fd, TUNSETIFF, (void *)&ifr);
 174
 175        // create or delete interface
 176        IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)(0 == (opts & OPT_d)));
 177
 178        return EXIT_SUCCESS;
 179}
 180
 181#endif
 182