Date: Wed, 16 Oct 2013 08:14:05 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256593 - user/ae/inet6/sys/netinet6 Message-ID: <201310160814.r9G8E5lo067207@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Wed Oct 16 08:14:05 2013 New Revision: 256593 URL: http://svnweb.freebsd.org/changeset/base/256593 Log: Remove in6_pcbladdr() function: * move code from in6_pcbladdr() into in6_pcbconnect_mbuf(); * remove sa6_embedscope() and use sa6_checkzone() instead; * remove in6_setscope() call; * pass outgoing interface determined with SAS algorithm into in6_pcblookup_hash_locked() to be able determine scope zone id; * initialize in6p_zoneid when connection has link-local address. Modified: user/ae/inet6/sys/netinet6/in6_pcb.c Modified: user/ae/inet6/sys/netinet6/in6_pcb.c ============================================================================== --- user/ae/inet6/sys/netinet6/in6_pcb.c Wed Oct 16 07:52:19 2013 (r256592) +++ user/ae/inet6/sys/netinet6/in6_pcb.c Wed Oct 16 08:14:05 2013 (r256593) @@ -289,82 +289,6 @@ in6_pcbbind(struct inpcb *inp, struct so } /* - * Transform old in6_pcbconnect() into an inner subroutine for new - * in6_pcbconnect(): Do some validity-checking on the remote - * address (in mbuf 'nam') and then determine local host address - * (i.e., which interface) to use to access that remote host. - * - * This preserves definition of in6_pcbconnect(), while supporting a - * slightly different version for T/TCP. (This is more than - * a bit of a kludge, but cleaning up the internal interfaces would - * have forced minor changes in every protocol). - */ -static int -in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam, - struct in6_addr *plocal_addr6) -{ - register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; - int error = 0; - struct ifnet *ifp = NULL; - int scope_ambiguous = 0; - struct in6_addr in6a; - - INP_WLOCK_ASSERT(inp); - INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */ - - if (nam->sa_len != sizeof (*sin6)) - return (EINVAL); - if (sin6->sin6_family != AF_INET6) - return (EAFNOSUPPORT); - if (sin6->sin6_port == 0) - return (EADDRNOTAVAIL); - - if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone) - scope_ambiguous = 1; - if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) - return(error); - - if (!TAILQ_EMPTY(&V_in6_ifaddrhead)) { - /* - * If the destination address is UNSPECIFIED addr, - * use the loopback addr, e.g ::1. - */ - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) - sin6->sin6_addr = in6addr_loopback; - } - if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0) - return (error); - - error = in6_selectsrc(sin6, inp->in6p_outputopts, - inp, NULL, inp->inp_cred, &ifp, &in6a); - if (error) - return (error); - - if (ifp && scope_ambiguous && - (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) { - return(error); - } - - /* - * Do not update this earlier, in case we return with an error. - * - * XXX: this in6_selectsrc result might replace the bound local - * address with the address specified by setsockopt(IPV6_PKTINFO). - * Is it the intended behavior? - */ - *plocal_addr6 = in6a; - - /* - * Don't do pcblookup call here; return interface in - * plocal_addr6 - * and exit to caller, that will do the lookup. - */ - - return (0); -} - -/* - * Outer subroutine: * Connect from a socket to a specified address. * Both address and port must be specified in argument sin. * If don't have a local address for this socket yet, @@ -375,30 +299,49 @@ in6_pcbconnect_mbuf(register struct inpc struct ucred *cred, struct mbuf *m) { struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; - register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; + struct ifnet *ifp = NULL; struct in6_addr addr6; int error; INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(pcbinfo); + if (nam->sa_len != sizeof(*sin6)) + return (EINVAL); + if (sin6->sin6_family != AF_INET6) + return (EAFNOSUPPORT); + if (sin6->sin6_port == 0) + return (EADDRNOTAVAIL); + /* + * If the destination address is UNSPECIFIED addr, use the loopback + * addr, e.g ::1. + */ + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) + sin6->sin6_addr = in6addr_loopback; + /* + * Check sin6_scope_id and automatically fill it, if possible. + */ + error = sa6_checkzone(sin6); + if (error != 0) + return (error); + if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0) + return (error); /* - * Call inner routine, to assign local interface address. - * in6_pcbladdr() may automatically fill in sin6_scope_id. + * Determine source address and outgoing interface. */ - if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) + error = in6_selectsrc(sin6, inp->in6p_outputopts, inp, NULL, + inp->inp_cred, &ifp, &addr6); + if (error) return (error); if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, - sin6->sin6_port, - IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) - ? &addr6 : &inp->in6p_laddr, - inp->inp_lport, 0, NULL) != NULL) { + sin6->sin6_port, IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) ? + &addr6: &inp->in6p_laddr, inp->inp_lport, 0, ifp) != NULL) return (EADDRINUSE); - } if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { if (inp->inp_lport == 0) { - error = in6_pcbbind(inp, (struct sockaddr *)0, cred); + error = in6_pcbbind(inp, NULL, cred); if (error) return (error); } @@ -406,6 +349,10 @@ in6_pcbconnect_mbuf(register struct inpc } inp->in6p_faddr = sin6->sin6_addr; inp->inp_fport = sin6->sin6_port; + if (IN6_IS_ADDR_LINKLOCAL(&inp->in6p_faddr) || + IN6_IS_ADDR_LINKLOCAL(&inp->in6p_laddr)) + inp->in6p_zoneid = in6_getscopezone(ifp, + IPV6_ADDR_SCOPE_LINKLOCAL); /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310160814.r9G8E5lo067207>