master xplshn/aruu / cmd / linux / tunctl.c
  1/* See LICENSE file for copyright and license details. */
  2
  3
  4#include <sys/ioctl.h>
  5#include <sys/socket.h>
  6#include <sys/stat.h>
  7#include <sys/types.h>
  8
  9#include <fcntl.h>
 10#include <limits.h>
 11#include <pwd.h>
 12#include <stdio.h>
 13#include <stdlib.h>
 14#include <string.h>
 15#include <unistd.h>
 16
 17#include <linux/if.h>
 18#include <linux/if_tun.h>
 19
 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,
 98		       owner_uid);
 99	} else if (dflag) {
100		if (ioctl(fd, TUNSETPERSIST, (void *)0) < 0)
101			eprintf("ioctl TUNSETPERSIST:");
102		printf("Set '%s' non-persistent\n", ifr.ifr_name);
103	}
104
105	close(fd);
106	return 0;
107}