svn commit: r256593 - user/ae/inet6/sys/netinet6
Andrey V. Elsukov
ae at FreeBSD.org
Wed Oct 16 08:14:05 UTC 2013
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)
More information about the svn-src-user
mailing list