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