Mac OS X 10.7+ natively supports tun devices (called utun). The "standard"
utun.ko driver is sometimes problematic (e.g. VmWare Fusion 5 and tun.ko
do not work together).
When OpenVPN is compiled with utun support it will if no dev-node is given
first try to use utun and if that is not available will try the
traditional tun devices
v2: Fixed tap support, get device name via ioctl, add manage
v3.1: Fix compiling without if/utun.h, fix manage errors
v4/v5: Don't try open to dynamically open utun0 -255 when early utun
initialization fails, fix fallback to tun, give fatal error message when
utun fails but no tun fallback should be done
v6: add commit message change log, replace strstr with strncmp, move
v7: Throw error if a user does the strange combination of --dev tun
--dev-type tap and --dev-node utun
A lot good input on earlier patches by Jonathan K. Bullard
<jkbullard@gmail.com>
Parts of the patches are inspired from Peter Sagerson's
<psagers@ignorare.net> utun patch
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Tested-by: Jonathan K. Bullard <jkbullard@gmail.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1371811708-8528-1-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/7739
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -459,7 +459,7 @@ SOCKET_INCLUDES=" |
459 | 459 |
" |
460 | 460 |
|
461 | 461 |
AC_CHECK_HEADERS( |
462 |
- [net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h], |
|
462 |
+ [net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h net/if_utun.h sys/kern_control.h], |
|
463 | 463 |
, |
464 | 464 |
, |
465 | 465 |
[[${SOCKET_INCLUDES}]] |
... | ... |
@@ -805,6 +805,17 @@ also specify |
805 | 805 |
or |
806 | 806 |
.B \-\-dev-type tap. |
807 | 807 |
|
808 |
+Under Mac OS X this option can be used to specify the default tun |
|
809 |
+implementation. Using |
|
810 |
+.B \-\-dev\-node utun |
|
811 |
+forces usage of the native Darwin tun kernel support. Use |
|
812 |
+.B \-\-dev\-node utunN |
|
813 |
+to select a specific utun instance. To force using the tun.kext (/dev/tunX) use |
|
814 |
+.B \-\-dev\-node tun |
|
815 |
+. When not specifying a |
|
816 |
+.B \-\-dev\-node |
|
817 |
+option openvpn will first try to open utun, and fall back to tun.kext. |
|
818 |
+ |
|
808 | 819 |
On Windows systems, select the TAP-Win32 adapter which |
809 | 820 |
is named |
810 | 821 |
.B node |
... | ... |
@@ -74,6 +74,12 @@ static void solaris_error_close (struct tuntap *tt, const struct env_set *es, co |
74 | 74 |
#include <stropts.h> |
75 | 75 |
#endif |
76 | 76 |
|
77 |
+#if defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H |
|
78 |
+#include <sys/kern_control.h> |
|
79 |
+#include <net/if_utun.h> |
|
80 |
+#include <sys/sys_domain.h> |
|
81 |
+#endif |
|
82 |
+ |
|
77 | 83 |
static void clear_tuntap (struct tuntap *tuntap); |
78 | 84 |
|
79 | 85 |
bool |
... | ... |
@@ -1277,6 +1283,87 @@ open_null (struct tuntap *tt) |
1277 | 1277 |
tt->actual_name = string_alloc ("null", NULL); |
1278 | 1278 |
} |
1279 | 1279 |
|
1280 |
+ |
|
1281 |
+#if defined (TARGET_OPENBSD) || (defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H) |
|
1282 |
+ |
|
1283 |
+/* |
|
1284 |
+ * OpenBSD and Mac OS X when using utun |
|
1285 |
+ * have a slightly incompatible TUN device from |
|
1286 |
+ * the rest of the world, in that it prepends a |
|
1287 |
+ * uint32 to the beginning of the IP header |
|
1288 |
+ * to designate the protocol (why not just |
|
1289 |
+ * look at the version field in the IP header to |
|
1290 |
+ * determine v4 or v6?). |
|
1291 |
+ * |
|
1292 |
+ * We strip off this field on reads and |
|
1293 |
+ * put it back on writes. |
|
1294 |
+ * |
|
1295 |
+ * I have not tested TAP devices on OpenBSD, |
|
1296 |
+ * but I have conditionalized the special |
|
1297 |
+ * TUN handling code described above to |
|
1298 |
+ * go away for TAP devices. |
|
1299 |
+ */ |
|
1300 |
+ |
|
1301 |
+#include <netinet/ip.h> |
|
1302 |
+#include <sys/uio.h> |
|
1303 |
+ |
|
1304 |
+static inline int |
|
1305 |
+header_modify_read_write_return (int len) |
|
1306 |
+{ |
|
1307 |
+ if (len > 0) |
|
1308 |
+ return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; |
|
1309 |
+ else |
|
1310 |
+ return len; |
|
1311 |
+} |
|
1312 |
+ |
|
1313 |
+int |
|
1314 |
+write_tun_header (struct tuntap* tt, uint8_t *buf, int len) |
|
1315 |
+{ |
|
1316 |
+ if (tt->type == DEV_TYPE_TUN) |
|
1317 |
+ { |
|
1318 |
+ u_int32_t type; |
|
1319 |
+ struct iovec iv[2]; |
|
1320 |
+ struct ip *iph; |
|
1321 |
+ |
|
1322 |
+ iph = (struct ip *) buf; |
|
1323 |
+ |
|
1324 |
+ if (tt->ipv6 && iph->ip_v == 6) |
|
1325 |
+ type = htonl (AF_INET6); |
|
1326 |
+ else |
|
1327 |
+ type = htonl (AF_INET); |
|
1328 |
+ |
|
1329 |
+ iv[0].iov_base = &type; |
|
1330 |
+ iv[0].iov_len = sizeof (type); |
|
1331 |
+ iv[1].iov_base = buf; |
|
1332 |
+ iv[1].iov_len = len; |
|
1333 |
+ |
|
1334 |
+ return header_modify_read_write_return (writev (tt->fd, iv, 2)); |
|
1335 |
+ } |
|
1336 |
+ else |
|
1337 |
+ return write (tt->fd, buf, len); |
|
1338 |
+} |
|
1339 |
+ |
|
1340 |
+int |
|
1341 |
+read_tun_header (struct tuntap* tt, uint8_t *buf, int len) |
|
1342 |
+{ |
|
1343 |
+ if (tt->type == DEV_TYPE_TUN) |
|
1344 |
+ { |
|
1345 |
+ u_int32_t type; |
|
1346 |
+ struct iovec iv[2]; |
|
1347 |
+ |
|
1348 |
+ iv[0].iov_base = &type; |
|
1349 |
+ iv[0].iov_len = sizeof (type); |
|
1350 |
+ iv[1].iov_base = buf; |
|
1351 |
+ iv[1].iov_len = len; |
|
1352 |
+ |
|
1353 |
+ return header_modify_read_write_return (readv (tt->fd, iv, 2)); |
|
1354 |
+ } |
|
1355 |
+ else |
|
1356 |
+ return read (tt->fd, buf, len); |
|
1357 |
+} |
|
1358 |
+#endif |
|
1359 |
+ |
|
1360 |
+ |
|
1280 | 1361 |
#ifndef WIN32 |
1281 | 1362 |
static void |
1282 | 1363 |
open_tun_generic (const char *dev, const char *dev_type, const char *dev_node, |
... | ... |
@@ -2055,23 +2142,6 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) |
2055 | 2055 |
|
2056 | 2056 |
#elif defined(TARGET_OPENBSD) |
2057 | 2057 |
|
2058 |
-/* |
|
2059 |
- * OpenBSD has a slightly incompatible TUN device from |
|
2060 |
- * the rest of the world, in that it prepends a |
|
2061 |
- * uint32 to the beginning of the IP header |
|
2062 |
- * to designate the protocol (why not just |
|
2063 |
- * look at the version field in the IP header to |
|
2064 |
- * determine v4 or v6?). |
|
2065 |
- * |
|
2066 |
- * We strip off this field on reads and |
|
2067 |
- * put it back on writes. |
|
2068 |
- * |
|
2069 |
- * I have not tested TAP devices on OpenBSD, |
|
2070 |
- * but I have conditionalized the special |
|
2071 |
- * TUN handling code described above to |
|
2072 |
- * go away for TAP devices. |
|
2073 |
- */ |
|
2074 |
- |
|
2075 | 2058 |
void |
2076 | 2059 |
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) |
2077 | 2060 |
{ |
... | ... |
@@ -2138,59 +2208,16 @@ close_tun (struct tuntap* tt) |
2138 | 2138 |
} |
2139 | 2139 |
} |
2140 | 2140 |
|
2141 |
-static inline int |
|
2142 |
-openbsd_modify_read_write_return (int len) |
|
2143 |
-{ |
|
2144 |
- if (len > 0) |
|
2145 |
- return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; |
|
2146 |
- else |
|
2147 |
- return len; |
|
2148 |
-} |
|
2149 |
- |
|
2150 | 2141 |
int |
2151 |
-write_tun (struct tuntap* tt, uint8_t *buf, int len) |
|
2142 |
+write_tun(struct tuntap *tt, uint8_t *buf, int len) |
|
2152 | 2143 |
{ |
2153 |
- if (tt->type == DEV_TYPE_TUN) |
|
2154 |
- { |
|
2155 |
- u_int32_t type; |
|
2156 |
- struct iovec iv[2]; |
|
2157 |
- struct ip *iph; |
|
2158 |
- |
|
2159 |
- iph = (struct ip *) buf; |
|
2160 |
- |
|
2161 |
- if (tt->ipv6 && iph->ip_v == 6) |
|
2162 |
- type = htonl (AF_INET6); |
|
2163 |
- else |
|
2164 |
- type = htonl (AF_INET); |
|
2165 |
- |
|
2166 |
- iv[0].iov_base = &type; |
|
2167 |
- iv[0].iov_len = sizeof (type); |
|
2168 |
- iv[1].iov_base = buf; |
|
2169 |
- iv[1].iov_len = len; |
|
2170 |
- |
|
2171 |
- return openbsd_modify_read_write_return (writev (tt->fd, iv, 2)); |
|
2172 |
- } |
|
2173 |
- else |
|
2174 |
- return write (tt->fd, buf, len); |
|
2144 |
+ return write_tun_header (tt, buf, len); |
|
2175 | 2145 |
} |
2176 | 2146 |
|
2177 | 2147 |
int |
2178 |
-read_tun (struct tuntap* tt, uint8_t *buf, int len) |
|
2148 |
+read_tun (struct tuntap *tt, uint8_t *buf, int len) |
|
2179 | 2149 |
{ |
2180 |
- if (tt->type == DEV_TYPE_TUN) |
|
2181 |
- { |
|
2182 |
- u_int32_t type; |
|
2183 |
- struct iovec iv[2]; |
|
2184 |
- |
|
2185 |
- iv[0].iov_base = &type; |
|
2186 |
- iv[0].iov_len = sizeof (type); |
|
2187 |
- iv[1].iov_base = buf; |
|
2188 |
- iv[1].iov_len = len; |
|
2189 |
- |
|
2190 |
- return openbsd_modify_read_write_return (readv (tt->fd, iv, 2)); |
|
2191 |
- } |
|
2192 |
- else |
|
2193 |
- return read (tt->fd, buf, len); |
|
2150 |
+ return read_tun_header (tt, buf, len); |
|
2194 | 2151 |
} |
2195 | 2152 |
|
2196 | 2153 |
#elif defined(TARGET_NETBSD) |
... | ... |
@@ -2550,10 +2577,177 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) |
2550 | 2550 |
* pointing to lo0. Need to unconfigure... (observed on 10.5) |
2551 | 2551 |
*/ |
2552 | 2552 |
|
2553 |
+/* |
|
2554 |
+ * utun is the native Darwin tun driver present since at least 10.7 |
|
2555 |
+ * Thanks goes to Jonathan Levin for providing an example how to utun |
|
2556 |
+ * (http://newosxbook.com/src.jl?tree=listings&file=17-15-utun.c) |
|
2557 |
+ */ |
|
2558 |
+ |
|
2559 |
+#ifdef HAVE_NET_IF_UTUN_H |
|
2560 |
+ |
|
2561 |
+/* Helper functions that tries to open utun device |
|
2562 |
+ return -2 on early initialization failures (utun not supported |
|
2563 |
+ at all (old OS X) and -1 on initlization failure of utun |
|
2564 |
+ device (utun works but utunX is already used */ |
|
2565 |
+static |
|
2566 |
+int utun_open_helper (struct ctl_info ctlInfo, int utunnum) |
|
2567 |
+{ |
|
2568 |
+ struct sockaddr_ctl sc; |
|
2569 |
+ int fd; |
|
2570 |
+ |
|
2571 |
+ fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); |
|
2572 |
+ |
|
2573 |
+ if (fd < 0) |
|
2574 |
+ { |
|
2575 |
+ msg (M_INFO, "Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)", |
|
2576 |
+ strerror (errno)); |
|
2577 |
+ return -2; |
|
2578 |
+ } |
|
2579 |
+ |
|
2580 |
+ if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) |
|
2581 |
+ { |
|
2582 |
+ close (fd); |
|
2583 |
+ msg (M_INFO, "Opening utun (%s): %s", "ioctl(CTLIOCGINFO)", |
|
2584 |
+ strerror (errno)); |
|
2585 |
+ return -2; |
|
2586 |
+ } |
|
2587 |
+ |
|
2588 |
+ |
|
2589 |
+ sc.sc_id = ctlInfo.ctl_id; |
|
2590 |
+ sc.sc_len = sizeof(sc); |
|
2591 |
+ sc.sc_family = AF_SYSTEM; |
|
2592 |
+ sc.ss_sysaddr = AF_SYS_CONTROL; |
|
2593 |
+ |
|
2594 |
+ sc.sc_unit = utunnum+1; |
|
2595 |
+ |
|
2596 |
+ |
|
2597 |
+ /* If the connect is successful, a utun%d device will be created, where "%d" |
|
2598 |
+ * is (sc.sc_unit - 1) */ |
|
2599 |
+ |
|
2600 |
+ if (connect (fd, (struct sockaddr *)&sc, sizeof(sc)) < 0) |
|
2601 |
+ { |
|
2602 |
+ msg (M_INFO, "Opening utun (%s): %s", "connect(AF_SYS_CONTROL)", |
|
2603 |
+ strerror (errno)); |
|
2604 |
+ close(fd); |
|
2605 |
+ return -1; |
|
2606 |
+ } |
|
2607 |
+ |
|
2608 |
+ set_nonblock (fd); |
|
2609 |
+ set_cloexec (fd); /* don't pass fd to scripts */ |
|
2610 |
+ |
|
2611 |
+ return fd; |
|
2612 |
+} |
|
2613 |
+ |
|
2614 |
+void |
|
2615 |
+open_darwin_utun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) |
|
2616 |
+{ |
|
2617 |
+ struct ctl_info ctlInfo; |
|
2618 |
+ int fd; |
|
2619 |
+ char utunname[20]; |
|
2620 |
+ int utunnum =-1; |
|
2621 |
+ socklen_t utunname_len = sizeof(utunname); |
|
2622 |
+ |
|
2623 |
+ /* dev_node is simply utun, do the normal dynamic utun |
|
2624 |
+ * otherwise try to parse the utun number */ |
|
2625 |
+ if (dev_node && !strcmp ("utun", dev_node)==0) |
|
2626 |
+ { |
|
2627 |
+ if (!sscanf (dev_node, "utun%d", &utunnum)==1) |
|
2628 |
+ msg (M_FATAL, "Cannot parse 'dev-node %s' please use 'dev-node utunX'" |
|
2629 |
+ "to use a utun device number X", dev_node); |
|
2630 |
+ } |
|
2631 |
+ |
|
2632 |
+ |
|
2633 |
+ |
|
2634 |
+ CLEAR (ctlInfo); |
|
2635 |
+ if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >= |
|
2636 |
+ sizeof(ctlInfo.ctl_name)) |
|
2637 |
+ { |
|
2638 |
+ msg (M_ERR, "Opening utun: UTUN_CONTROL_NAME too long"); |
|
2639 |
+ } |
|
2640 |
+ |
|
2641 |
+ /* try to open first available utun device if no specific utun is requested */ |
|
2642 |
+ if (utunnum == -1) |
|
2643 |
+ { |
|
2644 |
+ for (utunnum=0; utunnum<255; utunnum++) |
|
2645 |
+ { |
|
2646 |
+ fd = utun_open_helper (ctlInfo, utunnum); |
|
2647 |
+ /* Break if the fd is valid, |
|
2648 |
+ * or if early initalization failed (-2) */ |
|
2649 |
+ if (fd !=-1) |
|
2650 |
+ break; |
|
2651 |
+ } |
|
2652 |
+ } |
|
2653 |
+ else |
|
2654 |
+ { |
|
2655 |
+ fd = utun_open_helper (ctlInfo, utunnum); |
|
2656 |
+ } |
|
2657 |
+ |
|
2658 |
+ /* opening an utun device failed */ |
|
2659 |
+ tt->fd = fd; |
|
2660 |
+ |
|
2661 |
+ if (fd < 0) |
|
2662 |
+ return; |
|
2663 |
+ |
|
2664 |
+ /* Retrieve the assigned interface name. */ |
|
2665 |
+ if (getsockopt (fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len)) |
|
2666 |
+ msg (M_ERR | M_ERRNO, "Error retrieving utun interface name"); |
|
2667 |
+ |
|
2668 |
+ tt->actual_name = string_alloc (utunname, NULL); |
|
2669 |
+ |
|
2670 |
+ msg (M_INFO, "Opened utun device %s", utunname); |
|
2671 |
+ tt->is_utun = true; |
|
2672 |
+} |
|
2673 |
+ |
|
2674 |
+#endif |
|
2675 |
+ |
|
2553 | 2676 |
void |
2554 | 2677 |
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) |
2555 | 2678 |
{ |
2556 |
- open_tun_generic (dev, dev_type, dev_node, true, true, tt); |
|
2679 |
+#ifdef HAVE_NET_IF_UTUN_H |
|
2680 |
+ /* If dev_node does not start start with utun assume regular tun/tap */ |
|
2681 |
+ if ((!dev_node && tt->type==DEV_TYPE_TUN) || |
|
2682 |
+ (dev_node && !strncmp (dev_node, "utun", 4))) |
|
2683 |
+ { |
|
2684 |
+ |
|
2685 |
+ /* Check if user has specific dev_type tap and forced utun with |
|
2686 |
+ dev-node utun */ |
|
2687 |
+ if (tt->type!=DEV_TYPE_TUN) |
|
2688 |
+ msg (M_FATAL, "Cannot use utun devices with --dev-type %s", |
|
2689 |
+ dev_type_string (dev, dev_type)); |
|
2690 |
+ |
|
2691 |
+ /* Try utun first and fall back to normal tun if utun fails |
|
2692 |
+ and dev_node is not specified */ |
|
2693 |
+ open_darwin_utun(dev, dev_type, dev_node, tt); |
|
2694 |
+ |
|
2695 |
+ if (!tt->is_utun) |
|
2696 |
+ { |
|
2697 |
+ if (!dev_node) |
|
2698 |
+ { |
|
2699 |
+ /* No explicit utun and utun failed, try the generic way) */ |
|
2700 |
+ msg (M_INFO, "Failed to open utun device. Falling back to /dev/tun device"); |
|
2701 |
+ open_tun_generic (dev, dev_type, NULL, true, true, tt); |
|
2702 |
+ } |
|
2703 |
+ else |
|
2704 |
+ { |
|
2705 |
+ /* Specific utun device or generic utun request with no tun |
|
2706 |
+ fall back failed, consider this a fatal failure */ |
|
2707 |
+ msg (M_FATAL, "Cannot open utun device"); |
|
2708 |
+ } |
|
2709 |
+ } |
|
2710 |
+ } |
|
2711 |
+ else |
|
2712 |
+#endif |
|
2713 |
+ { |
|
2714 |
+ |
|
2715 |
+ /* Use plain dev-node tun to select /dev/tun style |
|
2716 |
+ * Unset dev_node variable prior to passing to open_tun_generic to |
|
2717 |
+ * let open_tun_generic pick the first available tun device */ |
|
2718 |
+ |
|
2719 |
+ if (dev_node && strcmp (dev_node, "tun")==0) |
|
2720 |
+ dev_node=NULL; |
|
2721 |
+ |
|
2722 |
+ open_tun_generic (dev, dev_type, dev_node, true, true, tt); |
|
2723 |
+ } |
|
2557 | 2724 |
} |
2558 | 2725 |
|
2559 | 2726 |
void |
... | ... |
@@ -2586,13 +2780,23 @@ close_tun (struct tuntap* tt) |
2586 | 2586 |
int |
2587 | 2587 |
write_tun (struct tuntap* tt, uint8_t *buf, int len) |
2588 | 2588 |
{ |
2589 |
- return write (tt->fd, buf, len); |
|
2589 |
+#ifdef HAVE_NET_IF_UTUN_H |
|
2590 |
+ if (tt->is_utun) |
|
2591 |
+ return write_tun_header (tt, buf, len); |
|
2592 |
+ else |
|
2593 |
+#endif |
|
2594 |
+ return write (tt->fd, buf, len); |
|
2590 | 2595 |
} |
2591 | 2596 |
|
2592 | 2597 |
int |
2593 | 2598 |
read_tun (struct tuntap* tt, uint8_t *buf, int len) |
2594 | 2599 |
{ |
2595 |
- return read (tt->fd, buf, len); |
|
2600 |
+#ifdef HAVE_NET_IF_UTUN_H |
|
2601 |
+ if (tt->is_utun) |
|
2602 |
+ return read_tun_header (tt, buf, len); |
|
2603 |
+ else |
|
2604 |
+#endif |
|
2605 |
+ return read (tt->fd, buf, len); |
|
2596 | 2606 |
} |
2597 | 2607 |
|
2598 | 2608 |
#elif defined(WIN32) |