master xplshn/aruu / cmd / linux / tunctl.c
  1/* See LICENSE file for copyright and license details. */
  2
  3#include <sys/ioctl.h>
  4#include <sys/socket.h>
  5#include <sys/stat.h>
  6#include <sys/types.h>
  7
  8#include <fcntl.h>
  9#include <limits.h>
 10#include <pwd.h>
 11#include <stdio.h>
 12#include <stdlib.h>
 13#include <string.h>
 14#include <unistd.h>
 15
 16#include <linux/if.h>
 17#include <linux/if_tun.h>
 18
 19#include "paths.h"
 20#include "util.h"
 21
 22static int   dflag;
 23static int   tflag = 1;
 24static int   Tflag;
 25static char *owner;
 26
 27static void
 28usage(void)
 29{
 30  eprintf("usage: %s [-dtT] [-u owner] [device]\n", argv0);
 31}
 32
 33// ?man tunctl: configure tun/tap interfaces
 34// ?man arguments: device
 35// ?man create or destroy tun/tap network interfaces
 36int
 37main(int argc, char *argv[])
 38{
 39  struct ifreq   ifr;
 40  struct passwd *pw;
 41  uid_t          owner_uid = 0;
 42  int            fd;
 43
 44  ARGBEGIN
 45  {
 46    // ?man -d: specify directory
 47    case 'd':
 48      dflag = 1;
 49      tflag = 0;
 50      break;
 51    // ?man -t: sort or specify timestamp
 52    case 't':
 53      tflag = 1;
 54      dflag = 0;
 55      break;
 56    // ?man -T: specify option flag
 57    case 'T':
 58      Tflag = 1;
 59      break;
 60    // ?man -u:str: unbuffered output
 61    case 'u':
 62      owner = EARGF(usage());
 63      break;
 64    default:
 65      usage();
 66  }
 67  ARGEND
 68
 69  if (owner) {
 70    pw = getpwnam(owner);
 71    if (!pw)
 72      owner_uid = estrtonum(owner, 0, UINT_MAX);
 73    else
 74      owner_uid = pw->pw_uid;
 75  }
 76
 77  fd = open("/dev/net/tun", O_RDWR);
 78  if (fd < 0)
 79    eprintf("open /dev/net/tun:");
 80
 81  memset(&ifr, 0, sizeof(ifr));
 82  ifr.ifr_flags = (Tflag ? IFF_TAP : IFF_TUN) | IFF_NO_PI;
 83
 84  if (argc > 0)
 85    estrlcpy(ifr.ifr_name, argv[0], sizeof(ifr.ifr_name));
 86
 87  if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)
 88    eprintf("ioctl TUNSETIFF:");
 89
 90  if (tflag) {
 91    if (ioctl(fd, TUNSETPERSIST, (void *)1) < 0)
 92      eprintf("ioctl TUNSETPERSIST:");
 93    if (owner) {
 94      if (ioctl(fd, TUNSETOWNER, (void *)(long)owner_uid) < 0)
 95        eprintf("ioctl TUNSETOWNER:");
 96    }
 97    printf("Set '%s' persistent and owned by %u\n", ifr.ifr_name, owner_uid);
 98  } else if (dflag) {
 99    if (ioctl(fd, TUNSETPERSIST, (void *)0) < 0)
100      eprintf("ioctl TUNSETPERSIST:");
101    printf("Set '%s' non-persistent\n", ifr.ifr_name);
102  }
103
104  close(fd);
105  return 0;
106}