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)
237 if (!
strcmp(
string,
"vpn_gateway"))
243 *out =
rl->spec.remote_endpoint;
256 else if (!
strcmp(
string,
"net_gateway"))
262 *out =
rl->ngi.gateway.addr;
267 " ROUTE: net_gateway undefined -- unable to get default gateway from system");
276 else if (!
strcmp(
string,
"remote_host"))
282 *out =
rl->spec.remote_host;
318 struct in_addr special = { 0 };
338 special.s_addr = htonl(special.s_addr);
339 char buf[INET_ADDRSTRLEN];
340 inet_ntop(AF_INET, &special, buf,
sizeof(buf));
346 NULL, AF_INET, network_list);
395 " ROUTE: " PACKAGE_NAME
396 " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
409 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
429 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
448 if (inet_pton(AF_INET6, r6o->
gateway, &
r6->gateway) != 1)
450 msg(
M_WARN, PACKAGE_NAME
"ROUTE6: cannot parse gateway spec '%s'", r6o->
gateway);
466 msg(
M_WARN, PACKAGE_NAME
" ROUTE: route metric for network %s (%s) must be >= 0",
486 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve route for host/network: %s",
493 const char *gateway,
const char *metric,
int table_id)
556 l2 = ((~gateway->netmask) + 1) >> 1;
558 r1->gateway = target;
560 r1->netmask = ~(l2 - 1);
574#ifndef TARGET_ANDROID
605 const char *remote_endpoint,
int default_metric,
in_addr_t remote_host,
631#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
649 bool defined =
false;
661 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve default gateway: %s",
684 struct addrinfo *netlist = NULL;
693 struct addrinfo *curele;
694 for (curele = netlist; curele; curele = curele->ai_next)
699 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
726 for (i = 0; bits >= 8; i++, bits -= 8)
728 if (
network->s6_addr[i] != host->s6_addr[i])
739 unsigned int mask = 0xff << (8 - bits);
741 if ((
network->s6_addr[i] & mask) == (host->s6_addr[i] & mask))
751 const char *remote_endpoint,
int default_metric,
752 const struct in6_addr *remote_host_ipv6,
struct env_set *
es,
757 bool need_remote_ipv6_route;
763 if (remote_host_ipv6)
769 if (default_metric >= 0)
782#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
801 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve VPN endpoint: %s",
810 need_remote_ipv6_route =
false;
827#ifndef TARGET_ANDROID
835 need_remote_ipv6_route =
true;
837 "ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
847 if (need_remote_ipv6_route)
855 r6->network = *remote_host_ipv6;
865 r6->iface = rl6->
rgi6.iface;
875 "ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n");
917 for (
int i = 0; i < rb->
n_bypass; ++i)
949 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
958 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
969 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
974#ifndef TARGET_ANDROID
1006 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1065 rl->
iflags &= ~RL_DID_LOCAL;
1096 rl->
iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
1112 "WARNING: OpenVPN was configured to add an IPv4 "
1113 "route. However, no IPv4 has been configured for %s, "
1114 "therefore the route installation may fail or may not work "
1119#ifdef ENABLE_MANAGEMENT
1144 "WARNING: OpenVPN was configured to add an IPv6 "
1145 "route. However, no IPv6 has been configured for %s, "
1146 "therefore the route installation may fail or may not work "
1184 rl->
iflags &= ~RL_ROUTES_ADDED;
1206 rl6->
iflags &= ~RL_ROUTES_ADDED;
1222 return "default (not set)";
1243 msg(msglevel,
" [redirect_default_gateway local=%d]", (rol->
flags &
RG_LOCAL) != 0);
1287 msg(msglevel,
"%s",
BSTR(&out));
1318 msg(msglevel,
"%s",
BSTR(&out));
1444 && netmask == 0xFFFFFFFF)
1454 for (i = 0; i < rgi->
n_addrs; ++i)
1469#if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1495#if !defined(TARGET_LINUX)
1497#if !defined(TARGET_AIX)
1509#if defined(TARGET_LINUX)
1510 const char *
iface = NULL;
1529 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1534 msg(
M_WARN,
"ERROR: Linux route add command failed");
1538#elif defined(TARGET_ANDROID)
1543 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1547 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1549 bool ret = management_android_control(
management,
"ROUTE", out);
1552#elif defined(_WIN32)
1556 network, netmask, gateway);
1569 const char *method =
"service";
1586 method =
"route.exe";
1591 method =
"ipapi [adaptive]";
1594 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1597 &
argv,
es, 0,
"ERROR: Windows route add command failed [adaptive]");
1600 method =
"route.exe";
1609 msg(
D_ROUTE,
"Route addition via %s %s", method,
1614#elif defined(TARGET_SOLARIS)
1638#elif defined(TARGET_FREEBSD)
1657#elif defined(TARGET_DRAGONFLY)
1676#elif defined(TARGET_DARWIN)
1703#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1722#elif defined(TARGET_AIX)
1726 argv_printf(&
argv,
"%s add -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
1732#elif defined(TARGET_HAIKU)
1735 argv_printf(&
argv,
"%s add %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
1743 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
1753 r->
flags &= ~RT_ADDED;
1763#if defined(__GNUC__) || defined(__clang__)
1764#pragma GCC diagnostic push
1765#pragma GCC diagnostic ignored "-Wconversion"
1776 int bits_to_clear = 128 -
r6->netbits;
1778 while (
byte >= 0 && bits_to_clear > 0)
1780 if (bits_to_clear >= 8)
1782 r6->network.s6_addr[
byte--] = 0;
1787 r6->network.s6_addr[
byte--] &= (0xff << bits_to_clear);
1798 bool gateway_needed =
false;
1810 if (
r6->iface != NULL)
1813 if (!IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1815 gateway_needed =
true;
1824#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1825 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1831 if (
r6->iface != NULL && gateway_needed
1832 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
1834 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
1836 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
1842 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1843 r6->metric, device);
1845 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu", network,
r6->netbits, gateway,
1862 gateway_needed =
true;
1865 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1868 "ROUTE6 WARNING: " PACKAGE_NAME
" needs a gateway "
1869 "parameter for a --route-ipv6 option and no default was set via "
1870 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1871 "IPv6 route to %s/%d.",
1872 network,
r6->netbits);
1877#if defined(TARGET_LINUX)
1881 metric =
r6->metric;
1885 int ret = net_route_v6_add(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
1886 device,
r6->table_id, metric);
1889 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1894 msg(
M_WARN,
"ERROR: Linux route add command failed");
1898#elif defined(TARGET_ANDROID)
1901 snprintf(out,
sizeof(out),
"%s/%d %s", network,
r6->netbits, device);
1905#elif defined(_WIN32)
1915#elif defined(TARGET_SOLARIS)
1928 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1940#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1957#elif defined(TARGET_DARWIN)
1959 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
1974#elif defined(TARGET_OPENBSD)
1976 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
1983#elif defined(TARGET_NETBSD)
1985 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1991#elif defined(TARGET_AIX)
1993 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1998#elif defined(TARGET_HAIKU)
2001 argv_printf(&
argv,
"%s add %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2002 gateway,
r6->netbits);
2009 "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");
2019 r6->flags &= ~RT_ADDED;
2033#if !defined(TARGET_LINUX)
2034 const char *network;
2035#if !defined(TARGET_AIX)
2036 const char *netmask;
2038#if !defined(TARGET_ANDROID)
2039 const char *gateway;
2054#if !defined(TARGET_LINUX)
2056#if !defined(TARGET_AIX)
2059#if !defined(TARGET_ANDROID)
2070#if defined(TARGET_LINUX)
2081 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2083#elif defined(_WIN32)
2086 network, netmask, gateway);
2093 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2098 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2109 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2112 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2115 "ERROR: Windows route delete command failed [adaptive]");
2124#elif defined(TARGET_SOLARIS)
2126 argv_printf(&
argv,
"%s delete %s -netmask %s %s", ROUTE_PATH, network, netmask, gateway);
2131#elif defined(TARGET_FREEBSD)
2133 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2138#elif defined(TARGET_DRAGONFLY)
2140 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2145#elif defined(TARGET_DARWIN)
2149 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s", ROUTE_PATH,
2150 network, netmask, rgi->iface);
2154 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2160#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2162 argv_printf(&
argv,
"%s delete -net %s %s -netmask %s", ROUTE_PATH, network, gateway, netmask);
2167#elif defined(TARGET_ANDROID)
2169 "needed. The VpnService API allows routes to be set "
2170 "on connect only and will clean up automatically.");
2171#elif defined(TARGET_AIX)
2175 argv_printf(&
argv,
"%s delete -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
2180#elif defined(TARGET_HAIKU)
2183 argv_printf(&
argv,
"%s delete %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
2190 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2194 r->
flags &= ~RT_ADDED;
2205 const char *network;
2213#if !defined(TARGET_LINUX)
2214 const char *gateway;
2216#if !defined(TARGET_SOLARIS)
2217 bool gateway_needed =
false;
2219 if (
r6->iface != NULL)
2222 gateway_needed =
true;
2231 gateway_needed =
true;
2240#if !defined(TARGET_LINUX) && !defined(_WIN32)
2244#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2245 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2251 if (
r6->iface != NULL && gateway_needed
2252 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
2254 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
2256 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
2261 msg(
D_ROUTE,
"delete_route_ipv6(%s/%d)", network,
r6->netbits);
2263#if defined(TARGET_LINUX)
2267 metric =
r6->metric;
2270 if (net_route_v6_del(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
2271 device,
r6->table_id, metric)
2274 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2277#elif defined(_WIN32)
2287#elif defined(TARGET_SOLARIS)
2291 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2296#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2312#elif defined(TARGET_DARWIN)
2314 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
2328#elif defined(TARGET_OPENBSD)
2330 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
2336#elif defined(TARGET_NETBSD)
2338 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2343#elif defined(TARGET_AIX)
2345 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2349#elif defined(TARGET_ANDROID)
2351 "needed. The VpnService API allows routes to be set "
2352 "on connect only and will clean up automatically.");
2353#elif defined(TARGET_HAIKU)
2356 argv_printf(&
argv,
"%s delete %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2357 gateway,
r6->netbits);
2363 "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");
2372#if defined(__GNUC__) || defined(__clang__)
2373#pragma GCC diagnostic pop
2383static const MIB_IPFORWARDTABLE *
2387 PMIB_IPFORWARDTABLE rt = NULL;
2390 status = GetIpForwardTable(NULL, &size, TRUE);
2391 if (
status == ERROR_INSUFFICIENT_BUFFER)
2393 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2394 status = GetIpForwardTable(rt, &size, TRUE);
2397 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2452 bool adapter_up =
false;
2466 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2478 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s", good, count, len,
2479 (
int)ret, ambig, adapter_up ?
"up" :
"down");
2485static const MIB_IPFORWARDROW *
2489 DWORD lowest_metric = MAXDWORD;
2490 const MIB_IPFORWARDROW *ret = NULL;
2495 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2497 const MIB_IPFORWARDROW *row = &routes->table[i];
2498 const in_addr_t net = ntohl(row->dwForwardDest);
2499 const in_addr_t mask = ntohl(row->dwForwardMask);
2500 const DWORD index = row->dwForwardIfIndex;
2501 const DWORD metric = row->dwForwardMetric1;
2505 (
int)index, (
int)metric);
2507 if (!net && !mask && metric < lowest_metric)
2510 lowest_metric = metric;
2536 DWORD best_if_index;
2542 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2545 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2550 msg(
D_ROUTE_DEBUG,
"GetBestInterfaceEx() returned if=%d", (
int)best_if_index);
2555 SOCKADDR_INET best_src;
2557 status = GetBestRoute2(&luid, best_if_index, NULL, dest, 0, best_route, &best_src);
2560 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2579 sa.si_family = AF_INET;
2580 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2583 MIB_IPFORWARD_ROW2 best_route;
2592 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2605 memcpy(rgi->
hwaddr, ai->Address, 6);
2609 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2629 bool on_tun =
false;
2634 ret = tun_adapter->Index;
2645 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2651 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2655 dmsg(
D_ROUTE_DEBUG,
"DEBUG: route find if: on_tun=%d count=%d index=%d", on_tun, count,
2674 SOCKADDR_INET DestinationAddress;
2675 CLEAR(DestinationAddress);
2676 DestinationAddress.si_family = AF_INET6;
2679 DestinationAddress.Ipv6.sin6_addr = *dest;
2682 MIB_IPFORWARD_ROW2 BestRoute;
2691 msg(
D_ROUTE,
"GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex,
2693 BestRoute.DestinationPrefix.PrefixLength,
2695 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d", (
int)BestRoute.Metric,
2696 (
int)BestRoute.Loopback, (
int)BestRoute.AutoconfigureAddress, (
int)BestRoute.Immortal);
2703 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr))
2725 MIB_IPFORWARDROW fr;
2727 fr.dwForwardDest = htonl(r->
network);
2728 fr.dwForwardMask = htonl(r->
netmask);
2729 fr.dwForwardPolicy = 0;
2730 fr.dwForwardNextHop = htonl(r->
gateway);
2731 fr.dwForwardIfIndex = if_index;
2732 fr.dwForwardType = 4;
2733 fr.dwForwardProto = 3;
2734 fr.dwForwardAge = 0;
2735 fr.dwForwardNextHopAS = 0;
2744 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2748 status = CreateIpForwardEntry(&fr);
2754 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2761 const unsigned int forward_metric_limit =
2764 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2769 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2771 status = CreateIpForwardEntry(&fr);
2775 "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2776 (
unsigned int)fr.dwForwardMetric1, (
unsigned int)fr.dwForwardType);
2780 else if (
status != ERROR_BAD_ARGUMENTS)
2790 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2797 "ERROR: route addition failed using CreateIpForwardEntry: "
2798 "%s [status=%u if_index=%u]",
2819 MIB_IPFORWARDROW fr;
2822 fr.dwForwardDest = htonl(r->
network);
2823 fr.dwForwardMask = htonl(r->
netmask);
2824 fr.dwForwardPolicy = 0;
2825 fr.dwForwardNextHop = htonl(r->
gateway);
2826 fr.dwForwardIfIndex = if_index;
2828 status = DeleteIpForwardEntry(&fr);
2836 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2863 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
2890 .prefix.ipv4.s_addr = htonl(r->
network),
2891 .gateway.ipv4.s_addr = htonl(r->
gateway),
2892 .iface = { .index = if_index, .name =
"" },
2896 if (
msg.prefix_len == -1)
2898 msg.prefix_len = 32;
2912 PMIB_IPFORWARD_ROW2 fwd_row;
2917 fwd_row->ValidLifetime = 0xffffffff;
2918 fwd_row->PreferredLifetime = 0xffffffff;
2919 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2921 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2922 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2923 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2924 fwd_row->NextHop.si_family = AF_INET6;
2925 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2934 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2942 if (err != NO_ERROR)
2946 fwd_row->InterfaceLuid = luid;
2947 fwd_row->InterfaceIndex = 0;
2952 err = CreateIpForwardEntry2(fwd_row);
2956 err = DeleteIpForwardEntry2(fwd_row);
2960 if (err != NO_ERROR)
2965 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2967 fwd_row->InterfaceIndex);
2971 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2976 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3008 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3014 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3020 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3056 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3060 (
int)
r->dwForwardIfIndex, (
int)
r->dwForwardType, (
int)
r->dwForwardProto,
3061 (
int)
r->dwForwardAge, (
int)
r->dwForwardNextHopAS, (
int)
r->dwForwardMetric1,
3062 (
int)
r->dwForwardMetric2, (
int)
r->dwForwardMetric3, (
int)
r->dwForwardMetric4,
3063 (
int)
r->dwForwardMetric5);
3077 msg(msglevel,
"SYSTEM ROUTING TABLE");
3080 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3088#elif defined(TARGET_ANDROID)
3103 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3105 strcpy(rgi->iface,
"android-gw");
3125 strcpy(rgi6->iface,
"android-gw");
3128#elif defined(TARGET_LINUX)
3135 char best_name[IFNAMSIZ];
3141 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3153 struct ifreq *ifr, *ifend;
3157 struct ifreq ifs[20];
3159 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3164 ifc.ifc_len =
sizeof(ifs);
3166 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3168 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3173 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3174 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3176 if (ifr->ifr_addr.sa_family == AF_INET)
3179 addr = ntohl(((
struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3182 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3185 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3189 if (!(ifreq.ifr_flags & IFF_UP))
3198 if (strcmp(ifreq.ifr_name, best_name))
3204 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3206 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3209 rgi->
flags &= ~RGI_ON_LINK;
3217 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3221 netmask = ntohl(((
struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3235 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3239 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3240 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3242 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3245 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3281 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3288 if (strlen(rgi6->iface) > 0)
3306#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3307 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3309#include <sys/types.h>
3310#include <sys/socket.h>
3311#include <netinet/in.h>
3312#include <net/route.h>
3313#include <net/if_dl.h>
3314#if !defined(TARGET_SOLARIS)
3320 struct rt_msghdr m_rtm;
3340#if defined(TARGET_DARWIN)
3341#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3342#elif defined(TARGET_NETBSD)
3343#define ROUNDUP(a) RT_ROUNDUP(a)
3345#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3348#if defined(TARGET_SOLARIS)
3349#define NEXTADDR(w, u) \
3350 if (rtm_addrs & (w)) \
3353 memmove(cp, &(u), l); \
3357#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3359#define NEXTADDR(w, u) \
3360 if (rtm_addrs & (w)) \
3362 l = ((struct sockaddr *)&(u))->sa_len; \
3363 memmove(cp, &(u), l); \
3367#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3370#define max(a, b) ((a) > (b) ? (a) : (b))
3372#if defined(__GNUC__) || defined(__clang__)
3373#pragma GCC diagnostic push
3374#pragma GCC diagnostic ignored "-Wconversion"
3381 struct rtmsg m_rtmsg;
3383 int seq, l, pid, rtm_addrs;
3385 struct sockaddr so_dst, so_mask;
3386 char *cp = m_rtmsg.m_space;
3387 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3388 struct rt_msghdr *rtm_aux;
3390#define rtm m_rtmsg.m_rtm
3397#ifdef TARGET_OPENBSD
3398 rtm_addrs = RTA_DST | RTA_NETMASK;
3400 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3403 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3404 bzero(&so_dst,
sizeof(so_dst));
3405 bzero(&so_mask,
sizeof(so_mask));
3406 bzero(&rtm,
sizeof(
struct rt_msghdr));
3408 rtm.rtm_type = RTM_GET;
3409 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3410 rtm.rtm_version = RTM_VERSION;
3411 rtm.rtm_seq = ++seq;
3412#ifdef TARGET_OPENBSD
3413 rtm.rtm_tableid = getrtable();
3415 rtm.rtm_addrs = rtm_addrs;
3417 so_dst.sa_family = AF_INET;
3418 so_mask.sa_family = AF_INET;
3420#ifndef TARGET_SOLARIS
3421 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3422 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3425 NEXTADDR(RTA_DST, so_dst);
3426 NEXTADDR(RTA_NETMASK, so_mask);
3428 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3431 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3437 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3444 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3445 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3451 cp = ((
char *)(rtm_aux + 1));
3452 if (rtm_aux->rtm_addrs)
3454 for (i = 1; i; i <<= 1)
3456 if (i & rtm_aux->rtm_addrs)
3458 sa = (
struct sockaddr *)cp;
3459 if (i == RTA_GATEWAY)
3463 else if (i == RTA_IFP)
3480 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3489 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3490 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3492 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3493 rgi->iface[adl->sdl_nlen] =
'\0';
3504 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3512 ifr.ifr_addr.sa_family = AF_INET;
3513 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3515 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3523 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3530#if defined(TARGET_SOLARIS)
3532 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3539 struct ifreq ifreq = { 0 };
3542 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3543 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3545 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3549 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3553 struct ifaddrs *ifap, *ifa;
3555 if (getifaddrs(&ifap) != 0)
3561 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3563 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3564 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3566 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3567 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3591#if defined(TARGET_SOLARIS)
3593#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3600 struct rtmsg m_rtmsg;
3602 int seq, l, pid, rtm_addrs;
3604 struct sockaddr_in6 so_dst, so_mask;
3605 char *cp = m_rtmsg.m_space;
3606 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3607 struct rt_msghdr *rtm_aux;
3614#ifdef TARGET_OPENBSD
3615 rtm_addrs = RTA_DST | RTA_NETMASK;
3617 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3620 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3621 bzero(&so_dst,
sizeof(so_dst));
3622 bzero(&so_mask,
sizeof(so_mask));
3623 bzero(&rtm,
sizeof(
struct rt_msghdr));
3625 rtm.rtm_type = RTM_GET;
3626 rtm.rtm_flags = RTF_UP;
3627 rtm.rtm_version = RTM_VERSION;
3628 rtm.rtm_seq = ++seq;
3629#ifdef TARGET_OPENBSD
3630 rtm.rtm_tableid = getrtable();
3633 so_dst.sin6_family = AF_INET6;
3634 so_mask.sin6_family = AF_INET6;
3637 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3639 so_dst.sin6_addr = *dest;
3641 rtm_addrs &= ~RTA_NETMASK;
3644 rtm.rtm_addrs = rtm_addrs;
3646#ifndef TARGET_SOLARIS
3647 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3648 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3651 NEXTADDR(RTA_DST, so_dst);
3652 NEXTADDR(RTA_NETMASK, so_mask);
3654 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3657 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3663 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3671 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3672 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3679 cp = ((
char *)(rtm_aux + 1));
3680 if (rtm_aux->rtm_addrs)
3682 for (i = 1; i; i <<= 1)
3684 if (i & rtm_aux->rtm_addrs)
3686 sa = (
struct sockaddr *)cp;
3687 if (i == RTA_GATEWAY)
3691 else if (i == RTA_IFP)
3707 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3708 struct in6_addr gw = s6->sin6_addr;
3710#ifndef TARGET_SOLARIS
3715 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3717 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3720 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3734 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3735 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3737 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3750#if defined(__GNUC__) || defined(__clang__)
3751#pragma GCC diagnostic pop
3756#elif defined(TARGET_HAIKU)
3763 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3766 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3770 struct ifconf config;
3771 config.ifc_len =
sizeof(config.ifc_value);
3772 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3774 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3778 uint32 size = (uint32)config.ifc_value;
3784 void *
buffer = malloc(size);
3787 config.ifc_len = size;
3789 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3795 struct ifreq *
interface = (struct ifreq *)
buffer;
3796 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3798 while (interface < end)
3800 struct route_entry
route = interface->ifr_route;
3801 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3803 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3805 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3808 int32 address_size = 0;
3809 if (
route.destination != NULL)
3811 address_size +=
route.destination->sa_len;
3813 if (
route.mask != NULL)
3815 address_size +=
route.mask->sa_len;
3817 if (
route.gateway != NULL)
3819 address_size +=
route.gateway->sa_len;
3822 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE + sizeof(struct route_entry)
3871 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3881 const int addrlen =
sizeof(
in_addr_t) * 8;
3883 if ((network & netmask) == network)
3885 for (i = 0; i <= addrlen; ++i)
3888 if (mask == netmask)
3912 const int addrlen =
sizeof(
in_addr_t) * 8;
3914 for (i = 0; i <= addrlen; ++i)
3917 if (mask == netmask)
3948 bool succeed =
false;
3955 iplist = iplist->Next;
4027 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4029 const MIB_IPFORWARDROW *row = &rt->table[i];
4030 const in_addr_t net = ntohl(row->dwForwardDest);
4031 const in_addr_t mask = ntohl(row->dwForwardMask);
4032 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