summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2017-01-16 07:03:33 +0000
committerngie <ngie@FreeBSD.org>2017-01-16 07:03:33 +0000
commit9e7f08fdcf999fe8b9562ce4e417276353b32093 (patch)
tree5e6ede87d5f2f069b000fa1263988a34b62d438c
parent34667460f5d08c2dc59e0ce931a1089be4644803 (diff)
downloadFreeBSD-src-9e7f08fdcf999fe8b9562ce4e417276353b32093.zip
FreeBSD-src-9e7f08fdcf999fe8b9562ce4e417276353b32093.tar.gz
MFC r310655:
Fix bsnmpd sending/receiving with multi-homed configurations or INADDR_ANY used as the listening address in snmpd_input(..) Stash the IPv4 address of the receiver via the recv(..) callback and use it in the send(..) callback for the transport by specifying IP_SENDSRCADDR for the control message type. Add sendmsg logic to the UDP transport's send(..) callback and use the respective send(..) callback for the transport instead of calling sendto in snmpd_input(..). Obtained from: Isilon OneFS (^/onefs/branches/BR_8_0_0_DEV@r507595)
-rw-r--r--contrib/bsnmp/snmpd/main.c22
-rw-r--r--contrib/bsnmp/snmpd/snmpd.h2
-rw-r--r--contrib/bsnmp/snmpd/trans_lsock.c4
-rw-r--r--contrib/bsnmp/snmpd/trans_udp.c31
-rw-r--r--contrib/bsnmp/snmpd/trans_udp.h1
5 files changed, 39 insertions, 21 deletions
diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c
index a9a3181..a2053e8 100644
--- a/contrib/bsnmp/snmpd/main.c
+++ b/contrib/bsnmp/snmpd/main.c
@@ -1040,10 +1040,8 @@ snmpd_input(struct port_input *pi, struct tport *tport)
#ifdef USE_TCPWRAPPERS
char client[16];
#endif
- struct msghdr msg;
- struct iovec iov[1];
- ret = tport->transport->vtab->recv(pi);
+ ret = tport->transport->vtab->recv(tport, pi);
if (ret == -1)
return (-1);
@@ -1186,21 +1184,15 @@ snmpd_input(struct port_input *pi, struct tport *tport)
sndbuf, &sndlen, "SNMP", ierr, vi, NULL);
if (ferr == SNMPD_INPUT_OK) {
- msg.msg_name = pi->peer;
- msg.msg_namelen = pi->peerlen;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- iov[0].iov_base = sndbuf;
- iov[0].iov_len = sndlen;
-
- slen = sendmsg(pi->fd, &msg, 0);
+ slen = tport->transport->vtab->send(tport, sndbuf, sndlen,
+ pi->peer, pi->peerlen);
if (slen == -1)
- syslog(LOG_ERR, "sendmsg: %m");
+ syslog(LOG_ERR, "send*: %m");
else if ((size_t)slen != sndlen)
- syslog(LOG_ERR, "sendmsg: short write %zu/%zu",
- sndlen, (size_t)slen);
+ syslog(LOG_ERR, "send*: short write %zu/%zu", sndlen,
+ (size_t)slen);
}
+
snmp_pdu_free(&pdu);
free(sndbuf);
snmp_input_consume(pi);
diff --git a/contrib/bsnmp/snmpd/snmpd.h b/contrib/bsnmp/snmpd/snmpd.h
index 5639dbf..6afbc96 100644
--- a/contrib/bsnmp/snmpd/snmpd.h
+++ b/contrib/bsnmp/snmpd/snmpd.h
@@ -193,7 +193,7 @@ struct transport_def {
ssize_t (*send)(struct tport *, const u_char *, size_t,
const struct sockaddr *, size_t);
- ssize_t (*recv)(struct port_input *);
+ ssize_t (*recv)(struct tport *, struct port_input *);
};
struct transport {
struct asn_oid index; /* transport table index */
diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c
index fb3b891..a390839 100644
--- a/contrib/bsnmp/snmpd/trans_lsock.c
+++ b/contrib/bsnmp/snmpd/trans_lsock.c
@@ -59,7 +59,7 @@ static void lsock_close_port(struct tport *);
static int lsock_init_port(struct tport *);
static ssize_t lsock_send(struct tport *, const u_char *, size_t,
const struct sockaddr *, size_t);
-static ssize_t lsock_recv(struct port_input *);
+static ssize_t lsock_recv(struct tport *, struct port_input *);
/* exported */
const struct transport_def lsock_trans = {
@@ -439,7 +439,7 @@ check_priv_stream(struct port_input *pi)
* Receive something
*/
static ssize_t
-lsock_recv(struct port_input *pi)
+lsock_recv(struct tport *tp __unused, struct port_input *pi)
{
struct msghdr msg;
struct iovec iov[1];
diff --git a/contrib/bsnmp/snmpd/trans_udp.c b/contrib/bsnmp/snmpd/trans_udp.c
index b6895a0..a5c262c 100644
--- a/contrib/bsnmp/snmpd/trans_udp.c
+++ b/contrib/bsnmp/snmpd/trans_udp.c
@@ -55,7 +55,7 @@ static void udp_close_port(struct tport *);
static int udp_init_port(struct tport *);
static ssize_t udp_send(struct tport *, const u_char *, size_t,
const struct sockaddr *, size_t);
-static ssize_t udp_recv(struct port_input *);
+static ssize_t udp_recv(struct tport *, struct port_input *);
/* exported */
const struct transport_def udp_trans = {
@@ -217,8 +217,30 @@ udp_send(struct tport *tp, const u_char *buf, size_t len,
const struct sockaddr *addr, size_t addrlen)
{
struct udp_port *p = (struct udp_port *)tp;
+ struct cmsghdr *cmsg;
+ struct in_addr *src_addr;
+ struct msghdr msg;
+ char cbuf[CMSG_SPACE(sizeof(struct in_addr))];
+ struct iovec iov;
- return (sendto(p->input.fd, buf, len, 0, addr, addrlen));
+ iov.iov_base = __DECONST(void*, buf);
+ iov.iov_len = len;
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = __DECONST(void *, addr);
+ msg.msg_namelen = addrlen;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof(cbuf);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_SENDSRCADDR;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ src_addr = (struct in_addr *)(void*)CMSG_DATA(cmsg);
+ memcpy(src_addr, &p->recv_addr, sizeof(struct in_addr));
+
+ return (sendmsg(p->input.fd, &msg, 0));
}
static void
@@ -309,8 +331,9 @@ recv_dgram(struct port_input *pi, struct in_addr *laddr)
* Receive something
*/
static ssize_t
-udp_recv(struct port_input *pi)
+udp_recv(struct tport *tp, struct port_input *pi)
{
+ struct udp_port *p = (struct udp_port *)tp;
struct in_addr *laddr;
struct msghdr msg;
char cbuf[CMSG_SPACE(sizeof(struct in_addr))];
@@ -330,6 +353,8 @@ udp_recv(struct port_input *pi)
ret = recv_dgram(pi, laddr);
+ memcpy(&p->recv_addr, laddr, sizeof(struct in_addr));
+
if (laddr->s_addr == INADDR_ANY) {
msg.msg_control = NULL;
msg.msg_controllen = 0;
diff --git a/contrib/bsnmp/snmpd/trans_udp.h b/contrib/bsnmp/snmpd/trans_udp.h
index d383711..ac8ab82 100644
--- a/contrib/bsnmp/snmpd/trans_udp.h
+++ b/contrib/bsnmp/snmpd/trans_udp.h
@@ -39,6 +39,7 @@ struct udp_port {
struct port_input input; /* common input stuff */
struct sockaddr_in ret; /* the return address */
+ struct in_addr recv_addr; /* the address the request was sent to */
};
/* argument for open call */
OpenPOWER on IntegriCloud