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