Browse code

Merge get_default_gateway() implementation for all 4+1 BSD variants.

This was 3 times mostly the same code, with the 4 traditional BSDs
only differing in a single line, while MacOS X had more refined code
to do not only gateway determination, but also netmask, interface name
and MAC address.

The MacOS X code works perfectly well on the other BSDs *if* one macro
is #ifdef'ed to use "(uint32_t)" on MacOS X and "(long)" on all other
BSDs, 32 and 64 bit variants. API change by OSX when going to 64bit.

Tested on FreeBSD 8.3/i386, FreeBSD 9.1/amd64, NetbSD 5.1/amd64,
OpenBSD 4.9/i386, OpenBSD 5.4/amd64 (= all affected platforms except
DragonFly BSD).

See also trac#42 and trac#340.

Signed-off-by: Gert Doering <gert@greenie.muc.de>
Lazy-Ack-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1389706398-26922-1-git-send-email-gert@greenie.muc.de>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8233

Gert Doering authored on 2014/01/14 22:33:18
Showing 1 changed files
... ...
@@ -2583,118 +2583,9 @@ get_default_gateway (struct route_gateway_info *rgi)
2583 2583
   gc_free (&gc);
2584 2584
 }
2585 2585
 
2586
-#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
2587
-
2588
-#include <sys/types.h>
2589
-#include <sys/socket.h>
2590
-#include <netinet/in.h>
2591
-#include <net/route.h>
2592
-
2593
-struct {
2594
-  struct rt_msghdr m_rtm;
2595
-  char       m_space[512];
2596
-} m_rtmsg;
2597
-
2598
-#define ROUNDUP(a) \
2599
-        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2600
-
2601
-/*
2602
- * FIXME -- add support for netmask, hwaddr, and iface
2603
- */
2604
-void
2605
-get_default_gateway (struct route_gateway_info *rgi)
2606
-{
2607
-  struct gc_arena gc = gc_new ();
2608
-  int s, seq, l, pid, rtm_addrs, i;
2609
-  struct sockaddr so_dst, so_mask;
2610
-  char *cp = m_rtmsg.m_space; 
2611
-  struct sockaddr *gate = NULL, *sa;
2612
-  struct  rt_msghdr *rtm_aux;
2613
-
2614
-#define NEXTADDR(w, u) \
2615
-        if (rtm_addrs & (w)) {\
2616
-            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2617
-        }
2618
-
2619
-#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2620
-
2621
-#define rtm m_rtmsg.m_rtm
2622
-
2623
-  CLEAR(*rgi);
2624
-
2625
-  pid = getpid();
2626
-  seq = 0;
2627
-  rtm_addrs = RTA_DST | RTA_NETMASK;
2628
-
2629
-  bzero(&so_dst, sizeof(so_dst));
2630
-  bzero(&so_mask, sizeof(so_mask));
2631
-  bzero(&rtm, sizeof(struct rt_msghdr));
2632
-
2633
-  rtm.rtm_type = RTM_GET;
2634
-  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2635
-  rtm.rtm_version = RTM_VERSION;
2636
-  rtm.rtm_seq = ++seq;
2637
-  rtm.rtm_addrs = rtm_addrs; 
2638
-
2639
-  so_dst.sa_family = AF_INET;
2640
-  so_dst.sa_len = sizeof(struct sockaddr_in);
2641
-  so_mask.sa_family = AF_INET;
2642
-  so_mask.sa_len = sizeof(struct sockaddr_in);
2643
-
2644
-  NEXTADDR(RTA_DST, so_dst);
2645
-  NEXTADDR(RTA_NETMASK, so_mask);
2646
-
2647
-  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2648
-
2649
-  s = socket(PF_ROUTE, SOCK_RAW, 0);
2650
-
2651
-  if (write(s, (char *)&m_rtmsg, l) < 0)
2652
-    {
2653
-      msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
2654
-      gc_free (&gc);
2655
-      close(s);
2656
-      return;
2657
-    }
2658
-
2659
-  do {
2660
-    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
2661
-  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
2662
-                        
2663
-  close(s);
2664
-
2665
-  rtm_aux = &rtm;
2666
-
2667
-  cp = ((char *)(rtm_aux + 1));
2668
-  if (rtm_aux->rtm_addrs) {
2669
-    for (i = 1; i; i <<= 1)
2670
-      if (i & rtm_aux->rtm_addrs) {
2671
-	sa = (struct sockaddr *)cp;
2672
-	if (i == RTA_GATEWAY )
2673
-	  gate = sa;
2674
-	ADVANCE(cp, sa);
2675
-      }
2676
-  }
2677
-  else
2678
-    {
2679
-      gc_free (&gc);
2680
-      return;
2681
-    }
2682
-
2683
-
2684
-  if (gate != NULL )
2685
-    {
2686
-      rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2687
-      rgi->flags |= RGI_ADDR_DEFINED;
2688
-
2689
-      gc_free (&gc);
2690
-    }
2691
-  else
2692
-    {
2693
-      gc_free (&gc);
2694
-    }
2695
-}
2696
-
2697
-#elif defined(TARGET_DARWIN)
2586
+#elif defined(TARGET_DARWIN) || \
2587
+	defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) || \
2588
+	defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2698 2589
 
2699 2590
 #include <sys/types.h>
2700 2591
 #include <sys/socket.h>
