svn commit: r194448 - in head: include/rpc lib/libc/rpc usr.sbin/mountd

Alexander Kabaev kan at FreeBSD.org
Thu Jun 18 17:10:44 UTC 2009


Author: kan
Date: Thu Jun 18 17:10:43 2009
New Revision: 194448
URL: http://svn.freebsd.org/changeset/base/194448

Log:
  Re-do r192913 in less intrusive way. Only do IP_RECVDSTADDR/IP_SENDSRCADDR
  dace for UPDv4 sockets bound to INADDR_ANY. Move the code to set
  IP_RECVDSTADDR/IP_SENDSRCADDR into svc_dg.c, so that both TLI and non-TLI
  users will be using it.
  
  Back out my previous commit to mountd. Turns out the problem was affecting
  more than one binary so it needs to me addressed in generic rpc code in
  libc in order to fix them all.
  
  Reported by:	lstewart
  Tested by:	lstewart

Modified:
  head/include/rpc/svc_dg.h
  head/lib/libc/rpc/svc_dg.c
  head/lib/libc/rpc/svc_generic.c
  head/usr.sbin/mountd/mountd.c

Modified: head/include/rpc/svc_dg.h
==============================================================================
--- head/include/rpc/svc_dg.h	Thu Jun 18 16:40:00 2009	(r194447)
+++ head/include/rpc/svc_dg.h	Thu Jun 18 17:10:43 2009	(r194448)
@@ -46,6 +46,7 @@ struct svc_dg_data {
 	XDR		su_xdrs;			/* XDR handle */
 	char		su_verfbody[MAX_AUTH_BYTES];	/* verifier body */
 	void		*su_cache;		/* cached data, NULL if none */
+	struct netbuf   su_srcaddr;		/* dst address of last msg */
 };
 
 #define __rpcb_get_dg_xidp(x)	(&((struct svc_dg_data *)(x)->xp_p2)->su_xid)

Modified: head/lib/libc/rpc/svc_dg.c
==============================================================================
--- head/lib/libc/rpc/svc_dg.c	Thu Jun 18 16:40:00 2009	(r194447)
+++ head/lib/libc/rpc/svc_dg.c	Thu Jun 18 17:10:43 2009	(r194448)
@@ -97,8 +97,9 @@ int svc_dg_enablecache(SVCXPRT *, u_int)
  */
 static const char svc_dg_str[] = "svc_dg_create: %s";
 static const char svc_dg_err1[] = "could not get transport information";
-static const char svc_dg_err2[] = " transport does not support data transfer";
+static const char svc_dg_err2[] = "transport does not support data transfer";
 static const char svc_dg_err3[] = "getsockname failed";
+static const char svc_dg_err4[] = "cannot set IP_RECVDSTADDR";
 static const char __no_mem_str[] = "out of memory";
 
 SVCXPRT *
@@ -156,6 +157,23 @@ svc_dg_create(fd, sendsize, recvsize)
 	xprt->xp_ltaddr.len = slen;
 	memcpy(xprt->xp_ltaddr.buf, &ss, slen);
 
+	if (ss.ss_family == AF_INET) {
+		struct sockaddr_in *sin;
+		static const int true_value = 1;
+
+		sin = (struct sockaddr_in *)(void *)&ss;
+		if (sin->sin_addr.s_addr == INADDR_ANY) {
+		    su->su_srcaddr.buf = mem_alloc(sizeof (ss));
+		    su->su_srcaddr.maxlen = sizeof (ss);
+
+		    if (_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR,
+				    &true_value, sizeof(true_value))) {
+			    warnx(svc_dg_str,  svc_dg_err4);
+			    goto freedata_nowarn;
+		    }
+		}
+	}
+
 	xprt_register(xprt);
 	return (xprt);
 freedata:
@@ -197,13 +215,15 @@ svc_dg_recvfrom(int fd, char *buf, int b
 	msg.msg_iovlen = 1;
 	msg.msg_namelen = *raddrlen;
 	msg.msg_name = (char *)raddr;
-	msg.msg_control = (caddr_t)tmp;
-	msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+	if (laddr != NULL) {
+	    msg.msg_control = (caddr_t)tmp;
+	    msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+	}
 	rlen = _recvmsg(fd, &msg, 0);
 	if (rlen >= 0)
 		*raddrlen = msg.msg_namelen;
 
-	if (rlen == -1 || !laddr ||
+	if (rlen == -1 || laddr == NULL ||
 	    msg.msg_controllen < sizeof(struct cmsghdr) ||
 	    msg.msg_flags & MSG_CTRUNC)
 		return rlen;
@@ -214,18 +234,19 @@ svc_dg_recvfrom(int fd, char *buf, int b
 		    cmsg->cmsg_type == IP_RECVDSTADDR) {
 			have_lin = TRUE;
 			memcpy(&lin->sin_addr,
-			    (struct in_addr *)CMSG_DATA(cmsg), sizeof(struct in_addr));
+			    (struct in_addr *)CMSG_DATA(cmsg),
+			    sizeof(struct in_addr));
 			break;
 		}
 	}
 
