about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2019-12-15 22:59:40 +0000
committerAlyssa Ross <hi@alyssa.is>2019-12-15 23:01:45 +0000
commitd37b0ea1f794a4d195323b16484ecc4f04cc4306 (patch)
tree69707349797ac600c3f548bc057ea10d28750c30
parenta44798c342e387812ef7194b447f3ad6669ed2be (diff)
downloadmktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar.gz
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar.bz2
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar.lz
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar.xz
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.tar.zst
mktuntap-d37b0ea1f794a4d195323b16484ecc4f04cc4306.zip
Add -B flag to open device in nonblocking mode
-rw-r--r--mktuntap.86
-rw-r--r--mktuntap.c31
2 files changed, 27 insertions, 10 deletions
diff --git a/mktuntap.8 b/mktuntap.8
index 909ff30..9bbfb78 100644
--- a/mktuntap.8
+++ b/mktuntap.8
@@ -24,6 +24,7 @@
 .Nm
 .Fl ( n | p )
 .Op Fl v
+.Op Fl B
 .Op Fl P
 .Op Fl E
 .Op Fl i Ar ifr_name
@@ -54,6 +55,11 @@ Create a TUN device.  Mutually exclusive with
 Set the
 .Dv IFF_VNET_HDR
 flag on the device.
+.It Fl B
+Open the device in nonblocking mode.  See discussion of
+.Dv O_NONBLOCK
+in
+.Xr open 2 .
 .It Fl P
 Don't set the
 .Dv IFF_NO_PI
diff --git a/mktuntap.c b/mktuntap.c
index 76b02c7..b4f5a7a 100644
--- a/mktuntap.c
+++ b/mktuntap.c
@@ -29,18 +29,24 @@
 #include <linux/if.h>
 #include <linux/if_tun.h>
 
+/*
+ * ifr_flags, ifr_name, etc. are macros, so throughout this program
+ * variable names are suffixed with underscores where not doing so
+ * would conflict with a macro.
+ */
+
 // Adapted 2019-12-14 from Documentation/networking/tuntuntap.txt in Linux.
-int tuntap_alloc(char *dev, short flags)
+int tuntap_alloc(char *dev, int open_flags, short ifr_flags_)
 {
 	struct ifreq ifr;
 	int fd, err;
 
-	if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
+	if ((fd = open("/dev/net/tun", O_RDWR | open_flags)) < 0)
 		return -1;
 
 	memset(&ifr, 0, sizeof(ifr));
 
-	ifr.ifr_flags = flags;
+	ifr.ifr_flags = ifr_flags_;
 	if (*dev)
 		strncpy(ifr.ifr_name, dev, IFNAMSIZ);
 
@@ -63,10 +69,10 @@ int main(int argc, char **argv)
 	char *ifr_name_in = NULL;
 	bool name_env = true;
 	bool tap = false, tun = false;
-	bool vnet_hdr = false, no_pi = true;
+	bool vnet_hdr = false, non_block = false, no_pi = true;
 
 	int c;
-	while ((c = getopt(argc, argv, "+npvPEi:")) != -1) {
+	while ((c = getopt(argc, argv, "+npvBPEi:")) != -1) {
 		switch (c) {
 		case 'n':
 			tun = true;
@@ -77,6 +83,9 @@ int main(int argc, char **argv)
 		case 'v':
 			vnet_hdr = true;
 			break;
+		case 'B':
+			non_block = true;
+			break;
 		case 'P':
 			no_pi = false;
 			break;
@@ -94,7 +103,6 @@ int main(int argc, char **argv)
 	if (argc - optind < 2 || !(tap ^ tun))
 		ex_usage();
 
-	// ifr_name is a macro, so add a trailing _.
 	char *ifr_name_ = calloc(IFNAMSIZ, sizeof(char));
 	if (ifr_name_in) {
 		if (strlen(ifr_name_in) > IFNAMSIZ - 1) {
@@ -121,12 +129,15 @@ int main(int argc, char **argv)
 	}
 	int target_fd = (int)target_fd_l;
 
-	short flags = tap ? IFF_TAP : IFF_TUN;
+	short open_flags = 0;
+	if (non_block)
+		open_flags |= O_NONBLOCK;
+	short ifr_flags_ = tap ? IFF_TAP : IFF_TUN;
 	if (no_pi)
-		flags |= IFF_NO_PI;
+		ifr_flags_ |= IFF_NO_PI;
 	if (vnet_hdr)
-		flags |= IFF_VNET_HDR;
-	int tuntap_fd = tuntap_alloc(ifr_name_, flags);
+		ifr_flags_ |= IFF_VNET_HDR;
+	int tuntap_fd = tuntap_alloc(ifr_name_, open_flags, ifr_flags_);
 	if (tuntap_fd < 0) {
 		fprintf(stderr, "mktuntap: failed to open tuntap device: %s\n", strerror(errno));
 		return EX_IOERR;