Browse code

Implemented get_default_gateway_mac_addr for Mac OS X (previously, was only defined for Windows and Linux). This enables OS X to report the MAC address of the default gateway to the server for ID purposes when client-side --push-peer-info option is specified.

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

James Yonan authored on 2011/02/14 12:46:37
Showing 3 changed files
... ...
@@ -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
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1.3f])
2
+define(PRODUCT_VERSION,[2.1.3g])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])