Detect IP_PKTINFO / IP_RECVDSTADDR support during the configure
phase instead of repeating the following test in eight different
places:

 #if (defined(linux) && defined(IP_PKTINFO)) \
     || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \
                                && HAVE_STRUCT_MSGHDR_MSG_FLAGS
 ...
 #endif

Two side-effects of this patch are:
* IP_PKTINFO support is enabled on Cygwin.
* setsockopt(IP_RECVDSTADDR) is no longer invoked on Windows when
  built with Visual Studio or MinGW-gcc.
---
 configure                                        |  204 +++++++++++++++-------
 configure.d/config_os_misc4                      |   97 ++++++++++
 configure.d/config_os_struct_members             |   24 ---
 include/net-snmp/library/snmpUDPBaseDomain.h     |    3 +-
 include/net-snmp/library/snmpUDPDomain.h         |    3 +-
 include/net-snmp/library/snmpUDPIPv4BaseDomain.h |    3 +-
 include/net-snmp/net-snmp-config.h.in            |   12 +-
 snmplib/transports/snmpUDPBaseDomain.c           |   44 +++--
 snmplib/transports/snmpUDPDomain.c               |    6 +-
 snmplib/transports/snmpUDPIPv4BaseDomain.c       |   12 +-
 10 files changed, 282 insertions(+), 126 deletions(-)

diff --git a/configure.d/config_os_misc4 b/configure.d/config_os_misc4
index b6cb040..cc8bad2 100644
--- a/configure.d/config_os_misc4
+++ b/configure.d/config_os_misc4
@@ -317,3 +317,100 @@ And this can be very slow.])
     fi         # "test $ac_inet_ip_h = yes"
     ;;
 esac
+
+#   Check whether IP_PKTINFO is usable.
+#
+
+AC_CACHE_CHECK([for IP_PKTINFO ],
+                [ac_cv_have_ip_pktinfo],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <stdio.h>  /* printf() */
+#include <stdlib.h> /* malloc() */
+#include <string.h> /* memset() */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+], [
+    void *buf;
+    int len;
+    void *from;
+    socklen_t *fromlen;
+
+    struct iovec iov;
+    char *cmsg = malloc(CMSG_SPACE(sizeof(struct in_pktinfo)));
+    struct cmsghdr *cm;
+    struct msghdr msg;
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    memset(&msg, 0, sizeof msg);
+    msg.msg_name = from;
+    msg.msg_namelen = *fromlen;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &cmsg;
+    msg.msg_controllen = sizeof(cmsg);
+
+    for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
+        if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO) {
+            struct in_pktinfo* src = (struct in_pktinfo *)CMSG_DATA(cm);
+            printf("Address: %s; index: %d\n", inet_ntoa(src->ipi_addr),
+                  src->ipi_ifindex);
+        }
+    }
+])],
+[ac_cv_have_ip_pktinfo=yes],
+[ac_cv_have_ip_pktinfo=no]
+)])
+if test x$ac_cv_have_ip_pktinfo = xyes; then
+    AC_DEFINE(HAVE_IP_PKTINFO, 1, [Set if IP_PKTINFO is usable])
+fi
+
+#   Check whether IP_RECVDSTADDR is usable.
+#
+
+AC_CACHE_CHECK([for IP_RECVDSTADDR ],
+                [ac_cv_have_ip_recvdstaddr],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <stdio.h>  /* printf() */
+#include <stdlib.h> /* malloc() */
+#include <string.h> /* memset() */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+], [
+    void *buf;
+    int len;
+    void *from;
+    socklen_t *fromlen;
+
+    struct iovec iov;
+    char *cmsg = malloc(CMSG_SPACE(sizeof(struct in_addr)));
+    struct cmsghdr *cm;
+    struct msghdr msg;
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    memset(&msg, 0, sizeof msg);
+    msg.msg_name = from;
+    msg.msg_namelen = *fromlen;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &cmsg;
+    msg.msg_controllen = sizeof(cmsg);
+
+    for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
+        if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) {
+            struct in_addr* src = (struct in_addr *)CMSG_DATA(cm);
+            printf("Address: %s\n", inet_ntoa(src));
+        }
+    }
+])],
+[ac_cv_have_ip_recvdstaddr=yes],
+[ac_cv_have_ip_recvdstaddr=no]
+)])
+if test x$ac_cv_have_ip_recvdstaddr = xyes; then
+    AC_DEFINE(HAVE_IP_RECVDSTADDR, 1, [Set if IP_RECVDSTADDR is usable])
+fi
diff --git a/configure.d/config_os_struct_members 
b/configure.d/config_os_struct_members
index ce77458..a62e661 100644
--- a/configure.d/config_os_struct_members
+++ b/configure.d/config_os_struct_members
@@ -205,30 +205,6 @@ AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id],,,[
 #endif
     ]])
 
