tunctl.c 4.5 KB

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