summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
authorJochen Friedrich <jochen@scram.de>2006-06-21 18:12:38 +0000
committerJochen Friedrich <jochen@scram.de>2006-06-21 18:12:38 +0000
commit6f83fc00bf3761b2a7876ccca48ea43614827e97 (patch)
tree498695552e402b8fbcf2026ad024d18279a723e8 /debian/patches
parent778f69df7a75648489d8ea48b92f9f9d5961effb (diff)
downloadpkg-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.README9
-rw-r--r--debian/patches/24_pktinfo.patch212
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;