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&reg; 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&#45;12, 2009. Register now&#33;
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

Reply via email to