Also, minor fix to OS X get_default_gateway function:
* include net/route.h directly rather than selectively paste stuff
from it into route.c
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6925 e7ae566f-a301-0410-adde-c780ea21d3b5
... | ... |
@@ -600,6 +600,27 @@ init_static (void) |
600 | 600 |
return false; |
601 | 601 |
#endif |
602 | 602 |
|
603 |
+#ifdef TEST_GET_DEFAULT_GATEWAY |
|
604 |
+ { |
|
605 |
+ struct gc_arena gc = gc_new (); |
|
606 |
+ in_addr_t addr; |
|
607 |
+ char macaddr[6]; |
|
608 |
+ |
|
609 |
+ if (get_default_gateway(&addr, NULL)) |
|
610 |
+ msg (M_INFO, "GW %s", print_in_addr_t(addr, 0, &gc)); |
|
611 |
+ else |
|
612 |
+ msg (M_INFO, "GDG ERROR"); |
|
613 |
+ |
|
614 |
+ if (get_default_gateway_mac_addr(macaddr)) |
|
615 |
+ msg (M_INFO, "MAC %s", format_hex_ex (macaddr, 6, 0, 1, ":", &gc)); |
|
616 |
+ else |
|
617 |
+ msg (M_INFO, "GDGMA ERROR"); |
|
618 |
+ |
|
619 |
+ gc_free (&gc); |
|
620 |
+ return false; |
|
621 |
+ } |
|
622 |
+#endif |
|
623 |
+ |
|
603 | 624 |
#ifdef GEN_PATH_TEST |
604 | 625 |
{ |
605 | 626 |
struct gc_arena gc = gc_new (); |
... | ... |
@@ -1791,70 +1791,26 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
1791 | 1791 |
#include <sys/types.h> |
1792 | 1792 |
#include <sys/socket.h> |
1793 | 1793 |
#include <netinet/in.h> |
1794 |
+#include <net/route.h> |
|
1795 |
+#include <net/if_dl.h> |
|
1794 | 1796 |
|
1795 |
-/* all of this is taken from <net/route.h> in Darwin */ |
|
1796 |
-#define RTA_DST 0x1 |
|
1797 |
-#define RTA_GATEWAY 0x2 |
|
1798 |
-#define RTA_NETMASK 0x4 |
|
1799 |
- |
|
1800 |
-#define RTM_GET 0x4 |
|
1801 |
-#define RTM_VERSION 5 |
|
1802 |
- |
|
1803 |
-#define RTF_UP 0x1 |
|
1804 |
-#define RTF_GATEWAY 0x2 |
|
1805 |
- |
|
1806 |
-/* |
|
1807 |
- * These numbers are used by reliable protocols for determining |
|
1808 |
- * retransmission behavior and are included in the routing structure. |
|
1809 |
- */ |
|
1810 |
-struct rt_metrics { |
|
1811 |
- u_long rmx_locks; /* Kernel must leave these values alone */ |
|
1812 |
- u_long rmx_mtu; /* MTU for this path */ |
|
1813 |
- u_long rmx_hopcount; /* max hops expected */ |
|
1814 |
- u_long rmx_expire; /* lifetime for route, e.g. redirect */ |
|
1815 |
- u_long rmx_recvpipe; /* inbound delay-bandwidth product */ |
|
1816 |
- u_long rmx_sendpipe; /* outbound delay-bandwidth product */ |
|
1817 |
- u_long rmx_ssthresh; /* outbound gateway buffer limit */ |
|
1818 |
- u_long rmx_rtt; /* estimated round trip time */ |
|
1819 |
- u_long rmx_rttvar; /* estimated rtt variance */ |
|
1820 |
- u_long rmx_pksent; /* packets sent using this route */ |
|
1821 |
- u_long rmx_filler[4]; /* will be used for T/TCP later */ |
|
1822 |
-}; |
|
1823 |
- |
|
1824 |
-/* |
|
1825 |
- * Structures for routing messages. |
|
1826 |
- */ |
|
1827 |
-struct rt_msghdr { |
|
1828 |
- u_short rtm_msglen; /* to skip over non-understood messages */ |
|
1829 |
- u_char rtm_version; /* future binary compatibility */ |
|
1830 |
- u_char rtm_type; /* message type */ |
|
1831 |
- u_short rtm_index; /* index for associated ifp */ |
|
1832 |
- int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ |
|
1833 |
- int rtm_addrs; /* bitmask identifying sockaddrs in msg */ |
|
1834 |
- pid_t rtm_pid; /* identify sender */ |
|
1835 |
- int rtm_seq; /* for sender to identify action */ |
|
1836 |
- int rtm_errno; /* why failed */ |
|
1837 |
- int rtm_use; /* from rtentry */ |
|
1838 |
- u_long rtm_inits; /* which metrics we are initializing */ |
|
1839 |
- struct rt_metrics rtm_rmx; /* metrics themselves */ |
|
1840 |
-}; |
|
1841 |
- |
|
1842 |
-struct { |
|
1797 |
+struct rtmsg { |
|
1843 | 1798 |
struct rt_msghdr m_rtm; |
1844 | 1799 |
char m_space[512]; |
1845 |
-} m_rtmsg; |
|
1800 |
+}; |
|
1846 | 1801 |
|
1847 | 1802 |
#define ROUNDUP(a) \ |
1848 | 1803 |
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) |
1849 | 1804 |
|
1850 |
-bool |
|
1851 |
-get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
|
1805 |
+static bool |
|
1806 |
+get_default_gateway_ex (in_addr_t *ret, in_addr_t *netmask, char **ifname) |
|
1852 | 1807 |
{ |
1853 | 1808 |
struct gc_arena gc = gc_new (); |
1809 |
+ struct rtmsg m_rtmsg; |
|
1854 | 1810 |
int s, seq, l, pid, rtm_addrs, i; |
1855 | 1811 |
struct sockaddr so_dst, so_mask; |
1856 | 1812 |
char *cp = m_rtmsg.m_space; |
1857 |
- struct sockaddr *gate = NULL, *sa; |
|
1813 |
+ struct sockaddr *gate = NULL, *ifp = NULL, *sa; |
|
1858 | 1814 |
struct rt_msghdr *rtm_aux; |
1859 | 1815 |
|
1860 | 1816 |
#define NEXTADDR(w, u) \ |
... | ... |
@@ -1868,8 +1824,9 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
1868 | 1868 |
|
1869 | 1869 |
pid = getpid(); |
1870 | 1870 |
seq = 0; |
1871 |
- rtm_addrs = RTA_DST | RTA_NETMASK; |
|
1871 |
+ rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP; |
|
1872 | 1872 |
|
1873 |
+ bzero(&m_rtmsg, sizeof(m_rtmsg)); |
|
1873 | 1874 |
bzero(&so_dst, sizeof(so_dst)); |
1874 | 1875 |
bzero(&so_mask, sizeof(so_mask)); |
1875 | 1876 |
bzero(&rtm, sizeof(struct rt_msghdr)); |
... | ... |
@@ -1911,11 +1868,16 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
1911 | 1911 |
cp = ((char *)(rtm_aux + 1)); |
1912 | 1912 |
if (rtm_aux->rtm_addrs) { |
1913 | 1913 |
for (i = 1; i; i <<= 1) |
1914 |
- if (i & rtm_aux->rtm_addrs) { |
|
1915 |
- sa = (struct sockaddr *)cp; |
|
1916 |
- if (i == RTA_GATEWAY ) |
|
1917 |
- gate = sa; |
|
1918 |
- ADVANCE(cp, sa); |
|
1914 |
+ { |
|
1915 |
+ if (i & rtm_aux->rtm_addrs) |
|
1916 |
+ { |
|
1917 |
+ sa = (struct sockaddr *)cp; |
|
1918 |
+ if (i == RTA_GATEWAY ) |
|
1919 |
+ gate = sa; |
|
1920 |
+ else if (i == RTA_IFP) |
|
1921 |
+ ifp = sa; |
|
1922 |
+ ADVANCE(cp, sa); |
|
1923 |
+ } |
|
1919 | 1924 |
} |
1920 | 1925 |
} |
1921 | 1926 |
else |
... | ... |
@@ -1938,6 +1900,16 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
1938 | 1938 |
*netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway |
1939 | 1939 |
} |
1940 | 1940 |
|
1941 |
+ if (ifp && ifname) |
|
1942 |
+ { |
|
1943 |
+ struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp; |
|
1944 |
+ char *name = malloc(adl->sdl_nlen+1); |
|
1945 |
+ check_malloc_return(name); |
|
1946 |
+ memcpy(name, adl->sdl_data, adl->sdl_nlen); |
|
1947 |
+ name[adl->sdl_nlen] = '\0'; |
|
1948 |
+ *ifname = name; |
|
1949 |
+ } |
|
1950 |
+ |
|
1941 | 1951 |
gc_free (&gc); |
1942 | 1952 |
return true; |
1943 | 1953 |
} |
... | ... |
@@ -1948,6 +1920,12 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
1948 | 1948 |
} |
1949 | 1949 |
} |
1950 | 1950 |
|
1951 |
+bool |
|
1952 |
+get_default_gateway (in_addr_t *ret, in_addr_t *netmask) |
|
1953 |
+{ |
|
1954 |
+ return get_default_gateway_ex(ret, netmask, NULL); |
|
1955 |
+} |
|
1956 |
+ |
|
1951 | 1957 |
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) |
1952 | 1958 |
|
1953 | 1959 |
#include <sys/types.h> |
... | ... |
@@ -2353,6 +2331,73 @@ get_default_gateway_mac_addr (unsigned char *macaddr) |
2353 | 2353 |
return false; |
2354 | 2354 |
} |
2355 | 2355 |
|
2356 |
+#elif defined(TARGET_DARWIN) |
|
2357 |
+ |
|
2358 |
+bool |
|
2359 |
+get_default_gateway_mac_addr (unsigned char *macaddr) |
|
2360 |
+{ |
|
2361 |
+# define max(a,b) ((a) > (b) ? (a) : (b)) |
|
2362 |
+ struct gc_arena gc = gc_new (); |
|
2363 |
+ struct ifconf ifc; |
|
2364 |
+ struct ifreq *ifr; |
|
2365 |
+ char *buffer, *cp; |
|
2366 |
+ bool status = false; |
|
2367 |
+ in_addr_t gw = 0; |
|
2368 |
+ char *ifname = NULL; |
|
2369 |
+ int sockfd = -1; |
|
2370 |
+ const int bufsize = 4096; |
|
2371 |
+ |
|
2372 |
+ if (!get_default_gateway_ex (&gw, NULL, &ifname)) /* get interface name of default gateway */ |
|
2373 |
+ { |
|
2374 |
+ msg (M_WARN, "GDGMA: get_default_gateway_ex failed"); |
|
2375 |
+ goto done; |
|
2376 |
+ } |
|
2377 |
+ |
|
2378 |
+ if (!ifname) |
|
2379 |
+ { |
|
2380 |
+ msg (M_WARN, "GDGMA: cannot get default gateway ifname"); |
|
2381 |
+ goto done; |
|
2382 |
+ } |
|
2383 |
+ |
|
2384 |
+ buffer = (char *) gc_malloc (bufsize, false, &gc); |
|
2385 |
+ |
|
2386 |
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0); |
|
2387 |
+ if (sockfd < 0) |
|
2388 |
+ { |
|
2389 |
+ msg (M_WARN, "GDGMA: socket failed"); |
|
2390 |
+ goto done; |
|
2391 |
+ } |
|
2392 |
+ |
|
2393 |
+ ifc.ifc_len = bufsize; |
|
2394 |
+ ifc.ifc_buf = buffer; |
|
2395 |
+ |
|
2396 |
+ if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0) |
|
2397 |
+ { |
|
2398 |
+ msg (M_WARN, "GDGMA: ioctl failed"); |
|
2399 |
+ goto done; |
|
2400 |
+ } |
|
2401 |
+ |
|
2402 |
+ for (cp = buffer; cp < buffer + bufsize; ) |
|
2403 |
+ { |
|
2404 |
+ ifr = (struct ifreq *)cp; |
|
2405 |
+ if (ifr->ifr_addr.sa_family == AF_LINK && !strncmp(ifr->ifr_name, ifname, IFNAMSIZ)) |
|
2406 |
+ { |
|
2407 |
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr; |
|
2408 |
+ memcpy(macaddr, LLADDR(sdl), 6); |
|
2409 |
+ status = true; |
|
2410 |
+ } |
|
2411 |
+ cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len); |
|
2412 |
+ } |
|
2413 |
+ |
|
2414 |
+ done: |
|
2415 |
+ if (sockfd >= 0) |
|
2416 |
+ close (sockfd); |
|
2417 |
+ free (ifname); |
|
2418 |
+ gc_free (&gc); |
|
2419 |
+ return status; |
|
2420 |
+# undef max |
|
2421 |
+} |
|
2422 |
+ |
|
2356 | 2423 |
#else |
2357 | 2424 |
|
2358 | 2425 |
bool |