read_config_file (options, p[1], level, file, line, msglevel, permission_mask, option_types_found, es);
}
#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
- else if (streq (p[0], "show-gateway") && !p[1])
+ else if (streq (p[0], "show-gateway") && !p[2])
{
struct route_gateway_info rgi;
+ struct route_ipv6_gateway_info rgi6;
+ struct in6_addr remote = IN6ADDR_ANY_INIT;
VERIFY_PERMISSION (OPT_P_GENERAL);
+ if (p[1])
+ get_ipv6_addr (p[1], &remote, NULL, NULL, M_WARN);
get_default_gateway(&rgi);
- print_default_gateway(M_INFO, &rgi);
+ get_default_gateway_ipv6(&rgi6, &remote);
+ print_default_gateway(M_INFO, &rgi, &rgi6);
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
}
#endif
{
setenv_route_addr (es, "net_gateway", rl->rgi.gateway.addr, -1);
#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
- print_default_gateway (D_ROUTE, &rl->rgi);
+ print_default_gateway (D_ROUTE, &rl->rgi, NULL);
#endif
}
else
}
void
-print_default_gateway(const int msglevel, const struct route_gateway_info *rgi)
+print_default_gateway(const int msglevel,
+ const struct route_gateway_info *rgi,
+ const struct route_ipv6_gateway_info *rgi6)
{
struct gc_arena gc = gc_new ();
- if (rgi->flags & RGI_ADDR_DEFINED)
+ if (rgi && (rgi->flags & RGI_ADDR_DEFINED))
{
struct buffer out = alloc_buf_gc (256, &gc);
buf_printf (&out, "ROUTE_GATEWAY");
buf_printf (&out, " HWADDR=%s", format_hex_ex (rgi->hwaddr, 6, 0, 1, ":", &gc));
msg (msglevel, "%s", BSTR (&out));
}
+
+ if (rgi6 && (rgi6->flags & RGI_ADDR_DEFINED))
+ {
+ struct buffer out = alloc_buf_gc (256, &gc);
+ buf_printf (&out, "ROUTE6_GATEWAY");
+ if (rgi6->flags & RGI_ON_LINK)
+ buf_printf (&out, " ON_LINK");
+ else
+ buf_printf (&out, " %s", print_in6_addr (rgi6->gateway.addr_ipv6, 0, &gc));
+ if (rgi6->flags & RGI_NETMASK_DEFINED)
+ buf_printf (&out, "/%d", rgi6->gateway.netbits_ipv6);
+#ifdef WIN32
+ if (rgi6->flags & RGI_IFACE_DEFINED)
+ buf_printf (&out, " I=%u", (unsigned int)rgi6->adapter_index);
+#else
+ if (rgi6->flags & RGI_IFACE_DEFINED)
+ buf_printf (&out, " IFACE=%s", rgi6->iface);
+#endif
+ if (rgi6->flags & RGI_HWADDR_DEFINED)
+ buf_printf (&out, " HWADDR=%s", format_hex_ex (rgi6->hwaddr, 6, 0, 1, ":", &gc));
+ msg (msglevel, "%s", BSTR (&out));
+ }
gc_free (&gc);
}
return ret;
}
+/* IPv6 implementation using GetIpForwardTable2() and dynamic linking (TBD)
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/aa814416(v=vs.85).aspx
+ */
+void
+get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
+ struct in6_addr *dest)
+{
+ msg(D_ROUTE, "no support for get_default_gateway_ipv6() on this system (windows)");
+ CLEAR(*rgi6);
+}
+
bool
add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index)
{
gc_free (&gc);
}
+/* IPv6 implementation using netlink (TBD)
+ */
+void
+get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
+ struct in6_addr *dest)
+{
+ msg(D_ROUTE, "no support for get_default_gateway_ipv6() on this system (Linux and Android)");
+ CLEAR(*rgi6);
+ struct in6_addr g = IN6ADDR_LOOPBACK_INIT;
+
+ rgi6->flags = RGI_ADDR_DEFINED | RGI_IFACE_DEFINED | RGI_HWADDR_DEFINED |
+ RGI_NETMASK_DEFINED;
+ rgi6->gateway.addr_ipv6 = g;
+ rgi6->gateway.netbits_ipv6 = 64;
+ memcpy( rgi6->hwaddr, "\1\2\3\4\5\6", 6 );
+ strcpy( rgi6->iface, "eth1" );
+}
+
#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || \
defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) || \
defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
gc_free (&gc);
}
+/* BSD implementation using routing socket (as does IPv4) (TBD)
+ */
+void
+get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
+ struct in6_addr *dest)
+{
+ msg(D_ROUTE, "no support for get_default_gateway_ipv6() on this system (BSD and OSX)");
+ CLEAR(*rgi6);
+}
+
#undef max
#else
{
CLEAR(*rgi);
}
+void
+get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
+ struct in6_addr *dest)
+{
+ msg(D_ROUTE, "no support for get_default_gateway_ipv6() on this system");
+ CLEAR(*rgi6);
+}
#endif