tunctl.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* Copyright 2002 Jeff Dike
  2. * Licensed under the GPL
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <pwd.h>
  11. #include <grp.h>
  12. #include <net/if.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/if_tun.h>
  15. /* TUNSETGROUP appeared in 2.6.23 */
  16. #ifndef TUNSETGROUP
  17. #define TUNSETGROUP _IOW('T', 206, int)
  18. #endif
  19. static void Usage(char *name, int status)
  20. {
  21. fprintf(stderr, "Create: %s [-b] [-u owner] [-g group] [-t device-name] "
  22. "[-f tun-clone-device]\n", name);
  23. fprintf(stderr, "Delete: %s -d device-name [-f tun-clone-device]\n\n",
  24. name);
  25. fprintf(stderr, "The default tun clone device is /dev/net/tun - some systems"
  26. " use\n/dev/misc/net/tun instead\n\n");
  27. fprintf(stderr, "-b will result in brief output (just the device name)\n");
  28. exit(status);
  29. }
  30. int main(int argc, char **argv)
  31. {
  32. struct ifreq ifr;
  33. struct passwd *pw;
  34. struct group *gr;
  35. uid_t owner = -1;
  36. gid_t group = -1;
  37. int tap_fd, opt, delete = 0, brief = 0;
  38. char *tun = "", *file = "/dev/net/tun", *name = argv[0], *end;
  39. while((opt = getopt(argc, argv, "bd:f:t:u:g:h")) > 0){
  40. switch(opt) {
  41. case 'b':
  42. brief = 1;
  43. break;
  44. case 'd':
  45. delete = 1;
  46. tun = optarg;
  47. break;
  48. case 'f':
  49. file = optarg;
  50. break;
  51. case 'u':
  52. pw = getpwnam(optarg);
  53. if(pw != NULL){
  54. owner = pw->pw_uid;
  55. break;
  56. }
  57. owner = strtol(optarg, &end, 0);
  58. if(*end != '\0'){
  59. fprintf(stderr, "'%s' is neither a username nor a numeric uid.\n",
  60. optarg);
  61. Usage(name, 1);
  62. }
  63. break;
  64. case 'g':
  65. gr = getgrnam(optarg);
  66. if(gr != NULL){
  67. group = gr->gr_gid;
  68. break;
  69. }
  70. group = strtol(optarg, &end, 0);
  71. if(*end != '\0'){
  72. fprintf(stderr, "'%s' is neither a groupname nor a numeric group.\n",
  73. optarg);
  74. Usage(name, 1);
  75. }
  76. break;
  77. case 't':
  78. tun = optarg;
  79. break;
  80. case 'h':
  81. Usage(name, 0);
  82. break;
  83. default:
  84. Usage(name, 1);
  85. }
  86. }
  87. argv += optind;
  88. argc -= optind;
  89. if(argc > 0)
  90. Usage(name, 1);
  91. if((tap_fd = open(file, O_RDWR)) < 0){
  92. fprintf(stderr, "Failed to open '%s' : ", file);
  93. perror("");
  94. exit(1);
  95. }
  96. memset(&ifr, 0, sizeof(ifr));
  97. ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  98. strncpy(ifr.ifr_name, tun, sizeof(ifr.ifr_name) - 1);
  99. if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){
  100. perror("TUNSETIFF");
  101. exit(1);
  102. }
  103. if(delete){
  104. if(ioctl(tap_fd, TUNSETPERSIST, 0) < 0){
  105. perror("disabling TUNSETPERSIST");
  106. exit(1);
  107. }
  108. printf("Set '%s' nonpersistent\n", ifr.ifr_name);
  109. }
  110. else {
  111. /* emulate behaviour prior to TUNSETGROUP */
  112. if(owner == -1 && group == -1) {
  113. owner = geteuid();
  114. }
  115. if(owner != -1) {
  116. if(ioctl(tap_fd, TUNSETOWNER, owner) < 0){
  117. perror("TUNSETOWNER");
  118. exit(1);
  119. }
  120. }
  121. if(group != -1) {
  122. if(ioctl(tap_fd, TUNSETGROUP, group) < 0){
  123. perror("TUNSETGROUP");
  124. exit(1);
  125. }
  126. }
  127. if(ioctl(tap_fd, TUNSETPERSIST, 1) < 0){
  128. perror("enabling TUNSETPERSIST");
  129. exit(1);
  130. }
  131. if(brief)
  132. printf("%s\n", ifr.ifr_name);
  133. else {
  134. printf("Set '%s' persistent and owned by", ifr.ifr_name);
  135. if(owner != -1)
  136. printf(" uid %d", owner);
  137. if(group != -1)
  138. printf(" gid %d", group);
  139. printf("\n");
  140. }
  141. }
  142. return(0);
  143. }