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
... | ... |
@@ -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 |
/* |