48#if defined(TARGET_LINUX) || defined(TARGET_ANDROID)
49#include <linux/rtnetlink.h>
52#if defined(TARGET_NETBSD)
59#define METRIC_NOT_USED ((DWORD)-1)
105#ifndef TARGET_ANDROID
195 if (!strcmp(parm,
"default"))
226 if (!
strcmp(
string,
"vpn_gateway"))
232 *out =
rl->spec.remote_endpoint;
245 else if (!
strcmp(
string,
"net_gateway"))
251 *out =
rl->ngi.gateway.addr;
256 " ROUTE: net_gateway undefined -- unable to get default gateway from system");
265 else if (!
strcmp(
string,
"remote_host"))
271 *out =
rl->spec.remote_host;
307 struct in_addr special = { 0 };
327 special.s_addr = htonl(special.s_addr);
328 char buf[INET_ADDRSTRLEN];
329 inet_ntop(AF_INET, &special, buf,
sizeof(buf));
335 NULL, AF_INET, network_list);
384 " ROUTE: " PACKAGE_NAME
385 " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
398 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
418 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
437 if (inet_pton(AF_INET6, r6o->
gateway, &
r6->gateway) != 1)
439 msg(
M_WARN, PACKAGE_NAME
"ROUTE6: cannot parse gateway spec '%s'", r6o->
gateway);
455 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
475 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
482 const char *gateway,
const char *metric,
int table_id)
545 l2 = ((~gateway->netmask) + 1) >> 1;
547 r1->gateway = target;
549 r1->netmask = ~(l2 - 1);
563#ifndef TARGET_ANDROID
594 const char *remote_endpoint,
int default_metric,
in_addr_t remote_host,
620#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
638 bool defined =
false;
650 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve default gateway: %s",
673 struct addrinfo *netlist = NULL;
682 const struct addrinfo *curele;
683 for (curele = netlist; curele; curele = curele->ai_next)
688 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
715 for (i = 0; bits >= 8; i++, bits -= 8)
717 if (
network->s6_addr[i] != host->s6_addr[i])
728 unsigned int mask = 0xff << (8 - bits);
730 if ((
network->s6_addr[i] & mask) == (host->s6_addr[i] & mask))
740 const char *remote_endpoint,
int default_metric,
741 const struct in6_addr *remote_host_ipv6,
struct env_set *
es,
746 bool need_remote_ipv6_route;
752 if (remote_host_ipv6)
758 if (default_metric >= 0)
771#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
790 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve VPN endpoint: %s",
799 need_remote_ipv6_route =
false;
816#ifndef TARGET_ANDROID
824 need_remote_ipv6_route =
true;
826 "ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
836 if (need_remote_ipv6_route)
844 r6->network = *remote_host_ipv6;
854 r6->iface = rl6->
rgi6.iface;
864 "ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n");
906 for (
int i = 0; i < rb->
n_bypass; ++i)
938 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
947 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
958 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
963#ifndef TARGET_ANDROID
995 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1054 rl->
iflags &= ~RL_DID_LOCAL;
1085 rl->
iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
1101 "WARNING: OpenVPN was configured to add an IPv4 "
1102 "route. However, no IPv4 has been configured for %s, "
1103 "therefore the route installation may fail or may not work "
1108#ifdef ENABLE_MANAGEMENT
1133 "WARNING: OpenVPN was configured to add an IPv6 "
1134 "route. However, no IPv6 has been configured for %s, "
1135 "therefore the route installation may fail or may not work "
1173 rl->
iflags &= ~RL_ROUTES_ADDED;
1195 rl6->
iflags &= ~RL_ROUTES_ADDED;
1211 return "default (not set)";
1232 msg(msglevel,
" [redirect_default_gateway local=%d]", (rol->
flags &
RG_LOCAL) != 0);
1276 msg(msglevel,
"%s",
BSTR(&out));
1307 msg(msglevel,
"%s",
BSTR(&out));
1412 && netmask == 0xFFFFFFFF)
1421 for (
int i = 0; i < rgi->
n_addrs; ++i)
1436#if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1462#if !defined(TARGET_LINUX)
1464#if !defined(TARGET_AIX)
1476#if defined(TARGET_LINUX)
1477 const char *
iface = NULL;
1496 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1501 msg(
M_WARN,
"ERROR: Linux route add command failed");
1505#elif defined(TARGET_ANDROID)
1510 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1514 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1516 bool ret = management_android_control(
management,
"ROUTE", out);
1519#elif defined(_WIN32)
1523 network, netmask, gateway);
1536 const char *method =
"service";
1553 method =
"route.exe";
1558 method =
"ipapi [adaptive]";
1561 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1564 &
argv,
es, 0,
"ERROR: Windows route add command failed [adaptive]");
1567 method =
"route.exe";
1576 msg(
D_ROUTE,
"Route addition via %s %s", method,
1581#elif defined(TARGET_SOLARIS)
1605#elif defined(TARGET_FREEBSD)
1624#elif defined(TARGET_DRAGONFLY)
1643#elif defined(TARGET_DARWIN)
1670#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1689#elif defined(TARGET_AIX)
1693 argv_printf(&
argv,
"%s add -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
1699#elif defined(TARGET_HAIKU)
1702 argv_printf(&
argv,
"%s add %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
1710 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
1720 r->
flags &= ~RT_ADDED;
1738 int bits_to_clear = 128 -
r6->netbits;
1740 while (
byte >= 0 && bits_to_clear > 0)
1742 if (bits_to_clear >= 8)
1744 r6->network.s6_addr[
byte--] = 0;
1749 r6->network.s6_addr[
byte--] &= (uint8_t)(0xff << bits_to_clear);
1760 bool gateway_needed =
false;
1772 if (
r6->iface != NULL)
1775 if (!IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1777 gateway_needed =
true;
1786#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1787 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1793 if (
r6->iface != NULL && gateway_needed
1794 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
1796 size_t len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
1798 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
1804 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1805 r6->metric, device);
1807 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu", network,
r6->netbits, gateway,
1824 gateway_needed =
true;
1827 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1830 "ROUTE6 WARNING: " PACKAGE_NAME
" needs a gateway "
1831 "parameter for a --route-ipv6 option and no default was set via "
1832 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1833 "IPv6 route to %s/%d.",
1834 network,
r6->netbits);
1839#if defined(TARGET_LINUX)
1843 metric =
r6->metric;
1847 int ret = net_route_v6_add(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
1848 device,
r6->table_id, metric);
1851 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1856 msg(
M_WARN,
"ERROR: Linux route add command failed");
1860#elif defined(TARGET_ANDROID)
1863 snprintf(out,
sizeof(out),
"%s/%d %s", network,
r6->netbits, device);
1867#elif defined(_WIN32)
1877#elif defined(TARGET_SOLARIS)
1890 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1902#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1919#elif defined(TARGET_DARWIN)
1921 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
1936#elif defined(TARGET_OPENBSD)
1938 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
1945#elif defined(TARGET_NETBSD)
1947 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1953#elif defined(TARGET_AIX)
1955 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1960#elif defined(TARGET_HAIKU)
1963 argv_printf(&
argv,
"%s add %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
1964 gateway,
r6->netbits);
1971 "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-up script");
1981 r6->flags &= ~RT_ADDED;
1995#if !defined(TARGET_LINUX)
1996 const char *network;
1997#if !defined(TARGET_AIX)
1998 const char *netmask;
2000 const char *gateway;
2014#if !defined(TARGET_LINUX)
2016#if !defined(TARGET_AIX)
2028#if defined(TARGET_LINUX)
2039 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2041#elif defined(_WIN32)
2044 network, netmask, gateway);
2051 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2056 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2067 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2070 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2073 "ERROR: Windows route delete command failed [adaptive]");
2082#elif defined(TARGET_SOLARIS)
2084 argv_printf(&
argv,
"%s delete %s -netmask %s %s", ROUTE_PATH, network, netmask, gateway);
2089#elif defined(TARGET_FREEBSD)
2091 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2096#elif defined(TARGET_DRAGONFLY)
2098 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2103#elif defined(TARGET_DARWIN)
2107 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s", ROUTE_PATH,
2108 network, netmask, rgi->iface);
2112 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2118#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2120 argv_printf(&
argv,
"%s delete -net %s %s -netmask %s", ROUTE_PATH, network, gateway, netmask);
2125#elif defined(TARGET_ANDROID)
2129 "needed. The VpnService API allows routes to be set "
2130 "on connect only and will clean up automatically. "
2131 "Tried to delete route %s netmask %s gateway %s",
2132 network, netmask, gateway);
2133#elif defined(TARGET_AIX)
2137 argv_printf(&
argv,
"%s delete -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
2142#elif defined(TARGET_HAIKU)
2145 argv_printf(&
argv,
"%s delete %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
2152 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2156 r->
flags &= ~RT_ADDED;
2167 const char *network;
2175#if !defined(TARGET_LINUX)
2176 const char *gateway;
2178#if !defined(TARGET_SOLARIS)
2179 bool gateway_needed =
false;
2181 if (
r6->iface != NULL)
2184 gateway_needed =
true;
2193 gateway_needed =
true;
2202#if !defined(TARGET_LINUX) && !defined(_WIN32)
2206#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2207 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2213 if (
r6->iface != NULL && gateway_needed
2214 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
2216 size_t len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
2218 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
2223 msg(
D_ROUTE,
"delete_route_ipv6(%s/%d)", network,
r6->netbits);
2225#if defined(TARGET_LINUX)
2229 metric =
r6->metric;
2232 if (net_route_v6_del(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
2233 device,
r6->table_id, metric)
2236 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2239#elif defined(_WIN32)
2249#elif defined(TARGET_SOLARIS)
2253 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2258#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2274#elif defined(TARGET_DARWIN)
2276 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
2290#elif defined(TARGET_OPENBSD)
2292 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
2298#elif defined(TARGET_NETBSD)
2300 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2305#elif defined(TARGET_AIX)
2307 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2311#elif defined(TARGET_ANDROID)
2313 "needed. The VpnService API allows routes to be set "
2314 "on connect only and will clean up automatically. "
2315 "Tried to delete %s gateway %s",
2317 gateway_needed ? gateway :
"(not needed)");
2318#elif defined(TARGET_HAIKU)
2321 argv_printf(&
argv,
"%s delete %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2322 gateway,
r6->netbits);
2328 "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-down script");
2344static const MIB_IPFORWARDTABLE *
2348 PMIB_IPFORWARDTABLE rt = NULL;
2351 status = GetIpForwardTable(NULL, &size, TRUE);
2352 if (
status == ERROR_INSUFFICIENT_BUFFER)
2354 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2355 status = GetIpForwardTable(rt, &size, TRUE);
2358 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%lu)",
2413 bool adapter_up =
false;
2427 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2439 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%u a=%d u/d=%s",
2440 good, count, len, ret, ambig, adapter_up ?
"up" :
"down");
2446static const MIB_IPFORWARDROW *
2450 DWORD lowest_metric = MAXDWORD;
2451 const MIB_IPFORWARDROW *ret = NULL;
2456 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2458 const MIB_IPFORWARDROW *row = &routes->table[i];
2459 const in_addr_t net = ntohl(row->dwForwardDest);
2460 const in_addr_t mask = ntohl(row->dwForwardMask);
2461 const DWORD index = row->dwForwardIfIndex;
2462 const DWORD metric = row->dwForwardMetric1;
2468 if (!net && !mask && metric < lowest_metric)
2471 lowest_metric = metric;
2497 DWORD best_if_index;
2503 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2506 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%lu)",
2516 SOCKADDR_INET best_src;
2518 status = GetBestRoute2(&luid, best_if_index, NULL, dest, 0, best_route, &best_src);
2521 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%lu)",
2540 sa.si_family = AF_INET;
2541 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2544 MIB_IPFORWARD_ROW2 best_route;
2553 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2566 memcpy(rgi->
hwaddr, ai->Address, 6);
2570 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2590 bool on_tun =
false;
2595 ret = tun_adapter->Index;
2606 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2612 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2617 on_tun, count, ret);
2634 SOCKADDR_INET DestinationAddress;
2635 CLEAR(DestinationAddress);
2636 DestinationAddress.si_family = AF_INET6;
2639 DestinationAddress.Ipv6.sin6_addr = *dest;
2642 MIB_IPFORWARD_ROW2 BestRoute;
2651 msg(
D_ROUTE,
"GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex,
2653 BestRoute.DestinationPrefix.PrefixLength,
2655 msg(
D_ROUTE,
"GDG6: Metric=%lu, Loopback=%u, AA=%u, I=%u", BestRoute.Metric,
2656 BestRoute.Loopback, BestRoute.AutoconfigureAddress, BestRoute.Immortal);
2663 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr))
2685 MIB_IPFORWARDROW fr;
2687 fr.dwForwardDest = htonl(r->
network);
2688 fr.dwForwardMask = htonl(r->
netmask);
2689 fr.dwForwardPolicy = 0;
2690 fr.dwForwardNextHop = htonl(r->
gateway);
2691 fr.dwForwardIfIndex = if_index;
2692 fr.dwForwardType = 4;
2693 fr.dwForwardProto = 3;
2694 fr.dwForwardAge = 0;
2695 fr.dwForwardNextHopAS = 0;
2704 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2708 status = CreateIpForwardEntry(&fr);
2714 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2722 const DWORD forward_metric_limit = 2048;
2724 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2729 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2731 status = CreateIpForwardEntry(&fr);
2735 "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%lu and dwForwardType=%lu",
2736 fr.dwForwardMetric1, fr.dwForwardType);
2740 else if (
status != ERROR_BAD_ARGUMENTS)
2750 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2757 "ERROR: route addition failed using CreateIpForwardEntry: "
2758 "%s [status=%lu if_index=%lu]",
2779 MIB_IPFORWARDROW fr;
2782 fr.dwForwardDest = htonl(r->
network);
2783 fr.dwForwardMask = htonl(r->
netmask);
2784 fr.dwForwardPolicy = 0;
2785 fr.dwForwardNextHop = htonl(r->
gateway);
2786 fr.dwForwardIfIndex = if_index;
2788 status = DeleteIpForwardEntry(&fr);
2796 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2823 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%lu]",
2850 .prefix.ipv4.s_addr = htonl(r->
network),
2851 .gateway.ipv4.s_addr = htonl(r->
gateway),
2852 .iface = { .index = if_index, .name =
"" },
2856 if (
msg.prefix_len == -1)
2858 msg.prefix_len = 32;
2872 PMIB_IPFORWARD_ROW2 fwd_row;
2877 fwd_row->ValidLifetime = 0xffffffff;
2878 fwd_row->PreferredLifetime = 0xffffffff;
2879 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2881 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2882 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2883 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2884 fwd_row->NextHop.si_family = AF_INET6;
2885 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2894 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2902 if (err != NO_ERROR)
2906 fwd_row->InterfaceLuid = luid;
2907 fwd_row->InterfaceIndex = 0;
2912 err = CreateIpForwardEntry2(fwd_row);
2916 err = DeleteIpForwardEntry2(fwd_row);
2920 if (err != NO_ERROR)
2925 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2927 fwd_row->InterfaceIndex);
2931 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2936 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
2968 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
2974 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
2980 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3016 buf_printf(&out,
"%s %s %s p=%lu i=%lu t=%lu pr=%lu a=%lu h=%lu m=%lu/%lu/%lu/%lu/%lu",
3020 r->dwForwardIfIndex,
r->dwForwardType,
r->dwForwardProto,
3021 r->dwForwardAge,
r->dwForwardNextHopAS,
r->dwForwardMetric1,
3022 r->dwForwardMetric2,
r->dwForwardMetric3,
r->dwForwardMetric4,
3023 r->dwForwardMetric5);
3037 msg(msglevel,
"SYSTEM ROUTING TABLE");
3040 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3048#elif defined(TARGET_ANDROID)
3063 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3065 strcpy(rgi->iface,
"android-gw");
3085 strcpy(rgi6->iface,
"android-gw");
3088#elif defined(TARGET_LINUX)
3095 char best_name[IFNAMSIZ];
3101 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3113 const struct ifreq *ifr;
3114 const struct ifreq *ifend;
3118 struct ifreq ifs[20];
3120 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3125 ifc.ifc_len =
sizeof(ifs);
3127 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3129 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3134 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3135 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3137 if (ifr->ifr_addr.sa_family == AF_INET)
3140 addr = ntohl(((
struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3143 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3146 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3150 if (!(ifreq.ifr_flags & IFF_UP))
3159 if (strcmp(ifreq.ifr_name, best_name))
3165 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3167 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3170 rgi->
flags &= ~RGI_ON_LINK;
3178 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3182 netmask = ntohl(((
struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3196 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3200 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3201 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3203 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3206 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3236 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3243 if (strlen(rgi6->iface) > 0)
3261#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3262 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3264#include <sys/types.h>
3265#include <sys/socket.h>
3266#include <netinet/in.h>
3267#include <net/route.h>
3268#include <net/if_dl.h>
3269#if !defined(TARGET_SOLARIS)
3275 struct rt_msghdr m_rtm;
3295#if defined(TARGET_DARWIN)
3296#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3297#elif defined(TARGET_NETBSD)
3298#define ROUNDUP(a) RT_ROUNDUP(a)
3300#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3303#if defined(TARGET_SOLARIS)
3304#define NEXTADDR(w, u) \
3305 if (rtm_addrs & (w)) \
3307 size_t l = sizeof(u); \
3308 memmove(cp, &(u), l); \
3312#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3314#define NEXTADDR(w, u) \
3315 if (rtm_addrs & (w)) \
3317 size_t l = ((struct sockaddr *)&(u))->sa_len; \
3318 memmove(cp, &(u), l); \
3322#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3325#define max(a, b) ((a) > (b) ? (a) : (b))
3331 struct rtmsg m_rtmsg;
3334 struct sockaddr so_dst, so_mask;
3335 char *cp = m_rtmsg.m_space;
3336 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3337 struct rt_msghdr *rtm_aux;
3339#define rtm m_rtmsg.m_rtm
3344 const int pid = getpid();
3346#ifdef TARGET_OPENBSD
3347 rtm_addrs = RTA_DST | RTA_NETMASK;
3349 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3352 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3353 bzero(&so_dst,
sizeof(so_dst));
3354 bzero(&so_mask,
sizeof(so_mask));
3355 bzero(&rtm,
sizeof(
struct rt_msghdr));
3357 rtm.rtm_type = RTM_GET;
3358 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3359 rtm.rtm_version = RTM_VERSION;
3360 rtm.rtm_seq = ++seq;
3361#ifdef TARGET_OPENBSD
3362 rtm.rtm_tableid = (u_short)getrtable();
3364 rtm.rtm_addrs = rtm_addrs;
3366 so_dst.sa_family = AF_INET;
3367 so_mask.sa_family = AF_INET;
3369#ifndef TARGET_SOLARIS
3370 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3371 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3374 NEXTADDR(RTA_DST, so_dst);
3375 NEXTADDR(RTA_NETMASK, so_mask);
3378 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3381 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3387 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3395 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3396 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3402 cp = (
char *)(rtm_aux + 1);
3403 if (rtm_aux->rtm_addrs)
3405 for (
unsigned int i = 1; i; i <<= 1)
3407 if (i & rtm_aux->rtm_addrs)
3409 sa = (
struct sockaddr *)cp;
3410 if (i == RTA_GATEWAY)
3414 else if (i == RTA_IFP)
3431 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3440 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3441 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3443 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3444 rgi->iface[adl->sdl_nlen] =
'\0';
3455 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3463 ifr.ifr_addr.sa_family = AF_INET;
3464 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3466 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3474 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3481#if defined(TARGET_SOLARIS)
3483 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3490 struct ifreq ifreq = { 0 };
3493 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3494 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3496 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3500 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3504 struct ifaddrs *ifap, *ifa;
3506 if (getifaddrs(&ifap) != 0)
3512 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3514 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3515 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3517 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3518 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3542#if defined(TARGET_SOLARIS)
3544#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3551 struct rtmsg m_rtmsg;
3554 struct sockaddr_in6 so_dst, so_mask;
3555 char *cp = m_rtmsg.m_space;
3556 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3557 struct rt_msghdr *rtm_aux;
3562 const int pid = getpid();
3564#ifdef TARGET_OPENBSD
3565 rtm_addrs = RTA_DST | RTA_NETMASK;
3567 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3570 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3571 bzero(&so_dst,
sizeof(so_dst));
3572 bzero(&so_mask,
sizeof(so_mask));
3573 bzero(&rtm,
sizeof(
struct rt_msghdr));
3575 rtm.rtm_type = RTM_GET;
3576 rtm.rtm_flags = RTF_UP;
3577 rtm.rtm_version = RTM_VERSION;
3578 rtm.rtm_seq = ++seq;
3579#ifdef TARGET_OPENBSD
3580 rtm.rtm_tableid = (u_short)getrtable();
3583 so_dst.sin6_family = AF_INET6;
3584 so_mask.sin6_family = AF_INET6;
3587 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3589 so_dst.sin6_addr = *dest;
3591 rtm_addrs &= ~RTA_NETMASK;
3594 rtm.rtm_addrs = rtm_addrs;
3596#ifndef TARGET_SOLARIS
3597 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3598 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3601 NEXTADDR(RTA_DST, so_dst);
3602 NEXTADDR(RTA_NETMASK, so_mask);
3605 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3608 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3614 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3622 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3623 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3630 cp = (
char *)(rtm_aux + 1);
3631 if (rtm_aux->rtm_addrs)
3633 for (
unsigned int i = 1; i; i <<= 1)
3635 if (i & rtm_aux->rtm_addrs)
3637 sa = (
struct sockaddr *)cp;
3638 if (i == RTA_GATEWAY)
3642 else if (i == RTA_IFP)
3658 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3659 struct in6_addr gw = s6->sin6_addr;
3661#ifndef TARGET_SOLARIS
3666 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3668 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3671 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3685 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3686 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3688 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3703#elif defined(TARGET_HAIKU)
3710 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3713 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3717 struct ifconf config;
3718 config.ifc_len =
sizeof(config.ifc_value);
3719 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3721 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3725 uint32 size = (uint32)config.ifc_value;
3731 void *
buffer = malloc(size);
3734 config.ifc_len = size;
3736 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3742 struct ifreq *
interface = (struct ifreq *)
buffer;
3743 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3745 while (interface < end)
3747 struct route_entry
route = interface->ifr_route;
3748 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3750 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3752 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3755 int32 address_size = 0;
3756 if (
route.destination != NULL)
3758 address_size +=
route.destination->sa_len;
3760 if (
route.mask != NULL)
3762 address_size +=
route.mask->sa_len;
3764 if (
route.gateway != NULL)
3766 address_size +=
route.gateway->sa_len;
3769 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE + sizeof(struct route_entry)
3818 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3828 const int addrlen =
sizeof(
in_addr_t) * 8;
3830 if ((network & netmask) == network)
3832 for (i = 0; i <= addrlen; ++i)
3835 if (mask == netmask)
3859 const int addrlen =
sizeof(
in_addr_t) * 8;
3861 for (i = 0; i <= addrlen; ++i)
3864 if (mask == netmask)
3895 bool succeed =
false;
3902 iplist = iplist->Next;
3974 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3976 const MIB_IPFORWARDROW *row = &rt->table[i];
3977 const in_addr_t net = ntohl(row->dwForwardDest);
3978 const in_addr_t mask = ntohl(row->dwForwardMask);
3979 if (mask > nonlocal_netmask && (addr & mask) == net)
void argv_msg(const msglvl_t msglevel, const struct argv *a)
Write the arguments stored in a struct argv via the msg() command.
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
bool argv_printf_cat(struct argv *argres, const char *format,...)
printf() inspired argv concatenation.
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
char * format_hex_ex(const uint8_t *data, size_t size, size_t maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Format a binary buffer as a hex string.
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
Register an address with a custom free function in a garbage collection arena.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
#define ALLOC_OBJ_GC(dptr, type, gc)
Allocate a garbage-collected object of the given type (uninitialised).
static void strncpynt(char *dest, const char *src, size_t maxlen)
Like strncpy() but always null-terminates the destination.
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
static void gc_freeaddrinfo_callback(void *addr)
Callback to free a struct addrinfo, suitable for use with gc_addspecial().
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
void setenv_int(struct env_set *es, const char *name, int value)
void setenv_str(struct env_set *es, const char *name, const char *value)
static SERVICE_STATUS status
void management_set_state(struct management *man, const int state, const char *detail, const in_addr_t *tun_local_ip, const struct in6_addr *tun_local_ip6, const struct openvpn_sockaddr *local, const struct openvpn_sockaddr *remote)
#define OPENVPN_STATE_ADD_ROUTES
static void net_ctx_reset(openvpn_net_ctx_t *ctx)
#define TUN_ADAPTER_INDEX_INVALID
#define IPV4_NETMASK_HOST
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
void print_route_options(const struct route_option_list *rol, msglvl_t msglevel)
static void undo_redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
static void print_route_option(const struct route_option *ro, msglvl_t msglevel)
static void add_host_route_if_nonlocal(struct route_bypass *rb, const in_addr_t addr)
bool add_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
bool is_special_addr(const char *addr_str)
struct route_option_list * clone_route_option_list(const struct route_option_list *src, struct gc_arena *a)
void setenv_routes_ipv6(struct env_set *es, const struct route_ipv6_list *rl6)
static void clear_route_list(struct route_list *rl)
static void test_route_helper(bool *ret, int *count, int *good, int *ambig, const IP_ADAPTER_INFO *adapters, const in_addr_t gateway)
static void del_bypass_routes(struct route_bypass *rb, in_addr_t gateway, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx)
static bool del_route_ipapi(const struct route_ipv4 *r, const struct tuntap *tt)
static bool redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
static bool add_route3(in_addr_t network, in_addr_t netmask, in_addr_t gateway, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx)
static void add_host_route_array(struct route_bypass *rb, const IP_ADDR_STRING *iplist)
int netmask_to_netbits2(in_addr_t netmask)
struct route_ipv6_option_list * new_route_ipv6_option_list(struct gc_arena *a)
static bool init_route(struct route_ipv4 *r, struct addrinfo **network_list, const struct route_option *ro, const struct route_list *rl)
void delete_routes_v6(struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
static bool get_special_addr(const struct route_list *rl, const char *string, in_addr_t *out, bool *status)
bool test_routes(const struct route_list *rl, const struct tuntap *tt)
static void add_block_local_routes(struct route_list *rl)
bool block_local_needed(const struct route_list *rl)
Get the decision whether to block traffic to local networks while the VPN is connected.
void get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6, const struct in6_addr *dest, openvpn_net_ctx_t *ctx)
static const MIB_IPFORWARDTABLE * get_windows_routing_table(struct gc_arena *gc)
static DWORD get_best_route(struct gc_arena *gc, SOCKADDR_INET *dest, MIB_IPFORWARD_ROW2 *best_route)
Determines the best route to a destination for both IPv4 and IPv6.
static int do_route_service(const bool add, const route_message_t *rt, const DWORD size, HANDLE pipe)
static const char * format_route_entry(const MIB_IPFORWARDROW *r, struct gc_arena *gc)
static int add_route_service(const struct route_ipv4 *, const struct tuntap *)
bool init_route_ipv6_list(struct route_ipv6_list *rl6, const struct route_ipv6_option_list *opt6, const char *remote_endpoint, int default_metric, const struct in6_addr *remote_host_ipv6, struct env_set *es, openvpn_net_ctx_t *ctx)
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)
static bool del_route_ipv6_service(const struct route_ipv6 *, const struct tuntap *)
void route_list_add_vpn_gateway(struct route_list *rl, struct env_set *es, const in_addr_t addr)
bool ipv6_net_contains_host(const struct in6_addr *network, unsigned int bits, const struct in6_addr *host)
check whether an IPv6 host address is covered by a given network/bits
void add_route_ipv6_to_option_list(struct route_ipv6_option_list *l, const char *prefix, const char *gateway, const char *metric, int table_id)
void copy_route_option_list(struct route_option_list *dest, const struct route_option_list *src, struct gc_arena *a)
void copy_route_ipv6_option_list(struct route_ipv6_option_list *dest, const struct route_ipv6_option_list *src, struct gc_arena *a)
bool add_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)
static int test_route(const IP_ADAPTER_INFO *adapters, const in_addr_t gateway, DWORD *index)
void print_default_gateway(const msglvl_t msglevel, const struct route_gateway_info *rgi, const struct route_ipv6_gateway_info *rgi6)
bool add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
static bool del_route_service(const struct route_ipv4 *, const struct tuntap *)
static int local_route(in_addr_t network, in_addr_t netmask, in_addr_t gateway, const struct route_gateway_info *rgi)
static int add_route_ipv6_service(const struct route_ipv6 *, const struct tuntap *)
static bool is_on_link(const int is_local_route, const unsigned int flags, const struct route_gateway_info *rgi)
static const MIB_IPFORWARDROW * get_default_gateway_row(const MIB_IPFORWARDTABLE *routes)
void get_default_gateway(struct route_gateway_info *rgi, in_addr_t dest, openvpn_net_ctx_t *ctx)
Retrieves the best gateway for a given destination based on the routing table.
static int route_ipv6_ipapi(bool add, const struct route_ipv6 *, const struct tuntap *)
static void add_block_local_item(struct route_list *rl, const struct route_gateway_address *gateway, in_addr_t target)
struct route_ipv6_option_list * clone_route_ipv6_option_list(const struct route_ipv6_option_list *src, struct gc_arena *a)
static const char * show_opt(const char *option)
static bool init_route_ipv6(struct route_ipv6 *r6, const struct route_ipv6_option *r6o, const struct route_ipv6_list *rl6)
struct route_option_list * new_route_option_list(struct gc_arena *a)
int test_local_addr(const in_addr_t addr, const struct route_gateway_info *rgi)
bool init_route_list(struct route_list *rl, const struct route_option_list *opt, const char *remote_endpoint, int default_metric, in_addr_t remote_host, struct env_set *es, openvpn_net_ctx_t *ctx)
static int add_route_ipapi(const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index)
void delete_route_ipv6(const struct route_ipv6 *r6, const struct tuntap *tt, const struct env_set *es, openvpn_net_ctx_t *ctx)
static int do_route_ipv6_service(const bool add, const struct route_ipv6 *r, const struct tuntap *tt)
void route_ipv6_clear_host_bits(struct route_ipv6 *r6)
static void clear_route_ipv6_list(struct route_ipv6_list *rl6)
void delete_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
void show_routes(msglvl_t msglevel)
bool netmask_to_netbits(const in_addr_t network, const in_addr_t netmask, int *netbits)
static void setenv_route_addr(struct env_set *es, const char *key, const in_addr_t addr, int i)
static DWORD windows_route_find_if_index(const struct route_ipv4 *r, const struct tuntap *tt)
static int do_route_ipv4_service(const bool add, const struct route_ipv4 *r, const struct tuntap *tt)
void setenv_routes(struct env_set *es, const struct route_list *rl)
void delete_routes_v4(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
static bool add_bypass_routes(struct route_bypass *rb, in_addr_t gateway, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx)
static void get_bypass_addresses(struct route_bypass *rb, const unsigned int flags)
static bool is_route_parm_defined(const char *parm)
static void setenv_route_ipv6(struct env_set *es, const struct route_ipv6 *r6, int i)
static bool add_bypass_address(struct route_bypass *rb, const in_addr_t a)
static void setenv_route(struct env_set *es, const struct route_ipv4 *r, int i)
void add_route_to_option_list(struct route_option_list *l, const char *network, const char *netmask, const char *gateway, const char *metric, int table_id)
static void del_route3(in_addr_t network, in_addr_t netmask, in_addr_t gateway, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx)
#define RL_DID_REDIRECT_DEFAULT_GATEWAY
#define RTSA_REMOTE_ENDPOINT
#define RGI_HWADDR_DEFINED
static in_addr_t netbits_to_netmask(const int netbits)
#define ROUTE_METHOD_SERVICE
#define RGI_IFACE_DEFINED
#define ROUTE_METHOD_IPAPI
#define RT_METRIC_DEFINED
#define ROUTE_DELETE_FIRST
#define TLA_NOT_IMPLEMENTED
#define ROUTE_METHOD_ADAPTIVE
#define ROUTE_METHOD_MASK
#define RTSA_DEFAULT_METRIC
#define RGI_NETMASK_DEFINED
int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
bool get_ipv6_addr(const char *hostname, struct in6_addr *network, unsigned int *netbits, msglvl_t msglevel)
Translate an IPv6 addr or hostname from string form to in6_addr.
in_addr_t getaddr(unsigned int flags, const char *hostname, int resolve_retry_seconds, bool *succeeded, struct signal_info *sig_info)
Translate an IPv4 addr or hostname from string form to in_addr_t.
#define IPV4_INVALID_ADDR
int openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, struct addrinfo **res)
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
#define GETADDR_HOST_ORDER
#define GETADDR_WARN_ON_SIGNAL
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
Container for unidirectional cipher and HMAC key material.
in_addr_t bypass[N_ROUTE_BYPASS]
struct route_gateway_address addrs[RGI_N_ADDRESSES]
struct route_gateway_address gateway
const struct route_option * option
struct in6_addr addr_ipv6
struct route_ipv6_gateway_address gateway
struct route_ipv6_gateway_address addrs[RGI_N_ADDRESSES]
struct route_ipv6_gateway_info rgi6
struct route_ipv6 * routes_ipv6
struct route_ipv6_gateway_info ngi6
struct in6_addr remote_host_ipv6
struct in6_addr remote_endpoint_ipv6
struct route_ipv6_option * routes_ipv6
struct route_ipv6_option * next
struct route_gateway_info rgi
struct route_ipv4 * routes
struct route_special_addr spec
struct route_gateway_info ngi
struct route_option * routes
struct route_option * next
struct route_bypass bypass
in_addr_t remote_endpoint
bool did_ifconfig_ipv6_setup
if the internal variables related to ifconfig-ipv6 of this struct have been set up.
struct tuntap_options options
bool did_ifconfig_setup
if the internal variables related to ifconfig of this struct have been set up.
const IP_ADAPTER_INFO * get_tun_adapter(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
bool is_adapter_up(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
const IP_ADAPTER_INFO * get_adapter_info(DWORD index, struct gc_arena *gc)
const IP_PER_ADAPTER_INFO * get_per_adapter_info(const DWORD index, struct gc_arena *gc)
bool is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
const IP_ADAPTER_INFO * get_adapter_info_list(struct gc_arena *gc)
const IP_ADAPTER_INFO * get_adapter(const IP_ADAPTER_INFO *ai, DWORD index)
DWORD adapter_index_of_ip(const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count, in_addr_t *netmask)
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
void netcmd_semaphore_release(void)
char * get_win_sys_path(void)
void netcmd_semaphore_lock(void)
bool send_msg_iservice(HANDLE pipe, const void *data, DWORD size, ack_message_t *ack, const char *context)
Send the size bytes in buffer data to the interactive service pipe and read the result in ack.
#define WIN_ROUTE_PATH_SUFFIX