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}