Browse code

NetBSD fixes - on 4.0 and up, use multi-af mode. On earlier systems that do not have TUNSIFHEAD (and do not have IPv6 capable tunnels), fall back to old IPv4-only code without address-family prepending. (cherry picked from commit 2a57c58b185deb11b0a62c584489fff59258146c)

Gert Doering authored on 2010/01/14 23:21:05
Showing 1 changed files
... ...
@@ -888,6 +888,13 @@ do_ifconfig (struct tuntap *tt,
888 888
 
889 889
 #elif defined(TARGET_NETBSD)
890 890
 
891
+/* whether or not NetBSD can do IPv6 can be seen by the availability of
892
+ * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
893
+ */
894
+#ifdef TUNSIFHEAD
895
+# define NETBSD_MULTI_AF
896
+#endif
897
+
891 898
       /* as on OpenBSD and Darwin, destroy and re-create tun0 interface
892 899
        */
893 900
       argv_printf (&argv, "%s %s destroy", IFCONFIG_PATH, actual );
... ...
@@ -922,6 +929,7 @@ do_ifconfig (struct tuntap *tt,
922 922
 
923 923
       if ( do_ipv6 )
924 924
 	{
925
+#ifdef NETBSD_MULTI_AF
925 926
 	  struct route_ipv6 r6;
926 927
 	  argv_printf (&argv,
927 928
 			  "%s %s inet6 %s/%d",
... ...
@@ -939,6 +947,10 @@ do_ifconfig (struct tuntap *tt,
939 939
 	  r6.netbits = tt->netbits_ipv6;
940 940
 	  r6.gateway = tt->local_ipv6;
941 941
 	  add_route_ipv6 (&r6, tt, 0, es);
942
+#else
943
+	  msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 (if your system is newer, recompile openvpn)" );
944
+	  tt->ipv6 = false;
945
+#endif
942 946
 	}
943 947
       tt->did_ifconfig = true;
944 948
 
... ...
@@ -1951,46 +1963,39 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
1951 1951
  * NetBSD before 4.0 does not support IPv6 on tun out of the box,
1952 1952
  * but there exists a patch (sys/net/if_tun.c, 1.79->1.80, see PR 32944).
1953 1953
  *
1954
- * When this patch is applied, only two things are left to openvpn:
1955
- * 1. Activate multicasting (this has already been done
1956
- *    before by the kernel, but we make sure that nobody
1957
- *    has deactivated multicasting inbetween.
1958
- * 2. Deactivate "link layer mode" (otherwise NetBSD 
1959
- *    prepends the address family to the packet, and we
1960
- *    would run into the same trouble as with OpenBSD.
1954
+ * NetBSD 4.0 and up do, but we need to put the tun interface into
1955
+ * "multi_af" mode, which will prepend the address family to all packets
1956
+ * (same as OpenBSD and FreeBSD).  If this is not enabled, the kernel
1957
+ * silently drops all IPv6 packets on output and gets confused on input.
1961 1958
  *
1962
- * ... unfortunately, it doesn't work that way.  If TUN_IFHEAD is disabled
1963
- * ("no prepending of the AF"), then the kernel code just drops IPv6 packets
1964
- * on output, and gets confused on input.
1959
+ * On earlier versions, multi_af is not available at all, so we have
1960
+ * two different NetBSD code variants here :-(
1965 1961
  *
1966
- * So we have to do it the same way as FreeBSD and OpenBSD do it 
1967
- * (and we really should merge FreeBSD, NetBSD and OpenBSD together)
1968 1962
  */
1969 1963
 
1970
-static inline int
1971
-netbsd_modify_read_write_return (int len)
1972
-{
1973
-  if (len > 0)
1974
-    return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
1975
-  else
1976
-    return len;
1977
-}
1978
-
1979 1964
 void
1980 1965
 open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
1981 1966
 {
1967
+#ifdef NETBSD_MULTI_AF
1982 1968
     open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
1969
+#else
1970
+    open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
1971
+#endif
1972
+
1983 1973
     if (tt->fd >= 0)
1984 1974
       {
1985 1975
         int i = IFF_POINTOPOINT|IFF_MULTICAST;
1986 1976
         ioctl (tt->fd, TUNSIFMODE, &i);  /* multicast on */
1987 1977
         i = 0;
1988 1978
         ioctl (tt->fd, TUNSLMODE, &i);   /* link layer mode off */
1979
+
1980
+#ifdef NETBSD_MULTI_AF
1989 1981
         i = 1;
1990 1982
         if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) 	/* multi-af mode on */
1991 1983
 	  {
1992 1984
 	    msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
1993 1985
 	  }
1986
+#endif
1994 1987
       }
1995 1988
 }
1996 1989
 
... ...
@@ -2007,6 +2012,17 @@ close_tun (struct tuntap *tt)
2007 2007
     }
2008 2008
 }
2009 2009
 
2010
+#ifdef NETBSD_MULTI_AF
2011
+
2012
+static inline int
2013
+netbsd_modify_read_write_return (int len)
2014
+{
2015
+  if (len > 0)
2016
+    return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
2017
+  else
2018
+    return len;
2019
+}
2020
+
2010 2021
 int
2011 2022
 write_tun (struct tuntap* tt, uint8_t *buf, int len)
2012 2023
 {
... ...
@@ -2053,6 +2069,21 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
2053 2053
     return read (tt->fd, buf, len);
2054 2054
 }
2055 2055
 
2056
+#else	/* not NETBSD_MULTI_AF -> older code, IPv4 only */
2057
+
2058
+int
2059
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
2060
+{
2061
+    return write (tt->fd, buf, len);
2062
+}
2063
+
2064
+int
2065
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
2066
+{
2067
+    return read (tt->fd, buf, len);
2068
+}
2069
+#endif	/* NETBSD_MULTI_AF */
2070
+
2056 2071
 #elif defined(TARGET_FREEBSD)
2057 2072
 
2058 2073
 static inline int