Browse code

Add support of utun devices under Mac OS X

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>

Arne Schwabe authored on 2013/06/21 19:48:28
Showing 4 changed files
... ...
@@ -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)
... ...
@@ -181,6 +181,9 @@ struct tuntap
181 181
   int ip_fd;
182 182
 #endif
183 183
 
184
+#ifdef HAVE_NET_IF_UTUN_H
185
+  bool is_utun;
186
+#endif
184 187
   /* used for printing status info only */
185 188
   unsigned int rwflags_debug;
186 189