This change makes it possible to configure an IPv6 address on a
tunnel without also having an IPv4 address.
---
 src/openvpn/tun.c | 366 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 188 insertions(+), 178 deletions(-)

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index e92edc2..927b6e8 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -642,16 +642,10 @@ do_ifconfig (struct tuntap *tt,
       const char *ifconfig_local = NULL;
       const char *ifconfig_remote_netmask = NULL;
       const char *ifconfig_broadcast = NULL;
-      const char *ifconfig_ipv6_local = NULL;
-      const char *ifconfig_ipv6_remote = NULL;
-      bool do_ipv6 = false;
       struct argv argv;

       argv_init (&argv);

-      msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
-                  tt->ipv6, tt->did_ifconfig_ipv6_setup );
-
       /*
        * We only handle TUN/TAP devices here, not --dev null devices.
        */
@@ -663,13 +657,6 @@ do_ifconfig (struct tuntap *tt,
       ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
       ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);

-      if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
-        {
-         ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
-         ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
-         do_ipv6 = true;
-       }
-
       /*
        * If TAP-style device, generate broadcast address.
        */
@@ -728,18 +715,6 @@ do_ifconfig (struct tuntap *tt,
                  argv_msg (M_INFO, &argv);
                  openvpn_execve_check (&argv, es, S_FATAL, "Linux ip addr add 
failed");
        }
-      if ( do_ipv6 )
-       {
-         argv_printf( &argv,
-                     "%s -6 addr add %s/%d dev %s",
-                     iproute_path,
-                     ifconfig_ipv6_local,
-                     tt->netbits_ipv6,
-                     actual
-                     );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "Linux ip -6 addr add 
failed");
-       }
       tt->did_ifconfig = true;
 #else
       if (tun)
@@ -763,29 +738,10 @@ do_ifconfig (struct tuntap *tt,
                          );
       argv_msg (M_INFO, &argv);
       openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig failed");
-      if ( do_ipv6 )
-       {
-         argv_printf (&argv,
-                         "%s %s add %s/%d",
-                         IFCONFIG_PATH,
-                         actual,
-                         ifconfig_ipv6_local,
-                         tt->netbits_ipv6
-                         );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig inet6 
failed");
-       }
       tt->did_ifconfig = true;

 #endif /*ENABLE_IPROUTE*/
 #elif defined(TARGET_ANDROID)
-
-      if (do_ipv6) {
-          struct buffer out6 = alloc_buf_gc (64, &gc);
-          buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6);
-          management_android_control(management, "IFCONFIG6",buf_bptr(&out6));
-      }
-
       struct buffer out = alloc_buf_gc (64, &gc);

       char* top;
