diff options
author | Jochen Friedrich <jochen@scram.de> | 2006-06-21 18:12:38 +0000 |
---|---|---|
committer | Jochen Friedrich <jochen@scram.de> | 2006-06-21 18:12:38 +0000 |
commit | 6f83fc00bf3761b2a7876ccca48ea43614827e97 (patch) | |
tree | 498695552e402b8fbcf2026ad024d18279a723e8 /debian/patches | |
parent | 778f69df7a75648489d8ea48b92f9f9d5961effb (diff) | |
download | pkg-net-snmp-6f83fc00bf3761b2a7876ccca48ea43614827e97.tar.gz |
Patch from Lars Ellenberg
git-svn-id: svn://svn.debian.org/pkg-net-snmp/trunk@50 db575a87-f10d-0410-9662-f1d5ac62e4ba
Diffstat (limited to 'debian/patches')
-rw-r--r-- | debian/patches/24_pktinfo.README | 9 | ||||
-rw-r--r-- | debian/patches/24_pktinfo.patch | 212 |
2 files changed, 221 insertions, 0 deletions
diff --git a/debian/patches/24_pktinfo.README b/debian/patches/24_pktinfo.README new file mode 100644 index 0000000..373187a --- /dev/null +++ b/debian/patches/24_pktinfo.README @@ -0,0 +1,9 @@ + send udp replies from the ip alias they have been received + if you have a box with some virtual/cluster/alias ips, + currently a udp request received on the alias ip will be + answered using the primary ip. + this patch uses the linux IP_PKTINFO socket option to + be able to send back replies with the same source ip + the corresponding request has been received on. + + -- Lars Ellenberg diff --git a/debian/patches/24_pktinfo.patch b/debian/patches/24_pktinfo.patch new file mode 100644 index 0000000..a73d39f --- /dev/null +++ b/debian/patches/24_pktinfo.patch @@ -0,0 +1,212 @@ +--- net-snmp-5.2.2.orig/snmplib/snmpUDPDomain.c 2005-09-16 12:30:41.000000000 +0200 ++++ net-snmp-5.2.2/snmplib/snmpUDPDomain.c 2006-06-06 23:28:31.822443722 +0200 +@@ -97,7 +97,7 @@ + } + + +- ++#ifndef 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 +@@ -178,6 +178,151 @@ + return rc; + } + ++#else ++/* we have IP_PKTINFO */ ++/* ++ * we try to remember the ip we received a request on, ++ * so we can use it again to send back the answer. ++ */ ++ ++struct _netsnmp_udp_info { ++ struct sockaddr_in remote; ++ struct cmsghdr cmsg; ++ struct in_pktinfo pktinfo; ++} __attribute((packed)); ++ ++static int ++netsnmp_udp_recv(netsnmp_transport *t, void *buf, int size, ++ void **opaque, int *olength) ++{ ++ int rc = -1; ++ struct _netsnmp_udp_info *info; ++ ++ if (t != NULL && t->sock >= 0) { ++ struct msghdr msg; ++ u_char hdrbuf[128]; /* FIXME how much do we need? */ ++ struct iovec iov; ++ struct cmsghdr *cmsg; ++ ++ info = malloc(sizeof(*info)); ++ if (info == NULL) { ++ /* XXX BUG ALERT ++ * why do you (re)initialize something that may need to be freed? ++ * ++ *opaque = NULL; ++ *olength = 0; ++ */ ++ return -1; ++ } else { ++ memset(info, 0, sizeof(*info)); ++ *opaque = info; ++ *olength = sizeof(*info); ++ } ++ ++ iov.iov_base=buf; ++ iov.iov_len=size; ++ ++ msg.msg_name=(caddr_t)&info->remote; ++ msg.msg_namelen=(uint)sizeof(info->remote); ++ msg.msg_iov=&iov; ++ msg.msg_iovlen=1; ++ msg.msg_control=hdrbuf; ++ msg.msg_controllen=sizeof(hdrbuf); ++ msg.msg_flags=0; ++ while (rc < 0) { ++ rc = recvmsg(t->sock, &msg, 0); ++ if (rc < 0 && errno != EINTR) { ++ break; ++ } ++ } ++ ++ if (rc >= 0) { ++ char *str, *str_local = "???"; ++ int pktinfo_found = 0; ++ str = netsnmp_udp_fmtaddr(NULL, &info->remote, sizeof(info->remote)); ++ if (msg.msg_controllen>0) { ++ for (cmsg=CMSG_FIRSTHDR(&msg);cmsg;cmsg=CMSG_NXTHDR(&msg,cmsg)) { ++ if (cmsg->cmsg_type==IP_PKTINFO) { ++ /* maybe it was easier to just copy msg_control opaque, ++ * and later supply it unaltered to sendmsg... ++ * but I'd rather be explicit. ++ */ ++ info->pktinfo = *(struct in_pktinfo*)CMSG_DATA(cmsg); ++ /* XXX static buffer; if you add more inet_ntoa, or move this line up, ++ * you'd need an other pair of strdup/free */ ++ str_local = inet_ntoa(info->pktinfo.ipi_addr); ++ pktinfo_found = 1; ++ } ++ } ++ } ++ DEBUGMSGTL(("netsnmp_udp", ++ "recvfrom fd %d got %d bytes (on %s from %s)\n", ++ t->sock, rc, str_local, str)); ++ free(str); ++ } else { ++ DEBUGMSGTL(("netsnmp_udp", "recvfrom fd %d err %d (\"%s\")\n", ++ t->sock, errno, strerror(errno))); ++ } ++ } ++ return rc; ++} ++ ++ ++ ++static int ++netsnmp_udp_send(netsnmp_transport *t, void *buf, int size, ++ void **opaque, int *olength) ++{ ++ int rc = -1; ++ struct sockaddr_in *to = NULL; ++ struct _netsnmp_udp_info *info = NULL; ++ ++ if (opaque != NULL && *opaque != NULL && ++ *olength == sizeof(struct _netsnmp_udp_info)) { ++ info = (struct _netsnmp_udp_info *) (*opaque); ++ to = &info->remote; ++ } else if (t != NULL && t->data != NULL && ++ t->data_length == sizeof(struct sockaddr_in)) { ++ to = (struct sockaddr_in *) (t->data); ++ } ++ if (to != NULL && t != NULL && t->sock >= 0) { ++ char *str = netsnmp_udp_fmtaddr(NULL, (void *) to, ++ sizeof(struct sockaddr_in)); ++ char *str_local = "DEFAULT"; ++ struct msghdr msg; ++ struct iovec iov; ++ ++ iov.iov_base=buf; ++ iov.iov_len=size; ++ ++ msg.msg_name=(caddr_t)to; ++ msg.msg_namelen=(uint)sizeof(*to); ++ msg.msg_iov=&iov; ++ msg.msg_iovlen=1; ++ msg.msg_control = NULL; ++ msg.msg_controllen = 0; ++ msg.msg_flags=0; ++ if (info) { ++ info->cmsg.cmsg_len = sizeof(info->cmsg) + sizeof(info->pktinfo); ++ info->cmsg.cmsg_level = SOL_IP; ++ info->cmsg.cmsg_type = IP_PKTINFO; ++ msg.msg_control = &info->cmsg; ++ msg.msg_controllen = info->cmsg.cmsg_len; ++ str_local = inet_ntoa(info->pktinfo.ipi_addr); ++ } ++ DEBUGMSGTL(("netsnmp_udp", "send %d bytes from %p with src ip %s to %s on fd %d\n", ++ size, buf, str_local, str, t->sock)); ++ free(str); ++ while (rc < 0) { ++ rc = sendmsg(t->sock, &msg, 0); ++ if (rc < 0 && errno != EINTR) { ++ break; ++ } ++ } ++ } ++ return rc; ++} ++#endif + + + static int +@@ -625,6 +770,17 @@ + } + #endif /*SO_REUSEADDR */ + #endif ++#ifdef IP_PKTINFO ++ /* ++ * if we have multiple ip aliases, send back on the ip we received with. ++ */ ++ { ++ int one = 1; ++ DEBUGMSGTL(("socket:option", "setting socket option IP_PKTINFO\n")); ++ setsockopt(fd, SOL_IP, IP_PKTINFO, (void *) &one, ++ sizeof(one)); ++ } ++#endif /*IP_PKTINFO */ + + /* + * Try to set the send and receive buffers to a reasonably large value, so +@@ -991,7 +1147,7 @@ + char **contextName) + { + com2SecEntry *c; +- struct sockaddr_in *from = (struct sockaddr_in *) opaque; ++ struct sockaddr_in *from = NULL; + char *ztcommunity = NULL; + + if (secName != NULL) { +@@ -1008,13 +1164,19 @@ + return 0; + } + ++#ifdef IP_PKTINFO ++ if (opaque && olength == sizeof(struct _netsnmp_udp_info)) ++ from = &((struct _netsnmp_udp_info *)opaque)->remote; ++#else ++ if (opaque && olength == sizeof(struct sockaddr_in)) ++ from = (struct sockaddr_in *) opaque; ++#endif + /* + * If there is no IPv4 source address, then there can be no valid security + * name. + */ + +- if (opaque == NULL || olength != sizeof(struct sockaddr_in) || +- from->sin_family != AF_INET) { ++ if (from == NULL || from->sin_family != AF_INET) { + DEBUGMSGTL(("netsnmp_udp_getSecName", + "no IPv4 source address in PDU?\n")); + return 1; |