This is a multi-part message in MIME format.
--------------040300060609070707030700
Content-Type: text/plain; charset=KOI8-R; format=flowed
Content-Transfer-Encoding: 7bit

Hi.

Here is what tcpdump sees when polling multihomed linux host with
address 10.1.1.16 on eth interface and address 10.20.0.1 on dummy
(loopback) interface:

22:21:45.418354 10.10.194.15.57311 > 10.20.0.1.snmp: C=public
GetRequest(28) .1.3.6.1.2.1.1.1.0 (DF)
22:21:45.419425 10.1.1.16.snmp > 10.10.194.15.57311: C=public
GetResponse(39) .1.3.6.1.2.1.1.1.0="Linux" (DF)

This is not very convinient when using stateful firewall somewhere
between that two hosts or on monitoring station, as responce has no
relation to request from point of view of linux iptables connection
tracking.

I attach the patch which corrects this behaviour for linux (Based on
thread
http://groups.google.com/group/linux...DSTADDR&rnum=1).
Hope it is useful.
--
Best,
Vladislav Bogdanov

--------------040300060609070707030700
Content-Type: text/plain;
name="net-snmp-5.3.1-local-addr.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="net-snmp-5.3.1-local-addr.patch"

diff -urNp net-snmp-5.3.1.orig/README net-snmp-5.3.1/README
--- net-snmp-5.3.1.orig/README 2006-07-14 00:55:27.000000000 +0300
+++ net-snmp-5.3.1/README 2006-09-06 00:17:16.000000000 +0300
@@ -343,6 +343,7 @@ THANKS
Andrew Rucker Jones
Dai.H.
Thomas Anders
+ Vladislav Bogdanov

We've probably forgotten people on this list. Let us know if you've
contributed code and we've left you out.
diff -urNp net-snmp-5.3.1.orig/snmplib/snmpUDPDomain.c net-snmp-5.3.1/snmplib/snmpUDPDomain.c
--- net-snmp-5.3.1.orig/snmplib/snmpUDPDomain.c 2005-11-06 00:01:42.000000000 +0200
+++ net-snmp-5.3.1/snmplib/snmpUDPDomain.c 2006-09-06 00:13:59.000000000 +0300
@@ -64,6 +64,11 @@

static netsnmp_tdomain udpDomain;

+typedef struct netsnmp_udp_addr_pair_s {
+ struct sockaddr_in remote_addr;
+ struct in_addr local_addr;
+} netsnmp_udp_addr_pair;
+
/*
* not static, since snmpUDPIPv6Domain needs it, but not public, either.
* (ie don't put it in a public header.)
@@ -78,17 +83,23 @@ void _netsnmp_udp_sockopt_set(int fd, in
static char *
netsnmp_udp_fmtaddr(netsnmp_transport *t, void *data, int len)
{
- struct sockaddr_in *to = NULL;
+ netsnmp_udp_addr_pair *addr_pair = NULL;

- if (data != NULL && len == sizeof(struct sockaddr_in)) {
- to = (struct sockaddr_in *) data;
+ if (data != NULL && len == sizeof(netsnmp_udp_addr_pair)) {
+ addr_pair = (netsnmp_udp_addr_pair *) data;
} else if (t != NULL && t->data != NULL) {
- to = (struct sockaddr_in *) t->data;
+ addr_pair = (netsnmp_udp_addr_pair *) t->data;
}
- if (to == NULL) {
+
+ if (addr_pair == NULL) {
return strdup("UDP: unknown");
} else {
+ struct sockaddr_in *to = NULL;
char tmp[64];
+ to = (struct sockaddr_in *) &(addr_pair->remote_addr);
+ if (to == NULL) {
+ return strdup("UDP: unknown");
+ }

sprintf(tmp, "UDP: [%s]:%hu",
inet_ntoa(to->sin_addr), ntohs(to->sin_port));
@@ -98,6 +109,77 @@ netsnmp_udp_fmtaddr(netsnmp_transport *t



+#if defined IP_PKTINFO
+
+# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
+
+static int netsnmp_udp_recvfrom(int s, char *buf, int len, struct sockaddr *from, int *fromlen, struct in_addr *dstip)
+{
+ int r;
+ struct iovec iov[1];
+ char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct cmsghdr *cmsgptr;
+ struct msghdr msg;
+
+ iov[0].iov_base = buf;
+ iov[0].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);
+
+ r = recvmsg(s, &msg, 0);
+
+ if (r == -1) {
+ return -1;
+ }
+
+ DEBUGMSGTL(("netsnmp_udp", "got source addr: %s\n", inet_ntoa(((struct sockaddr_in *)from)->sin_addr)));
+ 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, dstaddr(cmsgptr), sizeof(struct in_addr));
+ DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s\n",
+ inet_ntoa(*dstip)));
+ }
+ }
+ return r;
+}
+
+static int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote,
+ char *data, int len)
+{
+ struct iovec iov = { data, len };
+ struct {
+ struct cmsghdr cm;
+ struct in_pktinfo ipi;
+ } cmsg = {
+ .cm = {
+ .cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo),
+ .cmsg_level = SOL_IP,
+ .cmsg_type = IP_PKTINFO,
+ },
+ .ipi = {
+ .ipi_ifindex = 0,
+ .ipi_spec_dst = srcip ? srcip->s_addr : 0,
+ },
+ };
+ struct msghdr m = {
+ .msg_name = remote,
+ .msg_namelen = sizeof(struct sockaddr_in),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = &cmsg,
+ .msg_controllen = sizeof(cmsg),
+ .msg_flags = 0,
+ };
+ return sendmsg(fd, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
+}
+#endif /* IP_PKTINFO */
+
/*
* You can write something into opaque that will subsequently get passed back
* to your send function if you like. For instance, you might want to
@@ -110,27 +192,33 @@ netsnmp_udp_recv(netsnmp_transport *t, v
{
int rc = -1;
socklen_t fromlen = sizeof(struct sockaddr);
+ netsnmp_udp_addr_pair *addr_pair = NULL;
struct sockaddr *from;

if (t != NULL && t->sock >= 0) {
- from = (struct sockaddr *) malloc(sizeof(struct sockaddr_in));
- if (from == NULL) {
+ addr_pair = (netsnmp_udp_addr_pair *) malloc(sizeof(netsnmp_udp_addr_pair));
+ if (addr_pair == NULL) {
*opaque = NULL;
*olength = 0;
return -1;
} else {
- memset(from, 0, fromlen);
+ memset(addr_pair, 0, sizeof(netsnmp_udp_addr_pair));
+ from = (struct sockaddr *) &(addr_pair->remote_addr);
}

while (rc < 0) {
- rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
+#if defined IP_PKTINFO
+ rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr));
+#else
+ rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
+#endif /* IP_PKTINFO */
if (rc < 0 && errno != EINTR) {
break;
}
}

