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