-#       struct msghdr
-#   Library:
-#
-AC_CHECK_MEMBERS([struct msghdr.msg_control,
-                  struct msghdr.msg_flags],,,[
-    AC_INCLUDES_DEFAULT()
-    [
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
-    ]])
-
 #       struct sockaddr_un
 #   Library:
 #
diff --git a/include/net-snmp/library/snmpUDPBaseDomain.h 
b/include/net-snmp/library/snmpUDPBaseDomain.h
index e61cdc8..2665e98 100644
--- a/include/net-snmp/library/snmpUDPBaseDomain.h
+++ b/include/net-snmp/library/snmpUDPBaseDomain.h
@@ -18,8 +18,7 @@ extern          "C" {
     int netsnmp_udpbase_send(netsnmp_transport *t, void *buf, int size,
                              void **opaque, int *olength);
 
-#if defined(linux) && defined(IP_PKTINFO) \
-    || defined(IP_RECVDSTADDR) && !defined(_MSC_VER)
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
     int netsnmp_udpbase_recvfrom(int s, void *buf, int len,
                                  struct sockaddr *from, socklen_t *fromlen,
                                  struct sockaddr *dstip, socklen_t *dstlen,
diff --git a/include/net-snmp/library/snmpUDPDomain.h 
b/include/net-snmp/library/snmpUDPDomain.h
index f030360..3a09dfd 100644
--- a/include/net-snmp/library/snmpUDPDomain.h
+++ b/include/net-snmp/library/snmpUDPDomain.h
@@ -48,8 +48,7 @@ void            netsnmp_udp_ctor(void);
  * protected-ish functions used by other core-code
  */
 char *netsnmp_udp_fmtaddr(netsnmp_transport *t, void *data, int len);
-#if defined(linux) && defined(IP_PKTINFO) || \
-    defined(IP_RECVDSTADDR) && !defined(_MSC_VER)
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
 int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from,
                          socklen_t *fromlen, struct sockaddr *dstip,
                          socklen_t *dstlen, int *if_index);
diff --git a/include/net-snmp/library/snmpUDPIPv4BaseDomain.h 
b/include/net-snmp/library/snmpUDPIPv4BaseDomain.h
index 54f8a49..6f7f2c2 100644
--- a/include/net-snmp/library/snmpUDPIPv4BaseDomain.h
+++ b/include/net-snmp/library/snmpUDPIPv4BaseDomain.h
@@ -27,8 +27,7 @@ extern          "C" {
     netsnmp_transport *netsnmp_udpipv4base_transport(struct sockaddr_in *addr,
                                                      int local);
 
-#if defined(linux) && defined(IP_PKTINFO) \
-    || defined(IP_RECVDSTADDR) && !defined(_MSC_VER)
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
     int netsnmp_udpipv4_recvfrom(int s, void *buf, int len,
                                  struct sockaddr *from, socklen_t *fromlen,
                                  struct sockaddr *dstip, socklen_t *dstlen,
diff --git a/include/net-snmp/net-snmp-config.h.in 
b/include/net-snmp/net-snmp-config.h.in
index 7bc4186..1085b2f 100644
--- a/include/net-snmp/net-snmp-config.h.in
+++ b/include/net-snmp/net-snmp-config.h.in
@@ -296,6 +296,12 @@
 /* Define to 1 if you have the <iphlpapi.h> header file. */
 #undef HAVE_IPHLPAPI_H
 
+/* Set if IP_PKTINFO is usable */
+#undef HAVE_IP_PKTINFO
+
+/* Set if IP_RECVDSTADDR is usable */
+#undef HAVE_IP_RECVDSTADDR
+
 /* Define to 1 if you have the `kinfo_get_cpus' function. */
 #undef HAVE_KINFO_GET_CPUS
 
@@ -902,12 +908,6 @@
 /* Define to 1 if `m_mbufs' is a member of `struct mbstat'. */
 #undef HAVE_STRUCT_MBSTAT_M_MBUFS
 
-/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
-#undef HAVE_STRUCT_MSGHDR_MSG_CONTROL
-
-/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
-#undef HAVE_STRUCT_MSGHDR_MSG_FLAGS
-
 /* Define to 1 if `n_value' is a member of `struct nlist64'. */
 #undef HAVE_STRUCT_NLIST64_N_VALUE
 
diff --git a/snmplib/transports/snmpUDPBaseDomain.c 
b/snmplib/transports/snmpUDPBaseDomain.c
index 5a2c197..d67257b 100644
--- a/snmplib/transports/snmpUDPBaseDomain.c
+++ b/snmplib/transports/snmpUDPBaseDomain.c
@@ -97,22 +97,17 @@ _netsnmp_udp_sockopt_set(int fd, int local)
     netsnmp_sock_buffer_set(fd, SO_RCVBUF, local, 0);
 }
 
-#if (defined(linux) && defined(IP_PKTINFO)) \
-    || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \
-                               && HAVE_STRUCT_MSGHDR_MSG_FLAGS
-#if  defined(linux) && defined(IP_PKTINFO)
-#elif defined(IP_RECVDSTADDR)
-# ifndef IP_SENDSRCADDR
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
+# if defined(IP_RECVDSTADDR) && !defined(IP_SENDSRCADDR)
 #  define IP_SENDSRCADDR IP_RECVDSTADDR /* DragonFly BSD */
 # endif
-#endif
 
 #define netsnmp_udpbase_recvfrom_sendto_defined
 
 enum {
-#if  defined(linux) && defined(IP_PKTINFO)
+#if defined(HAVE_IP_PKTINFO)
     cmsg_data_size = sizeof(struct in_pktinfo)
-#elif defined(IP_RECVDSTADDR)
+#elif defined(HAVE_IP_RECVDSTADDR)
     cmsg_data_size = sizeof(struct in_addr)
 #endif
 };
@@ -155,7 +150,7 @@ netsnmp_udpbase_recvfrom(int s, void *buf, int len, struct 
sockaddr *from,
     }
 
     for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm)) {
-#if  defined(linux) && defined(IP_PKTINFO)
+#if defined(HAVE_IP_PKTINFO)
         if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO) {
             struct in_pktinfo* src = (struct in_pktinfo *)CMSG_DATA(cm);
             netsnmp_assert(dstip->sa_family == AF_INET);
@@ -163,15 +158,14 @@ netsnmp_udpbase_recvfrom(int s, void *buf, int len, 
struct sockaddr *from,
             *if_index = src->ipi_ifindex;
             DEBUGMSGTL(("udpbase:recv",
                         "got destination (local) addr %s, iface %d\n",
-                        inet_ntoa(((struct sockaddr_in*)dstip)->sin_addr),
-                        *if_index));
+                        inet_ntoa(src->ipi_addr), *if_index));
         }
