mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 03:52:28 +02:00
Use IPAPI for setting ipv6 routes when iservice not available
Currently we use netsh for this. The new code closely follows what interactive service does. Signed-off-by: Selva Nair <selva.nair@gmail.com> Acked-by: Lev Stipakov <lstipakov@gmail.com> Message-Id: <20230105022718.1641751-1-selva.nair@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25886.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
b20daf2743
commit
dd66958198
@ -65,6 +65,8 @@ static bool add_route_ipv6_service(const struct route_ipv6 *, const struct tunta
|
||||
|
||||
static bool del_route_ipv6_service(const struct route_ipv6 *, const struct tuntap *);
|
||||
|
||||
static bool route_ipv6_ipapi(bool add, const struct route_ipv6 *, const struct tuntap *);
|
||||
|
||||
#endif
|
||||
|
||||
static void delete_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx);
|
||||
@ -1975,58 +1977,8 @@ add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt,
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD adapter_index;
|
||||
if (r6->adapter_index) /* vpn server special route */
|
||||
{
|
||||
adapter_index = r6->adapter_index;
|
||||
gateway_needed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
adapter_index = tt->adapter_index;
|
||||
}
|
||||
|
||||
/* netsh interface ipv6 add route 2001:db8::/32 42 */
|
||||
argv_printf(&argv, "%s%s interface ipv6 add route %s/%d %lu",
|
||||
get_win_sys_path(),
|
||||
NETSH_PATH_SUFFIX,
|
||||
network,
|
||||
r6->netbits,
|
||||
adapter_index);
|
||||
|
||||
/* next-hop depends on TUN or TAP mode:
|
||||
* - in TAP mode, we use the "real" next-hop
|
||||
* - in TUN mode we use a special-case link-local address that the tapdrvr
|
||||
* knows about and will answer ND (neighbor discovery) packets for
|
||||
*/
|
||||
if (tt->type == DEV_TYPE_TUN && !gateway_needed)
|
||||
{
|
||||
argv_printf_cat( &argv, " %s", "fe80::8" );
|
||||
}
|
||||
else if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway) )
|
||||
{
|
||||
argv_printf_cat( &argv, " %s", gateway );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (r6->flags & RT_METRIC_DEFINED)
|
||||
{
|
||||
argv_printf_cat(&argv, " METRIC %d", r->metric);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* in some versions of Windows, routes are persistent across reboots by
|
||||
* default, unless "store=active" is set (pointed out by Tony Lim, thanks)
|
||||
*/
|
||||
argv_printf_cat( &argv, " store=active" );
|
||||
|
||||
argv_msg(D_ROUTE, &argv);
|
||||
|
||||
netcmd_semaphore_lock();
|
||||
status = openvpn_execve_check(&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
|
||||
netcmd_semaphore_release();
|
||||
status = route_ipv6_ipapi(true, r6, tt);
|
||||
}
|
||||
|
||||
#elif defined (TARGET_SOLARIS)
|
||||
|
||||
/* example: route add -inet6 2001:db8::/32 somegateway 0 */
|
||||
@ -2416,60 +2368,8 @@ delete_route_ipv6(const struct route_ipv6 *r6, const struct tuntap *tt,
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD adapter_index;
|
||||
if (r6->adapter_index) /* vpn server special route */
|
||||
{
|
||||
adapter_index = r6->adapter_index;
|
||||
gateway_needed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
adapter_index = tt->adapter_index;
|
||||
}
|
||||
|
||||
/* netsh interface ipv6 delete route 2001:db8::/32 42 */
|
||||
argv_printf(&argv, "%s%s interface ipv6 delete route %s/%d %lu",
|
||||
get_win_sys_path(),
|
||||
NETSH_PATH_SUFFIX,
|
||||
network,
|
||||
r6->netbits,
|
||||
adapter_index);
|
||||
|
||||
/* next-hop depends on TUN or TAP mode:
|
||||
* - in TAP mode, we use the "real" next-hop
|
||||
* - in TUN mode we use a special-case link-local address that the tapdrvr
|
||||
* knows about and will answer ND (neighbor discovery) packets for
|
||||
* (and "route deletion without specifying next-hop" does not work...)
|
||||
*/
|
||||
if (tt->type == DEV_TYPE_TUN && !gateway_needed)
|
||||
{
|
||||
argv_printf_cat( &argv, " %s", "fe80::8" );
|
||||
}
|
||||
else if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway) )
|
||||
{
|
||||
argv_printf_cat( &argv, " %s", gateway );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (r6->flags & RT_METRIC_DEFINED)
|
||||
{
|
||||
argv_printf_cat(&argv, "METRIC %d", r->metric);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Windows XP to 7 "just delete" routes, wherever they came from, but
|
||||
* in Windows 8(.1?), if you create them with "store=active", this is
|
||||
* how you should delete them as well (pointed out by Cedric Tabary)
|
||||
*/
|
||||
argv_printf_cat( &argv, " store=active" );
|
||||
|
||||
argv_msg(D_ROUTE, &argv);
|
||||
|
||||
netcmd_semaphore_lock();
|
||||
openvpn_execve_check(&argv, es, 0, "ERROR: Windows route delete ipv6 command failed");
|
||||
netcmd_semaphore_release();
|
||||
route_ipv6_ipapi(false, r6, tt);
|
||||
}
|
||||
|
||||
#elif defined (TARGET_SOLARIS)
|
||||
|
||||
/* example: route delete -inet6 2001:db8::/32 somegateway */
|
||||
@ -3049,6 +2949,73 @@ do_route_ipv4_service(const bool add, const struct route_ipv4 *r, const struct t
|
||||
return do_route_service(add, &msg, sizeof(msg), tt->options.msg_channel);
|
||||
}
|
||||
|
||||
/* Add or delete an ipv6 route */
|
||||
static bool
|
||||
route_ipv6_ipapi(const bool add, const struct route_ipv6 *r, const struct tuntap *tt)
|
||||
{
|
||||
DWORD err;
|
||||
PMIB_IPFORWARD_ROW2 fwd_row;
|
||||
struct gc_arena gc = gc_new();
|
||||
|
||||
fwd_row = gc_malloc(sizeof(*fwd_row), true, &gc);
|
||||
|
||||
fwd_row->ValidLifetime = 0xffffffff;
|
||||
fwd_row->PreferredLifetime = 0xffffffff;
|
||||
fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
|
||||
fwd_row->Metric = ((r->flags & RT_METRIC_DEFINED) ? r->metric : -1);
|
||||
fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
|
||||
fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->network;
|
||||
fwd_row->DestinationPrefix.PrefixLength = (UINT8) r->netbits;
|
||||
fwd_row->NextHop.si_family = AF_INET6;
|
||||
fwd_row->NextHop.Ipv6.sin6_addr = r->gateway;
|
||||
fwd_row->InterfaceIndex = r->adapter_index ? r->adapter_index : tt->adapter_index;
|
||||
|
||||
/* In TUN mode we use a special link-local address as the next hop.
|
||||
* The tapdrvr knows about it and will answer neighbor discovery packets.
|
||||
* (only do this for routes actually using the tun/tap device)
|
||||
*/
|
||||
if (tt->type == DEV_TYPE_TUN && !r->adapter_index)
|
||||
{
|
||||
inet_pton(AF_INET6, "fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
|
||||
}
|
||||
|
||||
/* Use LUID if interface index not available */
|
||||
if (fwd_row->InterfaceIndex == TUN_ADAPTER_INDEX_INVALID && strlen(tt->actual_name))
|
||||
{
|
||||
NET_LUID luid;
|
||||
err = ConvertInterfaceAliasToLuid(wide_string(tt->actual_name, &gc), &luid);
|
||||
if (err != NO_ERROR)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
fwd_row->InterfaceLuid = luid;
|
||||
fwd_row->InterfaceIndex = 0;
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
err = CreateIpForwardEntry2(fwd_row);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = DeleteIpForwardEntry2(fwd_row);
|
||||
}
|
||||
|
||||
out:
|
||||
if (err != NO_ERROR)
|
||||
{
|
||||
msg(M_WARN, "ROUTE: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
|
||||
(add ? "addition" : "deletion"), strerror_win32(err, &gc), err, fwd_row->InterfaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg(D_ROUTE, "IPv6 route %s using ipapi", add ? "added" : "deleted");
|
||||
}
|
||||
gc_free(&gc);
|
||||
|
||||
return (err == NO_ERROR);
|
||||
}
|
||||
|
||||
static bool
|
||||
do_route_ipv6_service(const bool add, const struct route_ipv6 *r, const struct tuntap *tt)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user