about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2019-12-15 20:22:47 +0000
committerAlyssa Ross <hi@alyssa.is>2019-12-15 23:00:57 +0000
commitf45fcb661ef5586656c2a3af787166e2bceab61d (patch)
treec9d7f1b4aa961f95d6bc660f1d08acdec0f6cf49
parent89990f7ae1b8b26f4d6915914e1ede95156e1a95 (diff)
downloadmktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar.gz
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar.bz2
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar.lz
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar.xz
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.tar.zst
mktuntap-f45fcb661ef5586656c2a3af787166e2bceab61d.zip
Don't close fd if it's the target
Without this, if the fd assigned by open(2) happened to be the one we
wanted, we would dup it to itself, and then close it, leaving no copy
of the fd.

I'm surprised duping an fd over itself doesn't cause an error, but
here we are.
-rw-r--r--mktuntap.85
-rw-r--r--mktuntap.c28
2 files changed, 23 insertions, 10 deletions
diff --git a/mktuntap.8 b/mktuntap.8
index 7e6414d..6f2a32f 100644
--- a/mktuntap.8
+++ b/mktuntap.8
@@ -23,6 +23,7 @@
 .Sh SYNOPSIS
 .Nm
 .Fl ( n | p )
+.Op Fl v
 .Op Fl E
 .Op Fl i Ar ifr_name
 .Ar fd
@@ -44,6 +45,10 @@ Create a TAP device.  Mutually exclusive with
 .It Fl n
 Create a TUN device.  Mutually exclusive with
 .Fl p .
+.It Fl v
+Set the
+.Dv IFF_VNET_HDR
+flag on the device.
 .It Fl E
 Don't set the TUNTAP_NAME environment variable.  Caution: if you use
 this without using
diff --git a/mktuntap.c b/mktuntap.c
index cae3f5a..8cbc335 100644
--- a/mktuntap.c
+++ b/mktuntap.c
@@ -61,10 +61,10 @@ void ex_usage()
 int main(int argc, char **argv)
 {
 	char *ifr_name_in = NULL;
-	bool name_env = true, tap = false, tun = false;
+	bool name_env = true, tap = false, tun = false, vnet_hdr = false;
 
 	int c;
-	while ((c = getopt(argc, argv, "+npEi:")) != -1) {
+	while ((c = getopt(argc, argv, "+npvEi:")) != -1) {
 		switch (c) {
 		case 'n':
 			tun = true;
@@ -72,6 +72,9 @@ int main(int argc, char **argv)
 		case 'p':
 			tap = true;
 			break;
+		case 'v':
+			vnet_hdr = true;
+			break;
 		case 'E':
 			name_env = false;
 			break;
@@ -113,19 +116,24 @@ int main(int argc, char **argv)
 	}
 	int target_fd = (int)target_fd_l;
 
-	int tuntap_fd = tuntap_alloc(ifr_name_, tap ? IFF_TAP : IFF_TUN);
+	short flags = tap ? IFF_TAP : IFF_TUN;
+	if (vnet_hdr)
+		flags |= IFF_VNET_HDR;
+	int tuntap_fd = tuntap_alloc(ifr_name_, flags);
 	if (tuntap_fd < 0) {
 		fprintf(stderr, "mktuntap: failed to open tuntap device: %s\n", strerror(errno));
 		return EX_IOERR;
 	}
 
-	if (dup2(tuntap_fd, target_fd) == -1) {
-		fprintf(stderr, "mktuntap: %s\n", strerror(errno));
-		return EX_IOERR;
-	}
-	if (close(tuntap_fd) == -1) {
-		fprintf(stderr, "mktuntap: %s\n", strerror(errno));
-		return EX_IOERR;
+	if (tuntap_fd != target_fd) {
+		if (dup2(tuntap_fd, target_fd) == -1) {
+			fprintf(stderr, "mktuntap: %s\n", strerror(errno));
+			return EX_IOERR;
+		}
+		if (close(tuntap_fd) == -1) {
+			fprintf(stderr, "mktuntap: %s\n", strerror(errno));
+			return EX_IOERR;
+		}
 	}
 
 	if (name_env) {