@@ -860,52 +816,6 @@ do_ifconfig (struct tuntap *tt,
       if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-2 
failed"))
        solaris_error_close (tt, es, actual, false);

-      if ( do_ipv6 )
-        {
-         argv_printf (&argv, "%s %s inet6 unplumb",
-                           IFCONFIG_PATH, actual );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, 0, NULL);
-
-         if ( tt->type == DEV_TYPE_TUN )
-          {
-             argv_printf (&argv,
-                           "%s %s inet6 plumb %s/%d %s up",
-                           IFCONFIG_PATH,
-                           actual,
-                           ifconfig_ipv6_local,
-                           tt->netbits_ipv6,
-                           ifconfig_ipv6_remote
-                           );
-           }
-         else                                          /* tap mode */
-           {
-             /* base IPv6 tap interface needs to be brought up first
-              */
-             argv_printf (&argv, "%s %s inet6 plumb up",
-                           IFCONFIG_PATH, actual );
-             argv_msg (M_INFO, &argv);
-             if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 
(prepare) failed"))
-               solaris_error_close (tt, es, actual, true);
-
-             /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
-              * after the system has noticed the interface and fired up
-              * the DHCPv6 client - but this takes quite a while, and the 
-              * server will ignore the DHCPv6 packets anyway.  So we don't.
-              */
-
-             /* static IPv6 addresses need to go to a subinterface (tap0:1)
-              */
-             argv_printf (&argv,
-                           "%s %s inet6 addif %s/%d up",
-                           IFCONFIG_PATH, actual,
-                           ifconfig_ipv6_local, tt->netbits_ipv6 );
-           }
-         argv_msg (M_INFO, &argv);
-         if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 
failed"))
-           solaris_error_close (tt, es, actual, true);
-        }
-
       if (!tun && tt->topology == TOP_SUBNET)
        {
          /* Add a network route for the local tun interface */
@@ -964,32 +874,9 @@ do_ifconfig (struct tuntap *tt,
                          );
       argv_msg (M_INFO, &argv);
       openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig failed");
-      if ( do_ipv6 )
-       {
-         argv_printf (&argv,
-                         "%s %s inet6 %s/%d",
-                         IFCONFIG_PATH,
-                         actual,
-                         ifconfig_ipv6_local,
-                         tt->netbits_ipv6
-                         );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig inet6 
failed");
-
-         /* and, hooray, we explicitely need to add a route... */
-         add_route_connected_v6_net(tt, es);
-       }
       tt->did_ifconfig = true;

 #elif defined(TARGET_NETBSD)
-
-/* whether or not NetBSD can do IPv6 can be seen by the availability of
- * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
- */
-#ifdef TUNSIFHEAD
-# define NETBSD_MULTI_AF
-#endif
-
       if (tun)
        argv_printf (&argv,
                          "%s %s %s %s mtu %d netmask 255.255.255.255 up",
@@ -1030,26 +917,6 @@ do_ifconfig (struct tuntap *tt,
       argv_msg (M_INFO, &argv);
       openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig failed");

-      if ( do_ipv6 )
-       {
-#ifdef NETBSD_MULTI_AF
-         argv_printf (&argv,
-                         "%s %s inet6 %s/%d",
-                         IFCONFIG_PATH,
-                         actual,
-                         ifconfig_ipv6_local,
-                         tt->netbits_ipv6
-                         );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig inet6 
failed");
-
-         /* and, hooray, we explicitely need to add a route... */
-         add_route_connected_v6_net(tt, es);
-#else
-         msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 
(if your system is newer, recompile openvpn)" );
-         tt->ipv6 = false;
-#endif
-       }
       tt->did_ifconfig = true;

 #elif defined(TARGET_DARWIN)
@@ -1115,22 +982,6 @@ do_ifconfig (struct tuntap *tt,
          add_route (&r, tt, 0, NULL, es);
        }

-      if ( do_ipv6 )
-       {
-          argv_printf (&argv,
-                              "%s %s inet6 %s/%d",
-                              IFCONFIG_PATH,
-                              actual,
-                              ifconfig_ipv6_local,
-                              tt->netbits_ipv6
-                              );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "MacOS X ifconfig inet6 
failed");
-
-         /* and, hooray, we explicitely need to add a route... */
-         add_route_connected_v6_net(tt, es);
-       }
-
 #elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)

       /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 
255.255.255.255 up */
@@ -1181,19 +1032,6 @@ do_ifconfig (struct tuntap *tt,
           add_route (&r, tt, 0, NULL, es);
         }

-      if ( do_ipv6 )
-       {
-          argv_printf (&argv,
-                              "%s %s inet6 %s/%d",
-                              IFCONFIG_PATH,
-                              actual,
-                              ifconfig_ipv6_local,
-                              tt->netbits_ipv6
-                              );
-         argv_msg (M_INFO, &argv);
-         openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 
failed");
-       }
-
 #elif defined(TARGET_AIX)
       {
        /* AIX ifconfig will complain if it can't find ODM path in env */
@@ -1216,19 +1054,6 @@ do_ifconfig (struct tuntap *tt,
        argv_msg (M_INFO, &argv);
        openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig failed");
        tt->did_ifconfig = true;
-
-       if ( do_ipv6 )
-         {
-           argv_printf (&argv,
-                               "%s %s inet6 %s/%d",
-                               IFCONFIG_PATH,
-                               actual,
-                               ifconfig_ipv6_local,
-                               tt->netbits_ipv6
-                               );
-           argv_msg (M_INFO, &argv);
-           openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig inet6 
failed");
-         }
        env_set_destroy (aix_es);
       }
 #elif defined (WIN32)
@@ -1270,8 +1095,193 @@ do_ifconfig (struct tuntap *tt,
        tt->did_ifconfig = true;
       }

-    /* IPv6 always uses "netsh" interface */
-    if ( do_ipv6 )
+#else
+      msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on 
this operating system.  You should ifconfig your TUN/TAP device manually or use 
an --up script.");
+#endif
+      argv_reset (&argv);
+
+}
+
+
+  if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
+  {
+      const char *ifconfig_ipv6_local = NULL;
+      const char *ifconfig_ipv6_remote = NULL;
+      struct argv argv;
+
+      argv_init (&argv);
+
+      msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
+                  tt->ipv6, tt->did_ifconfig_ipv6_setup );
+
+      ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
+      ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
+
+
+#if defined(TARGET_LINUX)
+#ifdef ENABLE_IPROUTE
+      argv_printf( &argv,
+                 "%s -6 addr add %s/%d dev %s",
+                 iproute_path,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6,
+                 actual
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "Linux ip -6 addr add failed");
+      tt->did_ifconfig = true;
+#else
+      argv_printf (&argv,
+                 "%s %s add %s/%d",
+                 IFCONFIG_PATH,
+                 actual,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig inet6 failed");
+      tt->did_ifconfig = true;
+
+#endif /*ENABLE_IPROUTE*/
+#elif defined(TARGET_ANDROID)
+      struct buffer out6 = alloc_buf_gc (64, &gc);
+      buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6);
+      management_android_control(management, "IFCONFIG6",buf_bptr(&out6));
+
+#elif defined(TARGET_SOLARIS)
+      argv_printf (&argv, "%s %s inet6 unplumb",
+                 IFCONFIG_PATH, actual );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, 0, NULL);
+
+      if ( tt->type == DEV_TYPE_TUN )
+       {
+         argv_printf (&argv,
+                     "%s %s inet6 plumb %s/%d %s up",
+                     IFCONFIG_PATH,
+                     actual,
+                     ifconfig_ipv6_local,
+                     tt->netbits_ipv6,
+                     ifconfig_ipv6_remote
+                     );
+       }
+      else                                             /* tap mode */
+       {
+         /* base IPv6 tap interface needs to be brought up first
+          */
+         argv_printf (&argv, "%s %s inet6 plumb up",
+                     IFCONFIG_PATH, actual );
+         argv_msg (M_INFO, &argv);
+         if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 
(prepare) failed"))
+           solaris_error_close (tt, es, actual, true);
+
+         /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
+          * after the system has noticed the interface and fired up
+          * the DHCPv6 client - but this takes quite a while, and the
+          * server will ignore the DHCPv6 packets anyway.  So we don't.
+          */
+
+         /* static IPv6 addresses need to go to a subinterface (tap0:1)
+          */
+         argv_printf (&argv,
+                     "%s %s inet6 addif %s/%d up",
+                     IFCONFIG_PATH, actual,
+                     ifconfig_ipv6_local, tt->netbits_ipv6 );
+       }
+      argv_msg (M_INFO, &argv);
+      if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 failed"))
+       solaris_error_close (tt, es, actual, true);
+
+#elif defined(TARGET_OPENBSD)
+      argv_printf (&argv,
+                 "%s %s inet6 %s/%d",
+                 IFCONFIG_PATH,
+                 actual,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig inet6 
failed");
+
+      /* and, hooray, we explicitely need to add a route... */
+      add_route_connected_v6_net(tt, es);
+      tt->did_ifconfig = true;
+
+#elif defined(TARGET_NETBSD)
+
+/* whether or not NetBSD can do IPv6 can be seen by the availability of
+ * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
+ */
+#ifdef TUNSIFHEAD
+# define NETBSD_MULTI_AF
+#endif
+
+#ifdef NETBSD_MULTI_AF
+      argv_printf (&argv,
+                 "%s %s inet6 %s/%d",
+                 IFCONFIG_PATH,
+                 actual,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig inet6 
failed");
+
+      /* and, hooray, we explicitely need to add a route... */
+      add_route_connected_v6_net(tt, es);
+#else
+      msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 
(if your system is newer, recompile openvpn)" );
+#endif
+
+#elif defined(TARGET_DARWIN)
+      /*
+       * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to 
OpenBSD...
+       */
+
+      argv_printf (&argv,
+                 "%s %s inet6 %s/%d",
+                 IFCONFIG_PATH,
+                 actual,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "MacOS X ifconfig inet6 
failed");
+
+      /* and, hooray, we explicitely need to add a route... */
+      add_route_connected_v6_net(tt, es);
+
+#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+
+      argv_printf (&argv,
+                 "%s %s inet6 %s/%d",
+                 IFCONFIG_PATH,
+                 actual,
+                 ifconfig_ipv6_local,
+                 tt->netbits_ipv6
+                 );
+      argv_msg (M_INFO, &argv);
+      openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 
failed");
+
+#elif defined(TARGET_AIX)
+      {
+       /* AIX ifconfig will complain if it can't find ODM path in env */
+       struct env_set *aix_es = env_set_create (NULL);
+       env_set_add( aix_es, "ODMDIR=/etc/objrepos" );
+
+       argv_printf (&argv,
+                   "%s %s inet6 %s/%d",
+                   IFCONFIG_PATH,
+                   actual,
+                   ifconfig_ipv6_local,
+                   tt->netbits_ipv6
+                   );
+       argv_msg (M_INFO, &argv);
+       openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig inet6 
failed");
+       env_set_destroy (aix_es);
+      }
+#elif defined (WIN32)
+      /* IPv6 always uses "netsh" interface */
       {
        char * saved_actual;

@@ -5211,7 +5221,7 @@ open_tun (const char *dev, const char *dev_type, const 
char *dev_node, struct tu

   if (tt->type == DEV_TYPE_TUN)
     {
-      if (!tt->did_ifconfig_setup)
+      if (!(tt->did_ifconfig_setup || tt->did_ifconfig_ipv6_setup))
        {
          msg (M_FATAL, "ERROR: --dev tun also requires --ifconfig");
        }
-- 
2.0.2


Reply via email to