svn commit: r312515 - stable/11/contrib/bsnmp/snmpd

Ngie Cooper ngie at FreeBSD.org
Fri Jan 20 06:22:43 UTC 2017


Author: ngie
Date: Fri Jan 20 06:22:42 2017
New Revision: 312515
URL: https://svnweb.freebsd.org/changeset/base/312515

Log:
  MFC r312331:
  r312331 (by glebius):
  
  Fix regression from r310655, which broke operation of bsnmpd if it is bound
  to a non-wildcard address.  As documented in ip(4), doing sendmsg(2) with
  IP_SENDSRCADDR on a socket that is bound to non-wildcard address is
  completely different to using this control message on a wildcard one.
  
  A fix is to add a bool to mark whether we did setsockopt(IP_RECVDSTADDR)
  on the socket, and use IP_SENDSRCADDR control message only if we did.
  
  While here, garbage collect absolutely useless udp_recv() function that
  establishes some structures on stack to never use them later.

Modified:
  stable/11/contrib/bsnmp/snmpd/trans_udp.c
  stable/11/contrib/bsnmp/snmpd/trans_udp.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/contrib/bsnmp/snmpd/trans_udp.c
==============================================================================
--- stable/11/contrib/bsnmp/snmpd/trans_udp.c	Fri Jan 20 05:51:25 2017	(r312514)
+++ stable/11/contrib/bsnmp/snmpd/trans_udp.c	Fri Jan 20 06:22:42 2017	(r312515)
@@ -34,6 +34,7 @@
 #include <sys/queue.h>
 #include <sys/ucred.h>
 
+#include <stdbool.h>
 #include <stdlib.h>
 #include <syslog.h>
 #include <string.h>
@@ -119,13 +120,15 @@ udp_init_port(struct tport *tp)
 	addr.sin_port = htons(p->port);
 	addr.sin_family = AF_INET;
 	addr.sin_len = sizeof(addr);
-	if (addr.sin_addr.s_addr == INADDR_ANY &&
-	    setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on,
-	    sizeof(on)) == -1) {
-		syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m");
-		close(p->input.fd);
-		p->input.fd = -1;
-		return (SNMP_ERR_GENERR);
+	if (addr.sin_addr.s_addr == INADDR_ANY) {
+		if (setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on,
+		    sizeof(on)) == -1) {
+			syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m");
+			close(p->input.fd);
+			p->input.fd = -1;
+			return (SNMP_ERR_GENERR);
+		}
+		p->recvdstaddr = true;
 	}
 	if (bind(p->input.fd, (struct sockaddr *)&addr, sizeof(addr))) {
 		if (errno == EADDRNOTAVAIL) {
@@ -218,7 +221,6 @@ udp_send(struct tport *tp, const u_char 
 {
 	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;
@@ -231,15 +233,20 @@ udp_send(struct tport *tp, const u_char 
 	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));
+	if (p->recvdstaddr) {
+		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));
+		memcpy(CMSG_DATA(cmsg), &p->dstaddr, sizeof(struct in_addr));
+	} else {
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+	}
 
 	return (sendmsg(p->input.fd, &msg, 0));
 }
@@ -260,11 +267,12 @@ check_priv_dgram(struct port_input *pi, 
  * Each receive should return one datagram.
  */
 static ssize_t
-recv_dgram(struct port_input *pi, struct in_addr *laddr)
+udp_recv(struct tport *tp, struct port_input *pi)
 {
 	u_char embuf[1000];
 	char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) +
 	    CMSG_SPACE(sizeof(struct in_addr))];
+	struct udp_port *p = (struct udp_port *)tp;
 	struct msghdr msg;
 	struct iovec iov[1];
 	ssize_t len;
@@ -316,7 +324,8 @@ recv_dgram(struct port_input *pi, struct
 	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
 		if (cmsg->cmsg_level == IPPROTO_IP &&
 		    cmsg->cmsg_type == IP_RECVDSTADDR)
-			memcpy(laddr, CMSG_DATA(cmsg), sizeof(struct in_addr));
+			memcpy(&p->dstaddr, CMSG_DATA(cmsg),
+			    sizeof(struct in_addr));
 		if (cmsg->cmsg_level == SOL_SOCKET &&
 		    cmsg->cmsg_type == SCM_CREDS)
 			cred = (struct sockcred *)CMSG_DATA(cmsg);
@@ -329,42 +338,6 @@ recv_dgram(struct port_input *pi, struct
 }
 
 /*
- * Receive something
- */
-static ssize_t
-udp_recv(struct tport *tp, struct port_input *pi)
-{
-	struct udp_port *p = (struct udp_port *)tp;
-	struct cmsghdr *cmsgp;
-	struct in_addr *laddr;
-	struct msghdr msg;
-	char cbuf[CMSG_SPACE(sizeof(struct in_addr))];
-	ssize_t ret;
-
-	memset(cbuf, 0, sizeof(cbuf));
-
-	msg.msg_control = cbuf;
-	msg.msg_controllen = sizeof(cbuf);
-
-	cmsgp = CMSG_FIRSTHDR(&msg);
-	cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
-	cmsgp->cmsg_level = IPPROTO_IP;
-	cmsgp->cmsg_type = IP_SENDSRCADDR;
-	laddr = (struct in_addr *)CMSG_DATA(cmsgp);
-
-	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;
-	}
-
-	return (ret);
-}
-
-/*
  * Port table
  */
 int

Modified: stable/11/contrib/bsnmp/snmpd/trans_udp.h
==============================================================================
--- stable/11/contrib/bsnmp/snmpd/trans_udp.h	Fri Jan 20 05:51:25 2017	(r312514)
+++ stable/11/contrib/bsnmp/snmpd/trans_udp.h	Fri Jan 20 06:22:42 2017	(r312515)
@@ -39,7 +39,9 @@ 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 */
+
+	bool		recvdstaddr;	/* IP_RECVDSTADDR is on */
+	struct in_addr	dstaddr;	/* address the request was sent to */
 };
 
 /* argument for open call */


More information about the svn-src-stable-11 mailing list