diff options
author | bz <bz@FreeBSD.org> | 2011-04-09 01:29:46 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2011-04-09 01:29:46 +0000 |
commit | 1710f285d41e00787d848603ddb97004fb6483dd (patch) | |
tree | f8764234490db15208c57726518cdea9113ea30a | |
parent | 65e270c51b99c45f0f2244d08ae299c1922c9815 (diff) | |
download | FreeBSD-src-1710f285d41e00787d848603ddb97004fb6483dd.zip FreeBSD-src-1710f285d41e00787d848603ddb97004fb6483dd.tar.gz |
After r219579 and r219779 unbreak v4-mapped v6 sockets for UDP
some more. Similar to what we do for TCP check for v4-mapped
addresses and then handle them or the normal v6 address case.
For either set inp_vflags before calling into the pcb connect
function so that we have an unambiguous view in case we need to
set the local address or port.
Looked at: tuexen (as part of more)
MFC after: 3 days
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 422a9c9..b048665 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -909,43 +909,41 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) INP_INFO_WLOCK(&V_udbinfo); INP_WLOCK(inp); - if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && - IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { struct sockaddr_in sin; + if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { + error = EINVAL; + goto out; + } if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto out; } in6_sin6_2_sin(&sin, sin6); + inp->inp_vflag |= INP_IPV4; + inp->inp_vflag &= ~INP_IPV6; error = prison_remote_ip4(td->td_ucred, &sin.sin_addr); if (error != 0) goto out; error = in_pcbconnect(inp, (struct sockaddr *)&sin, td->td_ucred); - if (error == 0) { - inp->inp_vflag |= INP_IPV4; - inp->inp_vflag &= ~INP_IPV6; + if (error == 0) soisconnected(so); - } goto out; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { error = EISCONN; goto out; } + inp->inp_vflag &= ~INP_IPV4; + inp->inp_vflag |= INP_IPV6; error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr); if (error != 0) goto out; error = in6_pcbconnect(inp, nam, td->td_ucred); - if (error == 0) { - if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { - /* should be non mapped addr */ - inp->inp_vflag &= ~INP_IPV4; - inp->inp_vflag |= INP_IPV6; - } + if (error == 0) soisconnected(so); - } out: INP_WUNLOCK(inp); INP_INFO_WUNLOCK(&V_udbinfo); |