[PATCH] Add VPN tunnel support for Darwin's utun device.

rcmuir at gmail.com rcmuir at gmail.com
Tue Dec 27 07:33:47 AEDT 2016


From: Robert Muir <rcmuir at gmail.com>

This tunnel device is available out of box since OS X 10.6. I found a previous
discussion [1] but no patches anywhere yet.

[1] http://lists.mindrot.org/pipermail/openssh-unix-dev/2014-October/033012.html

---
 configure.ac              |  9 ++++++-
 openbsd-compat/port-tun.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 openbsd-compat/port-tun.h |  3 ++-
 3 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index eb9f45dc..74a1e0bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -618,7 +618,14 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
 	AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect])
 	AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1],
 		[Define if your resolver libs need this for getrrsetbyname])
-	AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
+	AC_CHECK_HEADERS([net/if_utun.h])
+	if test "x$ac_cv_header_net_if_utun_h" = "xyes" ; then
+		AC_DEFINE([SSH_TUN_DARWIN], [1],
+		    [Open tunnel devices the Darwin way])
+	else
+		AC_DEFINE([SSH_TUN_FREEBSD], [1],
+		    [Open tunnel devices the FreeBSD way])
+	fi
 	AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
 	    [Use tunnel device compatibility to OpenBSD])
 	AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c
index a444adf1..7eac9a70 100644
--- a/openbsd-compat/port-tun.c
+++ b/openbsd-compat/port-tun.c
@@ -43,6 +43,7 @@
  *
  * SSH_TUN_LINUX	Use the (newer) Linux tun/tap device
  * SSH_TUN_FREEBSD	Use the FreeBSD tun/tap device
+ * SSH_TUN_DARWIN	Use the Darwin utun device
  * SSH_TUN_COMPAT_AF	Translate the OpenBSD address family
  * SSH_TUN_PREPEND_AF	Prepend/remove the address family
  */
@@ -194,6 +195,65 @@ sys_tun_open(int tun, int mode)
 }
 #endif /* SSH_TUN_FREEBSD */
 
+#ifdef SSH_TUN_DARWIN
+#include <sys/sys_domain.h>
+#include <sys/kern_control.h>
+#include <net/if_utun.h>
+
+int
+sys_tun_open(int tun, int mode)
+{
+	struct ctl_info info;
+	struct sockaddr_ctl addr;
+	int fd;
+
+	if (tun != SSH_TUNID_ANY && tun > SSH_TUNID_MAX) {
+		debug("%s: invalid tunnel %u", __func__, tun);
+		return (-1);
+	}
+
+	if (mode == SSH_TUNMODE_ETHERNET) {
+		debug("%s: no layer 2 tunnelling support", __func__);
+		return (-1);
+	}
+
+	fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
+	if (fd == -1) {
+		debug("%s: failed to create control socket: %s",
+		    __func__, strerror(errno));
+		return (-1);
+	}
+
+	bzero(&info, sizeof(info));
+	strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
+	if (ioctl(fd, CTLIOCGINFO, &info) == -1) {
+		debug("%s: failed to lookup utun control id: %s",
+		    __func__, strerror(errno));
+		goto failed;
+	}
+
+	bzero(&addr, sizeof(addr));
+	addr.sc_id = info.ctl_id;
+	addr.sc_len = sizeof(addr);
+	addr.sc_family = AF_SYSTEM;
+	addr.ss_sysaddr = AF_SYS_CONTROL;
+	if (tun != SSH_TUNID_ANY)
+		addr.sc_unit = tun + 1;
+
+	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+		debug("%s: failed to connect to utun device: %s",
+		    __func__, strerror(errno));
+		goto failed;
+	}
+
+	return (fd);
+
+ failed:
+	close(fd);
+	return (-1);
+}
+#endif /* SSH_TUN_DARWIN */
+
 /*
  * System-specific channel filters
  */
diff --git a/openbsd-compat/port-tun.h b/openbsd-compat/port-tun.h
index c53df01f..e2a51f15 100644
--- a/openbsd-compat/port-tun.h
+++ b/openbsd-compat/port-tun.h
@@ -19,7 +19,8 @@
 
 struct Channel;
 
-#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
+#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) || \
+    defined(SSH_TUN_DARWIN)
 # define CUSTOM_SYS_TUN_OPEN
 int	  sys_tun_open(int, int);
 #endif
-- 
2.11.0



More information about the openssh-unix-dev mailing list