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