rcmuir at gmail.com
2016-Dec-26 20:33 UTC
[PATCH] Add VPN tunnel support for Darwin's utun device.
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
rcmuir at gmail.com
2016-Dec-26 21:59 UTC
[PATCH] Add VPN tunnel support for Darwin's utun device.
From: Robert Muir <rcmuir at gmail.com> My patch had a mistake in the configure.ac, corrected version here. Cheers, Robert --- configure.ac | 17 ++++++++++---- openbsd-compat/port-tun.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ openbsd-compat/port-tun.h | 3 ++- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index eb9f45dc..7f2fd418 100644 --- a/configure.ac +++ b/configure.ac @@ -618,11 +618,18 @@ 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_DEFINE([SSH_TUN_COMPAT_AF], [1], - [Use tunnel device compatibility to OpenBSD]) - AC_DEFINE([SSH_TUN_PREPEND_AF], [1], - [Prepend the address family to IP tunnel traffic]) + 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]) + AC_DEFINE([SSH_TUN_PREPEND_AF], [1], + [Prepend the address family to IP tunnel traffic]) + AC_DEFINE([SSH_TUN_COMPAT_AF], [1], + [Use tunnel device compatibility to OpenBSD]) + fi m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) 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