-#elif defined(IP_RECVDSTADDR)
+#elif defined(HAVE_IP_RECVDSTADDR)
         if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) {
             struct in_addr* src = (struct in_addr *)CMSG_DATA(cm);
             ((struct sockaddr_in*)dstip)->sin_addr = *src;
             DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s\n",
-                        inet_ntoa(((struct sockaddr_in*)dstip)->sin_addr)));
+                        inet_ntoa(*src)));
         }
 #endif
     }
@@ -208,14 +202,20 @@ int netsnmp_udpbase_sendto(int fd, struct in_addr *srcip, 
int if_index,
         cm = CMSG_FIRSTHDR(&m);
         cm->cmsg_len = CMSG_LEN(cmsg_data_size);
 
-#if  defined(linux) && defined(IP_PKTINFO)
+#if defined(HAVE_IP_PKTINFO)
         cm->cmsg_level = SOL_IP;
         cm->cmsg_type = IP_PKTINFO;
 
         {
-            struct in_pktinfo ipi = { 0 };
-            ipi.ipi_ifindex = 0;
+            struct in_pktinfo ipi;
+
+            memset(&ipi, 0, sizeof(ipi));
+            ipi.ipi_ifindex = if_index;
+#if defined(cygwin)
+            ipi.ipi_addr.s_addr = srcip->s_addr;
+#else
             ipi.ipi_spec_dst.s_addr = srcip->s_addr;
+#endif
             memcpy(CMSG_DATA(cm), &ipi, sizeof(ipi));
         }
 
@@ -232,9 +232,15 @@ int netsnmp_udpbase_sendto(int fd, struct in_addr *srcip, 
int if_index,
         DEBUGMSGTL(("udpbase:sendto", "re-sending on iface %d\n", if_index));
 
         {
-            struct in_pktinfo ipi = { 0 };
+            struct in_pktinfo ipi;
+
+            memset(&ipi, 0, sizeof(ipi));
             ipi.ipi_ifindex = if_index;
+#if defined(cygwin)
+            ipi.ipi_addr.s_addr = INADDR_ANY;
+#else
             ipi.ipi_spec_dst.s_addr = INADDR_ANY;
+#endif
             memcpy(CMSG_DATA(cm), &ipi, sizeof(ipi));
         }
 #elif defined(IP_SENDSRCADDR)
@@ -253,7 +259,7 @@ int netsnmp_udpbase_sendto(int fd, struct in_addr *srcip, 
int if_index,
 
     return sendmsg(fd, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
 }
-#endif /* (linux && IP_PKTINFO) || IP_RECVDSTADDR */
+#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
 
 /*
  * You can write something into opaque that will subsequently get passed back 
diff --git a/snmplib/transports/snmpUDPDomain.c 
b/snmplib/transports/snmpUDPDomain.c
index 638c2b1..ba127b3 100644
--- a/snmplib/transports/snmpUDPDomain.c
+++ b/snmplib/transports/snmpUDPDomain.c
@@ -102,9 +102,7 @@ netsnmp_udp_fmtaddr(netsnmp_transport *t, void *data, int 
len)
 
 
 
-#if (defined(linux) && defined(IP_PKTINFO)) \
-    || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \
-                               && HAVE_STRUCT_MSGHDR_MSG_FLAGS
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
 
 int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, 
socklen_t *fromlen, struct sockaddr *dstip, socklen_t *dstlen, int *if_index)
 {
@@ -119,7 +117,7 @@ int netsnmp_udp_sendto(int fd, struct in_addr *srcip, int 
if_index, struct socka
     /** udpiv4 just calls udpbase. should we skip directly to there? */
     return netsnmp_udpipv4_sendto(fd, srcip, if_index, remote, data, len);
 }
-#endif /* (linux && IP_PKTINFO) || IP_RECVDSTADDR */
+#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
 
 /*
  * Open a UDP-based transport for SNMP.  Local is TRUE if addr is the local
diff --git a/snmplib/transports/snmpUDPIPv4BaseDomain.c 
b/snmplib/transports/snmpUDPIPv4BaseDomain.c
index 0ca046c..ae856b4 100644
--- a/snmplib/transports/snmpUDPIPv4BaseDomain.c
+++ b/snmplib/transports/snmpUDPIPv4BaseDomain.c
@@ -44,9 +44,7 @@
 #include <net-snmp/library/sd-daemon.h>
 #endif
 
-#if (defined(linux) && defined(IP_PKTINFO)) \
-    || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \
-                               && HAVE_STRUCT_MSGHDR_MSG_FLAGS
+#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
 
 int netsnmp_udpipv4_recvfrom(int s, void *buf, int len, struct sockaddr *from,
                              socklen_t *fromlen, struct sockaddr *dstip,
@@ -61,7 +59,7 @@ int netsnmp_udpipv4_sendto(int fd, struct in_addr *srcip, int 
if_index,
 {
     return netsnmp_udpbase_sendto(fd, srcip, if_index, remote, data, len);
 }
-#endif /* (linux && IP_PKTINFO) || IP_RECVDSTADDR */
+#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
 
 netsnmp_transport *
 netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
@@ -135,7 +133,8 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int 
local)
         t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
         t->local_length = 6;
 
-#if defined(linux) && defined(IP_PKTINFO)
+#ifndef WIN32
+#if defined(HAVE_IP_PKTINFO)
         { 
             int sockopt = 1;
             if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof 
sockopt) == -1) {
@@ -146,7 +145,7 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int 
local)
             }
             DEBUGMSGTL(("netsnmp_udpbase", "set IP_PKTINFO\n"));
         }
-#elif defined(IP_RECVDSTADDR)
+#elif defined(HAVE_IP_RECVDSTADDR)
         {
             int sockopt = 1;
             if (setsockopt(t->sock, IPPROTO_IP, IP_RECVDSTADDR, &sockopt, 
sizeof sockopt) == -1) {
@@ -158,6 +157,7 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int 
local)
             DEBUGMSGTL(("netsnmp_udp", "set IP_RECVDSTADDR\n"));
         }
 #endif
+#endif /* !defined(WIN32) */
         if (!socket_initialized) {
             rc = bind(t->sock, (struct sockaddr *) addr,
                     sizeof(struct sockaddr));
-- 
1.7.10.4


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to