Date: Thu, 18 Jun 2009 17:10:43 +0000 (UTC) From: Alexander Kabaev <kan@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r194448 - in head: include/rpc lib/libc/rpc usr.sbin/mountd Message-ID: <200906181710.n5IHAihc017562@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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],
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906181710.n5IHAihc017562>