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->rgi.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)
647 bool defined =
false;
659 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve default gateway: %s",
682 struct addrinfo *netlist = NULL;
691 struct addrinfo *curele;
692 for (curele = netlist; curele; curele = curele->ai_next)
697 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
720 unsigned int bits =
r6->netbits;
729 for (
i = 0; bits >= 8;
i++, bits -= 8)
731 if (
r6->network.s6_addr[
i] != host->s6_addr[
i])
742 mask = 0xff << (8 - bits);
744 if ((
r6->network.s6_addr[
i] & mask) == (host->s6_addr[
i] & mask))
754 const char *remote_endpoint,
int default_metric,
755 const struct in6_addr *remote_host_ipv6,
struct env_set *
es,
760 bool need_remote_ipv6_route;
766 if (remote_host_ipv6)
772 if (default_metric >= 0)
785#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
802 msg(
M_WARN, PACKAGE_NAME
" ROUTE: failed to parse/resolve VPN endpoint: %s",
811 need_remote_ipv6_route =
false;
828#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");
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(level,
" [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)
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;
1772 int bits_to_clear = 128 -
r6->netbits;
1774 while (
byte >= 0 && bits_to_clear > 0)
1776 if (bits_to_clear >= 8)
1778 r6->network.s6_addr[
byte--] = 0;
1783 r6->network.s6_addr[
byte--] &= (0xff << bits_to_clear);
1794 bool gateway_needed =
false;
1806 if (
r6->iface != NULL)
1809 if (!IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1811 gateway_needed =
true;
1820#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1821 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1827 if (
r6->iface != NULL && gateway_needed
1828 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
1830 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
1832 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
1838 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1839 r6->metric, device);
1841 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu", network,
r6->netbits, gateway,
1858 gateway_needed =
true;
1861 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1864 "ROUTE6 WARNING: " PACKAGE_NAME
" needs a gateway "
1865 "parameter for a --route-ipv6 option and no default was set via "
1866 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1867 "IPv6 route to %s/%d.",
1868 network,
r6->netbits);
1873#if defined(TARGET_LINUX)
1877 metric =
r6->metric;
1881 int ret = net_route_v6_add(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
1882 device,
r6->table_id, metric);
1885 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1890 msg(
M_WARN,
"ERROR: Linux route add command failed");
1894#elif defined(TARGET_ANDROID)
1897 snprintf(out,
sizeof(out),
"%s/%d %s", network,
r6->netbits, device);
1901#elif defined(_WIN32)
1911#elif defined(TARGET_SOLARIS)
1924 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1936#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1953#elif defined(TARGET_DARWIN)
1955 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
1970#elif defined(TARGET_OPENBSD)
1972 argv_printf(&
argv,
"%s add -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
1979#elif defined(TARGET_NETBSD)
1981 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1987#elif defined(TARGET_AIX)
1989 argv_printf(&
argv,
"%s add -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
1994#elif defined(TARGET_HAIKU)
1997 argv_printf(&
argv,
"%s add %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
1998 gateway,
r6->netbits);
2005 "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");
2015 r6->flags &= ~RT_ADDED;
2029#if !defined(TARGET_LINUX)
2030 const char *network;
2031#if !defined(TARGET_AIX)
2032 const char *netmask;
2034#if !defined(TARGET_ANDROID)
2035 const char *gateway;
2050#if !defined(TARGET_LINUX)
2052#if !defined(TARGET_AIX)
2055#if !defined(TARGET_ANDROID)
2066#if defined(TARGET_LINUX)
2077 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2079#elif defined(_WIN32)
2082 network, netmask, gateway);
2089 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2094 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2105 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2108 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2111 "ERROR: Windows route delete command failed [adaptive]");
2120#elif defined(TARGET_SOLARIS)
2122 argv_printf(&
argv,
"%s delete %s -netmask %s %s", ROUTE_PATH, network, netmask, gateway);
2127#elif defined(TARGET_FREEBSD)
2129 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2134#elif defined(TARGET_DRAGONFLY)
2136 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2141#elif defined(TARGET_DARWIN)
2145 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s", ROUTE_PATH,
2146 network, netmask, rgi->iface);
2150 argv_printf(&
argv,
"%s delete -net %s %s %s", ROUTE_PATH, network, gateway, netmask);
2156#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2158 argv_printf(&
argv,
"%s delete -net %s %s -netmask %s", ROUTE_PATH, network, gateway, netmask);
2163#elif defined(TARGET_ANDROID)
2165 "needed. The VpnService API allows routes to be set "
2166 "on connect only and will clean up automatically.");
2167#elif defined(TARGET_AIX)
2171 argv_printf(&
argv,
"%s delete -net %s/%d %s", ROUTE_PATH, network, netbits, gateway);
2176#elif defined(TARGET_HAIKU)
2179 argv_printf(&
argv,
"%s delete %s inet %s gw %s netmask %s", ROUTE_PATH, rgi->iface, network,
2186 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2190 r->
flags &= ~RT_ADDED;
2201 const char *network;
2209#if !defined(TARGET_LINUX)
2210 const char *gateway;
2212#if !defined(TARGET_SOLARIS)
2213 bool gateway_needed =
false;
2215 if (
r6->iface != NULL)
2218 gateway_needed =
true;
2226 gateway_needed =
true;
2235#if !defined(TARGET_LINUX) && !defined(_WIN32)
2239#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2240 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2246 if (
r6->iface != NULL && gateway_needed
2247 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
2249 int len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
2251 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
2256 msg(
D_ROUTE,
"delete_route_ipv6(%s/%d)", network,
r6->netbits);
2258#if defined(TARGET_LINUX)
2262 metric =
r6->metric;
2265 if (net_route_v6_del(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
2266 device,
r6->table_id, metric)
2269 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2272#elif defined(_WIN32)
2282#elif defined(TARGET_SOLARIS)
2286 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2291#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2307#elif defined(TARGET_DARWIN)
2309 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d", ROUTE_PATH, network,
r6->netbits);
2323#elif defined(TARGET_OPENBSD)
2325 argv_printf(&
argv,
"%s delete -inet6 %s -prefixlen %d %s", ROUTE_PATH, network,
r6->netbits,
2331#elif defined(TARGET_NETBSD)
2333 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2338#elif defined(TARGET_AIX)
2340 argv_printf(&
argv,
"%s delete -inet6 %s/%d %s", ROUTE_PATH, network,
r6->netbits, gateway);
2344#elif defined(TARGET_ANDROID)
2346 "needed. The VpnService API allows routes to be set "
2347 "on connect only and will clean up automatically.");
2348#elif defined(TARGET_HAIKU)
2351 argv_printf(&
argv,
"%s delete %s inet6 %s gw %s prefixlen %d", ROUTE_PATH,
r6->iface, network,
2352 gateway,
r6->netbits);
2358 "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");
2374static const MIB_IPFORWARDTABLE *
2378 PMIB_IPFORWARDTABLE rt = NULL;
2381 status = GetIpForwardTable(NULL, &size, TRUE);
2382 if (
status == ERROR_INSUFFICIENT_BUFFER)
2384 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2385 status = GetIpForwardTable(rt, &size, TRUE);
2388 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2397test_route(
const IP_ADAPTER_INFO *adapters,
const in_addr_t gateway, DWORD *index)
2410 const in_addr_t gateway)
2443 bool adapter_up =
false;
2457 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2469 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s", good, count, len,
2470 (
int)ret, ambig, adapter_up ?
"up" :
"down");
2476static const MIB_IPFORWARDROW *
2480 DWORD lowest_metric = MAXDWORD;
2481 const MIB_IPFORWARDROW *ret = NULL;
2486 for (DWORD
i = 0;
i < routes->dwNumEntries; ++
i)
2488 const MIB_IPFORWARDROW *row = &routes->table[
i];
2489 const in_addr_t net = ntohl(row->dwForwardDest);
2490 const in_addr_t mask = ntohl(row->dwForwardMask);
2491 const DWORD index = row->dwForwardIfIndex;
2492 const DWORD metric = row->dwForwardMetric1;
2496 (
int)index, (
int)metric);
2498 if (!net && !mask && metric < lowest_metric)
2501 lowest_metric = metric;
2527 DWORD best_if_index;
2533 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2536 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2541 msg(
D_ROUTE_DEBUG,
"GetBestInterfaceEx() returned if=%d", (
int)best_if_index);
2546 SOCKADDR_INET best_src;
2548 status = GetBestRoute2(&luid, best_if_index, NULL, dest, 0, best_route, &best_src);
2551 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2570 sa.si_family = AF_INET;
2571 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2574 MIB_IPFORWARD_ROW2 best_route;
2583 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2596 memcpy(rgi->
hwaddr, ai->Address, 6);
2600 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2620 bool on_tun =
false;
2625 ret = tun_adapter->Index;
2636 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2642 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2646 dmsg(
D_ROUTE_DEBUG,
"DEBUG: route find if: on_tun=%d count=%d index=%d", on_tun, count,
2665 SOCKADDR_INET DestinationAddress;
2666 CLEAR(DestinationAddress);
2667 DestinationAddress.si_family = AF_INET6;
2670 DestinationAddress.Ipv6.sin6_addr = *dest;
2673 MIB_IPFORWARD_ROW2 BestRoute;
2682 msg(
D_ROUTE,
"GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex,
2684 BestRoute.DestinationPrefix.PrefixLength,
2686 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d", (
int)BestRoute.Metric,
2687 (
int)BestRoute.Loopback, (
int)BestRoute.AutoconfigureAddress, (
int)BestRoute.Immortal);
2694 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr))
2716 MIB_IPFORWARDROW fr;
2718 fr.dwForwardDest = htonl(r->
network);
2719 fr.dwForwardMask = htonl(r->
netmask);
2720 fr.dwForwardPolicy = 0;
2721 fr.dwForwardNextHop = htonl(r->
gateway);
2722 fr.dwForwardIfIndex = if_index;
2723 fr.dwForwardType = 4;
2724 fr.dwForwardProto = 3;
2725 fr.dwForwardAge = 0;
2726 fr.dwForwardNextHopAS = 0;
2735 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2739 status = CreateIpForwardEntry(&fr);
2745 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2752 const unsigned int forward_metric_limit =
2755 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2760 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2762 status = CreateIpForwardEntry(&fr);
2766 "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2767 (
unsigned int)fr.dwForwardMetric1, (
unsigned int)fr.dwForwardType);
2771 else if (
status != ERROR_BAD_ARGUMENTS)
2781 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2788 "ERROR: route addition failed using CreateIpForwardEntry: "
2789 "%s [status=%u if_index=%u]",
2810 MIB_IPFORWARDROW fr;
2813 fr.dwForwardDest = htonl(r->
network);
2814 fr.dwForwardMask = htonl(r->
netmask);
2815 fr.dwForwardPolicy = 0;
2816 fr.dwForwardNextHop = htonl(r->
gateway);
2817 fr.dwForwardIfIndex = if_index;
2819 status = DeleteIpForwardEntry(&fr);
2827 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2854 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
2881 .prefix.ipv4.s_addr = htonl(r->
network),
2882 .gateway.ipv4.s_addr = htonl(r->
gateway),
2883 .iface = { .index = if_index, .name =
"" },
2887 if (
msg.prefix_len == -1)
2889 msg.prefix_len = 32;
2903 PMIB_IPFORWARD_ROW2 fwd_row;
2908 fwd_row->ValidLifetime = 0xffffffff;
2909 fwd_row->PreferredLifetime = 0xffffffff;
2910 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2912 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2913 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2914 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2915 fwd_row->NextHop.si_family = AF_INET6;
2916 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2925 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2933 if (err != NO_ERROR)
2937 fwd_row->InterfaceLuid = luid;
2938 fwd_row->InterfaceIndex = 0;
2943 err = CreateIpForwardEntry2(fwd_row);
2947 err = DeleteIpForwardEntry2(fwd_row);
2951 if (err != NO_ERROR)
2956 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2958 fwd_row->InterfaceIndex);
2962 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2967 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
2999 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3005 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3011 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3047 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3051 (
int)
r->dwForwardIfIndex, (
int)
r->dwForwardType, (
int)
r->dwForwardProto,
3052 (
int)
r->dwForwardAge, (
int)
r->dwForwardNextHopAS, (
int)
r->dwForwardMetric1,
3053 (
int)
r->dwForwardMetric2, (
int)
r->dwForwardMetric3, (
int)
r->dwForwardMetric4,
3054 (
int)
r->dwForwardMetric5);
3068 msg(msglev,
"SYSTEM ROUTING TABLE");
3071 for (DWORD
i = 0;
i < rt->dwNumEntries; ++
i)
3079#elif defined(TARGET_ANDROID)
3094 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3096 strcpy(rgi->iface,
"android-gw");
3116 strcpy(rgi6->iface,
"android-gw");
3119#elif defined(TARGET_LINUX)
3126 char best_name[IFNAMSIZ];
3132 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3144 struct ifreq *ifr, *ifend;
3145 in_addr_t addr, netmask;
3148 struct ifreq ifs[20];
3150 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3155 ifc.ifc_len =
sizeof(ifs);
3157 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3159 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3164 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3165 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3167 if (ifr->ifr_addr.sa_family == AF_INET)
3170 addr = ntohl(((
struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3173 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3176 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3180 if (!(ifreq.ifr_flags & IFF_UP))
3189 if (strcmp(ifreq.ifr_name, best_name))
3195 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3197 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3200 rgi->
flags &= ~RGI_ON_LINK;
3208 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3212 netmask = ntohl(((
struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3226 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3230 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3231 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3233 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3236 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3272 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3279 if (strlen(rgi6->iface) > 0)
3297#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3298 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3300#include <sys/types.h>
3301#include <sys/socket.h>
3302#include <netinet/in.h>
3303#include <net/route.h>
3304#include <net/if_dl.h>
3305#if !defined(TARGET_SOLARIS)
3311 struct rt_msghdr m_rtm;
3331#if defined(TARGET_DARWIN)
3332#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3333#elif defined(TARGET_NETBSD)
3334#define ROUNDUP(a) RT_ROUNDUP(a)
3336#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3339#if defined(TARGET_SOLARIS)
3340#define NEXTADDR(w, u) \
3341 if (rtm_addrs & (w)) \
3344 memmove(cp, &(u), l); \
3348#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3350#define NEXTADDR(w, u) \
3351 if (rtm_addrs & (w)) \
3353 l = ((struct sockaddr *)&(u))->sa_len; \
3354 memmove(cp, &(u), l); \
3358#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3361#define max(a, b) ((a) > (b) ? (a) : (b))
3367 struct rtmsg m_rtmsg;
3369 int seq, l, pid, rtm_addrs;
3371 struct sockaddr so_dst, so_mask;
3372 char *cp = m_rtmsg.m_space;
3373 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3374 struct rt_msghdr *rtm_aux;
3376#define rtm m_rtmsg.m_rtm
3383#ifdef TARGET_OPENBSD
3384 rtm_addrs = RTA_DST | RTA_NETMASK;
3386 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3389 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3390 bzero(&so_dst,
sizeof(so_dst));
3391 bzero(&so_mask,
sizeof(so_mask));
3392 bzero(&rtm,
sizeof(
struct rt_msghdr));
3394 rtm.rtm_type = RTM_GET;
3395 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3396 rtm.rtm_version = RTM_VERSION;
3397 rtm.rtm_seq = ++seq;
3398#ifdef TARGET_OPENBSD
3399 rtm.rtm_tableid = getrtable();
3401 rtm.rtm_addrs = rtm_addrs;
3403 so_dst.sa_family = AF_INET;
3404 so_mask.sa_family = AF_INET;
3406#ifndef TARGET_SOLARIS
3407 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3408 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3411 NEXTADDR(RTA_DST, so_dst);
3412 NEXTADDR(RTA_NETMASK, so_mask);
3414 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3417 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3423 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3430 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3431 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3437 cp = ((
char *)(rtm_aux + 1));
3438 if (rtm_aux->rtm_addrs)
3440 for (
i = 1;
i;
i <<= 1)
3442 if (
i & rtm_aux->rtm_addrs)
3444 sa = (
struct sockaddr *)cp;
3445 if (
i == RTA_GATEWAY)
3449 else if (
i == RTA_IFP)
3466 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3475 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3476 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3478 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3479 rgi->iface[adl->sdl_nlen] =
'\0';
3490 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3498 ifr.ifr_addr.sa_family = AF_INET;
3499 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3501 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3509 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3516#if defined(TARGET_SOLARIS)
3518 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3525 struct ifreq ifreq = { 0 };
3528 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3529 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3531 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3535 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3539 struct ifaddrs *ifap, *ifa;
3541 if (getifaddrs(&ifap) != 0)
3547 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3549 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3550 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3552 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3553 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3577#if defined(TARGET_SOLARIS)
3579#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3586 struct rtmsg m_rtmsg;
3588 int seq, l, pid, rtm_addrs;
3590 struct sockaddr_in6 so_dst, so_mask;
3591 char *cp = m_rtmsg.m_space;
3592 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3593 struct rt_msghdr *rtm_aux;
3600#ifdef TARGET_OPENBSD
3601 rtm_addrs = RTA_DST | RTA_NETMASK;
3603 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3606 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3607 bzero(&so_dst,
sizeof(so_dst));
3608 bzero(&so_mask,
sizeof(so_mask));
3609 bzero(&rtm,
sizeof(
struct rt_msghdr));
3611 rtm.rtm_type = RTM_GET;
3612 rtm.rtm_flags = RTF_UP;
3613 rtm.rtm_version = RTM_VERSION;
3614 rtm.rtm_seq = ++seq;
3615#ifdef TARGET_OPENBSD
3616 rtm.rtm_tableid = getrtable();
3619 so_dst.sin6_family = AF_INET6;
3620 so_mask.sin6_family = AF_INET6;
3623 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3625 so_dst.sin6_addr = *dest;
3627 rtm_addrs &= ~RTA_NETMASK;
3630 rtm.rtm_addrs = rtm_addrs;
3632#ifndef TARGET_SOLARIS
3633 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3634 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3637 NEXTADDR(RTA_DST, so_dst);
3638 NEXTADDR(RTA_NETMASK, so_mask);
3640 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3643 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3649 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3657 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3658 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3665 cp = ((
char *)(rtm_aux + 1));
3666 if (rtm_aux->rtm_addrs)
3668 for (
i = 1;
i;
i <<= 1)
3670 if (
i & rtm_aux->rtm_addrs)
3672 sa = (
struct sockaddr *)cp;
3673 if (
i == RTA_GATEWAY)
3677 else if (
i == RTA_IFP)
3693 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3694 struct in6_addr gw = s6->sin6_addr;
3696#ifndef TARGET_SOLARIS
3701 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3703 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3706 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3720 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3721 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3723 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3738#elif defined(TARGET_HAIKU)
3745 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3748 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3752 struct ifconf config;
3753 config.ifc_len =
sizeof(config.ifc_value);
3754 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3756 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3760 uint32 size = (uint32)config.ifc_value;
3766 void *
buffer = malloc(size);
3769 config.ifc_len = size;
3771 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3777 struct ifreq *
interface = (struct ifreq *)
buffer;
3778 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3780 while (interface < end)
3782 struct route_entry
route = interface->ifr_route;
3783 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3785 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3787 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3790 int32 address_size = 0;
3791 if (
route.destination != NULL)
3793 address_size +=
route.destination->sa_len;
3795 if (
route.mask != NULL)
3797 address_size +=
route.mask->sa_len;
3799 if (
route.gateway != NULL)
3801 address_size +=
route.gateway->sa_len;
3804 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE + sizeof(struct route_entry)
3853 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3863 const int addrlen =
sizeof(in_addr_t) * 8;
3865 if ((network & netmask) == network)
3867 for (
i = 0;
i <= addrlen; ++
i)
3870 if (mask == netmask)
3894 const int addrlen =
sizeof(in_addr_t) * 8;
3896 for (
i = 0;
i <= addrlen; ++
i)
3899 if (mask == netmask)
3930 bool succeed =
false;
3931 const in_addr_t ip =
3937 iplist = iplist->Next;
4001 const in_addr_t nonlocal_netmask =
4009 for (DWORD
i = 0;
i < rt->dwNumEntries; ++
i)
4011 const MIB_IPFORWARDROW *row = &rt->table[
i];
4012 const in_addr_t net = ntohl(row->dwForwardDest);
4013 const in_addr_t mask = ntohl(row->dwForwardMask);
4014 if (mask > nonlocal_netmask && (addr & mask) == net)
void argv_msg(const int msglev, 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,...)
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, 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)
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 bool route_ipv6_match_host(const struct route_ipv6 *r6, const struct in6_addr *host)
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.
void show_routes(int msglev)
static const char * format_route_entry(const MIB_IPFORWARDROW *r, struct gc_arena *gc)
static void print_route_option(const struct route_option *ro, int level)
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)
void print_route_options(const struct route_option_list *rol, int level)
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)
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 print_default_gateway(const int msglevel, const struct route_gateway_info *rgi, const struct route_ipv6_gateway_info *rgi6)
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)
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 void print_route(const struct route_ipv4 *r, int level)
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)
static int do_route_service(const bool add, const route_message_t *rt, const size_t size, HANDLE pipe)
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 print_routes(const struct route_list *rl, int level)
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, int 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 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_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)
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
void netcmd_semaphore_release(void)
char * get_win_sys_path(void)
void netcmd_semaphore_lock(void)
#define WIN_ROUTE_PATH_SUFFIX