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
This commit is contained in:
Alexander Kabaev 2009-06-18 17:10:43 +00:00
parent 46f39347f5
commit e7733ffa39
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=194448
4 changed files with 37 additions and 28 deletions

View File

@ -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)

View File

@ -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 buflen,
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 buflen,
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 buflen,
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);

View File

@ -199,7 +199,6 @@ svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
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, sendsz, recvsz)
}
}
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.
*/

View File

@ -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],