Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Dec 2016 04:29:10 +0000 (UTC)
From:      Ngie Cooper <ngie@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r310655 - head/contrib/bsnmp/snmpd
Message-ID:  <201612280429.uBS4TA1W085321@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ngie
Date: Wed Dec 28 04:29:09 2016
New Revision: 310655
URL: https://svnweb.freebsd.org/changeset/base/310655

Log:
  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(..).
  
  MFC after:      3 weeks
  Obtained from:  Isilon OneFS (^/onefs/branches/BR_8_0_0_DEV@r507595)
  Submitted by:   Thor Steingrimsson <thor.steingrimsson@isilon.com>
  Sponsored by:   Dell EMC Isilon

Modified:
  head/contrib/bsnmp/snmpd/main.c
  head/contrib/bsnmp/snmpd/snmpd.h
  head/contrib/bsnmp/snmpd/trans_lsock.c
  head/contrib/bsnmp/snmpd/trans_udp.c
  head/contrib/bsnmp/snmpd/trans_udp.h

Modified: head/contrib/bsnmp/snmpd/main.c
==============================================================================
--- head/contrib/bsnmp/snmpd/main.c	Wed Dec 28 03:56:25 2016	(r310654)
+++ head/contrib/bsnmp/snmpd/main.c	Wed Dec 28 04:29:09 2016	(r310655)
@@ -1040,10 +1040,8 @@ snmpd_input(struct port_input *pi, struc
 #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, struc
 	    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);

Modified: head/contrib/bsnmp/snmpd/snmpd.h
==============================================================================
--- head/contrib/bsnmp/snmpd/snmpd.h	Wed Dec 28 03:56:25 2016	(r310654)
+++ head/contrib/bsnmp/snmpd/snmpd.h	Wed Dec 28 04:29:09 2016	(r310655)
@@ -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 */

Modified: head/contrib/bsnmp/snmpd/trans_lsock.c
==============================================================================
--- head/contrib/bsnmp/snmpd/trans_lsock.c	Wed Dec 28 03:56:25 2016	(r310654)
+++ head/contrib/bsnmp/snmpd/trans_lsock.c	Wed Dec 28 04:29:09 2016	(r310655)
@@ -59,7 +59,7 @@ static void lsock_close_port(struct tpor
 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 = {
@@ -444,7 +444,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];

Modified: head/contrib/bsnmp/snmpd/trans_udp.c
==============================================================================
--- head/contrib/bsnmp/snmpd/trans_udp.c	Wed Dec 28 03:56:25 2016	(r310654)
+++ head/contrib/bsnmp/snmpd/trans_udp.c	Wed Dec 28 04:29:09 2016	(r310655)
@@ -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 
     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
  * 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;

Modified: head/contrib/bsnmp/snmpd/trans_udp.h
==============================================================================
--- head/contrib/bsnmp/snmpd/trans_udp.h	Wed Dec 28 03:56:25 2016	(r310654)
+++ head/contrib/bsnmp/snmpd/trans_udp.h	Wed Dec 28 04:29:09 2016	(r310655)
@@ -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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612280429.uBS4TA1W085321>