... ...
@@ -2707,8 +2598,25 @@ struct rtmsg {
2707 2707
   char       m_space[512];
2708 2708
 };
2709 2709
 
2710
-#define ROUNDUP(a) \
2710
+/* the route socket code is identical for all 4 supported BSDs and for
2711
+ * MacOS X (Darwin), with one crucial difference: when going from
2712
+ * 32 bit to 64 bit, the BSDs increased the structure size but kept
2713
+ * source code compatibility by keeping the use of "long", while
2714
+ * MacOS X decided to keep binary compatibility by *changing* the API
2715
+ * to use "uint32_t", thus 32 bit on all OS X variants
2716
+ *
2717
+ * We used to have a large amount of duplicate code here which really
2718
+ * differed only in this (long) vs. (uint32_t) - IMHO, worse than
2719
+ * having a combined block for all BSDs with this single #ifdef inside
2720
+ */
2721
+
2722
+#if defined(TARGET_DARWIN)
2723
+# define ROUNDUP(a) \
2711 2724
         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
2725
+#else
2726
+# define ROUNDUP(a) \
2727
+        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2728
+#endif
2712 2729
 
2713 2730
 #define NEXTADDR(w, u) \
2714 2731
         if (rtm_addrs & (w)) {\
... ...
@@ -2902,118 +2810,6 @@ get_default_gateway (struct route_gateway_info *rgi)
2902 2902
 
2903 2903
 #undef max
2904 2904
 
2905
-#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2906
-
2907
-#include <sys/types.h>
2908
-#include <sys/socket.h>
2909
-#include <netinet/in.h>
2910
-#include <net/route.h>
2911
-
2912
-struct {
2913
-  struct rt_msghdr m_rtm;
2914
-  char       m_space[512];
2915
-} m_rtmsg;
2916
-
2917
-#define ROUNDUP(a) \
2918
-        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2919
-
2920
-/*
2921
- * FIXME -- add support for netmask, hwaddr, and iface
2922
- */
2923
-void
2924
-get_default_gateway (struct route_gateway_info *rgi)
2925
-{
2926
-  struct gc_arena gc = gc_new ();
2927
-  int s, seq, l, rtm_addrs, i;
2928
-  pid_t pid;
2929
-  struct sockaddr so_dst, so_mask;
2930
-  char *cp = m_rtmsg.m_space; 
2931
-  struct sockaddr *gate = NULL, *sa;
2932
-  struct  rt_msghdr *rtm_aux;
2933
-
2934
-#define NEXTADDR(w, u) \
2935
-        if (rtm_addrs & (w)) {\
2936
-            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2937
-        }
2938
-
2939
-#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2940
-
2941
-#define rtm m_rtmsg.m_rtm
2942
-
2943
-  CLEAR(*rgi);
2944
-
2945
-  pid = getpid();
2946
-  seq = 0;
2947
-  rtm_addrs = RTA_DST | RTA_NETMASK;
2948
-
2949
-  bzero(&so_dst, sizeof(so_dst));
2950
-  bzero(&so_mask, sizeof(so_mask));
2951
-  bzero(&rtm, sizeof(struct rt_msghdr));
2952
-
2953
-  rtm.rtm_type = RTM_GET;
2954
-  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2955
-  rtm.rtm_version = RTM_VERSION;
2956
-  rtm.rtm_seq = ++seq;
2957
-  rtm.rtm_addrs = rtm_addrs; 
2958
-
2959
-  so_dst.sa_family = AF_INET;
2960
-  so_dst.sa_len = sizeof(struct sockaddr_in);
2961
-  so_mask.sa_family = AF_INET;
2962
-  so_mask.sa_len = sizeof(struct sockaddr_in);
2963
-
2964
-  NEXTADDR(RTA_DST, so_dst);
2965
-  NEXTADDR(RTA_NETMASK, so_mask);
2966
-
2967
-  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2968
-
2969
-  s = socket(PF_ROUTE, SOCK_RAW, 0);
2970
-
2971
-  if (write(s, (char *)&m_rtmsg, l) < 0)
2972
-    {
2973
-      msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
2974
-      gc_free (&gc);
2975
-      close(s);
2976
-      return;
2977
-    }
2978
-
2979
-  do {
2980
-    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
2981
-  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
2982
-                        
2983
-  close(s);
2984
-
2985
-  rtm_aux = &rtm;
2986
-
2987
-  cp = ((char *)(rtm_aux + 1));
2988
-  if (rtm_aux->rtm_addrs) {
2989
-    for (i = 1; i; i <<= 1)
2990
-      if (i & rtm_aux->rtm_addrs) {
2991
-	sa = (struct sockaddr *)cp;
2992
-	if (i == RTA_GATEWAY )
2993
-	  gate = sa;
2994
-	ADVANCE(cp, sa);
2995
-      }
2996
-  }
2997
-  else
2998
-    {
2999
-      gc_free (&gc);
3000
-      return;
3001
-    }
3002
-
3003
-
3004
-  if (gate != NULL )
3005
-    {
3006
-      rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
3007
-      rgi->flags |= RGI_ADDR_DEFINED;
3008
-
3009
-      gc_free (&gc);
3010
-    }
3011
-  else
3012
-    {
3013
-      gc_free (&gc);
3014
-    }
3015
-}
3016
-
3017 2905
 #else
3018 2906
 
3019 2907
 /*