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);
398 " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
450 if (inet_pton(AF_INET6, r6o->
gateway, &
r6->gateway) != 1)
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);
573#if defined(__GNUC__) || defined(__clang__)
574#pragma GCC diagnostic push
575#pragma GCC diagnostic ignored "-Wsign-compare"
581#ifndef TARGET_ANDROID
610#if defined(__GNUC__) || defined(__clang__)
611#pragma GCC diagnostic pop
616 const char *remote_endpoint,
int default_metric,
in_addr_t remote_host,
642#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
660 bool defined =
false;
695 struct addrinfo *netlist = NULL;
704 struct addrinfo *curele;
705 for (curele = netlist; curele; curele = curele->ai_next)
710 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
737 for (i = 0; bits >= 8; i++, bits -= 8)
739 if (
network->s6_addr[i] != host->s6_addr[i])
750 unsigned int mask = 0xff << (8 - bits);
752 if ((
network->s6_addr[i] & mask) == (host->s6_addr[i] & mask))
762 const char *remote_endpoint,
int default_metric,
763 const struct in6_addr *remote_host_ipv6,
struct env_set *
es,
768 bool need_remote_ipv6_route;
774 if (remote_host_ipv6)
780 if (default_metric >= 0)
793#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
821 need_remote_ipv6_route =
false;
838#ifndef TARGET_ANDROID
846 need_remote_ipv6_route =
true;
848 "ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
858 if (need_remote_ipv6_route)
866 r6->network = *remote_host_ipv6;
876 r6->iface = rl6->
rgi6.iface;
886 "ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n");
928 for (
int i = 0; i < rb->
n_bypass; ++i)
960 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
969 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
980 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
985#ifndef TARGET_ANDROID
1017 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1076 rl->
iflags &= ~RL_DID_LOCAL;
1107 rl->
iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
1123 "WARNING: OpenVPN was configured to add an IPv4 "
1124 "route. However, no IPv4 has been configured for %s, "
1125 "therefore the route installation may fail or may not work "
1130#ifdef ENABLE_MANAGEMENT
1155 "WARNING: OpenVPN was configured to add an IPv6 "
1156 "route. However, no IPv6 has been configured for %s, "
1157 "therefore the route installation may fail or may not work "
1195 rl->
iflags &= ~RL_ROUTES_ADDED;
1217 rl6->
iflags &= ~RL_ROUTES_ADDED;
1233 return "default (not set)";
1254 msg(msglevel,
" [redirect_default_gateway local=%d]", (rol->
flags &
RG_LOCAL) != 0);
1298 msg(msglevel,
"%s",
BSTR(&out));
1329 msg(msglevel,
"%s",
BSTR(&out));
1448#if defined(__GNUC__) || defined(__clang__)
1449#pragma GCC diagnostic push
1450#pragma GCC diagnostic ignored "-Wsign-compare"
1460 && netmask == 0xFFFFFFFF)
1469 for (
int i = 0; i < rgi->
n_addrs; ++i)
1482#if defined(__GNUC__) || defined(__clang__)
1483#pragma GCC diagnostic pop
1488#if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1514#if !defined(TARGET_LINUX)
1516#if !defined(TARGET_AIX)
1528#if defined(TARGET_LINUX)
1529 const char *
iface = NULL;
1548 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1553 msg(
M_WARN,
"ERROR: Linux route add command failed");
1557#elif defined(TARGET_ANDROID)
1562 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1566 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1568 bool ret = management_android_control(
management,
"ROUTE", out);
1571#elif defined(_WIN32)
1575 network, netmask, gateway);
1588 const char *method =
"service";
1605 method =
"route.exe";
1610 method =
"ipapi [adaptive]";
1613 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1616 &
argv,
es, 0,
"ERROR: Windows route add command failed [adaptive]");
1619 method =
"route.exe";
1628 msg(
D_ROUTE,
"Route addition via %s %s", method,
1633#elif defined(TARGET_SOLARIS)
1657#elif defined(TARGET_FREEBSD)
1676#elif defined(TARGET_DRAGONFLY)
1695#elif defined(TARGET_DARWIN)
1722#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1741#elif defined(TARGET_AIX)
1751#elif defined(TARGET_HAIKU)
1762 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
1772 r->
flags &= ~RT_ADDED;
1790 int bits_to_clear = 128 -
r6->netbits;
1792 while (
byte >= 0 && bits_to_clear > 0)
1794 if (bits_to_clear >= 8)
1796 r6->network.s6_addr[
byte--] = 0;
1801 r6->network.s6_addr[
byte--] &= (0xff << bits_to_clear);
1812 bool gateway_needed =
false;
1824 if (
r6->iface != NULL)
1827 if (!IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1829 gateway_needed =
true;
1838#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1839 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1845 if (
r6->iface != NULL && gateway_needed
1846 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
1848 size_t len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
1850 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
1856 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s", network,
r6->netbits, gateway,
1857 r6->metric, device);
1859 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu", network,
r6->netbits, gateway,
1876 gateway_needed =
true;
1879 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&
r6->gateway))
1883 "parameter for a --route-ipv6 option and no default was set via "
1884 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1885 "IPv6 route to %s/%d.",
1886 network,
r6->netbits);
1891#if defined(TARGET_LINUX)
1895 metric =
r6->metric;
1899 int ret = net_route_v6_add(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
1900 device,
r6->table_id, metric);
1903 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1908 msg(
M_WARN,
"ERROR: Linux route add command failed");
1912#elif defined(TARGET_ANDROID)
1915 snprintf(out,
sizeof(out),
"%s/%d %s", network,
r6->netbits, device);
1919#elif defined(_WIN32)
1929#elif defined(TARGET_SOLARIS)
1954#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1971#elif defined(TARGET_DARWIN)
1988#elif defined(TARGET_OPENBSD)
1997#elif defined(TARGET_NETBSD)
2005#elif defined(TARGET_AIX)
2012#elif defined(TARGET_HAIKU)
2016 gateway,
r6->netbits);
2023 "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");
2033 r6->flags &= ~RT_ADDED;
2047#if !defined(TARGET_LINUX)
2048 const char *network;
2049#if !defined(TARGET_AIX)
2050 const char *netmask;
2052 const char *gateway;
2066#if !defined(TARGET_LINUX)
2068#if !defined(TARGET_AIX)
2080#if defined(TARGET_LINUX)
2091 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2093#elif defined(_WIN32)
2096 network, netmask, gateway);
2103 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2108 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2119 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2122 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2125 "ERROR: Windows route delete command failed [adaptive]");
2134#elif defined(TARGET_SOLARIS)
2141#elif defined(TARGET_FREEBSD)
2148#elif defined(TARGET_DRAGONFLY)
2155#elif defined(TARGET_DARWIN)
2160 network, netmask, rgi->iface);
2170#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2177#elif defined(TARGET_ANDROID)
2181 "needed. The VpnService API allows routes to be set "
2182 "on connect only and will clean up automatically. "
2183 "Tried to delete route %s netmask %s gateway %s",
2184 network, netmask, gateway);
2185#elif defined(TARGET_AIX)
2194#elif defined(TARGET_HAIKU)
2204 "Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2208 r->
flags &= ~RT_ADDED;
2219 const char *network;
2227#if !defined(TARGET_LINUX)
2228 const char *gateway;
2230#if !defined(TARGET_SOLARIS)
2231 bool gateway_needed =
false;
2233 if (
r6->iface != NULL)
2236 gateway_needed =
true;
2245 gateway_needed =
true;
2254#if !defined(TARGET_LINUX) && !defined(_WIN32)
2258#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2259 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2265 if (
r6->iface != NULL && gateway_needed
2266 && IN6_IS_ADDR_LINKLOCAL(&
r6->gateway))
2268 size_t len = strlen(gateway) + 1 + strlen(
r6->iface) + 1;
2270 snprintf(tmp, len,
"%s%%%s", gateway,
r6->iface);
2275 msg(
D_ROUTE,
"delete_route_ipv6(%s/%d)", network,
r6->netbits);
2277#if defined(TARGET_LINUX)
2281 metric =
r6->metric;
2284 if (net_route_v6_del(ctx, &
r6->network,
r6->netbits, gateway_needed ? &
r6->gateway : NULL,
2285 device,
r6->table_id, metric)
2288 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2291#elif defined(_WIN32)
2301#elif defined(TARGET_SOLARIS)
2310#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2326#elif defined(TARGET_DARWIN)
2342#elif defined(TARGET_OPENBSD)
2350#elif defined(TARGET_NETBSD)
2357#elif defined(TARGET_AIX)
2363#elif defined(TARGET_ANDROID)
2365 "needed. The VpnService API allows routes to be set "
2366 "on connect only and will clean up automatically. "
2367 "Tried to delete %s gateway %s",
2369 gateway_needed ? gateway :
"(not needed)");
2370#elif defined(TARGET_HAIKU)
2374 gateway,
r6->netbits);
2380 "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");
2396static const MIB_IPFORWARDTABLE *
2400 PMIB_IPFORWARDTABLE rt = NULL;
2403 status = GetIpForwardTable(NULL, &size, TRUE);
2404 if (
status == ERROR_INSUFFICIENT_BUFFER)
2406 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2407 status = GetIpForwardTable(rt, &size, TRUE);
2410 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2465 bool adapter_up =
false;
2479 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2491 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s", good, count, len,
2492 (
int)ret, ambig, adapter_up ?
"up" :
"down");
2498static const MIB_IPFORWARDROW *
2502 DWORD lowest_metric = MAXDWORD;
2503 const MIB_IPFORWARDROW *ret = NULL;
2508 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2510 const MIB_IPFORWARDROW *row = &routes->table[i];
2511 const in_addr_t net = ntohl(row->dwForwardDest);
2512 const in_addr_t mask = ntohl(row->dwForwardMask);
2513 const DWORD index = row->dwForwardIfIndex;
2514 const DWORD metric = row->dwForwardMetric1;
2518 (
int)index, (
int)metric);
2520 if (!net && !mask && metric < lowest_metric)
2523 lowest_metric = metric;
2549 DWORD best_if_index;
2555 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2558 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2563 msg(
D_ROUTE_DEBUG,
"GetBestInterfaceEx() returned if=%d", (
int)best_if_index);
2568 SOCKADDR_INET best_src;
2570 status = GetBestRoute2(&luid, best_if_index, NULL, dest, 0, best_route, &best_src);
2573 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2592 sa.si_family = AF_INET;
2593 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2596 MIB_IPFORWARD_ROW2 best_route;
2605 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2618 memcpy(rgi->
hwaddr, ai->Address, 6);
2622 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2642 bool on_tun =
false;
2647 ret = tun_adapter->Index;
2658 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2664 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2668 dmsg(
D_ROUTE_DEBUG,
"DEBUG: route find if: on_tun=%d count=%d index=%d", on_tun, count,
2687 SOCKADDR_INET DestinationAddress;
2688 CLEAR(DestinationAddress);
2689 DestinationAddress.si_family = AF_INET6;
2692 DestinationAddress.Ipv6.sin6_addr = *dest;
2695 MIB_IPFORWARD_ROW2 BestRoute;
2704 msg(
D_ROUTE,
"GDG6: II=%lu DP=%s/%d NH=%s", BestRoute.InterfaceIndex,
2706 BestRoute.DestinationPrefix.PrefixLength,
2708 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d", (
int)BestRoute.Metric,
2709 (
int)BestRoute.Loopback, (
int)BestRoute.AutoconfigureAddress, (
int)BestRoute.Immortal);
2716 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr))
2738 MIB_IPFORWARDROW fr;
2740 fr.dwForwardDest = htonl(r->
network);
2741 fr.dwForwardMask = htonl(r->
netmask);
2742 fr.dwForwardPolicy = 0;
2743 fr.dwForwardNextHop = htonl(r->
gateway);
2744 fr.dwForwardIfIndex = if_index;
2745 fr.dwForwardType = 4;
2746 fr.dwForwardProto = 3;
2747 fr.dwForwardAge = 0;
2748 fr.dwForwardNextHopAS = 0;
2757 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2761 status = CreateIpForwardEntry(&fr);
2767 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2774 const unsigned int forward_metric_limit =
2777 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2782 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2784 status = CreateIpForwardEntry(&fr);
2788 "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2789 (
unsigned int)fr.dwForwardMetric1, (
unsigned int)fr.dwForwardType);
2793 else if (
status != ERROR_BAD_ARGUMENTS)
2803 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2810 "ERROR: route addition failed using CreateIpForwardEntry: "
2811 "%s [status=%u if_index=%u]",
2832 MIB_IPFORWARDROW fr;
2835 fr.dwForwardDest = htonl(r->
network);
2836 fr.dwForwardMask = htonl(r->
netmask);
2837 fr.dwForwardPolicy = 0;
2838 fr.dwForwardNextHop = htonl(r->
gateway);
2839 fr.dwForwardIfIndex = if_index;
2841 status = DeleteIpForwardEntry(&fr);
2849 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2876 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
2890#if defined(__GNUC__) || defined(__clang__)
2891#pragma GCC diagnostic push
2892#pragma GCC diagnostic ignored "-Wsign-compare"
2908 .prefix.ipv4.s_addr = htonl(r->
network),
2909 .gateway.ipv4.s_addr = htonl(r->
gateway),
2910 .iface = { .index = if_index, .name =
"" },
2914 if (
msg.prefix_len == -1)
2916 msg.prefix_len = 32;
2930 PMIB_IPFORWARD_ROW2 fwd_row;
2935 fwd_row->ValidLifetime = 0xffffffff;
2936 fwd_row->PreferredLifetime = 0xffffffff;
2937 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
2939 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
2940 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
2941 fwd_row->DestinationPrefix.PrefixLength = (UINT8)r->
netbits;
2942 fwd_row->NextHop.si_family = AF_INET6;
2943 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
2952 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
2960 if (err != NO_ERROR)
2964 fwd_row->InterfaceLuid = luid;
2965 fwd_row->InterfaceIndex = 0;
2970 err = CreateIpForwardEntry2(fwd_row);
2974 err = DeleteIpForwardEntry2(fwd_row);
2978 if (err != NO_ERROR)
2983 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
2985 fwd_row->InterfaceIndex);
2989 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
2994 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3026 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3032 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3038 msg(
D_ROUTE,
"IPv6 route %s via service %s", add ?
"addition" :
"deletion",
3044#if defined(__GNUC__) || defined(__clang__)
3045#pragma GCC diagnostic pop
3078 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3082 (
int)
r->dwForwardIfIndex, (
int)
r->dwForwardType, (
int)
r->dwForwardProto,
3083 (
int)
r->dwForwardAge, (
int)
r->dwForwardNextHopAS, (
int)
r->dwForwardMetric1,
3084 (
int)
r->dwForwardMetric2, (
int)
r->dwForwardMetric3, (
int)
r->dwForwardMetric4,
3085 (
int)
r->dwForwardMetric5);
3099 msg(msglevel,
"SYSTEM ROUTING TABLE");
3102 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3110#elif defined(TARGET_ANDROID)
3125 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3127 strcpy(rgi->iface,
"android-gw");
3147 strcpy(rgi6->iface,
"android-gw");
3150#elif defined(TARGET_LINUX)
3157 char best_name[IFNAMSIZ];
3163 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3175 struct ifreq *ifr, *ifend;
3179 struct ifreq ifs[20];
3181 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3186 ifc.ifc_len =
sizeof(ifs);
3188 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3190 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3195 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3196 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3198 if (ifr->ifr_addr.sa_family == AF_INET)
3201 addr = ntohl(((
struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
3204 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3207 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3211 if (!(ifreq.ifr_flags & IFF_UP))
3220 if (strcmp(ifreq.ifr_name, best_name))
3226 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3228 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3231 rgi->
flags &= ~RGI_ON_LINK;
3239 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3243 netmask = ntohl(((
struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr);
3257 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3261 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3262 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3264 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3267 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3303 if (net_route_v6_best_gw(ctx, dest, &rgi6->
gateway.
addr_ipv6, rgi6->iface) == 0)
3310 if (strlen(rgi6->iface) > 0)
3328#elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) || defined(TARGET_FREEBSD) \
3329 || defined(TARGET_DRAGONFLY) || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3331#include <sys/types.h>
3332#include <sys/socket.h>
3333#include <netinet/in.h>
3334#include <net/route.h>
3335#include <net/if_dl.h>
3336#if !defined(TARGET_SOLARIS)
3342 struct rt_msghdr m_rtm;
3362#if defined(TARGET_DARWIN)
3363#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3364#elif defined(TARGET_NETBSD)
3365#define ROUNDUP(a) RT_ROUNDUP(a)
3367#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3370#if defined(TARGET_SOLARIS)
3371#define NEXTADDR(w, u) \
3372 if (rtm_addrs & (w)) \
3374 size_t l = sizeof(u); \
3375 memmove(cp, &(u), l); \
3379#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3381#define NEXTADDR(w, u) \
3382 if (rtm_addrs & (w)) \
3384 size_t l = ((struct sockaddr *)&(u))->sa_len; \
3385 memmove(cp, &(u), l); \
3389#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3392#define max(a, b) ((a) > (b) ? (a) : (b))
3398 struct rtmsg m_rtmsg;
3401 struct sockaddr so_dst, so_mask;
3402 char *cp = m_rtmsg.m_space;
3403 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3404 struct rt_msghdr *rtm_aux;
3406#define rtm m_rtmsg.m_rtm
3411 const int pid = getpid();
3413#ifdef TARGET_OPENBSD
3414 rtm_addrs = RTA_DST | RTA_NETMASK;
3416 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3419 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3420 bzero(&so_dst,
sizeof(so_dst));
3421 bzero(&so_mask,
sizeof(so_mask));
3422 bzero(&rtm,
sizeof(
struct rt_msghdr));
3424 rtm.rtm_type = RTM_GET;
3425 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3426 rtm.rtm_version = RTM_VERSION;
3427 rtm.rtm_seq = ++seq;
3428#ifdef TARGET_OPENBSD
3429 rtm.rtm_tableid = (u_short)getrtable();
3431 rtm.rtm_addrs = rtm_addrs;
3433 so_dst.sa_family = AF_INET;
3434 so_mask.sa_family = AF_INET;
3436#ifndef TARGET_SOLARIS
3437 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3438 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3441 NEXTADDR(RTA_DST, so_dst);
3442 NEXTADDR(RTA_NETMASK, so_mask);
3445 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3448 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3454 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3462 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3463 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3469 cp = (
char *)(rtm_aux + 1);
3470 if (rtm_aux->rtm_addrs)
3472 for (
unsigned int i = 1; i; i <<= 1)
3474 if (i & rtm_aux->rtm_addrs)
3476 sa = (
struct sockaddr *)cp;
3477 if (i == RTA_GATEWAY)
3481 else if (i == RTA_IFP)
3498 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3507 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3508 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3510 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3511 rgi->iface[adl->sdl_nlen] =
'\0';
3522 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3530 ifr.ifr_addr.sa_family = AF_INET;
3531 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3533 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3541 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3548#if defined(TARGET_SOLARIS)
3550 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3557 struct ifreq ifreq = { 0 };
3560 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3561 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3563 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3567 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3571 struct ifaddrs *ifap, *ifa;
3573 if (getifaddrs(&ifap) != 0)
3579 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3581 if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK
3582 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ))
3584 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3585 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3609#if defined(TARGET_SOLARIS)
3611#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3618 struct rtmsg m_rtmsg;
3621 struct sockaddr_in6 so_dst, so_mask;
3622 char *cp = m_rtmsg.m_space;
3623 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3624 struct rt_msghdr *rtm_aux;
3629 const int pid = getpid();
3631#ifdef TARGET_OPENBSD
3632 rtm_addrs = RTA_DST | RTA_NETMASK;
3634 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3637 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3638 bzero(&so_dst,
sizeof(so_dst));
3639 bzero(&so_mask,
sizeof(so_mask));
3640 bzero(&rtm,
sizeof(
struct rt_msghdr));
3642 rtm.rtm_type = RTM_GET;
3643 rtm.rtm_flags = RTF_UP;
3644 rtm.rtm_version = RTM_VERSION;
3645 rtm.rtm_seq = ++seq;
3646#ifdef TARGET_OPENBSD
3647 rtm.rtm_tableid = (u_short)getrtable();
3650 so_dst.sin6_family = AF_INET6;
3651 so_mask.sin6_family = AF_INET6;
3654 && !IN6_IS_ADDR_UNSPECIFIED(dest))
3656 so_dst.sin6_addr = *dest;
3658 rtm_addrs &= ~RTA_NETMASK;
3661 rtm.rtm_addrs = rtm_addrs;
3663#ifndef TARGET_SOLARIS
3664 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3665 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3668 NEXTADDR(RTA_DST, so_dst);
3669 NEXTADDR(RTA_NETMASK, so_mask);
3672 rtm.rtm_msglen = (u_short)(cp - (
char *)&m_rtmsg);
3675 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3681 if (
write(sockfd, (
char *)&m_rtmsg, rtm.rtm_msglen) < 0)
3689 ret =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3690 }
while (ret > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3697 cp = (
char *)(rtm_aux + 1);
3698 if (rtm_aux->rtm_addrs)
3700 for (
unsigned int i = 1; i; i <<= 1)
3702 if (i & rtm_aux->rtm_addrs)
3704 sa = (
struct sockaddr *)cp;
3705 if (i == RTA_GATEWAY)
3709 else if (i == RTA_IFP)
3725 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3726 struct in6_addr gw = s6->sin6_addr;
3728#ifndef TARGET_SOLARIS
3733 if (gate->sa_len ==
sizeof(
struct sockaddr_in6) && IN6_IS_ADDR_LINKLOCAL(&gw))
3735 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3738 if (gate->sa_len !=
sizeof(
struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&gw))
3752 const struct sockaddr_dl *adl = (
struct sockaddr_dl *)ifp;
3753 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3755 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3770#elif defined(TARGET_HAIKU)
3777 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3780 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
3784 struct ifconf config;
3785 config.ifc_len =
sizeof(config.ifc_value);
3786 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
3788 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
3792 uint32 size = (uint32)config.ifc_value;
3798 void *
buffer = malloc(size);
3801 config.ifc_len = size;
3803 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
3809 struct ifreq *
interface = (struct ifreq *)
buffer;
3810 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
3812 while (interface < end)
3814 struct route_entry
route = interface->ifr_route;
3815 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
3817 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
3819 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
3822 int32 address_size = 0;
3823 if (
route.destination != NULL)
3825 address_size +=
route.destination->sa_len;
3827 if (
route.mask != NULL)
3829 address_size +=
route.mask->sa_len;
3831 if (
route.gateway != NULL)
3833 address_size +=
route.gateway->sa_len;
3836 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE + sizeof(struct route_entry)
3885 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3895 const int addrlen =
sizeof(
in_addr_t) * 8;
3897 if ((network & netmask) == network)
3899 for (i = 0; i <= addrlen; ++i)
3902 if (mask == netmask)
3926 const int addrlen =
sizeof(
in_addr_t) * 8;
3928 for (i = 0; i <= addrlen; ++i)
3931 if (mask == netmask)
3962 bool succeed =
false;
3969 iplist = iplist->Next;
4041 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4043 const MIB_IPFORWARDROW *row = &rt->table[i];
4044 const in_addr_t net = ntohl(row->dwForwardDest);
4045 const in_addr_t mask = ntohl(row->dwForwardMask);
4046 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