48 #if defined(TARGET_LINUX) || defined(TARGET_ANDROID)
49 #include <linux/rtnetlink.h>
52 #if defined(TARGET_NETBSD)
53 #include <net/route.h>
59 #define METRIC_NOT_USED ((DWORD)-1)
90 msg(
D_ROUTE,
"ROUTE: bypass_host_route[%d]=%s",
101 #define RTA_SUCCESS 1
189 buf_printf(&out,
"ROUTE network %s netmask %s gateway %s",
208 if (!strcmp(parm,
"default"))
242 if (!strcmp(
string,
"vpn_gateway"))
261 else if (!strcmp(
string,
"net_gateway"))
271 msg(
M_INFO,
PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
280 else if (!strcmp(
string,
"remote_host"))
317 struct addrinfo **network_list,
324 struct in_addr special = {0};
346 special.s_addr = htonl(special.s_addr);
347 char buf[INET_ADDRSTRLEN];
348 inet_ntop(AF_INET, &special, buf,
sizeof(buf));
350 AF_INET, network_list);
355 ro->
network, NULL, 0, NULL, AF_INET, network_list);
414 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");
556 const in_addr_t addr)
570 if ((rl->
rgi.
flags & rgi_needed) == rgi_needed
580 l2 = ((~
gateway->netmask)+1)>>1;
582 r1->gateway = target;
584 r1->netmask = ~(l2-1);
600 && (rl->
rgi.
flags & rgi_needed) == rgi_needed
606 #ifndef TARGET_ANDROID
631 const char *remote_endpoint,
633 in_addr_t remote_host,
660 #if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
676 bool defined =
false;
713 struct addrinfo *netlist = NULL;
722 struct addrinfo *curele;
723 for (curele = netlist; curele; curele = curele->ai_next)
728 new->
network = ntohl(((
struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
750 const struct in6_addr *host )
752 unsigned int bits = r6->
netbits;
761 for (i = 0; bits >= 8; i++, bits -= 8)
763 if (r6->
network.s6_addr[i] != host->s6_addr[i])
774 mask = 0xff << (8-bits);
776 if ( (r6->
network.s6_addr[i] & mask) == (host->s6_addr[i] & mask ))
787 const char *remote_endpoint,
789 const struct in6_addr *remote_host_ipv6,
795 bool need_remote_ipv6_route;
801 if (remote_host_ipv6)
807 if (default_metric >= 0)
814 remote_host_ipv6 ?
print_in6_addr(*remote_host_ipv6, 0, &gc) :
"n/a" );
820 #if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
831 if (inet_pton( AF_INET6, remote_endpoint,
846 need_remote_ipv6_route =
false;
863 #ifndef TARGET_ANDROID
871 need_remote_ipv6_route =
true;
872 msg(
D_ROUTE,
"ROUTE6: %s/%d overlaps IPv6 remote %s, adding host route to VPN endpoint",
882 if (need_remote_ipv6_route)
890 r6->
network = *remote_host_ipv6;
900 r6->iface = rl6->
rgi6.iface;
909 msg(
M_WARN,
"ROUTE6: IPv6 route overlaps with IPv6 remote address, but could not determine IPv6 gateway address + interface, expect failure\n" );
965 for (
int i = 0; i < rb->
n_bypass; ++i)
1007 const char err[] =
"NOTE: unable to redirect IPv4 default gateway --";
1016 msg(
M_WARN,
"%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
1027 msg(
M_WARN,
"%s Cannot read current default gateway from system", err);
1032 #ifndef TARGET_ANDROID
1062 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1069 &rl->
rgi,
es, ctx) && ret;
1192 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv4 "
1193 "route. However, no IPv4 has been configured for %s, "
1194 "therefore the route installation may fail or may not work "
1198 #ifdef ENABLE_MANAGEMENT
1228 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv6 "
1229 "route. However, no IPv6 has been configured for %s, "
1230 "therefore the route installation may fail or may not work "
1285 #ifndef ENABLE_SMALL
1292 return "default (not set)";
1303 msg(level,
" route %s/%s/%s/%s",
1317 msg(level,
" [redirect_default_gateway local=%d]",
1363 msg(msglevel,
"%s",
BSTR(&out));
1394 msg(msglevel,
"%s",
BSTR(&out));
1463 buf_printf( &name1,
"route_ipv6_network_%d", i );
1468 buf_printf( &name2,
"route_ipv6_gateway_%d", i );
1474 buf_printf( &name3,
"route_ipv6_metric_%d", i);
1510 #define LR_NOMATCH 0
1523 && (rgi->
flags & rgi_needed) == rgi_needed
1525 && netmask == 0xFFFFFFFF)
1535 for (i = 0; i < rgi->
n_addrs; ++i)
1550 #if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1577 #if !defined(TARGET_LINUX)
1579 #if !defined(TARGET_AIX)
1591 #if defined(TARGET_LINUX)
1592 const char *
iface = NULL;
1610 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1615 msg(
M_WARN,
"ERROR: Linux route add command failed");
1619 #elif defined (TARGET_ANDROID)
1624 openvpn_snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1630 bool ret = management_android_control(
management,
"ROUTE", out);
1633 #elif defined (_WIN32)
1654 const char *method =
"service";
1668 "ERROR: Windows route add command failed");
1671 method =
"route.exe";
1676 method =
"ipapi [adaptive]";
1679 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1682 "ERROR: Windows route add command failed [adaptive]");
1685 method =
"route.exe";
1694 msg(
D_ROUTE,
"Route addition via %s %s", method,
1699 #elif defined (TARGET_SOLARIS)
1725 "ERROR: Solaris route add command failed");
1728 #elif defined(TARGET_FREEBSD)
1749 "ERROR: FreeBSD route add command failed");
1752 #elif defined(TARGET_DRAGONFLY)
1773 "ERROR: DragonFly route add command failed");
1776 #elif defined(TARGET_DARWIN)
1807 "ERROR: OS X route add command failed");
1810 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1831 "ERROR: OpenBSD/NetBSD route add command failed");
1834 #elif defined(TARGET_AIX)
1840 network, netbits, gateway);
1843 "ERROR: AIX route add command failed");
1848 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");
1877 int bits_to_clear = 128 - r6->
netbits;
1879 while (
byte >= 0 && bits_to_clear > 0)
1881 if (bits_to_clear >= 8)
1883 r6->
network.s6_addr[
byte--] = 0; bits_to_clear -= 8;
1887 r6->
network.s6_addr[
byte--] &= (0xff << bits_to_clear); bits_to_clear = 0;
1894 unsigned int flags,
const struct env_set *
es,
1898 bool gateway_needed =
false;
1910 if (r6->iface != NULL)
1913 if (!IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway) )
1915 gateway_needed =
true;
1924 #if defined(TARGET_DARWIN) \
1925 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1926 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1932 if (r6->iface != NULL && gateway_needed
1933 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
1935 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
1936 char *tmp =
gc_malloc( len,
true, &gc );
1937 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
1943 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1946 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu",
1965 gateway_needed =
true;
1968 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway))
1971 "parameter for a --route-ipv6 option and no default was set via "
1972 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1973 "IPv6 route to %s/%d.", network, r6->
netbits);
1978 #if defined(TARGET_LINUX)
1987 gateway_needed ? &r6->
gateway : NULL,
1991 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1996 msg(
M_WARN,
"ERROR: Linux route add command failed");
2000 #elif defined (TARGET_ANDROID)
2007 #elif defined (_WIN32)
2017 #elif defined (TARGET_SOLARIS)
2044 "ERROR: Solaris route add -inet6 command failed");
2047 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2065 "ERROR: *BSD route add -inet6 command failed");
2068 #elif defined(TARGET_DARWIN)
2085 "ERROR: MacOS X route add -inet6 command failed");
2088 #elif defined(TARGET_OPENBSD)
2092 network, r6->
netbits, gateway );
2096 "ERROR: OpenBSD route add -inet6 command failed");
2099 #elif defined(TARGET_NETBSD)
2103 network, r6->
netbits, gateway );
2107 "ERROR: NetBSD route add -inet6 command failed");
2110 #elif defined(TARGET_AIX)
2114 network, r6->
netbits, gateway);
2117 "ERROR: AIX route add command failed");
2121 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");
2149 #if !defined(TARGET_LINUX)
2150 const char *network;
2151 #if !defined(TARGET_AIX)
2152 const char *netmask;
2154 #if !defined(TARGET_ANDROID)
2155 const char *gateway;
2170 #if !defined(TARGET_LINUX)
2172 #if !defined(TARGET_AIX)
2175 #if !defined(TARGET_ANDROID)
2186 #if defined(TARGET_LINUX)
2194 &r->
gateway, NULL, 0, metric) < 0)
2196 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2198 #elif defined (_WIN32)
2212 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2217 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2228 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2231 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2242 #elif defined (TARGET_SOLARIS)
2253 #elif defined(TARGET_FREEBSD)
2264 #elif defined(TARGET_DRAGONFLY)
2275 #elif defined(TARGET_DARWIN)
2279 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s",
2297 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2308 #elif defined(TARGET_ANDROID)
2310 "needed. The VpnService API allows routes to be set "
2311 "on connect only and will clean up automatically.");
2312 #elif defined(TARGET_AIX)
2318 network, netbits, gateway);
2324 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");
2337 unsigned int flags,
const struct env_set *
es,
2340 const char *network;
2347 #if !defined(_WIN32)
2348 #if !defined(TARGET_LINUX)
2349 const char *gateway;
2351 #if !defined(TARGET_SOLARIS)
2352 bool gateway_needed =
false;
2354 if (r6->iface != NULL)
2357 gateway_needed =
true;
2366 gateway_needed =
true;
2375 #if !defined(TARGET_LINUX) && !defined(_WIN32)
2379 #if defined(TARGET_DARWIN) \
2380 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2381 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2387 if (r6->iface != NULL && gateway_needed
2388 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
2390 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
2392 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
2399 #if defined(TARGET_LINUX)
2407 gateway_needed ? &r6->
gateway : NULL, device, 0,
2410 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2413 #elif defined (_WIN32)
2423 #elif defined (TARGET_SOLARIS)
2436 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2455 #elif defined(TARGET_DARWIN)
2473 #elif defined(TARGET_OPENBSD)
2477 network, r6->
netbits, gateway );
2482 #elif defined(TARGET_NETBSD)
2486 network, r6->
netbits, gateway );
2491 #elif defined(TARGET_AIX)
2495 network, r6->
netbits, gateway);
2498 #elif defined(TARGET_ANDROID)
2500 "needed. The VpnService API allows routes to be set "
2501 "on connect only and will clean up automatically.");
2503 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");
2519 static const MIB_IPFORWARDTABLE *
2523 PMIB_IPFORWARDTABLE rt = NULL;
2526 status = GetIpForwardTable(NULL, &size, TRUE);
2527 if (
status == ERROR_INSUFFICIENT_BUFFER)
2529 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2530 status = GetIpForwardTable(rt, &size, TRUE);
2533 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2544 const in_addr_t gateway,
2561 const IP_ADAPTER_INFO *adapters,
2562 const in_addr_t gateway)
2595 bool adapter_up =
false;
2609 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2621 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
2627 adapter_up ?
"up" :
"down");
2633 static const MIB_IPFORWARDROW *
2637 DWORD lowest_metric = MAXDWORD;
2638 const MIB_IPFORWARDROW *ret = NULL;
2643 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2645 const MIB_IPFORWARDROW *row = &routes->table[i];
2646 const in_addr_t net = ntohl(row->dwForwardDest);
2647 const in_addr_t mask = ntohl(row->dwForwardMask);
2648 const DWORD index = row->dwForwardIfIndex;
2649 const DWORD metric = row->dwForwardMetric1;
2658 if (!net && !mask && metric < lowest_metric)
2661 lowest_metric = metric;
2682 const IP_ADAPTER_INFO *ai;
2700 memcpy(rgi->
hwaddr, ai->Address, 6);
2718 bool on_tun =
false;
2723 ret = tun_adapter->Index;
2734 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2740 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2764 MIB_IPFORWARD_ROW2 BestRoute;
2765 SOCKADDR_INET DestinationAddress, BestSourceAddress;
2772 CLEAR(DestinationAddress);
2774 DestinationAddress.si_family = AF_INET6;
2777 DestinationAddress.Ipv6.sin6_addr = *dest;
2780 status = GetBestInterfaceEx( (
struct sockaddr *)&DestinationAddress, &BestIfIndex );
2784 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2790 msg(
D_ROUTE,
"GetBestInterfaceEx() returned if=%d", (
int) BestIfIndex );
2793 &DestinationAddress, 0,
2794 &BestRoute, &BestSourceAddress );
2798 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2805 BestRoute.InterfaceIndex,
2806 print_in6_addr( BestRoute.DestinationPrefix.Prefix.Ipv6.sin6_addr, 0, &gc),
2807 BestRoute.DestinationPrefix.PrefixLength,
2809 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d",
2810 (
int) BestRoute.Metric,
2811 (
int) BestRoute.Loopback,
2812 (
int) BestRoute.AutoconfigureAddress,
2813 (
int) BestRoute.Immortal );
2820 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr) )
2840 MIB_IPFORWARDROW fr;
2842 fr.dwForwardDest = htonl(r->
network);
2843 fr.dwForwardMask = htonl(r->
netmask);
2844 fr.dwForwardPolicy = 0;
2845 fr.dwForwardNextHop = htonl(r->
gateway);
2846 fr.dwForwardIfIndex = if_index;
2847 fr.dwForwardType = 4;
2848 fr.dwForwardProto = 3;
2849 fr.dwForwardAge = 0;
2850 fr.dwForwardNextHopAS = 0;
2859 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2864 status = CreateIpForwardEntry(&fr);
2870 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2877 const unsigned int forward_metric_limit = 2048;
2879 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2883 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2885 status = CreateIpForwardEntry(&fr);
2888 msg(
D_ROUTE,
"ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2889 (
unsigned int)fr.dwForwardMetric1,
2890 (
unsigned int)fr.dwForwardType);
2894 else if (
status != ERROR_BAD_ARGUMENTS)
2904 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2910 msg(
M_WARN,
"ERROR: route addition failed using CreateIpForwardEntry: "
2912 (
unsigned int)
status, (
unsigned int)if_index);
2932 MIB_IPFORWARDROW fr;
2935 fr.dwForwardDest = htonl(r->
network);
2936 fr.dwForwardMask = htonl(r->
netmask);
2937 fr.dwForwardPolicy = 0;
2938 fr.dwForwardNextHop = htonl(r->
gateway);
2939 fr.dwForwardIfIndex = if_index;
2941 status = DeleteIpForwardEntry(&fr);
2949 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
2976 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
3007 .prefix.ipv4.s_addr = htonl(r->
network),
3008 .gateway.ipv4.s_addr = htonl(r->
gateway),
3009 .iface = { .index = if_index, .name =
"" },
3014 if (
msg.prefix_len == -1)
3016 msg.prefix_len = 32;
3030 PMIB_IPFORWARD_ROW2 fwd_row;
3033 fwd_row =
gc_malloc(
sizeof(*fwd_row),
true, &gc);
3035 fwd_row->ValidLifetime = 0xffffffff;
3036 fwd_row->PreferredLifetime = 0xffffffff;
3037 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
3039 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
3040 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
3041 fwd_row->DestinationPrefix.PrefixLength = (UINT8) r->
netbits;
3042 fwd_row->NextHop.si_family = AF_INET6;
3043 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
3052 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
3060 if (err != NO_ERROR)
3064 fwd_row->InterfaceLuid = luid;
3065 fwd_row->InterfaceIndex = 0;
3070 err = CreateIpForwardEntry2(fwd_row);
3074 err = DeleteIpForwardEntry2(fwd_row);
3078 if (err != NO_ERROR)
3083 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
3085 fwd_row->InterfaceIndex);
3089 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
3094 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3132 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3138 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3145 add ?
"addition" :
"deletion",
3181 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3185 (
int)r->dwForwardPolicy,
3186 (
int)r->dwForwardIfIndex,
3187 (
int)r->dwForwardType,
3188 (
int)r->dwForwardProto,
3189 (
int)r->dwForwardAge,
3190 (
int)r->dwForwardNextHopAS,
3191 (
int)r->dwForwardMetric1,
3192 (
int)r->dwForwardMetric2,
3193 (
int)r->dwForwardMetric3,
3194 (
int)r->dwForwardMetric4,
3195 (
int)r->dwForwardMetric5);
3209 msg(msglev,
"SYSTEM ROUTING TABLE");
3212 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3220 #elif defined(TARGET_ANDROID)
3235 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3237 strcpy(rgi->iface,
"android-gw");
3258 strcpy(rgi6->iface,
"android-gw");
3261 #elif defined(TARGET_LINUX)
3268 char best_name[IFNAMSIZ];
3274 if (net_route_v4_best_gw(ctx, NULL, &rgi->
gateway.
addr, best_name) == 0)
3286 struct ifreq *ifr, *ifend;
3287 in_addr_t addr, netmask;
3290 struct ifreq ifs[20];
3292 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3297 ifc.ifc_len =
sizeof(ifs);
3299 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3301 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3306 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3307 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3309 if (ifr->ifr_addr.sa_family == AF_INET)
3312 addr = ntohl(((
struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
3315 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3318 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3322 if (!(ifreq.ifr_flags & IFF_UP))
3331 if (strcmp(ifreq.ifr_name, best_name))
3337 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3339 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3350 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3354 netmask = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3368 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3372 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3373 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3375 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3378 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3421 if (strlen(rgi6->iface) > 0)
3439 #elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) \
3440 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
3441 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3443 #include <sys/types.h>
3444 #include <sys/socket.h>
3445 #include <netinet/in.h>
3446 #include <net/route.h>
3447 #include <net/if_dl.h>
3448 #if !defined(TARGET_SOLARIS)
3449 #include <ifaddrs.h>
3453 struct rt_msghdr m_rtm;
3473 #if defined(TARGET_DARWIN)
3474 #define ROUNDUP(a) \
3475 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3476 #elif defined(TARGET_NETBSD)
3477 #define ROUNDUP(a) RT_ROUNDUP(a)
3479 #define ROUNDUP(a) \
3480 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3483 #if defined(TARGET_SOLARIS)
3484 #define NEXTADDR(w, u) \
3485 if (rtm_addrs & (w)) { \
3486 l = sizeof(u); memmove(cp, &(u), l); cp += ROUNDUP(l); \
3489 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3491 #define NEXTADDR(w, u) \
3492 if (rtm_addrs & (w)) { \
3493 l = ((struct sockaddr *)&(u))->sa_len; memmove(cp, &(u), l); cp += ROUNDUP(l); \
3496 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3499 #define max(a, b) ((a) > (b) ? (a) : (b))
3505 struct rtmsg m_rtmsg;
3507 int seq, l, pid, rtm_addrs;
3509 struct sockaddr so_dst, so_mask;
3510 char *cp = m_rtmsg.m_space;
3511 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3512 struct rt_msghdr *rtm_aux;
3514 #define rtm m_rtmsg.m_rtm
3521 #ifdef TARGET_OPENBSD
3522 rtm_addrs = RTA_DST | RTA_NETMASK;
3524 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3527 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3528 bzero(&so_dst,
sizeof(so_dst));
3529 bzero(&so_mask,
sizeof(so_mask));
3530 bzero(&rtm,
sizeof(
struct rt_msghdr));
3532 rtm.rtm_type = RTM_GET;
3533 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3534 rtm.rtm_version = RTM_VERSION;
3535 rtm.rtm_seq = ++seq;
3536 #ifdef TARGET_OPENBSD
3537 rtm.rtm_tableid = getrtable();
3539 rtm.rtm_addrs = rtm_addrs;
3541 so_dst.sa_family = AF_INET;
3542 so_mask.sa_family = AF_INET;
3544 #ifndef TARGET_SOLARIS
3545 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3546 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3549 NEXTADDR(RTA_DST, so_dst);
3550 NEXTADDR(RTA_NETMASK, so_mask);
3552 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3555 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3561 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3568 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3569 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3575 cp = ((
char *)(rtm_aux + 1));
3576 if (rtm_aux->rtm_addrs)
3578 for (i = 1; i; i <<= 1)
3580 if (i & rtm_aux->rtm_addrs)
3582 sa = (
struct sockaddr *)cp;
3583 if (i == RTA_GATEWAY)
3587 else if (i == RTA_IFP)
3604 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3613 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3614 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3616 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3617 rgi->iface[adl->sdl_nlen] =
'\0';
3628 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3636 ifr.ifr_addr.sa_family = AF_INET;
3637 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3639 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3647 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3654 #if defined(TARGET_SOLARIS)
3656 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3663 struct ifreq ifreq = { 0 };
3666 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3667 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3669 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3673 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3677 struct ifaddrs *ifap, *ifa;
3679 if (getifaddrs(&ifap) != 0)
3685 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3687 if (ifa->ifa_addr != NULL
3688 && ifa->ifa_addr->sa_family == AF_LINK
3689 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ) )
3691 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3692 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3716 #if defined(TARGET_SOLARIS)
3718 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3726 struct rtmsg m_rtmsg;
3728 int seq, l, pid, rtm_addrs;
3730 struct sockaddr_in6 so_dst, so_mask;
3731 char *cp = m_rtmsg.m_space;
3732 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3733 struct rt_msghdr *rtm_aux;
3740 #ifdef TARGET_OPENBSD
3741 rtm_addrs = RTA_DST | RTA_NETMASK;
3743 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3746 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3747 bzero(&so_dst,
sizeof(so_dst));
3748 bzero(&so_mask,
sizeof(so_mask));
3749 bzero(&rtm,
sizeof(
struct rt_msghdr));
3751 rtm.rtm_type = RTM_GET;
3752 rtm.rtm_flags = RTF_UP;
3753 rtm.rtm_version = RTM_VERSION;
3754 rtm.rtm_seq = ++seq;
3755 #ifdef TARGET_OPENBSD
3756 rtm.rtm_tableid = getrtable();
3759 so_dst.sin6_family = AF_INET6;
3760 so_mask.sin6_family = AF_INET6;
3763 && !IN6_IS_ADDR_UNSPECIFIED(dest) )
3765 so_dst.sin6_addr = *dest;
3767 rtm_addrs &= ~RTA_NETMASK;
3770 rtm.rtm_addrs = rtm_addrs;
3772 #ifndef TARGET_SOLARIS
3773 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3774 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3777 NEXTADDR(RTA_DST, so_dst);
3778 NEXTADDR(RTA_NETMASK, so_mask);
3780 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3783 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3789 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3797 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3799 while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3806 cp = ((
char *)(rtm_aux + 1));
3807 if (rtm_aux->rtm_addrs)
3809 for (i = 1; i; i <<= 1)
3811 if (i & rtm_aux->rtm_addrs)
3813 sa = (
struct sockaddr *)cp;
3814 if (i == RTA_GATEWAY)
3818 else if (i == RTA_IFP)
3834 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3835 struct in6_addr gw = s6->sin6_addr;
3837 #ifndef TARGET_SOLARIS
3842 if (gate->sa_len ==
sizeof(
struct sockaddr_in6)
3843 && IN6_IS_ADDR_LINKLOCAL(&gw) )
3845 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3848 if (gate->sa_len !=
sizeof(
struct sockaddr_in6)
3849 || IN6_IS_ADDR_UNSPECIFIED(&gw) )
3862 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3863 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3865 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3915 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
3925 const int addrlen =
sizeof(in_addr_t) * 8;
3927 if ((network & netmask) == network)
3929 for (i = 0; i <= addrlen; ++i)
3932 if (mask == netmask)
3956 const int addrlen =
sizeof(in_addr_t) * 8;
3958 for (i = 0; i <= addrlen; ++i)
3961 if (mask == netmask)
3992 bool succeed =
false;
3998 iplist = iplist->Next;
4062 const in_addr_t nonlocal_netmask = 0x80000000L;
4069 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4071 const MIB_IPFORWARDROW *row = &rt->table[i];
4072 const in_addr_t net = ntohl(row->dwForwardDest);
4073 const in_addr_t mask = ntohl(row->dwForwardMask);
4074 if (mask > nonlocal_netmask && (addr & mask) == net)