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
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders