Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Dec 2016 10:17:22 +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: r310586 - head/contrib/bsnmp/snmpd
Message-ID:  <201612261017.uBQAHMnE035676@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ngie
Date: Mon Dec 26 10:17:22 2016
New Revision: 310586
URL: https://svnweb.freebsd.org/changeset/base/310586

Log:
  Refactor transport sources a bit to facilitate changes coming down pipeline
  
  Add recv callback to transport layer to better facilitate code reuse and
  readability and for symmetry with send callback. Move recv_dgram and
  recv_stream to udp_recv and lsock_recv, respectively, and make the
  beforementioned functions recv callbacks for the udp and lsock transports,
  respectively.
  
  Consolidate the check_priv* functions in their relevant trans*.c source to
  limit scope/use.
  
  Note: this code is roughly based content from the submitter, although this
  was modified to be more of a direct move from snmpd/main.c to the trans_*.c
  sources, and to reduce unnecessary static function declarations.
  
  MFC after:	2 weeks
  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

Modified: head/contrib/bsnmp/snmpd/main.c
==============================================================================
--- head/contrib/bsnmp/snmpd/main.c	Mon Dec 26 10:16:05 2016	(r310585)
+++ head/contrib/bsnmp/snmpd/main.c	Mon Dec 26 10:17:22 2016	(r310586)
@@ -1024,154 +1024,6 @@ snmp_input_consume(struct port_input *pi
 	pi->length -= pi->consumed;
 }
 
-static void
-check_priv_dgram(struct port_input *pi, struct sockcred *cred)
-{
-
-	/* process explicitly sends credentials */
-	if (cred)
-		pi->priv = (cred->sc_euid == 0);
-	else
-		pi->priv = 0;
-}
-
-static void
-check_priv_stream(struct port_input *pi)
-{
-	struct xucred ucred;
-	socklen_t ucredlen;
-
-	/* obtain the accept time credentials */
-	ucredlen = sizeof(ucred);
-
-	if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 &&
-	    ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION)
-		pi->priv = (ucred.cr_uid == 0);
-	else
-		pi->priv = 0;
-}
-
-/*
- * Input from a stream socket.
- */
-static int
-recv_stream(struct port_input *pi)
-{
-	struct msghdr msg;
-	struct iovec iov[1];
-	ssize_t len;
-
-	if (pi->buf == NULL) {
-		/* no buffer yet - allocate one */
-		if ((pi->buf = buf_alloc(0)) == NULL) {
-			/* ups - could not get buffer. Return an error
-			 * the caller must close the transport. */
-			return (-1);
-		}
-		pi->buflen = buf_size(0);
-		pi->consumed = 0;
-		pi->length = 0;
-	}
-
-	/* try to get a message */
-	msg.msg_name = pi->peer;
-	msg.msg_namelen = pi->peerlen;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags = 0;
-
-	iov[0].iov_base = pi->buf + pi->length;
-	iov[0].iov_len = pi->buflen - pi->length;
-
-	len = recvmsg(pi->fd, &msg, 0);
-
-	if (len == -1 || len == 0)
-		/* receive error */
-		return (-1);
-
-	pi->length += len;
-
-	if (pi->cred)
-		check_priv_stream(pi);
-
-	return (0);
-}
-
-/*
- * Input from a datagram socket.
- * Each receive should return one datagram.
- */
-static int
-recv_dgram(struct port_input *pi, struct in_addr *laddr)
-{
-	u_char embuf[1000];
-	char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) +
-	    CMSG_SPACE(sizeof(struct in_addr))];
-	struct msghdr msg;
-	struct iovec iov[1];
-	ssize_t len;
-	struct cmsghdr *cmsg;
-	struct sockcred *cred = NULL;
-
-	if (pi->buf == NULL) {
-		/* no buffer yet - allocate one */
-		if ((pi->buf = buf_alloc(0)) == NULL) {
-			/* ups - could not get buffer. Read away input
-			 * and drop it */
-			(void)recvfrom(pi->fd, embuf, sizeof(embuf),
-			    0, NULL, NULL);
-			/* return error */
-			return (-1);
-		}
-		pi->buflen = buf_size(0);
-	}
-
-	/* try to get a message */
-	msg.msg_name = pi->peer;
-	msg.msg_namelen = pi->peerlen;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 1;
-	memset(cbuf, 0, sizeof(cbuf));
-	msg.msg_control = cbuf;
-	msg.msg_controllen = sizeof(cbuf);
-	msg.msg_flags = 0;
-
-	iov[0].iov_base = pi->buf;
-	iov[0].iov_len = pi->buflen;
-
-	len = recvmsg(pi->fd, &msg, 0);
-
-	if (len == -1 || len == 0)
-		/* receive error */
-		return (-1);
-
-	if (msg.msg_flags & MSG_TRUNC) {
-		/* truncated - drop */
-		snmpd_stats.silentDrops++;
-		snmpd_stats.inTooLong++;
-		return (-1);
-	}
-
-	pi->length = (size_t)len;
-
-	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
-	    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));
-		if (cmsg->cmsg_level == SOL_SOCKET &&
-		    cmsg->cmsg_type == SCM_CREDS)
-			cred = (struct sockcred *)CMSG_DATA(cmsg);
-	}
-
-	if (pi->cred)
-		check_priv_dgram(pi, cred);
-
-	return (0);
-}
-
 /*
  * Input from a socket
  */
@@ -1191,35 +1043,8 @@ snmpd_input(struct port_input *pi, struc
 #endif
 	struct msghdr msg;
 	struct iovec iov[1];
-	char cbuf[CMSG_SPACE(sizeof(struct in_addr))];
-	struct cmsghdr *cmsgp;
-
-	/* get input depending on the transport */
-	if (pi->stream) {
-		msg.msg_control = NULL;
-		msg.msg_controllen = 0;
-
-		ret = recv_stream(pi);
-	} else {
-		struct in_addr *laddr;
-
-		memset(cbuf, 0, CMSG_SPACE(sizeof(struct in_addr)));
-		msg.msg_control = cbuf;
-		msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
-		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);
-
-		if (laddr->s_addr == 0) {
-			msg.msg_control = NULL;
-			msg.msg_controllen = 0;
-		}
-	}
 
+	ret = tport->transport->vtab->recv(pi);
 	if (ret == -1)
 		return (-1);
 

Modified: head/contrib/bsnmp/snmpd/snmpd.h
==============================================================================
--- head/contrib/bsnmp/snmpd/snmpd.h	Mon Dec 26 10:16:05 2016	(r310585)
+++ head/contrib/bsnmp/snmpd/snmpd.h	Mon Dec 26 10:17:22 2016	(r310586)
@@ -193,6 +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 *);
 };
 struct transport {
 	struct asn_oid	index;		/* transport table index */

Modified: head/contrib/bsnmp/snmpd/trans_lsock.c
==============================================================================
--- head/contrib/bsnmp/snmpd/trans_lsock.c	Mon Dec 26 10:16:05 2016	(r310585)
+++ head/contrib/bsnmp/snmpd/trans_lsock.c	Mon Dec 26 10:17:22 2016	(r310586)
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/stat.h>
+#include <sys/ucred.h>
 #include <sys/un.h>
 
 #include <errno.h>
@@ -58,6 +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 *);
 
 /* exported */
 const struct transport_def lsock_trans = {
@@ -67,7 +69,8 @@ const struct transport_def lsock_trans =
 	lsock_stop,
 	lsock_close_port,
 	lsock_init_port,
-	lsock_send
+	lsock_send,
+	lsock_recv
 };
 static struct transport *my_trans;
 
@@ -421,6 +424,73 @@ lsock_send(struct tport *tp, const u_cha
 	return (sendto(peer->input.fd, buf, len, 0, addr, addrlen));
 }
 
+static void
+check_priv_stream(struct port_input *pi)
+{
+	struct xucred ucred;
+	socklen_t ucredlen;
+
+	/* obtain the accept time credentials */
+	ucredlen = sizeof(ucred);
+
+	if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 &&
+	    ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION)
+		pi->priv = (ucred.cr_uid == 0);
+	else
+		pi->priv = 0;
+}
+
+/*
+ * Receive something
+ */
+static ssize_t
+lsock_recv(struct port_input *pi)
+{
+	struct msghdr msg;
+	struct iovec iov[1];
+	ssize_t len;
+
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+
+	if (pi->buf == NULL) {
+		/* no buffer yet - allocate one */
+		if ((pi->buf = buf_alloc(0)) == NULL) {
+			/* ups - could not get buffer. Return an error
+			 * the caller must close the transport. */
+			return (-1);
+		}
+		pi->buflen = buf_size(0);
+		pi->consumed = 0;
+		pi->length = 0;
+	}
+
+	/* try to get a message */
+	msg.msg_name = pi->peer;
+	msg.msg_namelen = pi->peerlen;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags = 0;
+
+	iov[0].iov_base = pi->buf + pi->length;
+	iov[0].iov_len = pi->buflen - pi->length;
+
+	len = recvmsg(pi->fd, &msg, 0);
+
+	if (len == -1 || len == 0)
+		/* receive error */
+		return (-1);
+
+	pi->length += len;
+
+	if (pi->cred)
+		check_priv_stream(pi);
+
+	return (0);
+}
+
 /*
  * Dependency to create a lsock port
  */

Modified: head/contrib/bsnmp/snmpd/trans_udp.c
==============================================================================
--- head/contrib/bsnmp/snmpd/trans_udp.c	Mon Dec 26 10:16:05 2016	(r310585)
+++ head/contrib/bsnmp/snmpd/trans_udp.c	Mon Dec 26 10:17:22 2016	(r310586)
@@ -32,6 +32,7 @@
  */
 #include <sys/types.h>
 #include <sys/queue.h>
+#include <sys/ucred.h>
 
 #include <stdlib.h>
 #include <syslog.h>
@@ -54,6 +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 *);
 
 /* exported */
 const struct transport_def udp_trans = {
@@ -63,7 +65,8 @@ const struct transport_def udp_trans = {
 	udp_stop,
 	udp_close_port,
 	udp_init_port,
-	udp_send
+	udp_send,
+	udp_recv
 };
 static struct transport *my_trans;
 
@@ -218,6 +221,123 @@ udp_send(struct tport *tp, const u_char 
 	return (sendto(p->input.fd, buf, len, 0, addr, addrlen));
 }
 
+static void
+check_priv_dgram(struct port_input *pi, struct sockcred *cred)
+{
+
+	/* process explicitly sends credentials */
+	if (cred)
+		pi->priv = (cred->sc_euid == 0);
+	else
+		pi->priv = 0;
+}
+
+/*
+ * Input from a datagram socket.
+ * Each receive should return one datagram.
+ */
+static int
+recv_dgram(struct port_input *pi, struct in_addr *laddr)
+{
+	u_char embuf[1000];
+	char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) +
+	    CMSG_SPACE(sizeof(struct in_addr))];
+	struct msghdr msg;
+	struct iovec iov[1];
+	ssize_t len;
+	struct cmsghdr *cmsg;
+	struct sockcred *cred = NULL;
+
+	if (pi->buf == NULL) {
+		/* no buffer yet - allocate one */
+		if ((pi->buf = buf_alloc(0)) == NULL) {
+			/* ups - could not get buffer. Read away input
+			 * and drop it */
+			(void)recvfrom(pi->fd, embuf, sizeof(embuf),
+			    0, NULL, NULL);
+			/* return error */
+			return (-1);
+		}
+		pi->buflen = buf_size(0);
+	}
+
+	/* try to get a message */
+	msg.msg_name = pi->peer;
+	msg.msg_namelen = pi->peerlen;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	memset(cbuf, 0, sizeof(cbuf));
+	msg.msg_control = cbuf;
+	msg.msg_controllen = sizeof(cbuf);
+	msg.msg_flags = 0;
+
+	iov[0].iov_base = pi->buf;
+	iov[0].iov_len = pi->buflen;
+
+	len = recvmsg(pi->fd, &msg, 0);
+
+	if (len == -1 || len == 0)
+		/* receive error */
+		return (-1);
+
+	if (msg.msg_flags & MSG_TRUNC) {
+		/* truncated - drop */
+		snmpd_stats.silentDrops++;
+		snmpd_stats.inTooLong++;
+		return (-1);
+	}
+
+	pi->length = (size_t)len;
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+	    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));
+		if (cmsg->cmsg_level == SOL_SOCKET &&
+		    cmsg->cmsg_type == SCM_CREDS)
+			cred = (struct sockcred *)CMSG_DATA(cmsg);
+	}
+
+	if (pi->cred)
+		check_priv_dgram(pi, cred);
+
+	return (0);
+}
+
+/*
+ * Receive something
+ */
+static ssize_t
+udp_recv(struct port_input *pi)
+{
+	struct in_addr *laddr;
+	struct msghdr msg;
+	char cbuf[CMSG_SPACE(sizeof(struct in_addr))];
+	struct cmsghdr *cmsgp;
+	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);
+
+	if (laddr->s_addr == INADDR_ANY) {
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+	}
+
+	return (ret);
+}
+
 /*
  * Port table
  */



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