-	if (!have_lin)
-		return rlen;
-
 	lin->sin_family = AF_INET;
 	lin->sin_port = 0;
 	*laddrlen = sizeof(struct sockaddr_in);
 
+	if (!have_lin)
+		lin->sin_addr.s_addr = INADDR_ANY;
+
 	return rlen;
 }
 
@@ -246,7 +267,7 @@ again:
 	alen = sizeof (struct sockaddr_storage);
 	rlen = svc_dg_recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz,
 	    (struct sockaddr *)(void *)&ss, &alen,
-	    (struct sockaddr *)xprt->xp_ltaddr.buf, &xprt->xp_ltaddr.len);
+	    (struct sockaddr *)su->su_srcaddr.buf, &su->su_srcaddr.len);
 	if (rlen == -1 && errno == EINTR)
 		goto again;
 	if (rlen == -1 || (rlen < (ssize_t)(4 * sizeof (u_int32_t))))
@@ -300,7 +321,8 @@ svc_dg_sendto(int fd, char *buf, int buf
 	msg.msg_namelen = raddrlen;
 	msg.msg_name = (char *)raddr;
 
-	if (laddr->sa_family == AF_INET && lin->s_addr != INADDR_ANY) {
+	if (laddr != NULL && laddr->sa_family == AF_INET &&
+	    lin->s_addr != INADDR_ANY) {
 		msg.msg_control = (caddr_t)tmp;
 		msg.msg_controllen = CMSG_LEN(sizeof(*lin));
 		cmsg = CMSG_FIRSTHDR(&msg);
@@ -346,8 +368,8 @@ svc_dg_reply(xprt, msg)
 		if (svc_dg_sendto(xprt->xp_fd, rpc_buffer(xprt), slen,
 		    (struct sockaddr *)xprt->xp_rtaddr.buf,
 		    (socklen_t)xprt->xp_rtaddr.len,
-		    (struct sockaddr *)xprt->xp_ltaddr.buf,
-		    xprt->xp_ltaddr.len) == (ssize_t) slen) {
+		    (struct sockaddr *)su->su_srcaddr.buf,
+		    (socklen_t)su->su_srcaddr.len) == (ssize_t) slen) {
 			stat = TRUE;
 			if (su->su_cache)
 				cache_set(xprt, slen);
@@ -393,6 +415,8 @@ svc_dg_destroy(xprt)
 		(void)_close(xprt->xp_fd);
 	XDR_DESTROY(&(su->su_xdrs));
 	(void) mem_free(rpc_buffer(xprt), su->su_iosz);
+	if (su->su_srcaddr.buf)
+		(void) mem_free(su->su_srcaddr.buf, su->su_srcaddr.maxlen);
 	(void) mem_free(su, sizeof (*su));
 	if (xprt->xp_rtaddr.buf)
 		(void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);

Modified: head/lib/libc/rpc/svc_generic.c
==============================================================================
--- head/lib/libc/rpc/svc_generic.c	Thu Jun 18 16:40:00 2009	(r194447)
+++ head/lib/libc/rpc/svc_generic.c	Thu Jun 18 17:10:43 2009	(r194448)
@@ -199,7 +199,6 @@ svc_tli_create(fd, nconf, bindaddr, send
 	struct __rpc_sockinfo si;
 	struct sockaddr_storage ss;
 	socklen_t slen;
-	static const int true_value = 1;
 
 	if (fd == RPC_ANYFD) {
 		if (nconf == NULL) {
@@ -226,14 +225,6 @@ svc_tli_create(fd, nconf, bindaddr, send
 		}
 	}
 
-	if (si.si_af == AF_INET && si.si_socktype == SOCK_DGRAM) {
-		if (_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR,
-			        &true_value, sizeof(true_value))) {
-			warnx("svc_tli_create: cannot set IP_RECVDSTADDR");
-			return (NULL);
-		}
-	}
-
 	/*
 	 * If the fd is unbound, try to bind it.
 	 */

Modified: head/usr.sbin/mountd/mountd.c
==============================================================================
--- head/usr.sbin/mountd/mountd.c	Thu Jun 18 16:40:00 2009	(r194447)
+++ head/usr.sbin/mountd/mountd.c	Thu Jun 18 17:10:43 2009	(r194448)
@@ -568,13 +568,6 @@ create_service(struct netconfig *nconf)
 					continue;
 				}
 			}
-			if (si.si_socktype == SOCK_DGRAM &&
-			    setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &one,
-			        sizeof one) < 0) {
-				syslog(LOG_ERR,
-				    "can't disable v4-in-v6 on IPv6 socket");
-				exit(1);
-			}
 			break;
 		case AF_INET6:
 			if (inet_pton(AF_INET6, hosts[nhostsbak],


More information about the svn-src-head mailing list