View | Details | Raw Unified | Return to bug 156178
Collapse All | Expand All

(-)net-snmp/files/patch-snmpUDPDomain.c (+137 lines)
Line 0 Link Here
1
--- snmplib/snmpUDPDomain.c.orig	2009-07-08 17:12:01.000000000 +0200
2
+++ snmplib/snmpUDPDomain.c	2011-02-08 12:49:30.000000000 +0100
3
@@ -128,14 +128,20 @@
4
 
5
 
6
 #if defined(linux) && defined(IP_PKTINFO)
7
-
8
-# define netsnmp_dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
9
+#define netsnmp_dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
10
+#elif defined(IP_RECVDSTADDR)
11
+#define netsnmp_dstaddr(x) (&(struct cmsghdr *)(CMSG_DATA(x)))
12
+#endif
13
 
14
 int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, struct in_addr *dstip)
15
 {
16
     int r;
17
     struct iovec iov[1];
18
+#if defined(linux) && defined(IP_PKTINFO)
19
     char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
20
+#elif defined(IP_RECVDSTADDR)
21
+    char cmsg[CMSG_SPACE(sizeof(struct in_addr))];
22
+#endif
23
     struct cmsghdr *cmsgptr;
24
     struct msghdr msg;
25
 
26
@@ -157,6 +163,7 @@
27
     }
28
     
29
     DEBUGMSGTL(("netsnmp_udp", "got source addr: %s\n", inet_ntoa(((struct sockaddr_in *)from)->sin_addr)));
30
+#if defined(linux) && defined(IP_PKTINFO)
31
     for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
32
         if (cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
33
             memcpy((void *) dstip, netsnmp_dstaddr(cmsgptr), sizeof(struct in_addr));
34
@@ -164,9 +171,20 @@
35
                     inet_ntoa(*dstip)));
36
         }
37
     }
38
+#elif defined(IP_RECVDSTADDR)
39
+    for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
40
+        if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR) {
41
+            memcpy((void *) dstip, CMSG_DATA(cmsgptr), sizeof(struct in_addr));
42
+            DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s\n",
43
+                    inet_ntoa(*dstip)));
44
+        }
45
+    }
46
+#endif
47
     return r;
48
 }
49
 
50
+
51
+#if defined(linux) && defined(IP_PKTINFO)
52
 int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote,
53
 			void *data, int len)
54
 {
55
@@ -194,7 +212,35 @@
56
 
57
     return sendmsg(fd, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
58
 }
59
-#endif /* linux && IP_PKTINFO */
60
+#elif defined(IP_RECVDSTADDR)
61
+int netsnmp_udp_sendto(int fd, struct in_addr *srcip, struct sockaddr *remote,
62
+			void *data, int len)
63
+{
64
+    struct iovec iov = { data, len };
65
+    struct cmsghdr *cm;
66
+    struct in_addr ip;
67
+    struct msghdr m;
68
+    char   cmbuf[CMSG_SPACE(sizeof(struct in_addr))];
69
+
70
+    memset(&m, 0, sizeof(struct msghdr));
71
+    m.msg_name		= remote;
72
+    m.msg_namelen	= sizeof(struct sockaddr_in);
73
+    m.msg_iov		= &iov;
74
+    m.msg_iovlen	= 1;
75
+    m.msg_control	= cmbuf;
76
+    m.msg_controllen	= sizeof(cmbuf);
77
+    m.msg_flags		= 0;
78
+
79
+    cm = CMSG_FIRSTHDR(&m);
80
+    cm->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
81
+    cm->cmsg_level = IPPROTO_IP;
82
+    cm->cmsg_type = IP_SENDSRCADDR;
83
+
84
+    memcpy((struct in_addr *)CMSG_DATA(cm), srcip, sizeof(struct in_addr));
85
+
86
+    return sendmsg(fd, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
87
+}
88
+#endif
89
 
90
 /*
91
  * You can write something into opaque that will subsequently get passed back 
92
@@ -223,11 +269,11 @@
93
         }
94
 
95
 	while (rc < 0) {
96
-#if defined(linux) && defined(IP_PKTINFO)
97
+#if (defined(linux) && defined(IP_PKTINFO)) || defined(IP_RECVDSTADDR)
98
             rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr));
99
 #else
100
             rc = recvfrom(t->sock, buf, size, NETSNMP_DONTWAIT, from, &fromlen);
101
-#endif /* linux && IP_PKTINFO */
102
+#endif
103
 	    if (rc < 0 && errno != EINTR) {
104
 		break;
105
 	    }
106
@@ -276,11 +322,11 @@
107
                     size, buf, str, t->sock));
108
         free(str);
109
 	while (rc < 0) {
110
-#if defined(linux) && defined(IP_PKTINFO)
111
+#if (defined(linux) && defined(IP_PKTINFO)) || defined(IP_RECVDSTADDR)
112
             rc = netsnmp_udp_sendto(t->sock, addr_pair ? &(addr_pair->local_addr) : NULL, to, buf, size);
113
 #else
114
             rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
115
-#endif /* linux && IP_PKTINFO */
116
+#endif
117
 	    if (rc < 0 && errno != EINTR) {
118
                 DEBUGMSGTL(("netsnmp_udp", "sendto error, rc %d (errno %d)\n",
119
                             rc, errno));
120
@@ -660,6 +706,17 @@
121
             }
122
             DEBUGMSGTL(("netsnmp_udp", "set IP_PKTINFO\n"));
123
         }
124
+#elif defined(IP_RECVDSTADDR)
125
+        { 
126
+            int sockopt = 1;
127
+            if (setsockopt(t->sock, IPPROTO_IP, IP_RECVDSTADDR, &sockopt, sizeof sockopt) == -1) {
128
+                DEBUGMSGTL(("netsnmp_udp", "couldn't set IP_RECVDSTADDR: %s\n",
129
+                    strerror(errno)));
130
+                netsnmp_transport_free(t);
131
+                return NULL;
132
+            }
133
+            DEBUGMSGTL(("netsnmp_udp", "set IP_RECVDSTADDR\n"));
134
+        }
135
 #endif
136
         rc = bind(t->sock, (struct sockaddr *) addr,
137
                   sizeof(struct sockaddr));

Return to bug 156178