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"))
236 msg(
M_INFO, PACKAGE_NAME
" ROUTE: vpn_gateway undefined");
245 else if (!strcmp(
string,
"net_gateway"))
256 " ROUTE: net_gateway undefined -- unable to get default gateway from system");
265 else if (!strcmp(
string,
"remote_host"))
275 msg(
M_INFO, PACKAGE_NAME
" ROUTE: remote_host undefined");
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,
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)
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/%u 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");
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 "
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));
1355 buf_printf(&name1,
"route_ipv6_network_%d", i);
1359 buf_printf(&name2,
"route_ipv6_gateway_%d", i);
1365 buf_printf(&name3,
"route_ipv6_metric_%d", i);
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");
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/%u -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1805 r6->metric, device);
1807 msg(
D_ROUTE,
"add_route_ipv6(%s/%u -> %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/%u.",
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");
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");
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/%u)", 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]",
2778 MIB_IPFORWARDROW fr;
2781 fr.dwForwardDest = htonl(r->
network);
2782 fr.dwForwardMask = htonl(r->
netmask);
2783 fr.dwForwardPolicy = 0;
2784 fr.dwForwardNextHop = htonl(r->
gateway);
2785 fr.dwForwardIfIndex = if_index;
2787 const DWORD
status = DeleteIpForwardEntry(&fr);
2794 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2821 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%d if_index=%lu]",
2848 .prefix.ipv4.s_addr = htonl(r->
network),
2849 .gateway.ipv4.s_addr = htonl(r->
gateway),
2850 .iface = { .index = if_index, .name =
"" },
2854 if (
msg.prefix_len == -1)
2856 msg.prefix_len = 32;
2870 PMIB_IPFORWARD_ROW2 fwd_row;
2875 fwd_row->ValidLifetime = 0xffffffff;
2876 fwd_row->PreferredLifetime = 0xffffffff;
2877 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2879 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2880 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2881 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2882 fwd_row->NextHop.si_family = AF_INET6;
2883 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2892 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2900 if (err != NO_ERROR)
2904 fwd_row->InterfaceLuid = luid;
2905 fwd_row->InterfaceIndex = 0;
2910 err = CreateIpForwardEntry2(fwd_row);
2914 err = DeleteIpForwardEntry2(fwd_row);
2918 if (err != NO_ERROR)
2923 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2925 fwd_row->InterfaceIndex);
2929 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2934 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
2966 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
2972 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
2978 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3014 buf_printf(&out,
"%s %s %s p=%lu i=%lu t=%lu pr=%lu a=%lu h=%lu m=%lu/%lu/%lu/%lu/%lu",
3018 r->dwForwardIfIndex, r->dwForwardType, r->dwForwardProto,
3019 r->dwForwardAge, r->dwForwardNextHopAS, r->dwForwardMetric1,
3020 r->dwForwardMetric2, r->dwForwardMetric3, r->dwForwardMetric4,
3021 r->dwForwardMetric5);
3035 msg(msglevel,
"SYSTEM ROUTING TABLE");
3038 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3046#elif defined(TARGET_ANDROID)
3061 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3063 strcpy(rgi->iface,
"android-gw");
3083 strcpy(rgi6->iface,
"android-gw");
3086#elif defined(TARGET_LINUX)
3093 char best_name[IFNAMSIZ];
3099 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3111 const struct ifreq *ifr;
3112 const struct ifreq *ifend;
3116 struct ifreq ifs[20];
3118 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3123 ifc.ifc_len =
sizeof(ifs);
3125 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3127 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3132 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3133 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3135 if (ifr->ifr_addr.sa_family == AF_INET)
3138 addr = ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3141 strncpynt(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
3144 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3148 if (!(ifreq.ifr_flags & IFF_UP))
3153 if (rgi->flags & RGI_ON_LINK)
3157 if (strcmp(ifreq.ifr_name, best_name))
3163 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3165 rgi->gateway.addr = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3166 if (rgi->gateway.addr)
3168 rgi->flags &= ~RGI_ON_LINK;
3176 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3180 netmask = ntohl(((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3183 if (((rgi->gateway.addr ^ addr) & netmask) != 0)
3189 rgi->gateway.netmask = netmask;
3190 rgi->flags |= RGI_NETMASK_DEFINED;
3194 strncpynt(rgi->iface, ifreq.ifr_name, sizeof(rgi->iface));
3195 rgi->flags |= RGI_IFACE_DEFINED;
3198 memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
3199 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3201 msg(M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3204 memcpy(rgi->hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3205 rgi->flags |= RGI_HWADDR_DEFINED;
3234 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3241 if (strlen(rgi6->iface) > 0)
3259#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3260 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3262#include <sys/types.h>
3263#include <sys/socket.h>
3264#include <netinet/in.h>
3265#include <net/route.h>
3266#include <net/if_dl.h>
3267#if !defined(TARGET_SOLARIS)
3273 struct rt_msghdr m_rtm;
3293#if defined(TARGET_DARWIN)
3294#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3295#elif defined(TARGET_NETBSD)
3296#define ROUNDUP(a) RT_ROUNDUP(a)
3298#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3301#if defined(TARGET_SOLARIS)
3302#define NEXTADDR(w, u) \
3303 if (rtm_addrs & (w)) \
3305 size_t l = sizeof(u); \
3306 memmove(cp, &(u), l); \
3310#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3312#define NEXTADDR(w, u) \
3313 if (rtm_addrs & (w)) \
3315 size_t l = ((struct sockaddr *)&(u))->sa_len; \
3316 memmove(cp, &(u), l); \
3320#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3323#define max(a, b) ((a) > (b) ? (a) : (b))
3329 struct rtmsg m_rtmsg;
3332 struct sockaddr so_dst, so_mask;
3333 char *cp = m_rtmsg.m_space;
3334 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3335 struct rt_msghdr *rtm_aux;
3337#define rtm m_rtmsg.m_rtm
3342 const int pid = getpid();
3344#ifdef TARGET_OPENBSD
3345 rtm_addrs = RTA_DST | RTA_NETMASK;
3347 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3350 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3351 bzero(&so_dst,
sizeof(so_dst));
3352 bzero(&so_mask,
sizeof(so_mask));
3353 bzero(&rtm,
sizeof(
struct rt_msghdr));
3355 rtm.rtm_type = RTM_GET;
3356 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3357 rtm.rtm_version = RTM_VERSION;
3358 rtm.rtm_seq = ++seq;
3359#ifdef TARGET_OPENBSD
3360 rtm.rtm_tableid = (u_short)getrtable();
3362 rtm.rtm_addrs = rtm_addrs;
3364 so_dst.sa_family = AF_INET;
3365 so_mask.sa_family = AF_INET;
3367#ifndef TARGET_SOLARIS
3368 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3369 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3372 NEXTADDR(RTA_DST, so_dst);
3373 NEXTADDR(RTA_NETMASK, so_mask);
3376 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3379 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3385 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3393 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3394 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3400 cp = (
char *)(rtm_aux + 1);
3401 if (rtm_aux->rtm_addrs)
3403 for (
unsigned int i = 1; i; i <<= 1)
3405 if (i & rtm_aux->rtm_addrs)
3407 sa = (
struct sockaddr *)cp;
3408 if (i == RTA_GATEWAY)
3412 else if (i == RTA_IFP)
3429 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3438 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3439 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3441 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3442 rgi->iface[adl->sdl_nlen] =
'\0';
3453 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3461 ifr.ifr_addr.sa_family = AF_INET;
3462 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3464 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3472 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3479#if defined(TARGET_SOLARIS)
3481 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3488 struct ifreq ifreq = { 0 };
3491 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3492 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3494 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3498 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3502 struct ifaddrs *ifap, *ifa;
3504 if (getifaddrs(&ifap) != 0)
3510 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3512 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3513 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3515 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3516 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3540#if defined(TARGET_SOLARIS)
3542#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3549 struct rtmsg m_rtmsg;
3552 struct sockaddr_in6 so_dst, so_mask;
3553 char *cp = m_rtmsg.m_space;
3554 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3555 struct rt_msghdr *rtm_aux;
3560 const int pid = getpid();
3562#ifdef TARGET_OPENBSD
3563 rtm_addrs = RTA_DST | RTA_NETMASK;
3565 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3568 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3569 bzero(&so_dst,
sizeof(so_dst));
3570 bzero(&so_mask,
sizeof(so_mask));
3571 bzero(&rtm,
sizeof(
struct rt_msghdr));
3573 rtm.rtm_type = RTM_GET;
3574 rtm.rtm_flags = RTF_UP;
3575 rtm.rtm_version = RTM_VERSION;
3576 rtm.rtm_seq = ++seq;
3577#ifdef TARGET_OPENBSD
3578 rtm.rtm_tableid = (u_short)getrtable();
3581 so_dst.sin6_family = AF_INET6;
3582 so_mask.sin6_family = AF_INET6;
3585 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3587 so_dst.sin6_addr = *dest;
3589 rtm_addrs &= ~RTA_NETMASK;
3592 rtm.rtm_addrs = rtm_addrs;
3594#ifndef TARGET_SOLARIS
3595 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3596 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3599 NEXTADDR(RTA_DST, so_dst);
3600 NEXTADDR(RTA_NETMASK, so_mask);
3603 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3606 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3612 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3620 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3621 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3628 cp = (
char *)(rtm_aux + 1);
3629 if (rtm_aux->rtm_addrs)
3631 for (
unsigned int i = 1; i; i <<= 1)
3633 if (i & rtm_aux->rtm_addrs)
3635 sa = (
struct sockaddr *)cp;
3636 if (i == RTA_GATEWAY)
3640 else if (i == RTA_IFP)
3656 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3657 struct in6_addr gw = s6->sin6_addr;
3659#ifndef TARGET_SOLARIS
3664 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3666 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3669 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3683 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3684 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3686 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3701#elif defined(TARGET_HAIKU)
3708 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3711 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3715 struct ifconf config;
3716 config.ifc_len =
sizeof(config.ifc_value);
3717 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3719 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3723 uint32 size = (uint32)config.ifc_value;
3729 void *
buffer = malloc(size);
3732 config.ifc_len = size;
3734 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3740 struct ifreq *
interface = (struct ifreq *)
buffer;
3741 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3743 while (interface < end)
3745 struct route_entry
route = interface->ifr_route;
3746 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3748 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3750 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3753 int32 address_size = 0;
3754 if (
route.destination != NULL)
3756 address_size +=
route.destination->sa_len;
3758 if (
route.mask != NULL)
3760 address_size +=
route.mask->sa_len;
3762 if (
route.gateway != NULL)
3764 address_size +=
route.gateway->sa_len;
3767 interface = (struct ifreq *)((addr_t)interface +
IF_NAMESIZE +
sizeof(
struct route_entry)
3816 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3825 const int addrlen =
sizeof(
in_addr_t) * 8;
3827 if ((network & netmask) == network)
3829 for (
int i = 0; i <= addrlen; ++i)
3832 if (mask == netmask)
3856 const int addrlen =
sizeof(
in_addr_t) * 8;
3858 for (i = 0; i <= addrlen; ++i)
3861 if (mask == netmask)
3892 bool succeed =
false;
3899 iplist = iplist->Next;
3971 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3973 const MIB_IPFORWARDROW *row = &rt->table[i];
3974 const in_addr_t net = ntohl(row->dwForwardDest);
3975 const in_addr_t mask = ntohl(row->dwForwardMask);
3976 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 print_bypass_addresses(const struct route_bypass *rb)
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.
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