49 #if defined(TARGET_LINUX) || defined(TARGET_ANDROID)
50 #include <linux/rtnetlink.h>
53 #if defined(TARGET_NETBSD)
54 #include <net/route.h>
60 #define METRIC_NOT_USED ((DWORD)-1)
93 msg(
D_ROUTE,
"ROUTE: bypass_host_route[%d]=%s",
104 #define RTA_SUCCESS 1
192 buf_printf(&out,
"ROUTE network %s netmask %s gateway %s",
211 if (!strcmp(parm,
"default"))
245 if (!strcmp(
string,
"vpn_gateway"))
264 else if (!strcmp(
string,
"net_gateway"))
274 msg(
M_INFO,
PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
283 else if (!strcmp(
string,
"remote_host"))
320 struct addrinfo **network_list,
327 struct in_addr special = {0};
349 special.s_addr = htonl(special.s_addr);
350 char buf[INET_ADDRSTRLEN];
351 inet_ntop(AF_INET, &special, buf,
sizeof(buf));
353 AF_INET, network_list);
358 ro->
network, NULL, 0, NULL, AF_INET, network_list);
417 msg(
M_WARN,
PACKAGE_NAME " ROUTE: " PACKAGE_NAME " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
559 const in_addr_t addr)
581 l2 = ((~
gateway->netmask)+1)>>1;
583 r1->gateway = target;
585 r1->netmask = ~(l2-1);
599 #ifndef TARGET_ANDROID
625 && (rl->
rgi.
flags & rgi_needed) == rgi_needed
633 const char *remote_endpoint,
635 in_addr_t remote_host,
662 #if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
678 bool defined =
false;
718 struct addrinfo *netlist = NULL;
727 struct addrinfo *curele;
728 for (curele = netlist; curele; curele = curele->ai_next)
733 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
755 const struct in6_addr *host )
757 unsigned int bits = r6->
netbits;
766 for (i = 0; bits >= 8; i++, bits -= 8)
768 if (r6->
network.s6_addr[i] != host->s6_addr[i])
779 mask = 0xff << (8-bits);
781 if ( (r6->
network.s6_addr[i] & mask) == (host->s6_addr[i] & mask ))
792 const char *remote_endpoint,
794 const struct in6_addr *remote_host_ipv6,
800 bool need_remote_ipv6_route;
806 if (remote_host_ipv6)
812 if (default_metric >= 0)
819 remote_host_ipv6 ?
print_in6_addr(*remote_host_ipv6, 0, &gc) :
"n/a" );
825 #if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
836 if (inet_pton( AF_INET6, remote_endpoint,
851 need_remote_ipv6_route =
false;
868 #ifndef TARGET_ANDROID
876 need_remote_ipv6_route =
true;
877 msg(
D_ROUTE,
"ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
887 if (need_remote_ipv6_route)
895 r6->
network = *remote_host_ipv6;
905 r6->iface = rl6->
rgi6.iface;
914 msg(
M_WARN,
"ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n" );
970 for (
int i = 0; i < rb->
n_bypass; ++i)
1012 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
1021 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
1032 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
1037 #ifndef TARGET_ANDROID
1067 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1074 &rl->
rgi,
es, ctx) && ret;
1197 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv4 "
1198 "route. However, no IPv4 has been configured for %s, "
1199 "therefore the route installation may fail or may not work "
1203 #ifdef ENABLE_MANAGEMENT
1233 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv6 "
1234 "route. However, no IPv6 has been configured for %s, "
1235 "therefore the route installation may fail or may not work "
1291 #ifndef ENABLE_SMALL
1298 return "default (not set)";
1309 msg(level,
" route %s/%s/%s/%s",
1323 msg(level,
" [redirect_default_gateway local=%d]",
1369 msg(msglevel,
"%s",
BSTR(&out));
1400 msg(msglevel,
"%s",
BSTR(&out));
1469 buf_printf( &name1,
"route_ipv6_network_%d", i );
1474 buf_printf( &name2,
"route_ipv6_gateway_%d", i );
1480 buf_printf( &name3,
"route_ipv6_metric_%d", i);
1516 #define LR_NOMATCH 0
1529 && (rgi->
flags & rgi_needed) == rgi_needed
1531 && netmask == 0xFFFFFFFF)
1541 for (i = 0; i < rgi->
n_addrs; ++i)
1556 #if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1583 #if !defined(TARGET_LINUX)
1585 #if !defined(TARGET_AIX)
1597 #if defined(TARGET_LINUX)
1598 const char *
iface = NULL;
1616 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1621 msg(
M_WARN,
"ERROR: Linux route add command failed");
1625 #elif defined (TARGET_ANDROID)
1630 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1634 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1636 bool ret = management_android_control(
management,
"ROUTE", out);
1639 #elif defined (_WIN32)
1660 const char *method =
"service";
1674 "ERROR: Windows route add command failed");
1677 method =
"route.exe";
1682 method =
"ipapi [adaptive]";
1685 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1688 "ERROR: Windows route add command failed [adaptive]");
1691 method =
"route.exe";
1700 msg(
D_ROUTE,
"Route addition via %s %s", method,
1705 #elif defined (TARGET_SOLARIS)
1731 "ERROR: Solaris route add command failed");
1734 #elif defined(TARGET_FREEBSD)
1755 "ERROR: FreeBSD route add command failed");
1758 #elif defined(TARGET_DRAGONFLY)
1779 "ERROR: DragonFly route add command failed");
1782 #elif defined(TARGET_DARWIN)
1813 "ERROR: OS X route add command failed");
1816 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1837 "ERROR: OpenBSD/NetBSD route add command failed");
1840 #elif defined(TARGET_AIX)
1846 network, netbits, gateway);
1849 "ERROR: AIX route add command failed");
1854 msg(
M_FATAL,
"Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
1883 int bits_to_clear = 128 - r6->
netbits;
1885 while (
byte >= 0 && bits_to_clear > 0)
1887 if (bits_to_clear >= 8)
1889 r6->
network.s6_addr[
byte--] = 0; bits_to_clear -= 8;
1893 r6->
network.s6_addr[
byte--] &= (0xff << bits_to_clear); bits_to_clear = 0;
1900 unsigned int flags,
const struct env_set *
es,
1904 bool gateway_needed =
false;
1916 if (r6->iface != NULL)
1919 if (!IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway) )
1921 gateway_needed =
true;
1930 #if defined(TARGET_DARWIN) \
1931 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1932 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1938 if (r6->iface != NULL && gateway_needed
1939 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
1941 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
1942 char *tmp =
gc_malloc( len,
true, &gc );
1943 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
1949 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1952 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu",
1971 gateway_needed =
true;
1974 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway))
1977 "parameter for a --route-ipv6 option and no default was set via "
1978 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1979 "IPv6 route to %s/%d.", network, r6->
netbits);
1984 #if defined(TARGET_LINUX)
1993 gateway_needed ? &r6->
gateway : NULL,
1997 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
2002 msg(
M_WARN,
"ERROR: Linux route add command failed");
2006 #elif defined (TARGET_ANDROID)
2009 snprintf(out,
sizeof(out),
"%s/%d %s", network, r6->
netbits, device);
2013 #elif defined (_WIN32)
2023 #elif defined (TARGET_SOLARIS)
2050 "ERROR: Solaris route add -inet6 command failed");
2053 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2071 "ERROR: *BSD route add -inet6 command failed");
2074 #elif defined(TARGET_DARWIN)
2091 "ERROR: MacOS X route add -inet6 command failed");
2094 #elif defined(TARGET_OPENBSD)
2098 network, r6->
netbits, gateway );
2102 "ERROR: OpenBSD route add -inet6 command failed");
2105 #elif defined(TARGET_NETBSD)
2109 network, r6->
netbits, gateway );
2113 "ERROR: NetBSD route add -inet6 command failed");
2116 #elif defined(TARGET_AIX)
2120 network, r6->
netbits, gateway);
2123 "ERROR: AIX route add command failed");
2127 msg(
M_FATAL,
"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");
2155 #if !defined(TARGET_LINUX)
2156 const char *network;
2157 #if !defined(TARGET_AIX)
2158 const char *netmask;
2160 #if !defined(TARGET_ANDROID)
2161 const char *gateway;
2176 #if !defined(TARGET_LINUX)
2178 #if !defined(TARGET_AIX)
2181 #if !defined(TARGET_ANDROID)
2192 #if defined(TARGET_LINUX)
2200 &r->
gateway, NULL, 0, metric) < 0)
2202 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2204 #elif defined (_WIN32)
2218 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2223 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2234 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2237 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2248 #elif defined (TARGET_SOLARIS)
2259 #elif defined(TARGET_FREEBSD)
2270 #elif defined(TARGET_DRAGONFLY)
2281 #elif defined(TARGET_DARWIN)
2285 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s",
2303 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2314 #elif defined(TARGET_ANDROID)
2316 "needed. The VpnService API allows routes to be set "
2317 "on connect only and will clean up automatically.");
2318 #elif defined(TARGET_AIX)
2324 network, netbits, gateway);
2330 msg(
M_FATAL,
"Sorry, but I don't know how to do 'route' commands on this operating system. Try putting your routes in a --route-up script");
2343 unsigned int flags,
const struct env_set *
es,
2346 const char *network;
2353 #if !defined(_WIN32)
2354 #if !defined(TARGET_LINUX)
2355 const char *gateway;
2357 #if !defined(TARGET_SOLARIS)
2358 bool gateway_needed =
false;
2360 if (r6->iface != NULL)
2363 gateway_needed =
true;
2372 gateway_needed =
true;
2381 #if !defined(TARGET_LINUX) && !defined(_WIN32)
2385 #if defined(TARGET_DARWIN) \
2386 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2387 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2393 if (r6->iface != NULL && gateway_needed
2394 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
2396 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
2398 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
2405 #if defined(TARGET_LINUX)
2413 gateway_needed ? &r6->
gateway : NULL, device, 0,
2416 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2419 #elif defined (_WIN32)
2429 #elif defined (TARGET_SOLARIS)
2442 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2461 #elif defined(TARGET_DARWIN)
2479 #elif defined(TARGET_OPENBSD)
2483 network, r6->
netbits, gateway );
2488 #elif defined(TARGET_NETBSD)
2492 network, r6->
netbits, gateway );
2497 #elif defined(TARGET_AIX)
2501 network, r6->
netbits, gateway);
2504 #elif defined(TARGET_ANDROID)
2506 "needed. The VpnService API allows routes to be set "
2507 "on connect only and will clean up automatically.");
2509 msg(
M_FATAL,
"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");
2525 static const MIB_IPFORWARDTABLE *
2529 PMIB_IPFORWARDTABLE rt = NULL;
2532 status = GetIpForwardTable(NULL, &size, TRUE);
2533 if (
status == ERROR_INSUFFICIENT_BUFFER)
2535 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2536 status = GetIpForwardTable(rt, &size, TRUE);
2539 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2550 const in_addr_t gateway,
2567 const IP_ADAPTER_INFO *adapters,
2568 const in_addr_t gateway)
2601 bool adapter_up =
false;
2615 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2627 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
2633 adapter_up ?
"up" :
"down");
2639 static const MIB_IPFORWARDROW *
2643 DWORD lowest_metric = MAXDWORD;
2644 const MIB_IPFORWARDROW *ret = NULL;
2649 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2651 const MIB_IPFORWARDROW *row = &routes->table[i];
2652 const in_addr_t net = ntohl(row->dwForwardDest);
2653 const in_addr_t mask = ntohl(row->dwForwardMask);
2654 const DWORD index = row->dwForwardIfIndex;
2655 const DWORD metric = row->dwForwardMetric1;
2664 if (!net && !mask && metric < lowest_metric)
2667 lowest_metric = metric;
2688 const IP_ADAPTER_INFO *ai;
2706 memcpy(rgi->
hwaddr, ai->Address, 6);
2724 bool on_tun =
false;
2729 ret = tun_adapter->Index;
2740 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2746 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2770 MIB_IPFORWARD_ROW2 BestRoute;
2771 SOCKADDR_INET DestinationAddress, BestSourceAddress;
2778 CLEAR(DestinationAddress);
2780 DestinationAddress.si_family = AF_INET6;
2783 DestinationAddress.Ipv6.sin6_addr = *dest;
2786 status = GetBestInterfaceEx( (
struct sockaddr *)&DestinationAddress, &BestIfIndex );
2790 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2796 msg(
D_ROUTE,
"GetBestInterfaceEx() returned if=%d", (
int) BestIfIndex );
2799 &DestinationAddress, 0,
2800 &BestRoute, &BestSourceAddress );
2804 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2811 BestRoute.InterfaceIndex,
2812 print_in6_addr( BestRoute.DestinationPrefix.Prefix.Ipv6.sin6_addr, 0, &gc),
2813 BestRoute.DestinationPrefix.PrefixLength,
2815 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d",
2816 (
int) BestRoute.Metric,
2817 (
int) BestRoute.Loopback,
2818 (
int) BestRoute.AutoconfigureAddress,
2819 (
int) BestRoute.Immortal );
2826 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr) )
2846 MIB_IPFORWARDROW fr;
2848 fr.dwForwardDest = htonl(r->
network);
2849 fr.dwForwardMask = htonl(r->
netmask);
2850 fr.dwForwardPolicy = 0;
2851 fr.dwForwardNextHop = htonl(r->
gateway);
2852 fr.dwForwardIfIndex = if_index;
2853 fr.dwForwardType = 4;
2854 fr.dwForwardProto = 3;
2855 fr.dwForwardAge = 0;
2856 fr.dwForwardNextHopAS = 0;
2865 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2870 status = CreateIpForwardEntry(&fr);
2876 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2883 const unsigned int forward_metric_limit = 2048;
2885 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2889 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2891 status = CreateIpForwardEntry(&fr);
2894 msg(
D_ROUTE,
"ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2895 (
unsigned int)fr.dwForwardMetric1,
2896 (
unsigned int)fr.dwForwardType);
2900 else if (
status != ERROR_BAD_ARGUMENTS)
2910 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2916 msg(
M_WARN,
"ERROR: route addition failed using CreateIpForwardEntry: "
2918 (
unsigned int)
status, (
unsigned int)if_index);
2938 MIB_IPFORWARDROW fr;
2941 fr.dwForwardDest = htonl(r->
network);
2942 fr.dwForwardMask = htonl(r->
netmask);
2943 fr.dwForwardPolicy = 0;
2944 fr.dwForwardNextHop = htonl(r->
gateway);
2945 fr.dwForwardIfIndex = if_index;
2947 status = DeleteIpForwardEntry(&fr);
2955 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2982 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
3013 .prefix.ipv4.s_addr = htonl(r->
network),
3014 .gateway.ipv4.s_addr = htonl(r->
gateway),
3015 .iface = { .index = if_index, .name =
"" },
3020 if (
msg.prefix_len == -1)
3022 msg.prefix_len = 32;
3036 PMIB_IPFORWARD_ROW2 fwd_row;
3039 fwd_row =
gc_malloc(
sizeof(*fwd_row),
true, &gc);
3041 fwd_row->ValidLifetime = 0xffffffff;
3042 fwd_row->PreferredLifetime = 0xffffffff;
3043 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
3045 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
3046 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
3047 fwd_row->DestinationPrefix.PrefixLength = (UINT8) r->
netbits;
3048 fwd_row->NextHop.si_family = AF_INET6;
3049 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
3058 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
3066 if (err != NO_ERROR)
3070 fwd_row->InterfaceLuid = luid;
3071 fwd_row->InterfaceIndex = 0;
3076 err = CreateIpForwardEntry2(fwd_row);
3080 err = DeleteIpForwardEntry2(fwd_row);
3084 if (err != NO_ERROR)
3089 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
3091 fwd_row->InterfaceIndex);
3095 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
3100 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3138 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3144 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3151 add ?
"addition" :
"deletion",
3187 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3191 (
int)r->dwForwardPolicy,
3192 (
int)r->dwForwardIfIndex,
3193 (
int)r->dwForwardType,
3194 (
int)r->dwForwardProto,
3195 (
int)r->dwForwardAge,
3196 (
int)r->dwForwardNextHopAS,
3197 (
int)r->dwForwardMetric1,
3198 (
int)r->dwForwardMetric2,
3199 (
int)r->dwForwardMetric3,
3200 (
int)r->dwForwardMetric4,
3201 (
int)r->dwForwardMetric5);
3215 msg(msglev,
"SYSTEM ROUTING TABLE");
3218 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3226 #elif defined(TARGET_ANDROID)
3241 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3243 strcpy(rgi->iface,
"android-gw");
3264 strcpy(rgi6->iface,
"android-gw");
3267 #elif defined(TARGET_LINUX)
3274 char best_name[IFNAMSIZ];
3280 if (net_route_v4_best_gw(ctx, NULL, &rgi->
gateway.
addr, best_name) == 0)
3292 struct ifreq *ifr, *ifend;
3293 in_addr_t addr, netmask;
3296 struct ifreq ifs[20];
3298 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3303 ifc.ifc_len =
sizeof(ifs);
3305 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3307 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3312 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3313 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3315 if (ifr->ifr_addr.sa_family == AF_INET)
3318 addr = ntohl(((
struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
3321 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3324 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3328 if (!(ifreq.ifr_flags & IFF_UP))
3337 if (strcmp(ifreq.ifr_name, best_name))
3343 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3345 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3356 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3360 netmask = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3374 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3378 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3379 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3381 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3384 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3427 if (strlen(rgi6->iface) > 0)
3445 #elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) \
3446 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
3447 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3449 #include <sys/types.h>
3450 #include <sys/socket.h>
3451 #include <netinet/in.h>
3452 #include <net/route.h>
3453 #include <net/if_dl.h>
3454 #if !defined(TARGET_SOLARIS)
3455 #include <ifaddrs.h>
3459 struct rt_msghdr m_rtm;
3479 #if defined(TARGET_DARWIN)
3480 #define ROUNDUP(a) \
3481 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3482 #elif defined(TARGET_NETBSD)
3483 #define ROUNDUP(a) RT_ROUNDUP(a)
3485 #define ROUNDUP(a) \
3486 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3489 #if defined(TARGET_SOLARIS)
3490 #define NEXTADDR(w, u) \
3491 if (rtm_addrs & (w)) { \
3492 l = sizeof(u); memmove(cp, &(u), l); cp += ROUNDUP(l); \
3495 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3497 #define NEXTADDR(w, u) \
3498 if (rtm_addrs & (w)) { \
3499 l = ((struct sockaddr *)&(u))->sa_len; memmove(cp, &(u), l); cp += ROUNDUP(l); \
3502 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3505 #define max(a, b) ((a) > (b) ? (a) : (b))
3511 struct rtmsg m_rtmsg;
3513 int seq, l, pid, rtm_addrs;
3515 struct sockaddr so_dst, so_mask;
3516 char *cp = m_rtmsg.m_space;
3517 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3518 struct rt_msghdr *rtm_aux;
3520 #define rtm m_rtmsg.m_rtm
3527 #ifdef TARGET_OPENBSD
3528 rtm_addrs = RTA_DST | RTA_NETMASK;
3530 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3533 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3534 bzero(&so_dst,
sizeof(so_dst));
3535 bzero(&so_mask,
sizeof(so_mask));
3536 bzero(&rtm,
sizeof(
struct rt_msghdr));
3538 rtm.rtm_type = RTM_GET;
3539 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3540 rtm.rtm_version = RTM_VERSION;
3541 rtm.rtm_seq = ++seq;
3542 #ifdef TARGET_OPENBSD
3543 rtm.rtm_tableid = getrtable();
3545 rtm.rtm_addrs = rtm_addrs;
3547 so_dst.sa_family = AF_INET;
3548 so_mask.sa_family = AF_INET;
3550 #ifndef TARGET_SOLARIS
3551 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3552 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3555 NEXTADDR(RTA_DST, so_dst);
3556 NEXTADDR(RTA_NETMASK, so_mask);
3558 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3561 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3567 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3574 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3575 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3581 cp = ((
char *)(rtm_aux + 1));
3582 if (rtm_aux->rtm_addrs)
3584 for (i = 1; i; i <<= 1)
3586 if (i & rtm_aux->rtm_addrs)
3588 sa = (
struct sockaddr *)cp;
3589 if (i == RTA_GATEWAY)
3593 else if (i == RTA_IFP)
3610 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3619 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3620 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3622 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3623 rgi->iface[adl->sdl_nlen] =
'\0';
3634 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3642 ifr.ifr_addr.sa_family = AF_INET;
3643 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3645 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3653 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3660 #if defined(TARGET_SOLARIS)
3662 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3669 struct ifreq ifreq = { 0 };
3672 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3673 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3675 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3679 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3683 struct ifaddrs *ifap, *ifa;
3685 if (getifaddrs(&ifap) != 0)
3691 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3693 if (ifa->ifa_addr != NULL
3694 && ifa->ifa_addr->sa_family == AF_LINK
3695 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ) )
3697 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3698 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3722 #if defined(TARGET_SOLARIS)
3724 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3732 struct rtmsg m_rtmsg;
3734 int seq, l, pid, rtm_addrs;
3736 struct sockaddr_in6 so_dst, so_mask;
3737 char *cp = m_rtmsg.m_space;
3738 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3739 struct rt_msghdr *rtm_aux;
3746 #ifdef TARGET_OPENBSD
3747 rtm_addrs = RTA_DST | RTA_NETMASK;
3749 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3752 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3753 bzero(&so_dst,
sizeof(so_dst));
3754 bzero(&so_mask,
sizeof(so_mask));
3755 bzero(&rtm,
sizeof(
struct rt_msghdr));
3757 rtm.rtm_type = RTM_GET;
3758 rtm.rtm_flags = RTF_UP;
3759 rtm.rtm_version = RTM_VERSION;
3760 rtm.rtm_seq = ++seq;
3761 #ifdef TARGET_OPENBSD
3762 rtm.rtm_tableid = getrtable();
3765 so_dst.sin6_family = AF_INET6;
3766 so_mask.sin6_family = AF_INET6;
3769 && !IN6_IS_ADDR_UNSPECIFIED(dest) )
3771 so_dst.sin6_addr = *dest;
3773 rtm_addrs &= ~RTA_NETMASK;
3776 rtm.rtm_addrs = rtm_addrs;
3778 #ifndef TARGET_SOLARIS
3779 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3780 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3783 NEXTADDR(RTA_DST, so_dst);
3784 NEXTADDR(RTA_NETMASK, so_mask);
3786 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3789 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3795 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3803 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3805 while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3812 cp = ((
char *)(rtm_aux + 1));
3813 if (rtm_aux->rtm_addrs)
3815 for (i = 1; i; i <<= 1)
3817 if (i & rtm_aux->rtm_addrs)
3819 sa = (
struct sockaddr *)cp;
3820 if (i == RTA_GATEWAY)
3824 else if (i == RTA_IFP)
3840 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3841 struct in6_addr gw = s6->sin6_addr;
3843 #ifndef TARGET_SOLARIS
3848 if (gate->sa_len ==
sizeof(
struct sockaddr_in6)
3849 && IN6_IS_ADDR_LINKLOCAL(&gw) )
3851 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3854 if (gate->sa_len !=
sizeof(
struct sockaddr_in6)
3855 || IN6_IS_ADDR_UNSPECIFIED(&gw) )
3868 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3869 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3871 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3921 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3931 const int addrlen =
sizeof(in_addr_t) * 8;
3933 if ((network & netmask) == network)
3935 for (i = 0; i <= addrlen; ++i)
3938 if (mask == netmask)
3962 const int addrlen =
sizeof(in_addr_t) * 8;
3964 for (i = 0; i <= addrlen; ++i)
3967 if (mask == netmask)
3998 bool succeed =
false;
4004 iplist = iplist->Next;
4068 const in_addr_t nonlocal_netmask = 0x80000000L;
4075 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4077 const MIB_IPFORWARDROW *row = &rt->table[i];
4078 const in_addr_t net = ntohl(row->dwForwardDest);
4079 const in_addr_t mask = ntohl(row->dwForwardMask);
4080 if (mask > nonlocal_netmask && (addr & mask) == net)