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