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
239 if (!
strcmp(
string,
"vpn_gateway"))
245 *out =
rl->spec.remote_endpoint;
258 else if (!
strcmp(
string,
"net_gateway"))
264 *out =
rl->ngi.gateway.addr;
269 " ROUTE: net_gateway undefined -- unable to get default gateway from system");
278 else if (!
strcmp(
string,
"remote_host"))
284 *out =
rl->spec.remote_host;
320 struct in_addr special = { 0 };
340 special.s_addr = htonl(special.s_addr);
341 char buf[INET_ADDRSTRLEN];
342 inet_ntop(AF_INET, &special, buf,
sizeof(buf));
348 NULL, AF_INET, network_list);
397 " ROUTE: " PACKAGE_NAME
398 " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
411 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
431 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
450 if (inet_pton(AF_INET6, r6o->
gateway, &
r6->gateway) != 1)
452 msg(
M_WARN, PACKAGE_NAME
"ROUTE6: cannot parse gateway spec '%s'", r6o->
gateway);
468 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
488 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
495 const char *gateway,
const char *metric,
int table_id)
558 l2 = ((~gateway->netmask) + 1) >> 1;
560 r1->gateway = target;
562 r1->netmask = ~(l2 - 1);
576#ifndef TARGET_ANDROID
607 const char *remote_endpoint,
int default_metric,
in_addr_t remote_host,
633#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
651 bool defined =
false;
663 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve default gateway: %s",
686 struct addrinfo *netlist = NULL;
695 struct addrinfo *curele;
696 for (curele = netlist; curele; curele = curele->ai_next)
701 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
728 for (i = 0; bits >= 8; i++, bits -= 8)
730 if (
network->s6_addr[i] != host->s6_addr[i])
741 unsigned int mask = 0xff << (8 - bits);
743 if ((
network->s6_addr[i] & mask) == (host->s6_addr[i] & mask))
753 const char *remote_endpoint,
int default_metric,
754 const struct in6_addr *remote_host_ipv6,
struct env_set *
es,
759 bool need_remote_ipv6_route;
765 if (remote_host_ipv6)
771 if (default_metric >= 0)
784#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
803 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve VPN endpoint: %s",
812 need_remote_ipv6_route =
false;
829#ifndef TARGET_ANDROID
837 need_remote_ipv6_route =
true;
839 "ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
849 if (need_remote_ipv6_route)
857 r6->network = *remote_host_ipv6;
867 r6->iface = rl6->
rgi6.iface;
877 "ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n");
919 for (
int i = 0; i < rb->
n_bypass; ++i)
951 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
960 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
971 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
976#ifndef TARGET_ANDROID
1008 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1067 rl->
iflags &= ~RL_DID_LOCAL;
1098 rl->
iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
1114 "WARNING: OpenVPN was configured to add an IPv4 "
1115 "route. However, no IPv4 has been configured for %s, "
1116 "therefore the route installation may fail or may not work "
1121#ifdef ENABLE_MANAGEMENT
1146 "WARNING: OpenVPN was configured to add an IPv6 "
1147 "route. However, no IPv6 has been configured for %s, "
1148 "therefore the route installation may fail or may not work "
1186 rl->
iflags &= ~RL_ROUTES_ADDED;
1208 rl6->
iflags &= ~RL_ROUTES_ADDED;
1224 return "default (not set)";
1245 msg(msglevel,
" [redirect_default_gateway local=%d]", (rol->
flags &
RG_LOCAL) != 0);
1289 msg(msglevel,
"%s",
BSTR(&out));
1320 msg(msglevel,
"%s",
BSTR(&out));
1446 && netmask == 0xFFFFFFFF)
1456 for (i = 0; i < rgi->
n_addrs; ++i)
1471#if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1497#if !defined(TARGET_LINUX)
1499#if !defined(TARGET_AIX)
1511#if defined(TARGET_LINUX)
1512 const char *
iface = NULL;
1531 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1536 msg(
M_WARN,
"ERROR: Linux route add command failed");
1540#elif defined(TARGET_ANDROID)
1545 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1549 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1551 bool ret = management_android_control(
management,
"ROUTE", out);
1554#elif defined(_WIN32)
1558 network, netmask, gateway);
1571 const char *method =
"service";
1588 method =
"route.exe";
1593 method =
"ipapi [adaptive]";
1596 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1599 &
argv,
es, 0,
"ERROR: Windows route add command failed [adaptive]");
1602 method =
"route.exe";
1611 msg(
D_ROUTE,
"Route addition via %s %s", method,
1616#elif defined(TARGET_SOLARIS)
1640#elif defined(TARGET_FREEBSD)
1659#elif defined(TARGET_DRAGONFLY)
1678#elif defined(TARGET_DARWIN)
1705#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1724#elif defined(TARGET_AIX)
1728 argv_printf(&
argv,
"%s add -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
1734#elif defined(TARGET_HAIKU)
1737 argv_printf(&
argv,
"%s add %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
1745 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
1755 r->
flags &= ~RT_ADDED;
1765#if defined(__GNUC__) || defined(__clang__)
1766#pragma GCC diagnostic push
1767#pragma GCC diagnostic ignored "-Wconversion"
1778 int bits_to_clear = 128 -
r6->netbits;
1780 while (
byte >= 0 && bits_to_clear > 0)
1782 if (bits_to_clear >= 8)
1784 r6->network.s6_addr[
byte--] = 0;
1789 r6->network.s6_addr[
byte--] &= (0xff << bits_to_clear);
1800 bool gateway_needed =
false;
1812 if (
r6->iface != NULL)
1815 if (!IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1817 gateway_needed =
true;
1826#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1827 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1833 if (
r6->iface != NULL && gateway_needed
1834 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
1836 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
1838 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
1844 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1845 r6->metric, device);
1847 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu", network,
r6->netbits, gateway,
1864 gateway_needed =
true;
1867 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1870 "ROUTE6 WARNING: " PACKAGE_NAME
" needs a gateway "
1871 "parameter for a --route-ipv6 option and no default was set via "
1872 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1873 "IPv6 route to %s/%d.",
1874 network,
r6->netbits);
1879#if defined(TARGET_LINUX)
1883 metric =
r6->metric;
1887 int ret = net_route_v6_add(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
1888 device,
r6->table_id, metric);
1891 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1896 msg(
M_WARN,
"ERROR: Linux route add command failed");
1900#elif defined(TARGET_ANDROID)
1903 snprintf(out,
sizeof(out),
"%s/%d %s", network,
r6->netbits, device);
1907#elif defined(_WIN32)
1917#elif defined(TARGET_SOLARIS)
1930 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1942#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1959#elif defined(TARGET_DARWIN)
1961 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
1976#elif defined(TARGET_OPENBSD)
1978 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
1985#elif defined(TARGET_NETBSD)
1987 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1993#elif defined(TARGET_AIX)
1995 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2000#elif defined(TARGET_HAIKU)
2003 argv_printf(&
argv,
"%s add %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2004 gateway,
r6->netbits);
2011 "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");
2021 r6->flags &= ~RT_ADDED;
2035#if !defined(TARGET_LINUX)
2036 const char *network;
2037#if !defined(TARGET_AIX)
2038 const char *netmask;
2040 const char *gateway;
2054#if !defined(TARGET_LINUX)
2056#if !defined(TARGET_AIX)
2068#if defined(TARGET_LINUX)
2079 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2081#elif defined(_WIN32)
2084 network, netmask, gateway);
2091 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2096 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2107 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2110 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2113 "ERROR: Windows route delete command failed [adaptive]");
2122#elif defined(TARGET_SOLARIS)
2124 argv_printf(&
argv,
"%s delete %s -netmask %s %s", ROUTE_PATH, network, netmask, gateway);
2129#elif defined(TARGET_FREEBSD)
2131 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2136#elif defined(TARGET_DRAGONFLY)
2138 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2143#elif defined(TARGET_DARWIN)
2147 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s", ROUTE_PATH,
2148 network, netmask, rgi->iface);
2152 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2158#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2160 argv_printf(&
argv,
"%s delete -net %s %s -netmask %s", ROUTE_PATH, network, gateway, netmask);
2165#elif defined(TARGET_ANDROID)
2169 "needed. The VpnService API allows routes to be set "
2170 "on connect only and will clean up automatically. "
2171 "Tried to delete route %s netmask %s gateway %s",
2172 network, netmask, gateway);
2173#elif defined(TARGET_AIX)
2177 argv_printf(&
argv,
"%s delete -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
2182#elif defined(TARGET_HAIKU)
2185 argv_printf(&
argv,
"%s delete %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
2192 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2196 r->
flags &= ~RT_ADDED;
2207 const char *network;
2215#if !defined(TARGET_LINUX)
2216 const char *gateway;
2218#if !defined(TARGET_SOLARIS)
2219 bool gateway_needed =
false;
2221 if (
r6->iface != NULL)
2224 gateway_needed =
true;
2233 gateway_needed =
true;
2242#if !defined(TARGET_LINUX) && !defined(_WIN32)
2246#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2247 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2253 if (
r6->iface != NULL && gateway_needed
2254 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
2256 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
2258 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
2263 msg(
D_ROUTE,
"delete_route_ipv6(%s/%d)", network,
r6->netbits);
2265#if defined(TARGET_LINUX)
2269 metric =
r6->metric;
2272 if (net_route_v6_del(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
2273 device,
r6->table_id, metric)
2276 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2279#elif defined(_WIN32)
2289#elif defined(TARGET_SOLARIS)
2293 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2298#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2314#elif defined(TARGET_DARWIN)
2316 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
2330#elif defined(TARGET_OPENBSD)
2332 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
2338#elif defined(TARGET_NETBSD)
2340 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2345#elif defined(TARGET_AIX)
2347 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2351#elif defined(TARGET_ANDROID)
2353 "needed. The VpnService API allows routes to be set "
2354 "on connect only and will clean up automatically. "
2355 "Tried to delete %s gateway %s",
2357 gateway_needed ? gateway :
"(not needed)");
2358#elif defined(TARGET_HAIKU)
2361 argv_printf(&
argv,
"%s delete %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2362 gateway,
r6->netbits);
2368 "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");
2377#if defined(__GNUC__) || defined(__clang__)
2378#pragma GCC diagnostic pop
2388static const MIB_IPFORWARDTABLE *
2392 PMIB_IPFORWARDTABLE rt = NULL;
2395 status = GetIpForwardTable(NULL, &size, TRUE);
2396 if (
status == ERROR_INSUFFICIENT_BUFFER)
2398 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2399 status = GetIpForwardTable(rt, &size, TRUE);
2402 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2457 bool adapter_up =
false;
2471 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2483 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s", good, count, len,
2484 (
int)ret, ambig, adapter_up ?
"up" :
"down");
2490static const MIB_IPFORWARDROW *
2494 DWORD lowest_metric = MAXDWORD;
2495 const MIB_IPFORWARDROW *ret = NULL;
2500 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2502 const MIB_IPFORWARDROW *row = &routes->table[i];
2503 const in_addr_t net = ntohl(row->dwForwardDest);
2504 const in_addr_t mask = ntohl(row->dwForwardMask);
2505 const DWORD index = row->dwForwardIfIndex;
2506 const DWORD metric = row->dwForwardMetric1;
2510 (
int)index, (
int)metric);
2512 if (!net && !mask && metric < lowest_metric)
2515 lowest_metric = metric;
2541 DWORD best_if_index;
2547 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2550 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2555 msg(
D_ROUTE_DEBUG,
"GetBestInterfaceEx() returned if=%d", (
int)best_if_index);
2560 SOCKADDR_INET best_src;
2562 status = GetBestRoute2(&luid, best_if_index, NULL, dest, 0, best_route, &best_src);
2565 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2584 sa.si_family = AF_INET;
2585 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2588 MIB_IPFORWARD_ROW2 best_route;
2597 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2610 memcpy(rgi->
hwaddr, ai->Address, 6);
2614 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2634 bool on_tun =
false;
2639 ret = tun_adapter->Index;
2650 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2656 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2660 dmsg(
D_ROUTE_DEBUG,
"DEBUG: route find if: on_tun=%d count=%d index=%d", on_tun, count,
2679 SOCKADDR_INET DestinationAddress;
2680 CLEAR(DestinationAddress);
2681 DestinationAddress.si_family = AF_INET6;
2684 DestinationAddress.Ipv6.sin6_addr = *dest;
2687 MIB_IPFORWARD_ROW2 BestRoute;
2696 msg(
D_ROUTE,
"GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex,
2698 BestRoute.DestinationPrefix.PrefixLength,
2700 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d", (
int)BestRoute.Metric,
2701 (
int)BestRoute.Loopback, (
int)BestRoute.AutoconfigureAddress, (
int)BestRoute.Immortal);
2708 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr))
2730 MIB_IPFORWARDROW fr;
2732 fr.dwForwardDest = htonl(r->
network);
2733 fr.dwForwardMask = htonl(r->
netmask);
2734 fr.dwForwardPolicy = 0;
2735 fr.dwForwardNextHop = htonl(r->
gateway);
2736 fr.dwForwardIfIndex = if_index;
2737 fr.dwForwardType = 4;
2738 fr.dwForwardProto = 3;
2739 fr.dwForwardAge = 0;
2740 fr.dwForwardNextHopAS = 0;
2749 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2753 status = CreateIpForwardEntry(&fr);
2759 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2766 const unsigned int forward_metric_limit =
2769 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2774 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2776 status = CreateIpForwardEntry(&fr);
2780 "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2781 (
unsigned int)fr.dwForwardMetric1, (
unsigned int)fr.dwForwardType);
2785 else if (
status != ERROR_BAD_ARGUMENTS)
2795 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2802 "ERROR: route addition failed using CreateIpForwardEntry: "
2803 "%s [status=%u if_index=%u]",
2824 MIB_IPFORWARDROW fr;
2827 fr.dwForwardDest = htonl(r->
network);
2828 fr.dwForwardMask = htonl(r->
netmask);
2829 fr.dwForwardPolicy = 0;
2830 fr.dwForwardNextHop = htonl(r->
gateway);
2831 fr.dwForwardIfIndex = if_index;
2833 status = DeleteIpForwardEntry(&fr);
2841 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2868 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
2895 .prefix.ipv4.s_addr = htonl(r->
network),
2896 .gateway.ipv4.s_addr = htonl(r->
gateway),
2897 .iface = { .index = if_index, .name =
"" },
2901 if (
msg.prefix_len == -1)
2903 msg.prefix_len = 32;
2917 PMIB_IPFORWARD_ROW2 fwd_row;
2922 fwd_row->ValidLifetime = 0xffffffff;
2923 fwd_row->PreferredLifetime = 0xffffffff;
2924 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2926 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2927 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2928 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2929 fwd_row->NextHop.si_family = AF_INET6;
2930 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2939 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2947 if (err != NO_ERROR)
2951 fwd_row->InterfaceLuid = luid;
2952 fwd_row->InterfaceIndex = 0;
2957 err = CreateIpForwardEntry2(fwd_row);
2961 err = DeleteIpForwardEntry2(fwd_row);
2965 if (err != NO_ERROR)
2970 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2972 fwd_row->InterfaceIndex);
2976 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2981 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3013 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3019 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3025 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3061 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3065 (
int)
r->dwForwardIfIndex, (
int)
r->dwForwardType, (
int)
r->dwForwardProto,
3066 (
int)
r->dwForwardAge, (
int)
r->dwForwardNextHopAS, (
int)
r->dwForwardMetric1,
3067 (
int)
r->dwForwardMetric2, (
int)
r->dwForwardMetric3, (
int)
r->dwForwardMetric4,
3068 (
int)
r->dwForwardMetric5);
3082 msg(msglevel,
"SYSTEM ROUTING TABLE");
3085 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3093#elif defined(TARGET_ANDROID)
3108 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3110 strcpy(rgi->iface,
"android-gw");
3130 strcpy(rgi6->iface,
"android-gw");
3133#elif defined(TARGET_LINUX)
3140 char best_name[IFNAMSIZ];
3146 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3158 struct ifreq *ifr, *ifend;
3162 struct ifreq ifs[20];
3164 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3169 ifc.ifc_len =
sizeof(ifs);
3171 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3173 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3178 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3179 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3181 if (ifr->ifr_addr.sa_family == AF_INET)
3184 addr = ntohl(((
struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3187 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3190 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3194 if (!(ifreq.ifr_flags & IFF_UP))
3203 if (strcmp(ifreq.ifr_name, best_name))
3209 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3211 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3214 rgi->
flags &= ~RGI_ON_LINK;
3222 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3226 netmask = ntohl(((
struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3240 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3244 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3245 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3247 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3250 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3286 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3293 if (strlen(rgi6->iface) > 0)
3311#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3312 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3314#include <sys/types.h>
3315#include <sys/socket.h>
3316#include <netinet/in.h>
3317#include <net/route.h>
3318#include <net/if_dl.h>
3319#if !defined(TARGET_SOLARIS)
3325 struct rt_msghdr m_rtm;
3345#if defined(TARGET_DARWIN)
3346#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3347#elif defined(TARGET_NETBSD)
3348#define ROUNDUP(a) RT_ROUNDUP(a)
3350#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3353#if defined(TARGET_SOLARIS)
3354#define NEXTADDR(w, u) \
3355 if (rtm_addrs & (w)) \
3358 memmove(cp, &(u), l); \
3362#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3364#define NEXTADDR(w, u) \
3365 if (rtm_addrs & (w)) \
3367 l = ((struct sockaddr *)&(u))->sa_len; \
3368 memmove(cp, &(u), l); \
3372#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3375#define max(a, b) ((a) > (b) ? (a) : (b))
3377#if defined(__GNUC__) || defined(__clang__)
3378#pragma GCC diagnostic push
3379#pragma GCC diagnostic ignored "-Wconversion"
3386 struct rtmsg m_rtmsg;
3388 int seq, l, pid, rtm_addrs;
3390 struct sockaddr so_dst, so_mask;
3391 char *cp = m_rtmsg.m_space;
3392 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3393 struct rt_msghdr *rtm_aux;
3395#define rtm m_rtmsg.m_rtm
3402#ifdef TARGET_OPENBSD
3403 rtm_addrs = RTA_DST | RTA_NETMASK;
3405 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3408 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3409 bzero(&so_dst,
sizeof(so_dst));
3410 bzero(&so_mask,
sizeof(so_mask));
3411 bzero(&rtm,
sizeof(
struct rt_msghdr));
3413 rtm.rtm_type = RTM_GET;
3414 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3415 rtm.rtm_version = RTM_VERSION;
3416 rtm.rtm_seq = ++seq;
3417#ifdef TARGET_OPENBSD
3418 rtm.rtm_tableid = getrtable();
3420 rtm.rtm_addrs = rtm_addrs;
3422 so_dst.sa_family = AF_INET;
3423 so_mask.sa_family = AF_INET;
3425#ifndef TARGET_SOLARIS
3426 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3427 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3430 NEXTADDR(RTA_DST, so_dst);
3431 NEXTADDR(RTA_NETMASK, so_mask);
3433 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3436 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3442 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3449 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3450 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3456 cp = ((
char *)(rtm_aux + 1));
3457 if (rtm_aux->rtm_addrs)
3459 for (i = 1; i; i <<= 1)
3461 if (i & rtm_aux->rtm_addrs)
3463 sa = (
struct sockaddr *)cp;
3464 if (i == RTA_GATEWAY)
3468 else if (i == RTA_IFP)
3485 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3494 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3495 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3497 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3498 rgi->iface[adl->sdl_nlen] =
'\0';
3509 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3517 ifr.ifr_addr.sa_family = AF_INET;
3518 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3520 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3528 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3535#if defined(TARGET_SOLARIS)
3537 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3544 struct ifreq ifreq = { 0 };
3547 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3548 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3550 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3554 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3558 struct ifaddrs *ifap, *ifa;
3560 if (getifaddrs(&ifap) != 0)
3566 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3568 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3569 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3571 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3572 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3596#if defined(TARGET_SOLARIS)
3598#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3605 struct rtmsg m_rtmsg;
3607 int seq, l, pid, rtm_addrs;
3609 struct sockaddr_in6 so_dst, so_mask;
3610 char *cp = m_rtmsg.m_space;
3611 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3612 struct rt_msghdr *rtm_aux;
3619#ifdef TARGET_OPENBSD
3620 rtm_addrs = RTA_DST | RTA_NETMASK;
3622 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3625 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3626 bzero(&so_dst,
sizeof(so_dst));
3627 bzero(&so_mask,
sizeof(so_mask));
3628 bzero(&rtm,
sizeof(
struct rt_msghdr));
3630 rtm.rtm_type = RTM_GET;
3631 rtm.rtm_flags = RTF_UP;
3632 rtm.rtm_version = RTM_VERSION;
3633 rtm.rtm_seq = ++seq;
3634#ifdef TARGET_OPENBSD
3635 rtm.rtm_tableid = getrtable();
3638 so_dst.sin6_family = AF_INET6;
3639 so_mask.sin6_family = AF_INET6;
3642 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3644 so_dst.sin6_addr = *dest;
3646 rtm_addrs &= ~RTA_NETMASK;
3649 rtm.rtm_addrs = rtm_addrs;
3651#ifndef TARGET_SOLARIS
3652 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3653 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3656 NEXTADDR(RTA_DST, so_dst);
3657 NEXTADDR(RTA_NETMASK, so_mask);
3659 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3662 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3668 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3676 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3677 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3684 cp = ((
char *)(rtm_aux + 1));
3685 if (rtm_aux->rtm_addrs)
3687 for (i = 1; i; i <<= 1)
3689 if (i & rtm_aux->rtm_addrs)
3691 sa = (
struct sockaddr *)cp;
3692 if (i == RTA_GATEWAY)
3696 else if (i == RTA_IFP)
3712 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3713 struct in6_addr gw = s6->sin6_addr;
3715#ifndef TARGET_SOLARIS
3720 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3722 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3725 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3739 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3740 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3742 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3755#if defined(__GNUC__) || defined(__clang__)
3756#pragma GCC diagnostic pop
3761#elif defined(TARGET_HAIKU)
3768 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3771 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3775 struct ifconf config;
3776 config.ifc_len =
sizeof(config.ifc_value);
3777 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3779 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3783 uint32 size = (uint32)config.ifc_value;
3789 void *
buffer = malloc(size);
3792 config.ifc_len = size;
3794 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3800 struct ifreq *
interface = (struct ifreq *)
buffer;
3801 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3803 while (interface < end)
3805 struct route_entry
route = interface->ifr_route;
3806 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3808 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3810 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3813 int32 address_size = 0;
3814 if (
route.destination != NULL)
3816 address_size +=
route.destination->sa_len;
3818 if (
route.mask != NULL)
3820 address_size +=
route.mask->sa_len;
3822 if (
route.gateway != NULL)
3824 address_size +=
route.gateway->sa_len;
3827 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE + sizeof(struct route_entry)
3876 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3886 const int addrlen =
sizeof(
in_addr_t) * 8;
3888 if ((network & netmask) == network)
3890 for (i = 0; i <= addrlen; ++i)
3893 if (mask == netmask)
3917 const int addrlen =
sizeof(
in_addr_t) * 8;
3919 for (i = 0; i <= addrlen; ++i)
3922 if (mask == netmask)
3953 bool succeed =
false;
3960 iplist = iplist->Next;
4032 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4034 const MIB_IPFORWARDROW *row = &rt->table[i];
4035 const in_addr_t net = ntohl(row->dwForwardDest);
4036 const in_addr_t mask = ntohl(row->dwForwardMask);
4037 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,...)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
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)
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
#define ALLOC_OBJ_GC(dptr, type, gc)
static void strncpynt(char *dest, const char *src, size_t maxlen)
static void check_malloc_return(void *p)
static void gc_free(struct gc_arena *a)
static void gc_freeaddrinfo_callback(void *addr)
static struct gc_arena gc_new(void)
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 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 const char * route_string(const struct route_ipv4 *r, struct gc_arena *gc)
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 void print_route(const struct route_ipv4 *r, msglvl_t msglevel)
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)
void print_routes(const struct route_list *rl, msglvl_t msglevel)
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)
#define TUN_ADAPTER_INDEX_INVALID
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