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)
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
1070 dmsg(
D_ROUTE,
"ROUTE remote_host protocol differs from tunneled");
1077 &rl->
rgi,
es, ctx) && ret;
1200 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv4 "
1201 "route. However, no IPv4 has been configured for %s, "
1202 "therefore the route installation may fail or may not work "
1206 #ifdef ENABLE_MANAGEMENT
1235 msg(
M_INFO,
"WARNING: OpenVPN was configured to add an IPv6 "
1236 "route. However, no IPv6 has been configured for %s, "
1237 "therefore the route installation may fail or may not work "
1293 #ifndef ENABLE_SMALL
1300 return "default (not set)";
1311 msg(level,
" route %s/%s/%s/%s",
1325 msg(level,
" [redirect_default_gateway local=%d]",
1371 msg(msglevel,
"%s",
BSTR(&out));
1402 msg(msglevel,
"%s",
BSTR(&out));
1471 buf_printf( &name1,
"route_ipv6_network_%d", i );
1476 buf_printf( &name2,
"route_ipv6_gateway_%d", i );
1482 buf_printf( &name3,
"route_ipv6_metric_%d", i);
1518 #define LR_NOMATCH 0
1531 && (rgi->
flags & rgi_needed) == rgi_needed
1533 && netmask == 0xFFFFFFFF)
1543 for (i = 0; i < rgi->
n_addrs; ++i)
1558 #if defined(TARGET_LINUX) || defined(_WIN32) || defined(TARGET_DARWIN)
1585 #if !defined(TARGET_LINUX)
1587 #if !defined(TARGET_AIX)
1599 #if defined(TARGET_LINUX)
1600 const char *
iface = NULL;
1618 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
1623 msg(
M_WARN,
"ERROR: Linux route add command failed");
1627 #elif defined (TARGET_ANDROID)
1632 snprintf(out,
sizeof(out),
"%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1636 snprintf(out,
sizeof(out),
"%s %s %s", network, netmask, gateway);
1638 bool ret = management_android_control(
management,
"ROUTE", out);
1641 #elif defined (_WIN32)
1662 const char *method =
"service";
1676 "ERROR: Windows route add command failed");
1679 method =
"route.exe";
1684 method =
"ipapi [adaptive]";
1687 msg(
D_ROUTE,
"Route addition fallback to route.exe");
1690 "ERROR: Windows route add command failed [adaptive]");
1693 method =
"route.exe";
1702 msg(
D_ROUTE,
"Route addition via %s %s", method,
1707 #elif defined (TARGET_SOLARIS)
1733 "ERROR: Solaris route add command failed");
1736 #elif defined(TARGET_FREEBSD)
1757 "ERROR: FreeBSD route add command failed");
1760 #elif defined(TARGET_DRAGONFLY)
1781 "ERROR: DragonFly route add command failed");
1784 #elif defined(TARGET_DARWIN)
1815 "ERROR: OS X route add command failed");
1818 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1839 "ERROR: OpenBSD/NetBSD route add command failed");
1842 #elif defined(TARGET_AIX)
1848 network, netbits, gateway);
1851 "ERROR: AIX route add command failed");
1855 #elif defined(TARGET_HAIKU)
1866 "ERROR: Haiku inet route add command failed");
1870 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");
1899 int bits_to_clear = 128 - r6->
netbits;
1901 while (
byte >= 0 && bits_to_clear > 0)
1903 if (bits_to_clear >= 8)
1905 r6->
network.s6_addr[
byte--] = 0; bits_to_clear -= 8;
1909 r6->
network.s6_addr[
byte--] &= (0xff << bits_to_clear); bits_to_clear = 0;
1916 unsigned int flags,
const struct env_set *
es,
1920 bool gateway_needed =
false;
1932 if (r6->iface != NULL)
1935 if (!IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway) )
1937 gateway_needed =
true;
1946 #if defined(TARGET_DARWIN) \
1947 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
1948 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1954 if (r6->iface != NULL && gateway_needed
1955 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
1957 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
1959 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
1965 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1968 msg(
D_ROUTE,
"add_route_ipv6(%s/%d -> %s metric %d) IF %lu",
1987 gateway_needed =
true;
1990 if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&r6->
gateway))
1993 "parameter for a --route-ipv6 option and no default was set via "
1994 "--ifconfig-ipv6 or --route-ipv6-gateway option. Not installing "
1995 "IPv6 route to %s/%d.", network, r6->
netbits);
2000 #if defined(TARGET_LINUX)
2009 gateway_needed ? &r6->
gateway : NULL,
2013 msg(
D_ROUTE,
"NOTE: Linux route add command failed because route exists");
2018 msg(
M_WARN,
"ERROR: Linux route add command failed");
2022 #elif defined (TARGET_ANDROID)
2025 snprintf(out,
sizeof(out),
"%s/%d %s", network, r6->
netbits, device);
2029 #elif defined (_WIN32)
2039 #elif defined (TARGET_SOLARIS)
2066 "ERROR: Solaris route add -inet6 command failed");
2069 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2087 "ERROR: *BSD route add -inet6 command failed");
2090 #elif defined(TARGET_DARWIN)
2107 "ERROR: MacOS X route add -inet6 command failed");
2110 #elif defined(TARGET_OPENBSD)
2114 network, r6->
netbits, gateway );
2118 "ERROR: OpenBSD route add -inet6 command failed");
2121 #elif defined(TARGET_NETBSD)
2125 network, r6->
netbits, gateway );
2129 "ERROR: NetBSD route add -inet6 command failed");
2132 #elif defined(TARGET_AIX)
2136 network, r6->
netbits, gateway);
2139 "ERROR: AIX route add command failed");
2142 #elif defined(TARGET_HAIKU)
2153 "ERROR: Haiku inet6 route add command failed");
2157 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");
2185 #if !defined(TARGET_LINUX)
2186 const char *network;
2187 #if !defined(TARGET_AIX)
2188 const char *netmask;
2190 #if !defined(TARGET_ANDROID)
2191 const char *gateway;
2206 #if !defined(TARGET_LINUX)
2208 #if !defined(TARGET_AIX)
2211 #if !defined(TARGET_ANDROID)
2222 #if defined(TARGET_LINUX)
2230 &r->
gateway, NULL, 0, metric) < 0)
2232 msg(
M_WARN,
"ERROR: Linux route delete command failed");
2234 #elif defined (_WIN32)
2248 msg(
D_ROUTE,
"Route deletion via service %s",
status ?
"succeeded" :
"failed");
2253 msg(
D_ROUTE,
"Route deletion via IPAPI %s",
status ?
"succeeded" :
"failed");
2264 msg(
D_ROUTE,
"Route deletion via IPAPI %s [adaptive]",
status ?
"succeeded" :
"failed");
2267 msg(
D_ROUTE,
"Route deletion fallback to route.exe");
2278 #elif defined (TARGET_SOLARIS)
2289 #elif defined(TARGET_FREEBSD)
2300 #elif defined(TARGET_DRAGONFLY)
2311 #elif defined(TARGET_DARWIN)
2315 argv_printf(&
argv,
"%s delete -cloning -net %s -netmask %s -interface %s",
2333 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2344 #elif defined(TARGET_ANDROID)
2346 "needed. The VpnService API allows routes to be set "
2347 "on connect only and will clean up automatically.");
2348 #elif defined(TARGET_AIX)
2354 network, netbits, gateway);
2359 #elif defined(TARGET_HAIKU)
2372 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");
2388 const char *network;
2395 #if !defined(_WIN32)
2396 #if !defined(TARGET_LINUX)
2397 const char *gateway;
2399 #if !defined(TARGET_SOLARIS)
2400 bool gateway_needed =
false;
2402 if (r6->iface != NULL)
2405 gateway_needed =
true;
2414 gateway_needed =
true;
2423 #if !defined(TARGET_LINUX) && !defined(_WIN32)
2427 #if defined(TARGET_DARWIN) \
2428 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
2429 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2435 if (r6->iface != NULL && gateway_needed
2436 && IN6_IS_ADDR_LINKLOCAL(&r6->
gateway) )
2438 int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
2440 snprintf( tmp, len,
"%s%%%s", gateway, r6->iface );
2447 #if defined(TARGET_LINUX)
2455 gateway_needed ? &r6->
gateway : NULL, device, 0,
2458 msg(
M_WARN,
"ERROR: Linux route v6 delete command failed");
2461 #elif defined (_WIN32)
2471 #elif defined (TARGET_SOLARIS)
2484 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2503 #elif defined(TARGET_DARWIN)
2521 #elif defined(TARGET_OPENBSD)
2525 network, r6->
netbits, gateway );
2530 #elif defined(TARGET_NETBSD)
2534 network, r6->
netbits, gateway );
2539 #elif defined(TARGET_AIX)
2543 network, r6->
netbits, gateway);
2547 #elif defined(TARGET_ANDROID)
2549 "needed. The VpnService API allows routes to be set "
2550 "on connect only and will clean up automatically.");
2551 #elif defined(TARGET_HAIKU)
2564 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");
2580 static const MIB_IPFORWARDTABLE *
2584 PMIB_IPFORWARDTABLE rt = NULL;
2587 status = GetIpForwardTable(NULL, &size, TRUE);
2588 if (
status == ERROR_INSUFFICIENT_BUFFER)
2590 rt = (PMIB_IPFORWARDTABLE)
gc_malloc(size,
false,
gc);
2591 status = GetIpForwardTable(rt, &size, TRUE);
2594 msg(
D_ROUTE,
"NOTE: GetIpForwardTable returned error: %s (code=%u)",
2605 const in_addr_t gateway,
2622 const IP_ADAPTER_INFO *adapters,
2623 const in_addr_t gateway)
2656 bool adapter_up =
false;
2670 for (r = rl->
routes, len = 0; r; r = r->
next, ++len)
2682 msg(
D_ROUTE,
"TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
2688 adapter_up ?
"up" :
"down");
2694 static const MIB_IPFORWARDROW *
2698 DWORD lowest_metric = MAXDWORD;
2699 const MIB_IPFORWARDROW *ret = NULL;
2704 for (DWORD i = 0; i < routes->dwNumEntries; ++i)
2706 const MIB_IPFORWARDROW *row = &routes->table[i];
2707 const in_addr_t net = ntohl(row->dwForwardDest);
2708 const in_addr_t mask = ntohl(row->dwForwardMask);
2709 const DWORD index = row->dwForwardIfIndex;
2710 const DWORD metric = row->dwForwardMetric1;
2719 if (!net && !mask && metric < lowest_metric)
2722 lowest_metric = metric;
2748 DWORD best_if_index;
2754 status = GetBestInterfaceEx((
struct sockaddr *)dest, &best_if_index);
2757 msg(
D_ROUTE,
"NOTE: GetBestInterfaceEx returned error: %s (code=%u)",
2763 msg(
D_ROUTE_DEBUG,
"GetBestInterfaceEx() returned if=%d", (
int)best_if_index);
2768 SOCKADDR_INET best_src;
2770 status = GetBestRoute2(&luid, best_if_index, NULL,
2771 dest, 0, best_route, &best_src);
2774 msg(
D_ROUTE,
"NOTE: GetIpForwardEntry2 returned error: %s (code=%u)",
2794 sa.si_family = AF_INET;
2795 sa.Ipv4.sin_addr.s_addr = htonl(dest);
2798 MIB_IPFORWARD_ROW2 best_route;
2807 rgi->
gateway.
addr = ntohl(best_route.NextHop.Ipv4.sin_addr.S_un.S_addr);
2820 memcpy(rgi->
hwaddr, ai->Address, 6);
2824 in_addr_t nm = inet_addr(ai->IpAddressList.IpMask.String);
2844 bool on_tun =
false;
2849 ret = tun_adapter->Index;
2860 msg(
M_WARN,
"Warning: route gateway is not reachable on any active network adapters: %s",
2866 msg(
M_WARN,
"Warning: route gateway is ambiguous: %s (%d matches)",
2892 SOCKADDR_INET DestinationAddress;
2893 CLEAR(DestinationAddress);
2894 DestinationAddress.si_family = AF_INET6;
2897 DestinationAddress.Ipv6.sin6_addr = *dest;
2900 MIB_IPFORWARD_ROW2 BestRoute;
2910 BestRoute.InterfaceIndex,
2911 print_in6_addr( BestRoute.DestinationPrefix.Prefix.Ipv6.sin6_addr, 0, &
gc),
2912 BestRoute.DestinationPrefix.PrefixLength,
2914 msg(
D_ROUTE,
"GDG6: Metric=%d, Loopback=%d, AA=%d, I=%d",
2915 (
int) BestRoute.Metric,
2916 (
int) BestRoute.Loopback,
2917 (
int) BestRoute.AutoconfigureAddress,
2918 (
int) BestRoute.Immortal );
2925 if (IN6_IS_ADDR_UNSPECIFIED(&BestRoute.NextHop.Ipv6.sin6_addr) )
2945 MIB_IPFORWARDROW fr;
2947 fr.dwForwardDest = htonl(r->
network);
2948 fr.dwForwardMask = htonl(r->
netmask);
2949 fr.dwForwardPolicy = 0;
2950 fr.dwForwardNextHop = htonl(r->
gateway);
2951 fr.dwForwardIfIndex = if_index;
2952 fr.dwForwardType = 4;
2953 fr.dwForwardProto = 3;
2954 fr.dwForwardAge = 0;
2955 fr.dwForwardNextHopAS = 0;
2964 msg(
M_WARN,
"Warning: address %s is not a network address in relation to netmask %s",
2969 status = CreateIpForwardEntry(&fr);
2975 else if (
status == ERROR_OBJECT_ALREADY_EXISTS)
2982 const unsigned int forward_metric_limit = 2048;
2984 for (; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2988 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2990 status = CreateIpForwardEntry(&fr);
2993 msg(
D_ROUTE,
"ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2994 (
unsigned int)fr.dwForwardMetric1,
2995 (
unsigned int)fr.dwForwardType);
2999 else if (
status != ERROR_BAD_ARGUMENTS)
3009 if (
status == ERROR_OBJECT_ALREADY_EXISTS)
3015 msg(
M_WARN,
"ERROR: route addition failed using CreateIpForwardEntry: "
3017 (
unsigned int)
status, (
unsigned int)if_index);
3037 MIB_IPFORWARDROW fr;
3040 fr.dwForwardDest = htonl(r->
network);
3041 fr.dwForwardMask = htonl(r->
netmask);
3042 fr.dwForwardPolicy = 0;
3043 fr.dwForwardNextHop = htonl(r->
gateway);
3044 fr.dwForwardIfIndex = if_index;
3046 status = DeleteIpForwardEntry(&fr);
3054 msg(
M_WARN,
"ERROR: route deletion failed using DeleteIpForwardEntry: %s",
3081 msg(
M_WARN,
"ERROR: route %s failed using service: %s [status=%u if_index=%d]",
3112 .prefix.ipv4.s_addr = htonl(r->
network),
3113 .gateway.ipv4.s_addr = htonl(r->
gateway),
3114 .iface = { .index = if_index, .name =
"" },
3119 if (
msg.prefix_len == -1)
3121 msg.prefix_len = 32;
3135 PMIB_IPFORWARD_ROW2 fwd_row;
3140 fwd_row->ValidLifetime = 0xffffffff;
3141 fwd_row->PreferredLifetime = 0xffffffff;
3142 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
3144 fwd_row->DestinationPrefix.Prefix.si_family = AF_INET6;
3145 fwd_row->DestinationPrefix.Prefix.Ipv6.sin6_addr = r->
network;
3146 fwd_row->DestinationPrefix.PrefixLength = (UINT8) r->
netbits;
3147 fwd_row->NextHop.si_family = AF_INET6;
3148 fwd_row->NextHop.Ipv6.sin6_addr = r->
gateway;
3157 inet_pton(AF_INET6,
"fe80::8", &fwd_row->NextHop.Ipv6.sin6_addr);
3165 if (err != NO_ERROR)
3169 fwd_row->InterfaceLuid = luid;
3170 fwd_row->InterfaceIndex = 0;
3175 err = CreateIpForwardEntry2(fwd_row);
3179 err = DeleteIpForwardEntry2(fwd_row);
3183 if (err != NO_ERROR)
3188 msg(
M_WARN,
"ERROR: route %s failed using ipapi: %s [status=%lu if_index=%lu]",
3190 fwd_row->InterfaceIndex);
3194 msg(
D_ROUTE,
"IPv6 route addition using ipapi failed because route exists");
3199 msg(
D_ROUTE,
"IPv6 route %s using ipapi", add ?
"added" :
"deleted");
3237 inet_pton(AF_INET6,
"fe80::8", &
msg.gateway.ipv6);
3243 msg.iface.name[
sizeof(
msg.iface.name) - 1] =
'\0';
3250 add ?
"addition" :
"deletion",
3286 buf_printf(&out,
"%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
3290 (
int)r->dwForwardPolicy,
3291 (
int)r->dwForwardIfIndex,
3292 (
int)r->dwForwardType,
3293 (
int)r->dwForwardProto,
3294 (
int)r->dwForwardAge,
3295 (
int)r->dwForwardNextHopAS,
3296 (
int)r->dwForwardMetric1,
3297 (
int)r->dwForwardMetric2,
3298 (
int)r->dwForwardMetric3,
3299 (
int)r->dwForwardMetric4,
3300 (
int)r->dwForwardMetric5);
3314 msg(msglev,
"SYSTEM ROUTING TABLE");
3317 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
3325 #elif defined(TARGET_ANDROID)
3340 rgi->
gateway.
addr = 127 << 24 |
'd' << 16 |
'g' << 8 |
'w';
3342 strcpy(rgi->iface,
"android-gw");
3363 strcpy(rgi6->iface,
"android-gw");
3366 #elif defined(TARGET_LINUX)
3373 char best_name[IFNAMSIZ];
3379 if (net_route_v4_best_gw(ctx, &dest, &rgi->
gateway.
addr, best_name) == 0)
3391 struct ifreq *ifr, *ifend;
3392 in_addr_t addr, netmask;
3395 struct ifreq ifs[20];
3397 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3402 ifc.ifc_len =
sizeof(ifs);
3404 if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
3406 msg(
M_WARN,
"GDG: ioctl(SIOCGIFCONF) failed");
3411 ifend = ifs + (ifc.ifc_len /
sizeof(
struct ifreq));
3412 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
3414 if (ifr->ifr_addr.sa_family == AF_INET)
3417 addr = ntohl(((
struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
3420 strncpynt(ifreq.ifr_name, ifr->ifr_name,
sizeof(ifreq.ifr_name));
3423 if (ioctl(sd, SIOCGIFFLAGS, &ifreq) < 0)
3427 if (!(ifreq.ifr_flags & IFF_UP))
3436 if (strcmp(ifreq.ifr_name, best_name))
3442 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl(sd, SIOCGIFDSTADDR, &ifreq) >= 0)
3444 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3455 if (ioctl(sd, SIOCGIFNETMASK, &ifreq) < 0)
3459 netmask = ntohl(((
struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
3473 strncpynt(rgi->iface, ifreq.ifr_name,
sizeof(rgi->iface));
3477 memset(&ifreq.ifr_hwaddr, 0,
sizeof(
struct sockaddr));
3478 if (ioctl(sd, SIOCGIFHWADDR, &ifreq) < 0)
3480 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3483 memcpy(rgi->
hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
3526 if (strlen(rgi6->iface) > 0)
3544 #elif defined(TARGET_DARWIN) || defined(TARGET_SOLARIS) \
3545 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
3546 || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
3548 #include <sys/types.h>
3549 #include <sys/socket.h>
3550 #include <netinet/in.h>
3551 #include <net/route.h>
3552 #include <net/if_dl.h>
3553 #if !defined(TARGET_SOLARIS)
3554 #include <ifaddrs.h>
3558 struct rt_msghdr m_rtm;
3578 #if defined(TARGET_DARWIN)
3579 #define ROUNDUP(a) \
3580 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
3581 #elif defined(TARGET_NETBSD)
3582 #define ROUNDUP(a) RT_ROUNDUP(a)
3584 #define ROUNDUP(a) \
3585 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
3588 #if defined(TARGET_SOLARIS)
3589 #define NEXTADDR(w, u) \
3590 if (rtm_addrs & (w)) { \
3591 l = sizeof(u); memmove(cp, &(u), l); cp += ROUNDUP(l); \
3594 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
3596 #define NEXTADDR(w, u) \
3597 if (rtm_addrs & (w)) { \
3598 l = ((struct sockaddr *)&(u))->sa_len; memmove(cp, &(u), l); cp += ROUNDUP(l); \
3601 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
3604 #define max(a, b) ((a) > (b) ? (a) : (b))
3610 struct rtmsg m_rtmsg;
3612 int seq, l, pid, rtm_addrs;
3614 struct sockaddr so_dst, so_mask;
3615 char *cp = m_rtmsg.m_space;
3616 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3617 struct rt_msghdr *rtm_aux;
3619 #define rtm m_rtmsg.m_rtm
3626 #ifdef TARGET_OPENBSD
3627 rtm_addrs = RTA_DST | RTA_NETMASK;
3629 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3632 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3633 bzero(&so_dst,
sizeof(so_dst));
3634 bzero(&so_mask,
sizeof(so_mask));
3635 bzero(&rtm,
sizeof(
struct rt_msghdr));
3637 rtm.rtm_type = RTM_GET;
3638 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3639 rtm.rtm_version = RTM_VERSION;
3640 rtm.rtm_seq = ++seq;
3641 #ifdef TARGET_OPENBSD
3642 rtm.rtm_tableid = getrtable();
3644 rtm.rtm_addrs = rtm_addrs;
3646 so_dst.sa_family = AF_INET;
3647 so_mask.sa_family = AF_INET;
3649 #ifndef TARGET_SOLARIS
3650 so_dst.sa_len =
sizeof(
struct sockaddr_in);
3651 so_mask.sa_len =
sizeof(
struct sockaddr_in);
3654 NEXTADDR(RTA_DST, so_dst);
3655 NEXTADDR(RTA_NETMASK, so_mask);
3657 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3660 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3666 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3673 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3674 }
while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3680 cp = ((
char *)(rtm_aux + 1));
3681 if (rtm_aux->rtm_addrs)
3683 for (i = 1; i; i <<= 1)
3685 if (i & rtm_aux->rtm_addrs)
3687 sa = (
struct sockaddr *)cp;
3688 if (i == RTA_GATEWAY)
3692 else if (i == RTA_IFP)
3709 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)gate)->sin_addr.s_addr);
3718 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3719 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi->iface))
3721 memcpy(rgi->iface, adl->sdl_data, adl->sdl_nlen);
3722 rgi->iface[adl->sdl_nlen] =
'\0';
3733 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3741 ifr.ifr_addr.sa_family = AF_INET;
3742 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
3744 if (ioctl(sockfd, SIOCGIFNETMASK, (
char *)&ifr) < 0)
3752 rgi->
gateway.
netmask = ntohl(((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
3759 #if defined(TARGET_SOLARIS)
3761 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3768 struct ifreq ifreq = { 0 };
3771 strncpynt(ifreq.ifr_name, rgi->iface,
sizeof(ifreq.ifr_name));
3772 if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
3774 msg(
M_WARN,
"GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
3778 memcpy(rgi->
hwaddr, &ifreq.ifr_addr.sa_data, 6);
3782 struct ifaddrs *ifap, *ifa;
3784 if (getifaddrs(&ifap) != 0)
3790 for (ifa = ifap; ifa; ifa = ifa->ifa_next)
3792 if (ifa->ifa_addr != NULL
3793 && ifa->ifa_addr->sa_family == AF_LINK
3794 && !strncmp(ifa->ifa_name, rgi->iface, IFNAMSIZ) )
3796 struct sockaddr_dl *sdl = (
struct sockaddr_dl *)ifa->ifa_addr;
3797 memcpy(rgi->
hwaddr, LLADDR(sdl), 6);
3821 #if defined(TARGET_SOLARIS)
3823 #define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in6)))
3831 struct rtmsg m_rtmsg;
3833 int seq, l, pid, rtm_addrs;
3835 struct sockaddr_in6 so_dst, so_mask;
3836 char *cp = m_rtmsg.m_space;
3837 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
3838 struct rt_msghdr *rtm_aux;
3845 #ifdef TARGET_OPENBSD
3846 rtm_addrs = RTA_DST | RTA_NETMASK;
3848 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
3851 bzero(&m_rtmsg,
sizeof(m_rtmsg));
3852 bzero(&so_dst,
sizeof(so_dst));
3853 bzero(&so_mask,
sizeof(so_mask));
3854 bzero(&rtm,
sizeof(
struct rt_msghdr));
3856 rtm.rtm_type = RTM_GET;
3857 rtm.rtm_flags = RTF_UP;
3858 rtm.rtm_version = RTM_VERSION;
3859 rtm.rtm_seq = ++seq;
3860 #ifdef TARGET_OPENBSD
3861 rtm.rtm_tableid = getrtable();
3864 so_dst.sin6_family = AF_INET6;
3865 so_mask.sin6_family = AF_INET6;
3868 && !IN6_IS_ADDR_UNSPECIFIED(dest) )
3870 so_dst.sin6_addr = *dest;
3872 rtm_addrs &= ~RTA_NETMASK;
3875 rtm.rtm_addrs = rtm_addrs;
3877 #ifndef TARGET_SOLARIS
3878 so_dst.sin6_len =
sizeof(
struct sockaddr_in6);
3879 so_mask.sin6_len =
sizeof(
struct sockaddr_in6);
3882 NEXTADDR(RTA_DST, so_dst);
3883 NEXTADDR(RTA_NETMASK, so_mask);
3885 rtm.rtm_msglen = l = cp - (
char *)&m_rtmsg;
3888 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
3894 if (
write(sockfd, (
char *)&m_rtmsg, l) < 0)
3902 l =
read(sockfd, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
3904 while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3911 cp = ((
char *)(rtm_aux + 1));
3912 if (rtm_aux->rtm_addrs)
3914 for (i = 1; i; i <<= 1)
3916 if (i & rtm_aux->rtm_addrs)
3918 sa = (
struct sockaddr *)cp;
3919 if (i == RTA_GATEWAY)
3923 else if (i == RTA_IFP)
3939 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *)gate;
3940 struct in6_addr gw = s6->sin6_addr;
3942 #ifndef TARGET_SOLARIS
3947 if (gate->sa_len ==
sizeof(
struct sockaddr_in6)
3948 && IN6_IS_ADDR_LINKLOCAL(&gw) )
3950 gw.s6_addr[2] = gw.s6_addr[3] = 0;
3953 if (gate->sa_len !=
sizeof(
struct sockaddr_in6)
3954 || IN6_IS_ADDR_UNSPECIFIED(&gw) )
3968 const struct sockaddr_dl *adl = (
struct sockaddr_dl *) ifp;
3969 if (adl->sdl_nlen && adl->sdl_nlen <
sizeof(rgi6->iface))
3971 memcpy(rgi6->iface, adl->sdl_data, adl->sdl_nlen);
3986 #elif defined(TARGET_HAIKU)
3993 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
3996 msg(
M_ERRNO,
"%s: Error opening socket for AF_INET", __func__);
4000 struct ifconf config;
4001 config.ifc_len =
sizeof(config.ifc_value);
4002 if (ioctl(sockfd, SIOCGRTSIZE, &config,
sizeof(
struct ifconf)) < 0)
4004 msg(
M_ERRNO,
"%s: Error getting routing table size", __func__);
4008 uint32 size = (uint32)config.ifc_value;
4014 void *
buffer = malloc(size);
4017 config.ifc_len = size;
4019 if (ioctl(sockfd, SIOCGRTTABLE, &config,
sizeof(
struct ifconf)) < 0)
4025 struct ifreq *
interface = (struct ifreq *)
buffer;
4026 struct ifreq *end = (
struct ifreq *)((uint8 *)
buffer + size);
4028 while (interface < end)
4030 struct route_entry
route = interface->ifr_route;
4031 if ((
route.flags & RTF_GATEWAY) != 0 && (
route.flags & RTF_DEFAULT) != 0)
4033 rgi->
gateway.
addr = ntohl(((
struct sockaddr_in *)
route.gateway)->sin_addr.s_addr);
4035 strncpy(rgi->iface, interface->ifr_name,
sizeof(rgi->iface));
4038 int32 address_size = 0;
4039 if (
route.destination != NULL)
4041 address_size +=
route.destination->sa_len;
4043 if (
route.mask != NULL)
4045 address_size +=
route.mask->sa_len;
4047 if (
route.gateway != NULL)
4049 address_size +=
route.gateway->sa_len;
4052 interface = (struct ifreq *)((addr_t)
interface +
IF_NAMESIZE
4053 + sizeof(struct route_entry) + address_size);
4101 msg(
D_ROUTE,
"no support for get_default_gateway_ipv6() on this system");
4111 const int addrlen =
sizeof(in_addr_t) * 8;
4113 if ((network & netmask) == network)
4115 for (i = 0; i <= addrlen; ++i)
4118 if (mask == netmask)
4142 const int addrlen =
sizeof(in_addr_t) * 8;
4144 for (i = 0; i <= addrlen; ++i)
4147 if (mask == netmask)
4178 bool succeed =
false;
4184 iplist = iplist->Next;
4248 const in_addr_t nonlocal_netmask = 0x80000000L;
4255 for (DWORD i = 0; i < rt->dwNumEntries; ++i)
4257 const MIB_IPFORWARDROW *row = &rt->table[i];
4258 const in_addr_t net = ntohl(row->dwForwardDest);
4259 const in_addr_t mask = ntohl(row->dwForwardMask);
4260 if (mask > nonlocal_netmask && (addr & mask) == net)