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>
(cherry picked from commit fbc04bedbcce02fc625357b7475ddbc7164cabbf)

Arne Schwabe authored on 2013/06/21 19:48:28
Showing 4 changed files
... ...
@@ -454,7 +454,7 @@ SOCKET_INCLUDES="
454 454
 "
455 455
 
456 456
 AC_CHECK_HEADERS(
457
-	[net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h],
457
+	[net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h net/if_utun.h sys/kern_control.h],
458 458
 	,
459 459
 	,
460 460
 	[[${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
... ...
@@ -73,6 +73,12 @@ static void solaris_error_close (struct tuntap *tt, const struct env_set *es, co
73 73
 #include <stropts.h>
74 74
 #endif
75 75
 
76
+#if defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H
77
+#include <sys/kern_control.h>
78
+#include <net/if_utun.h>
79
+#include <sys/sys_domain.h>
80
+#endif
81
+
76 82
 static void clear_tuntap (struct tuntap *tuntap);
77 83
 
78 84
 bool
... ...
@@ -1248,6 +1254,87 @@ open_null (struct tuntap *tt)
1248 1248
   tt->actual_name = string_alloc ("null", NULL);
1249 1249
 }
1250 1250
 
1251
+
1252
+#if defined (TARGET_OPENBSD) || (defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H)
1253
+
1254
+/*
1255
+ * OpenBSD and Mac OS X when using utun
1256
+ * have a slightly incompatible TUN device from
1257
+ * the rest of the world, in that it prepends a
1258
+ * uint32 to the beginning of the IP header
1259
+ * to designate the protocol (why not just
1260
+ * look at the version field in the IP header to
1261
+ * determine v4 or v6?).
1262
+ *
1263
+ * We strip off this field on reads and
1264
+ * put it back on writes.
1265
+ *
1266
+ * I have not tested TAP devices on OpenBSD,
1267
+ * but I have conditionalized the special
1268
+ * TUN handling code described above to
1269
+ * go away for TAP devices.
1270
+ */
1271
+
1272
+#include <netinet/ip.h>
1273
+#include <sys/uio.h>
1274
+
1275
+static inline int
1276
+header_modify_read_write_return (int len)
1277
+{
1278
+    if (len > 0)
1279
+        return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
1280
+    else
1281
+        return len;
1282
+}
1283
+
1284
+int
1285
+write_tun_header (struct tuntap* tt, uint8_t *buf, int len)
1286
+{
1287
+    if (tt->type == DEV_TYPE_TUN)
1288
+      {
1289
+        u_int32_t type;
1290
+        struct iovec iv[2];
1291
+        struct ip *iph;
1292
+
1293
+        iph = (struct ip *) buf;
1294
+
1295
+        if (tt->ipv6 && iph->ip_v == 6)
1296
+            type = htonl (AF_INET6);
1297
+        else
1298
+            type = htonl (AF_INET);
1299
+
1300
+        iv[0].iov_base = &type;
1301
+        iv[0].iov_len = sizeof (type);
1302
+        iv[1].iov_base = buf;
1303
+        iv[1].iov_len = len;
1304
+
1305
+        return header_modify_read_write_return (writev (tt->fd, iv, 2));
1306
+      }
1307
+    else
1308
+        return write (tt->fd, buf, len);
1309
+}
1310
+
1311
+int
1312
+read_tun_header (struct tuntap* tt, uint8_t *buf, int len)
1313
+{
1314
+    if (tt->type == DEV_TYPE_TUN)
1315
+      {
1316
+        u_int32_t type;
1317
+        struct iovec iv[2];
1318
+
1319
+        iv[0].iov_base = &type;
1320
+        iv[0].iov_len = sizeof (type);
1321
+        iv[1].iov_base = buf;
1322
+        iv[1].iov_len = len;
1323
+
1324
+        return header_modify_read_write_return (readv (tt->fd, iv, 2));
1325
+      }
1326
+    else
1327
+        return read (tt->fd, buf, len);
1328
+}
1329
+#endif
1330
+
1331
+
1251 1332
 #ifndef WIN32
1252 1333
 static void
1253 1334
 open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
... ...
@@ -1972,23 +2059,6 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
1972 1972
 
1973 1973
 #elif defined(TARGET_OPENBSD)
1974 1974
 
1975
-/*
1976
- * OpenBSD has a slightly incompatible TUN device from
1977
- * the rest of the world, in that it prepends a
1978
- * uint32 to the beginning of the IP header
1979
- * to designate the protocol (why not just
1980
- * look at the version field in the IP header to
1981
- * determine v4 or v6?).
1982
- *
1983
- * We strip off this field on reads and
1984
- * put it back on writes.
1985
- *
1986
- * I have not tested TAP devices on OpenBSD,
1987
- * but I have conditionalized the special
1988
- * TUN handling code described above to
1989
- * go away for TAP devices.
1990
- */
1991
-
1992 1975
 void
1993 1976
 open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
1994 1977
 {
... ...
@@ -2055,59 +2125,16 @@ close_tun (struct tuntap* tt)
2055 2055
     }
2056 2056
 }
2057 2057
 
2058
-static inline int
2059
-openbsd_modify_read_write_return (int len)
2060
-{
2061
- if (len > 0)
2062
-    return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
2063
-  else
2064
-    return len;
2065
-}
2066
-
2067 2058
 int
2068
-write_tun (struct tuntap* tt, uint8_t *buf, int len)
2059
+write_tun(struct tuntap *tt, uint8_t *buf, int len)
2069 2060
 {
2070
-  if (tt->type == DEV_TYPE_TUN)
2071
-    {
2072
-      u_int32_t type;
2073
-      struct iovec iv[2];
2074
-      struct ip *iph;
2075
-
2076
-      iph = (struct ip *) buf;
2077
-
2078
-      if (tt->ipv6 && iph->ip_v == 6)
2079
-	type = htonl (AF_INET6);
2080
-      else 
2081
-	type = htonl (AF_INET);
2082
-
2083
-      iv[0].iov_base = &type;
2084
-      iv[0].iov_len = sizeof (type);
2085
-      iv[1].iov_base = buf;
2086
-      iv[1].iov_len = len;
2087
-
2088
-      return openbsd_modify_read_write_return (writev (tt->fd, iv, 2));
2089
-    }
2090
-  else
2091
-    return write (tt->fd, buf, len);
2061
+  return write_tun_header (tt, buf, len);
2092 2062
 }
2093 2063
 
2094 2064
 int
2095
-read_tun (struct tuntap* tt, uint8_t *buf, int len)
2065
+read_tun (struct tuntap *tt, uint8_t *buf, int len)
2096 2066
 {
2097
-  if (tt->type == DEV_TYPE_TUN)
2098
-    {
2099
-      u_int32_t type;
2100
-      struct iovec iv[2];
2101
-
2102
-      iv[0].iov_base = &type;
2103
-      iv[0].iov_len = sizeof (type);
2104
-      iv[1].iov_base = buf;
2105
-      iv[1].iov_len = len;
2106
-
2107
-      return openbsd_modify_read_write_return (readv (tt->fd, iv, 2));
2108
-    }
2109
-  else
2110
-    return read (tt->fd, buf, len);
2067
+    return read_tun_header (tt, buf, len);
2111 2068
 }
2112 2069
 
2113 2070
 #elif defined(TARGET_NETBSD)
... ...
@@ -2467,10 +2494,177 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
2467 2467
  * pointing to lo0.  Need to unconfigure...  (observed on 10.5)
2468 2468
  */
2469 2469
 
2470
+/*
2471
+ * utun is the native Darwin tun driver present since at least 10.7
2472
+ * Thanks goes to Jonathan Levin for providing an example how to utun
2473
+ * (http://newosxbook.com/src.jl?tree=listings&file=17-15-utun.c)
2474
+ */
2475
+
2476
+#ifdef HAVE_NET_IF_UTUN_H
2477
+
2478
+/* Helper functions that tries to open utun device
2479
+   return -2 on early initialization failures (utun not supported
2480
+   at all (old OS X) and -1 on initlization failure of utun
2481
+   device (utun works but utunX is already used */
2482
+static
2483
+int utun_open_helper (struct ctl_info ctlInfo, int utunnum)
2484
+{
2485
+  struct sockaddr_ctl sc;
2486
+  int fd;
2487
+
2488
+  fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
2489
+
2490
+  if (fd < 0)
2491
+    {
2492
+      msg (M_INFO, "Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)",
2493
+           strerror (errno));
2494
+      return -2;
2495
+    }
2496
+
2497
+  if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1)
2498
+    {
2499
+      close (fd);
2500
+      msg (M_INFO, "Opening utun (%s): %s", "ioctl(CTLIOCGINFO)",
2501
+           strerror (errno));
2502
+      return -2;
2503
+    }
2504
+
2505
+
2506
+  sc.sc_id = ctlInfo.ctl_id;
2507
+  sc.sc_len = sizeof(sc);
2508
+  sc.sc_family = AF_SYSTEM;
2509
+  sc.ss_sysaddr = AF_SYS_CONTROL;
2510
+
2511
+  sc.sc_unit = utunnum+1;
2512
+
2513
+
2514
+  /* If the connect is successful, a utun%d device will be created, where "%d"
2515
+   * is (sc.sc_unit - 1) */
2516
+
2517
+  if (connect (fd, (struct sockaddr *)&sc, sizeof(sc)) < 0)
2518
+    {
2519
+      msg (M_INFO, "Opening utun (%s): %s", "connect(AF_SYS_CONTROL)",
2520
+           strerror (errno));
2521
+      close(fd);
2522
+      return -1;
2523
+    }
2524
+
2525
+  set_nonblock (fd);
2526
+  set_cloexec (fd); /* don't pass fd to scripts */
2527
+
2528
+  return fd;
2529
+}
2530
+
2531
+void
2532
+open_darwin_utun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
2533
+{
2534
+  struct ctl_info ctlInfo;
2535
+  int fd;
2536
+  char utunname[20];
2537
+  int utunnum =-1;
2538
+  socklen_t utunname_len = sizeof(utunname);
2539
+
2540
+  /* dev_node is simply utun, do the normal dynamic utun
2541
+   * otherwise try to parse the utun number */
2542
+  if (dev_node && !strcmp ("utun", dev_node)==0)
2543
+    {
2544
+      if (!sscanf (dev_node, "utun%d", &utunnum)==1)
2545
+        msg (M_FATAL, "Cannot parse 'dev-node %s' please use 'dev-node utunX'"
2546
+             "to use a utun device number X", dev_node);
2547
+    }
2548
+
2549
+
2550
+
2551
+  CLEAR (ctlInfo);
2552
+  if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >=
2553
+      sizeof(ctlInfo.ctl_name))
2554
+    {
2555
+      msg (M_ERR, "Opening utun: UTUN_CONTROL_NAME too long");
2556
+    }
2557
+
2558
+  /* try to open first available utun device if no specific utun is requested */
2559
+  if (utunnum == -1)
2560
+    {
2561
+      for (utunnum=0; utunnum<255; utunnum++)
2562
+        {
2563
+          fd = utun_open_helper (ctlInfo, utunnum);
2564
+          /* Break if the fd is valid,
2565
+           * or if early initalization failed (-2) */
2566
+          if (fd !=-1)
2567
+            break;
2568
+        }
2569
+    }
2570
+  else
2571
+    {
2572
+      fd = utun_open_helper (ctlInfo, utunnum);
2573
+    }
2574
+
2575
+  /* opening an utun device failed */
2576
+  tt->fd = fd;
2577
+
2578
+  if (fd < 0)
2579
+      return;
2580
+
2581
+  /* Retrieve the assigned interface name. */
2582
+  if (getsockopt (fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len))
2583
+   msg (M_ERR | M_ERRNO, "Error retrieving utun interface name");
2584
+
2585
+  tt->actual_name = string_alloc (utunname, NULL);
2586
+
2587
+  msg (M_INFO, "Opened utun device %s", utunname);
2588
+  tt->is_utun = true;
2589
+}
2590
+
2591
+#endif
2592
+
2470 2593
 void
2471 2594
 open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
2472 2595
 {
2473
-  open_tun_generic (dev, dev_type, dev_node, true, true, tt);
2596
+#ifdef HAVE_NET_IF_UTUN_H
2597
+  /* If dev_node does not start start with utun assume regular tun/tap */
2598
+  if ((!dev_node && tt->type==DEV_TYPE_TUN) ||
2599
+      (dev_node && !strncmp (dev_node, "utun", 4)))
2600
+    {
2601
+
2602
+      /* Check if user has specific dev_type tap and forced utun with
2603
+         dev-node utun */
2604
+      if (tt->type!=DEV_TYPE_TUN)
2605
+        msg (M_FATAL, "Cannot use utun devices with --dev-type %s",
2606
+             dev_type_string (dev, dev_type));
2607
+
2608
+      /* Try utun first and fall back to normal tun if utun fails
2609
+         and dev_node is not specified */
2610
+      open_darwin_utun(dev, dev_type, dev_node, tt);
2611
+
2612
+      if (!tt->is_utun)
2613
+        {
2614
+          if (!dev_node)
2615
+            {
2616
+              /* No explicit utun and utun failed, try the generic way) */
2617
+              msg (M_INFO, "Failed to open utun device. Falling back to /dev/tun device");
2618
+              open_tun_generic (dev, dev_type, NULL, true, true, tt);
2619
+            }
2620
+          else
2621
+            {
2622
+              /* Specific utun device or generic utun request with no tun
2623
+                 fall back failed, consider this a fatal failure */
2624
+              msg (M_FATAL, "Cannot open utun device");
2625
+            }
2626
+        }
2627
+    }
2628
+  else
2629
+#endif
2630
+    {
2631
+
2632
+      /* Use plain dev-node tun to select /dev/tun style
2633
+       * Unset dev_node variable prior to passing to open_tun_generic to
2634
+       * let open_tun_generic pick the first available tun device */
2635
+
2636
+      if (dev_node && strcmp (dev_node, "tun")==0)
2637
+        dev_node=NULL;
2638
+
2639
+      open_tun_generic (dev, dev_type, dev_node, true, true, tt);
2640
+    }
2474 2641
 }
2475 2642
 
2476 2643
 void
... ...
@@ -2503,13 +2697,23 @@ close_tun (struct tuntap* tt)
2503 2503
 int
2504 2504
 write_tun (struct tuntap* tt, uint8_t *buf, int len)
2505 2505
 {
2506
-  return write (tt->fd, buf, len);
2506
+#ifdef HAVE_NET_IF_UTUN_H
2507
+  if (tt->is_utun)
2508
+    return write_tun_header (tt, buf, len);
2509
+  else
2510
+#endif
2511
+    return write (tt->fd, buf, len);
2507 2512
 }
2508 2513
 
2509 2514
 int
2510 2515
 read_tun (struct tuntap* tt, uint8_t *buf, int len)
2511 2516
 {
2512
-  return read (tt->fd, buf, len);
2517
+#ifdef HAVE_NET_IF_UTUN_H
2518
+  if (tt->is_utun)
2519
+    return read_tun_header (tt, buf, len);
2520
+  else
2521
+#endif
2522
+    return read (tt->fd, buf, len);
2513 2523
 }
2514 2524
 
2515 2525
 #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