if (rc >= 0) {
- char *str = netsnmp_udp_fmtaddr(NULL, from, fromlen);
+ char *str = netsnmp_udp_fmtaddr(NULL, addr_pair, sizeof(netsnmp_udp_addr_pair));
DEBUGMSGTL(("netsnmp_udp",
"recvfrom fd %d got %d bytes (from %s)\n",
t->sock, rc, str));
@@ -139,8 +227,8 @@ netsnmp_udp_recv(netsnmp_transport *t, v
DEBUGMSGTL(("netsnmp_udp", "recvfrom fd %d err %d (\"%s\")\n",
t->sock, errno, strerror(errno)));
}
- *opaque = (void *)from;
- *olength = sizeof(struct sockaddr_in);
+ *opaque = (void *)addr_pair;
+ *olength = sizeof(netsnmp_udp_addr_pair);
}
return rc;
}
@@ -152,24 +240,31 @@ netsnmp_udp_send(netsnmp_transport *t, v
void **opaque, int *olength)
{
int rc = -1;
+ netsnmp_udp_addr_pair *addr_pair = NULL;
struct sockaddr *to = NULL;

if (opaque != NULL && *opaque != NULL &&
- *olength == sizeof(struct sockaddr_in)) {
- to = (struct sockaddr *) (*opaque);
+ *olength == sizeof(netsnmp_udp_addr_pair)) {
+ addr_pair = (netsnmp_udp_addr_pair *) (*opaque);
} else if (t != NULL && t->data != NULL &&
- t->data_length == sizeof(struct sockaddr_in)) {
- to = (struct sockaddr *) (t->data);
+ t->data_length == sizeof(netsnmp_udp_addr_pair)) {
+ addr_pair = (netsnmp_udp_addr_pair *) (t->data);
}

+ to = (struct sockaddr *) &(addr_pair->remote_addr);
+
if (to != NULL && t != NULL && t->sock >= 0) {
- char *str = netsnmp_udp_fmtaddr(NULL, (void *) to,
- sizeof(struct sockaddr_in));
+ char *str = netsnmp_udp_fmtaddr(NULL, (void *) addr_pair,
+ sizeof(netsnmp_udp_addr_pair));
DEBUGMSGTL(("netsnmp_udp", "send %d bytes from %p to %s on fd %d\n",
size, buf, str, t->sock));
free(str);
while (rc < 0) {
- rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
+#if defined IP_PKTINFO
+ rc = netsnmp_udp_sendto(t->sock, addr_pair ? &(addr_pair->local_addr) : NULL, to, buf, size);
+#else
+ rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
+#endif /* IP_PKTINFO */
if (rc < 0 && errno != EINTR) {
DEBUGMSGTL(("netsnmp_udp", "sendto error, rc %d (errno %d)\n",
rc, errno));
@@ -486,18 +581,26 @@ netsnmp_udp_transport(struct sockaddr_in
int rc = 0;
char *str = NULL;
char *client_socket = NULL;
+ netsnmp_udp_addr_pair *addr_pair = NULL;

if (addr == NULL || addr->sin_family != AF_INET) {
return NULL;
}

+ addr_pair = (struct udp_addr_pair *) malloc(sizeof(netsnmp_udp_addr_pair));
+ if (addr_pair == NULL) {
+ return NULL;
+ }
+ memset(addr_pair, 0, sizeof(netsnmp_udp_addr_pair));
+ memcpy(&(addr_pair->remote_addr), addr, sizeof(struct sockaddr_in));
+
t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
if (t == NULL) {
return NULL;
}

- str = netsnmp_udp_fmtaddr(NULL, (void *)addr,
- sizeof(struct sockaddr_in));
+ str = netsnmp_udp_fmtaddr(NULL, (void *)addr_pair,
+ sizeof(netsnmp_udp_addr_pair));
DEBUGMSGTL(("netsnmp_udp", "open %s %s:%d\n", local ? "local" : "remote",
str,addr->sin_port));
free(str);
@@ -532,6 +635,18 @@ netsnmp_udp_transport(struct sockaddr_in
t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
t->local_length = 6;

+#ifdef IP_PKTINFO
+ {
+ int sockopt = 1;
+ int sockoptlen = sizeof(int);
+ if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof sockopt) == -1) {
+ DEBUGMSGTL(("netsnmp_udp", "couldn't set IP_PKTINFO: %s\n",
+ strerror(errno)));
+ return NULL;
+ }
+ DEBUGMSGTL(("netsnmp_udp", "set IP_PKTINFO\n"));
+ }
+#endif
rc = bind(t->sock, (struct sockaddr *) addr,
sizeof(struct sockaddr));
if (rc != 0) {
@@ -561,7 +679,7 @@ netsnmp_udp_transport(struct sockaddr_in
* transport-specific data pointer for later use by netsnmp_udp_send.
*/

- t->data = malloc(sizeof(struct sockaddr_in));
+ t->data = malloc(sizeof(netsnmp_udp_addr_pair));
t->remote = malloc(6);
if (t->data == NULL || t->remote == NULL) {
netsnmp_transport_free(t);
@@ -571,8 +689,8 @@ netsnmp_udp_transport(struct sockaddr_in
t->remote[4] = (htons(addr->sin_port) & 0xff00) >> 8;
t->remote[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
t->remote_length = 6;
- memcpy(t->data, addr, sizeof(struct sockaddr_in));
- t->data_length = sizeof(struct sockaddr_in);
+ memcpy(t->data, addr_pair, sizeof(netsnmp_udp_addr_pair));
+ t->data_length = sizeof(netsnmp_udp_addr_pair);
}

/*
@@ -993,7 +1111,8 @@ netsnmp_udp_getSecName(void *opaque, int
char **contextName)
{
com2SecEntry *c;
- struct sockaddr_in *from = (struct sockaddr_in *) opaque;
+ netsnmp_udp_addr_pair *addr_pair = (netsnmp_udp_addr_pair *) opaque;
+ struct sockaddr_in *from = (struct sockaddr_in *) &(addr_pair->remote_addr);
char *ztcommunity = NULL;

if (secName != NULL) {
@@ -1015,7 +1134,7 @@ netsnmp_udp_getSecName(void *opaque, int
* name.
*/

- if (opaque == NULL || olength != sizeof(struct sockaddr_in) ||
+ if (opaque == NULL || olength != sizeof(netsnmp_udp_addr_pair) ||
from->sin_family != AF_INET) {
DEBUGMSGTL(("netsnmp_udp_getSecName",
"no IPv4 source address in PDU?\n"));

--------------040300060609070707030700
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=...057&dat=121642
--------------040300060609070707030700
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/...et-snmp-coders

--------------040300060609070707030700--