If snmpd receives a broadcast request, it stores it's destination (i.e. the broadcast address) and tries to send the response with the same source address. sendmsg() does not like broadcast addresses there and returns error + response is not sent, which makes some users sad. I have no idea, why they send broadcast snmpget at all, is this supported scenario?
I was playing with sendmsg() and it seems to me it's enough just to set source interface index instead of source IP address - see the patch below. It stores the interface index, where incoming packet was received and sets it when sending response. The patch needs some clean-up of course, it's probably not necessary to store the destination (local) address anymore, it's just a first version I played with. Do you think it might work? It works with the broadcast requests, I have even tested the use case with two interfaces in the same network (see patches 1553447 and 1509943) but I am still afraid it might break something else. Jan --- net-snmp/include/net-snmp/library/snmpUDPDomain.h | 4 ++-- net-snmp/snmplib/snmpDTLSUDPDomain.c | 2 +- net-snmp/snmplib/snmpUDPDomain.c | 18 ++++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/net-snmp/include/net-snmp/library/snmpUDPDomain.h b/net-snmp/include/net-snmp/library/snmpUDPDomain.h index d5d2401..774788f 100644 --- a/net-snmp/include/net-snmp/library/snmpUDPDomain.h +++ b/net-snmp/include/net-snmp/library/snmpUDPDomain.h @@ -58,8 +58,8 @@ void netsnmp_udp_ctor(void); char *netsnmp_udp_fmtaddr(netsnmp_transport *t, void *data, int len); #if defined(linux) && defined(IP_PKTINFO) int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, - socklen_t *fromlen, struct in_addr *dstip); -int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote, + socklen_t *fromlen, struct in_addr *dstip, int *if_index); +int netsnmp_udp_sendto(int fd, struct in_addr *srcip, int if_index, struct sockaddr *remote, void *data, int len); #endif diff --git a/net-snmp/snmplib/snmpDTLSUDPDomain.c b/net-snmp/snmplib/snmpDTLSUDPDomain.c index b51f3e8..8daff63 100644 --- a/net-snmp/snmplib/snmpDTLSUDPDomain.c +++ b/net-snmp/snmplib/snmpDTLSUDPDomain.c @@ -566,7 +566,7 @@ netsnmp_dtlsudp_recv(netsnmp_transport *t, void *buf, int size, while (rc < 0) { #if defined(linux) && defined(IP_PKTINFO) - rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr)); + rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr), &(addr_pair->if_index)); #else rc = recvfrom(t->sock, buf, size, NETSNMP_DONTWAIT, from, &fromlen); #endif /* linux && IP_PKTINFO */ diff --git a/net-snmp/snmplib/snmpUDPDomain.c b/net-snmp/snmplib/snmpUDPDomain.c index 91f4fa1..41e4543 100644 --- a/net-snmp/snmplib/snmpUDPDomain.c +++ b/net-snmp/snmplib/snmpUDPDomain.c @@ -76,6 +76,7 @@ static netsnmp_tdomain udpDomain; typedef struct netsnmp_udp_addr_pair_s { struct sockaddr_in remote_addr; struct in_addr local_addr; + int if_index; } netsnmp_udp_addr_pair; /* @@ -131,7 +132,7 @@ netsnmp_udp_fmtaddr(netsnmp_transport *t, void *data, int len) # define netsnmp_dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr)) -int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, struct in_addr *dstip) +int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, struct in_addr *dstip, int *if_index) { int r; struct iovec iov[1]; @@ -160,14 +161,15 @@ int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, sockl for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO) { memcpy((void *) dstip, netsnmp_dstaddr(cmsgptr), sizeof(struct in_addr)); - DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s\n", - inet_ntoa(*dstip))); + *if_index = (((struct in_pktinfo *)(CMSG_DATA(cmsgptr)))->ipi_ifindex); + DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s, iface %d\n", + inet_ntoa(*dstip), *if_index)); } } return r; } -int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote, +int netsnmp_udp_sendto(int fd, struct in_addr *srcip, int if_index, struct sockaddr *remote, void *data, int len) { struct iovec iov = { data, len }; @@ -181,8 +183,8 @@ int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote, cmsg.cm.cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); cmsg.cm.cmsg_level = SOL_IP; cmsg.cm.cmsg_type = IP_PKTINFO; - cmsg.ipi.ipi_ifindex = 0; - cmsg.ipi.ipi_spec_dst.s_addr = (srcip ? srcip->s_addr : INADDR_ANY); + cmsg.ipi.ipi_ifindex = if_index; + cmsg.ipi.ipi_spec_dst.s_addr = INADDR_ANY; m.msg_name = remote; m.msg_namelen = sizeof(struct sockaddr_in); @@ -224,7 +226,7 @@ netsnmp_udp_recv(netsnmp_transport *t, void *buf, int size, while (rc < 0) { #if defined(linux) && defined(IP_PKTINFO) - rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr)); + rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr), &(addr_pair->if_index)); #else rc = recvfrom(t->sock, buf, size, NETSNMP_DONTWAIT, from, &fromlen); #endif /* linux && IP_PKTINFO */ @@ -277,7 +279,7 @@ netsnmp_udp_send(netsnmp_transport *t, void *buf, int size, free(str); while (rc < 0) { #if defined(linux) && defined(IP_PKTINFO) - rc = netsnmp_udp_sendto(t->sock, addr_pair ? &(addr_pair->local_addr) : NULL, to, buf, size); + rc = netsnmp_udp_sendto(t->sock, addr_pair ? &(addr_pair->local_addr) : NULL, addr_pair ? addr_pair->if_index : 0, to, buf, size); #else rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr)); #endif /* linux && IP_PKTINFO */ ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Net-snmp-coders mailing list Net-snmp-coders@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/net-snmp-coders