File:  [DragonFly] / src / sys / netinet6 / in6_pcb.c
Revision 1.16: download - view: text, annotated - select for diffs
Thu Jun 3 13:30:26 2004 UTC (10 years, 3 months ago) by joerg
Branches: MAIN
CVS tags: HEAD
Don't cast away the const before dereferencing.

    1: /*	$FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.10.2.9 2003/01/24 05:11:35 sam Exp $	*/
    2: /*	$DragonFly: src/sys/netinet6/in6_pcb.c,v 1.16 2004/06/03 13:30:26 joerg Exp $	*/
    3: /*	$KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $	*/
    4:   
    5: /*
    6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    7:  * All rights reserved.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. Neither the name of the project nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  *
   21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  *
   33:  */
   34: 
   35: /*
   36:  * Copyright (c) 1982, 1986, 1991, 1993
   37:  *	The Regents of the University of California.  All rights reserved.
   38:  *
   39:  * Redistribution and use in source and binary forms, with or without
   40:  * modification, are permitted provided that the following conditions
   41:  * are met:
   42:  * 1. Redistributions of source code must retain the above copyright
   43:  *    notice, this list of conditions and the following disclaimer.
   44:  * 2. Redistributions in binary form must reproduce the above copyright
   45:  *    notice, this list of conditions and the following disclaimer in the
   46:  *    documentation and/or other materials provided with the distribution.
   47:  * 3. All advertising materials mentioning features or use of this software
   48:  *    must display the following acknowledgement:
   49:  *	This product includes software developed by the University of
   50:  *	California, Berkeley and its contributors.
   51:  * 4. Neither the name of the University nor the names of its contributors
   52:  *    may be used to endorse or promote products derived from this software
   53:  *    without specific prior written permission.
   54:  *
   55:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   56:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   59:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   60:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   61:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   63:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   64:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   65:  * SUCH DAMAGE.
   66:  *
   67:  *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
   68:  */
   69: 
   70: #include "opt_inet.h"
   71: #include "opt_inet6.h"
   72: #include "opt_ipsec.h"
   73: 
   74: #include <sys/param.h>
   75: #include <sys/systm.h>
   76: #include <sys/malloc.h>
   77: #include <sys/mbuf.h>
   78: #include <sys/domain.h>
   79: #include <sys/protosw.h>
   80: #include <sys/socket.h>
   81: #include <sys/socketvar.h>
   82: #include <sys/sockio.h>
   83: #include <sys/errno.h>
   84: #include <sys/time.h>
   85: #include <sys/proc.h>
   86: #include <sys/jail.h>
   87: 
   88: #include <vm/vm_zone.h>
   89: 
   90: #include <net/if.h>
   91: #include <net/if_types.h>
   92: #include <net/route.h>
   93: 
   94: #include <netinet/in.h>
   95: #include <netinet/in_var.h>
   96: #include <netinet/in_systm.h>
   97: #include <netinet/ip6.h>
   98: #include <netinet/ip_var.h>
   99: #include <netinet6/ip6_var.h>
  100: #include <netinet6/nd6.h>
  101: #include <netinet/in_pcb.h>
  102: #include <netinet6/in6_pcb.h>
  103: 
  104: #ifdef IPSEC
  105: #include <netinet6/ipsec.h>
  106: #ifdef INET6
  107: #include <netinet6/ipsec6.h>
  108: #endif
  109: #include <netinet6/ah.h>
  110: #ifdef INET6
  111: #include <netinet6/ah6.h>
  112: #endif
  113: #include <netproto/key/key.h>
  114: #endif /* IPSEC */
  115: 
  116: #ifdef FAST_IPSEC
  117: #include "ipsec.h"
  118: #include "ipsec6.h"
  119: #include <netipsec/key.h>
  120: #define	IPSEC
  121: #endif /* FAST_IPSEC */
  122: 
  123: struct	in6_addr zeroin6_addr;
  124: 
  125: int
  126: in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
  127: {
  128: 	struct socket *so = inp->inp_socket;
  129: 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
  130: 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
  131: 	u_short	lport = 0;
  132: 	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
  133: 
  134: 	if (!in6_ifaddr) /* XXX broken! */
  135: 		return (EADDRNOTAVAIL);
  136: 	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
  137: 		return(EINVAL);
  138: 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
  139: 		wild = 1;
  140: 	if (nam) {
  141: 		sin6 = (struct sockaddr_in6 *)nam;
  142: 		if (nam->sa_len != sizeof(*sin6))
  143: 			return(EINVAL);
  144: 		/*
  145: 		 * family check.
  146: 		 */
  147: 		if (nam->sa_family != AF_INET6)
  148: 			return(EAFNOSUPPORT);
  149: 
  150: 		/* KAME hack: embed scopeid */
  151: 		if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0)
  152: 			return EINVAL;
  153: 		/* this must be cleared for ifa_ifwithaddr() */
  154: 		sin6->sin6_scope_id = 0;
  155: 
  156: 		lport = sin6->sin6_port;
  157: 		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
  158: 			/*
  159: 			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
  160: 			 * allow compepte duplication of binding if
  161: 			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
  162: 			 * and a multicast address is bound on both
  163: 			 * new and duplicated sockets.
  164: 			 */
  165: 			if (so->so_options & SO_REUSEADDR)
  166: 				reuseport = SO_REUSEADDR|SO_REUSEPORT;
  167: 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  168: 			struct ifaddr *ia = NULL;
  169: 
  170: 			sin6->sin6_port = 0;		/* yech... */
  171: 			if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
  172: 				return(EADDRNOTAVAIL);
  173: 
  174: 			/*
  175: 			 * XXX: bind to an anycast address might accidentally
  176: 			 * cause sending a packet with anycast source address.
  177: 			 * We should allow to bind to a deprecated address, since
  178: 			 * the application dare to use it.
  179: 			 */
  180: 			if (ia &&
  181: 			    ((struct in6_ifaddr *)ia)->ia6_flags &
  182: 			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
  183: 				return(EADDRNOTAVAIL);
  184: 			}
  185: 		}
  186: 		if (lport) {
  187: 			struct inpcb *t;
  188: 			struct proc *p = td->td_proc; /* may be NULL */
  189: 
  190: 			/* GROSS */
  191: 			if (ntohs(lport) < IPV6PORT_RESERVED && p &&
  192: 			    suser_cred(p->p_ucred, PRISON_ROOT))
  193: 				return(EACCES);
  194: 			if (so->so_cred->cr_uid != 0 &&
  195: 			    !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
  196: 				t = in6_pcblookup_local(pcbinfo,
  197: 				    &sin6->sin6_addr, lport,
  198: 				    INPLOOKUP_WILDCARD);
  199: 				if (t &&
  200: 				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
  201: 				     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
  202: 				     (t->inp_socket->so_options &
  203: 				      SO_REUSEPORT) == 0) &&
  204: 				    (so->so_cred->cr_uid !=
  205: 				     t->inp_socket->so_cred->cr_uid))
  206: 					return (EADDRINUSE);
  207: 				if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
  208: 				    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  209: 					struct sockaddr_in sin;
  210: 
  211: 					in6_sin6_2_sin(&sin, sin6);
  212: 					t = in_pcblookup_local(pcbinfo,
  213: 						sin.sin_addr, lport,
  214: 						INPLOOKUP_WILDCARD);
  215: 					if (t &&
  216: 					    (so->so_cred->cr_uid !=
  217: 					     t->inp_socket->so_cred->cr_uid) &&
  218: 					    (ntohl(t->inp_laddr.s_addr) !=
  219: 					     INADDR_ANY ||
  220: 					     INP_SOCKAF(so) ==
  221: 					     INP_SOCKAF(t->inp_socket)))
  222: 						return (EADDRINUSE);
  223: 				}
  224: 			}
  225: 			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
  226: 						lport, wild);
  227: 			if (t && (reuseport & t->inp_socket->so_options) == 0)
  228: 				return(EADDRINUSE);
  229: 			if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
  230: 			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  231: 				struct sockaddr_in sin;
  232: 
  233: 				in6_sin6_2_sin(&sin, sin6);
  234: 				t = in_pcblookup_local(pcbinfo, sin.sin_addr,
  235: 						       lport, wild);
  236: 				if (t &&
  237: 				    (reuseport & t->inp_socket->so_options)
  238: 				    == 0 &&
  239: 				    (ntohl(t->inp_laddr.s_addr)
  240: 				     != INADDR_ANY ||
  241: 				     INP_SOCKAF(so) ==
  242: 				     INP_SOCKAF(t->inp_socket)))
  243: 					return (EADDRINUSE);
  244: 			}
  245: 		}
  246: 		inp->in6p_laddr = sin6->sin6_addr;
  247: 	}
  248: 	if (lport == 0) {
  249: 		int e;
  250: 		if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, td)) != 0)
  251: 			return(e);
  252: 	}
  253: 	else {
  254: 		inp->inp_lport = lport;
  255: 		if (in_pcbinsporthash(inp) != 0) {
  256: 			inp->in6p_laddr = in6addr_any;
  257: 			inp->inp_lport = 0;
  258: 			return (EAGAIN);
  259: 		}
  260: 	}
  261: 	return(0);
  262: }
  263: 
  264: /*
  265:  *   Transform old in6_pcbconnect() into an inner subroutine for new
  266:  *   in6_pcbconnect(): Do some validity-checking on the remote
  267:  *   address (in mbuf 'nam') and then determine local host address
  268:  *   (i.e., which interface) to use to access that remote host.
  269:  *
  270:  *   This preserves definition of in6_pcbconnect(), while supporting a
  271:  *   slightly different version for T/TCP.  (This is more than
  272:  *   a bit of a kludge, but cleaning up the internal interfaces would
  273:  *   have forced minor changes in every protocol).
  274:  */
  275: 
  276: int
  277: in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam,
  278: 	     struct in6_addr **plocal_addr6)
  279: {
  280: 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
  281: 	struct ifnet *ifp = NULL;
  282: 	int error = 0;
  283: 
  284: 	if (nam->sa_len != sizeof (*sin6))
  285: 		return (EINVAL);
  286: 	if (sin6->sin6_family != AF_INET6)
  287: 		return (EAFNOSUPPORT);
  288: 	if (sin6->sin6_port == 0)
  289: 		return (EADDRNOTAVAIL);
  290: 
  291: 	/* KAME hack: embed scopeid */
  292: 	if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
  293: 		return EINVAL;
  294: 
  295: 	if (in6_ifaddr) {
  296: 		/*
  297: 		 * If the destination address is UNSPECIFIED addr,
  298: 		 * use the loopback addr, e.g ::1.
  299: 		 */
  300: 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  301: 			sin6->sin6_addr = in6addr_loopback;
  302: 	}
  303: 	{
  304: 		/*
  305: 		 * XXX: in6_selectsrc might replace the bound local address
  306: 		 * with the address specified by setsockopt(IPV6_PKTINFO).
  307: 		 * Is it the intended behavior?
  308: 		 */
  309: 		*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
  310: 					      inp->in6p_moptions,
  311: 					      &inp->in6p_route,
  312: 					      &inp->in6p_laddr, &error);
  313: 		if (*plocal_addr6 == 0) {
  314: 			if (error == 0)
  315: 				error = EADDRNOTAVAIL;
  316: 			return(error);
  317: 		}
  318: 		/*
  319: 		 * Don't do pcblookup call here; return interface in
  320: 		 * plocal_addr6
  321: 		 * and exit to caller, that will do the lookup.
  322: 		 */
  323: 	}
  324: 
  325: 	if (inp->in6p_route.ro_rt)
  326: 		ifp = inp->in6p_route.ro_rt->rt_ifp;
  327: 
  328: 	return(0);
  329: }
  330: 
  331: /*
  332:  * Outer subroutine:
  333:  * Connect from a socket to a specified address.
  334:  * Both address and port must be specified in argument sin.
  335:  * If don't have a local address for this socket yet,
  336:  * then pick one.
  337:  */
  338: int
  339: in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
  340: {
  341: 	struct in6_addr *addr6;
  342: 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
  343: 	int error;
  344: 
  345: 	/*
  346: 	 * Call inner routine, to assign local interface address.
  347: 	 * in6_pcbladdr() may automatically fill in sin6_scope_id.
  348: 	 */
  349: 	if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
  350: 		return(error);
  351: 
  352: 	if (in6_pcblookup_hash(inp->inp_cpcbinfo, &sin6->sin6_addr,
  353: 			       sin6->sin6_port,
  354: 			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
  355: 			      ? addr6 : &inp->in6p_laddr,
  356: 			      inp->inp_lport, 0, NULL) != NULL) {
  357: 		return (EADDRINUSE);
  358: 	}
  359: 	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
  360: 		if (inp->inp_lport == 0) {
  361: 			error = in6_pcbbind(inp, (struct sockaddr *)0, td);
  362: 			if (error)
  363: 				return (error);
  364: 		}
  365: 		inp->in6p_laddr = *addr6;
  366: 	}
  367: 	inp->in6p_faddr = sin6->sin6_addr;
  368: 	inp->inp_fport = sin6->sin6_port;
  369: 	/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
  370: 	inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
  371: 	if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
  372: 		inp->in6p_flowinfo |=
  373: 		    (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
  374: 
  375: 	in_pcbinsconnhash(inp);
  376: 	return (0);
  377: }
  378: 
  379: #if 0
  380: /*
  381:  * Return an IPv6 address, which is the most appropriate for given
  382:  * destination and user specified options.
  383:  * If necessary, this function lookups the routing table and return
  384:  * an entry to the caller for later use.
  385:  */
  386: struct in6_addr *
  387: in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
  388: 	      struct ip6_moptions *mopts, struct route_in6 *ro,
  389: 	      struct in6_addr *laddr, int *errorp)
  390: {
  391: 	struct in6_addr *dst;
  392: 	struct in6_ifaddr *ia6 = 0;
  393: 	struct in6_pktinfo *pi = NULL;
  394: 
  395: 	dst = &dstsock->sin6_addr;
  396: 	*errorp = 0;
  397: 
  398: 	/*
  399: 	 * If the source address is explicitly specified by the caller,
  400: 	 * use it.
  401: 	 */
  402: 	if (opts && (pi = opts->ip6po_pktinfo) &&
  403: 	    !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
  404: 		return(&pi->ipi6_addr);
  405: 
  406: 	/*
  407: 	 * If the source address is not specified but the socket(if any)
  408: 	 * is already bound, use the bound address.
  409: 	 */
  410: 	if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
  411: 		return(laddr);
  412: 
  413: 	/*
  414: 	 * If the caller doesn't specify the source address but
  415: 	 * the outgoing interface, use an address associated with
  416: 	 * the interface.
  417: 	 */
  418: 	if (pi && pi->ipi6_ifindex) {
  419: 		/* XXX boundary check is assumed to be already done. */
  420: 		ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
  421: 				       dst);
  422: 		if (ia6 == 0) {
  423: 			*errorp = EADDRNOTAVAIL;
  424: 			return(0);
  425: 		}
  426: 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
  427: 	}
  428: 
  429: 	/*
  430: 	 * If the destination address is a link-local unicast address or
  431: 	 * a multicast address, and if the outgoing interface is specified
  432: 	 * by the sin6_scope_id filed, use an address associated with the
  433: 	 * interface.
  434: 	 * XXX: We're now trying to define more specific semantics of
  435: 	 *      sin6_scope_id field, so this part will be rewritten in
  436: 	 *      the near future.
  437: 	 */
  438: 	if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
  439: 	    dstsock->sin6_scope_id) {
  440: 		/*
  441: 		 * I'm not sure if boundary check for scope_id is done
  442: 		 * somewhere...
  443: 		 */
  444: 		if (dstsock->sin6_scope_id < 0 ||
  445: 		    if_index < dstsock->sin6_scope_id) {
  446: 			*errorp = ENXIO; /* XXX: better error? */
  447: 			return(0);
  448: 		}
  449: 		ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
  450: 				       dst);
  451: 		if (ia6 == 0) {
  452: 			*errorp = EADDRNOTAVAIL;
  453: 			return(0);
  454: 		}
  455: 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
  456: 	}
  457: 
  458: 	/*
  459: 	 * If the destination address is a multicast address and
  460: 	 * the outgoing interface for the address is specified
  461: 	 * by the caller, use an address associated with the interface.
  462: 	 * There is a sanity check here; if the destination has node-local
  463: 	 * scope, the outgoing interfacde should be a loopback address.
  464: 	 * Even if the outgoing interface is not specified, we also
  465: 	 * choose a loopback interface as the outgoing interface.
  466: 	 */
  467: 	if (IN6_IS_ADDR_MULTICAST(dst)) {
  468: 		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
  469: 
  470: 		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
  471: 			ifp = &loif[0];
  472: 		}
  473: 
  474: 		if (ifp) {
  475: 			ia6 = in6_ifawithscope(ifp, dst);
  476: 			if (ia6 == 0) {
  477: 				*errorp = EADDRNOTAVAIL;
  478: 				return(0);
  479: 			}
  480: 			return(&ia6->ia_addr.sin6_addr);
  481: 		}
  482: 	}
  483: 
  484: 	/*
  485: 	 * If the next hop address for the packet is specified
  486: 	 * by caller, use an address associated with the route
  487: 	 * to the next hop.
  488: 	 */
  489: 	{
  490: 		struct sockaddr_in6 *sin6_next;
  491: 		struct rtentry *rt;
  492: 
  493: 		if (opts && opts->ip6po_nexthop) {
  494: 			sin6_next = satosin6(opts->ip6po_nexthop);
  495: 			rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
  496: 			if (rt) {
  497: 				ia6 = in6_ifawithscope(rt->rt_ifp, dst);
  498: 				if (ia6 == 0)
  499: 					ia6 = ifatoia6(rt->rt_ifa);
  500: 			}
  501: 			if (ia6 == 0) {
  502: 				*errorp = EADDRNOTAVAIL;
  503: 				return(0);
  504: 			}
  505: 			return(&satosin6(&ia6->ia_addr)->sin6_addr);
  506: 		}
  507: 	}
  508: 
  509: 	/*
  510: 	 * If route is known or can be allocated now,
  511: 	 * our src addr is taken from the i/f, else punt.
  512: 	 */
  513: 	if (ro) {
  514: 		if (ro->ro_rt &&
  515: 		    !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
  516: 			RTFREE(ro->ro_rt);
  517: 			ro->ro_rt = (struct rtentry *)0;
  518: 		}
  519: 		if (ro->ro_rt == (struct rtentry *)0 ||
  520: 		    ro->ro_rt->rt_ifp == (struct ifnet *)0) {
  521: 			struct sockaddr_in6 *dst6;
  522: 
  523: 			/* No route yet, so try to acquire one */
  524: 			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  525: 			dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
  526: 			dst6->sin6_family = AF_INET6;
  527: 			dst6->sin6_len = sizeof(struct sockaddr_in6);
  528: 			dst6->sin6_addr = *dst;
  529: 			if (IN6_IS_ADDR_MULTICAST(dst)) {
  530: 				ro->ro_rt = rtalloc1(&((struct route *)ro)
  531: 						     ->ro_dst, 0, 0UL);
  532: 			} else {
  533: 				rtalloc((struct route *)ro);
  534: 			}
  535: 		}
  536: 
  537: 		/*
  538: 		 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
  539: 		 * the address. But we don't know why it does so.
  540: 		 * It is necessary to ensure the scope even for lo0
  541: 		 * so doesn't check out IFF_LOOPBACK.
  542: 		 */
  543: 
  544: 		if (ro->ro_rt) {
  545: 			ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
  546: 			if (ia6 == 0) /* xxx scope error ?*/
  547: 				ia6 = ifatoia6(ro->ro_rt->rt_ifa);
  548: 		}
  549: 		if (ia6 == 0) {
  550: 			*errorp = EHOSTUNREACH;	/* no route */
  551: 			return(0);
  552: 		}
  553: 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
  554: 	}
  555: 
  556: 	*errorp = EADDRNOTAVAIL;
  557: 	return(0);
  558: }
  559: 
  560: /*
  561:  * Default hop limit selection. The precedence is as follows:
  562:  * 1. Hoplimit valued specified via ioctl.
  563:  * 2. (If the outgoing interface is detected) the current
  564:  *     hop limit of the interface specified by router advertisement.
  565:  * 3. The system default hoplimit.
  566: */
  567: int
  568: in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
  569: {
  570: 	if (in6p && in6p->in6p_hops >= 0)
  571: 		return(in6p->in6p_hops);
  572: 	else if (ifp)
  573: 		return(nd_ifinfo[ifp->if_index].chlim);
  574: 	else
  575: 		return(ip6_defhlim);
  576: }
  577: #endif
  578: 
  579: void
  580: in6_pcbdisconnect(struct inpcb *inp)
  581: {
  582: 	bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
  583: 	inp->inp_fport = 0;
  584: 	/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
  585: 	inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
  586: 	in_pcbremconnhash(inp);
  587: 	if (inp->inp_socket->so_state & SS_NOFDREF)
  588: 		in6_pcbdetach(inp);
  589: }
  590: 
  591: void
  592: in6_pcbdetach(struct inpcb *inp)
  593: {
  594: 	struct socket *so = inp->inp_socket;
  595: 	struct inpcbinfo *ipi = inp->inp_pcbinfo;
  596: 
  597: #ifdef IPSEC
  598: 	if (inp->in6p_sp != NULL)
  599: 		ipsec6_delete_pcbpolicy(inp);
  600: #endif /* IPSEC */
  601: 	inp->inp_gencnt = ++ipi->ipi_gencnt;
  602: 	in_pcbremlists(inp);
  603: 	sotoinpcb(so) = 0;
  604: 	sofree(so);
  605: 
  606: 	if (inp->in6p_options)
  607: 		m_freem(inp->in6p_options);
  608:  	ip6_freepcbopts(inp->in6p_outputopts);
  609:  	ip6_freemoptions(inp->in6p_moptions);
  610: 	if (inp->in6p_route.ro_rt)
  611: 		rtfree(inp->in6p_route.ro_rt);
  612: 	/* Check and free IPv4 related resources in case of mapped addr */
  613: 	if (inp->inp_options)
  614: 		(void)m_free(inp->inp_options);
  615: 	ip_freemoptions(inp->inp_moptions);
  616: 
  617: 	inp->inp_vflag = 0;
  618: 	zfree(ipi->ipi_zone, inp);
  619: }
  620: 
  621: /*
  622:  * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
  623:  * modified to match the pru_sockaddr() and pru_peeraddr() entry points
  624:  * in struct pr_usrreqs, so that protocols can just reference then directly
  625:  * without the need for a wrapper function.  The socket must have a valid
  626:  * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
  627:  * except through a kernel programming error, so it is acceptable to panic
  628:  * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
  629:  * because there actually /is/ a programming error somewhere... XXX)
  630:  */
  631: int
  632: in6_setsockaddr(struct socket *so, struct sockaddr **nam)
  633: {
  634: 	int s;
  635: 	struct inpcb *inp;
  636: 	struct sockaddr_in6 *sin6;
  637: 
  638: 	/*
  639: 	 * Do the malloc first in case it blocks.
  640: 	 */
  641: 	MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
  642: 	bzero(sin6, sizeof *sin6);
  643: 	sin6->sin6_family = AF_INET6;
  644: 	sin6->sin6_len = sizeof(*sin6);
  645: 
  646: 	s = splnet();
  647: 	inp = sotoinpcb(so);
  648: 	if (!inp) {
  649: 		splx(s);
  650: 		free(sin6, M_SONAME);
  651: 		return EINVAL;
  652: 	}
  653: 	sin6->sin6_port = inp->inp_lport;
  654: 	sin6->sin6_addr = inp->in6p_laddr;
  655: 	splx(s);
  656: 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  657: 		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
  658: 	else
  659: 		sin6->sin6_scope_id = 0;	/*XXX*/
  660: 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  661: 		sin6->sin6_addr.s6_addr16[1] = 0;
  662: 
  663: 	*nam = (struct sockaddr *)sin6;
  664: 	return 0;
  665: }
  666: 
  667: int
  668: in6_setpeeraddr(struct socket *so, struct sockaddr **nam)
  669: {
  670: 	int s;
  671: 	struct inpcb *inp;
  672: 	struct sockaddr_in6 *sin6;
  673: 
  674: 	/*
  675: 	 * Do the malloc first in case it blocks.
  676: 	 */
  677: 	MALLOC(sin6, struct sockaddr_in6 *, sizeof(*sin6), M_SONAME, M_WAITOK);
  678: 	bzero((caddr_t)sin6, sizeof (*sin6));
  679: 	sin6->sin6_family = AF_INET6;
  680: 	sin6->sin6_len = sizeof(struct sockaddr_in6);
  681: 
  682: 	s = splnet();
  683: 	inp = sotoinpcb(so);
  684: 	if (!inp) {
  685: 		splx(s);
  686: 		free(sin6, M_SONAME);
  687: 		return EINVAL;
  688: 	}
  689: 	sin6->sin6_port = inp->inp_fport;
  690: 	sin6->sin6_addr = inp->in6p_faddr;
  691: 	splx(s);
  692: 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  693: 		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
  694: 	else
  695: 		sin6->sin6_scope_id = 0;	/*XXX*/
  696: 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  697: 		sin6->sin6_addr.s6_addr16[1] = 0;
  698: 
  699: 	*nam = (struct sockaddr *)sin6;
  700: 	return 0;
  701: }
  702: 
  703: int
  704: in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
  705: {
  706: 	struct	inpcb *inp = sotoinpcb(so);
  707: 	int	error;
  708: 
  709: 	if (inp == NULL)
  710: 		return EINVAL;
  711: 	if (inp->inp_vflag & INP_IPV4) {
  712: 		error = in_setsockaddr(so, nam);
  713: 		if (error == 0)
  714: 			in6_sin_2_v4mapsin6_in_sock(nam);
  715: 	} else
  716: 	/* scope issues will be handled in in6_setsockaddr(). */
  717: 	error = in6_setsockaddr(so, nam);
  718: 
  719: 	return error;
  720: }
  721: 
  722: int
  723: in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
  724: {
  725: 	struct	inpcb *inp = sotoinpcb(so);
  726: 	int	error;
  727: 
  728: 	if (inp == NULL)
  729: 		return EINVAL;
  730: 	if (inp->inp_vflag & INP_IPV4) {
  731: 		error = in_setpeeraddr(so, nam);
  732: 		if (error == 0)
  733: 			in6_sin_2_v4mapsin6_in_sock(nam);
  734: 	} else
  735: 	/* scope issues will be handled in in6_setpeeraddr(). */
  736: 	error = in6_setpeeraddr(so, nam);
  737: 
  738: 	return error;
  739: }
  740: 
  741: /*
  742:  * Pass some notification to all connections of a protocol
  743:  * associated with address dst.  The local address and/or port numbers
  744:  * may be specified to limit the search.  The "usual action" will be
  745:  * taken, depending on the ctlinput cmd.  The caller must filter any
  746:  * cmds that are uninteresting (e.g., no error in the map).
  747:  * Call the protocol specific routine (if any) to report
  748:  * any errors for each matching socket.
  749:  *
  750:  * Must be called at splnet.
  751:  */
  752: void
  753: in6_pcbnotify(struct inpcbhead *head, struct sockaddr *dst, u_int fport_arg,
  754: 	      const struct sockaddr *src, u_int lport_arg, int cmd,
  755: 	      void (*notify) (struct inpcb *, int))
  756: {
  757: 	struct inpcb *inp, *ninp;
  758: 	struct sockaddr_in6 sa6_src, *sa6_dst;
  759: 	u_short	fport = fport_arg, lport = lport_arg;
  760: 	u_int32_t flowinfo;
  761: 	int errno, s;
  762: 
  763: 	if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
  764: 		return;
  765: 
  766: 	sa6_dst = (struct sockaddr_in6 *)dst;
  767: 	if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
  768: 		return;
  769: 
  770: 	/*
  771: 	 * note that src can be NULL when we get notify by local fragmentation.
  772: 	 */
  773: 	sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
  774: 	flowinfo = sa6_src.sin6_flowinfo;
  775: 
  776: 	/*
  777: 	 * Redirects go to all references to the destination,
  778: 	 * and use in6_rtchange to invalidate the route cache.
  779: 	 * Dead host indications: also use in6_rtchange to invalidate
  780: 	 * the cache, and deliver the error to all the sockets.
  781: 	 * Otherwise, if we have knowledge of the local port and address,
  782: 	 * deliver only to that socket.
  783: 	 */
  784: 	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
  785: 		fport = 0;
  786: 		lport = 0;
  787: 		bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
  788: 
  789: 		if (cmd != PRC_HOSTDEAD)
  790: 			notify = in6_rtchange;
  791: 	}
  792: 	errno = inet6ctlerrmap[cmd];
  793: 	s = splnet();
  794:  	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
  795:  		ninp = LIST_NEXT(inp, inp_list);
  796: 
  797:  		if ((inp->inp_vflag & INP_IPV6) == 0)
  798: 			continue;
  799: 
  800: 		/*
  801: 		 * Detect if we should notify the error. If no source and
  802: 		 * destination ports are specifed, but non-zero flowinfo and
  803: 		 * local address match, notify the error. This is the case
  804: 		 * when the error is delivered with an encrypted buffer
  805: 		 * by ESP. Otherwise, just compare addresses and ports
  806: 		 * as usual.
  807: 		 */
  808: 		if (lport == 0 && fport == 0 && flowinfo &&
  809: 		    inp->inp_socket != NULL &&
  810: 		    flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
  811: 		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
  812: 			goto do_notify;
  813: 		else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
  814: 					     &sa6_dst->sin6_addr) ||
  815: 			 inp->inp_socket == 0 ||
  816: 			 (lport && inp->inp_lport != lport) ||
  817: 			 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
  818: 			  !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
  819: 					      &sa6_src.sin6_addr)) ||
  820: 			 (fport && inp->inp_fport != fport))
  821: 			continue;
  822: 
  823: 	  do_notify:
  824: 		if (notify)
  825: 			(*notify)(inp, errno);
  826: 	}
  827: 	splx(s);
  828: }
  829: 
  830: /*
  831:  * Lookup a PCB based on the local address and port.
  832:  */
  833: struct inpcb *
  834: in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
  835: 		    u_int lport_arg, int wild_okay)
  836: {
  837: 	struct inpcb *inp;
  838: 	int matchwild = 3, wildcard;
  839: 	u_short lport = lport_arg;
  840: 	struct inpcbporthead *porthash;
  841: 	struct inpcbport *phd;
  842: 	struct inpcb *match = NULL;
  843: 
  844: 	/*
  845: 	 * Best fit PCB lookup.
  846: 	 *
  847: 	 * First see if this local port is in use by looking on the
  848: 	 * port hash list.
  849: 	 */
  850: 	porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
  851: 	    pcbinfo->porthashmask)];
  852: 	LIST_FOREACH(phd, porthash, phd_hash) {
  853: 		if (phd->phd_port == lport)
  854: 			break;
  855: 	}
  856: 	if (phd != NULL) {
  857: 		/*
  858: 		 * Port is in use by one or more PCBs. Look for best
  859: 		 * fit.
  860: 		 */
  861: 		LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
  862: 			wildcard = 0;
  863: 			if ((inp->inp_vflag & INP_IPV6) == 0)
  864: 				continue;
  865: 			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
  866: 				wildcard++;
  867: 			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
  868: 				if (IN6_IS_ADDR_UNSPECIFIED(laddr))
  869: 					wildcard++;
  870: 				else if (!IN6_ARE_ADDR_EQUAL(
  871: 					&inp->in6p_laddr, laddr))
  872: 					continue;
  873: 			} else {
  874: 				if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
  875: 					wildcard++;
  876: 			}
  877: 			if (wildcard && !wild_okay)
  878: 				continue;
  879: 			if (wildcard < matchwild) {
  880: 				match = inp;
  881: 				if (wildcard == 0)
  882: 					break;
  883: 				else
  884: 					matchwild = wildcard;
  885: 			}
  886: 		}
  887: 	}
  888: 	return (match);
  889: }
  890: 
  891: void
  892: in6_pcbpurgeif0(struct in6pcb *head, struct ifnet *ifp)
  893: {
  894: 	struct in6pcb *in6p;
  895: 	struct ip6_moptions *im6o;
  896: 	struct in6_multi_mship *imm, *nimm;
  897: 
  898: 	for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) {
  899: 		im6o = in6p->in6p_moptions;
  900: 		if ((in6p->inp_vflag & INP_IPV6) &&
  901: 		    im6o) {
  902: 			/*
  903: 			 * Unselect the outgoing interface if it is being
  904: 			 * detached.
  905: 			 */
  906: 			if (im6o->im6o_multicast_ifp == ifp)
  907: 				im6o->im6o_multicast_ifp = NULL;
  908: 
  909: 			/*
  910: 			 * Drop multicast group membership if we joined
  911: 			 * through the interface being detached.
  912: 			 * XXX controversial - is it really legal for kernel
  913: 			 * to force this?
  914: 			 */
  915: 			for (imm = im6o->im6o_memberships.lh_first;
  916: 			     imm != NULL; imm = nimm) {
  917: 				nimm = imm->i6mm_chain.le_next;
  918: 				if (imm->i6mm_maddr->in6m_ifp == ifp) {
  919: 					LIST_REMOVE(imm, i6mm_chain);
  920: 					in6_delmulti(imm->i6mm_maddr);
  921: 					free(imm, M_IPMADDR);
  922: 				}
  923: 			}
  924: 		}
  925: 	}
  926: }
  927: 
  928: /*
  929:  * Check for alternatives when higher level complains
  930:  * about service problems.  For now, invalidate cached
  931:  * routing information.  If the route was created dynamically
  932:  * (by a redirect), time to try a default gateway again.
  933:  */
  934: void
  935: in6_losing(struct inpcb *in6p)
  936: {
  937: 	struct rtentry *rt;
  938: 	struct rt_addrinfo info;
  939: 
  940: 	if ((rt = in6p->in6p_route.ro_rt) != NULL) {
  941: 		bzero((caddr_t)&info, sizeof(info));
  942: 		info.rti_flags = rt->rt_flags;
  943: 		info.rti_info[RTAX_DST] = rt_key(rt);
  944: 		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  945: 		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  946: 		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
  947: 		if (rt->rt_flags & RTF_DYNAMIC)
  948: 			(void)rtrequest1(RTM_DELETE, &info, NULL);
  949: 		in6p->in6p_route.ro_rt = NULL;
  950: 		rtfree(rt);
  951: 		/*
  952: 		 * A new route can be allocated
  953: 		 * the next time output is attempted.
  954: 		 */
  955: 	}
  956: }
  957: 
  958: /*
  959:  * After a routing change, flush old routing
  960:  * and allocate a (hopefully) better one.
  961:  */
  962: void
  963: in6_rtchange(struct inpcb *inp, int errno)
  964: {
  965: 	if (inp->in6p_route.ro_rt) {
  966: 		rtfree(inp->in6p_route.ro_rt);
  967: 		inp->in6p_route.ro_rt = 0;
  968: 		/*
  969: 		 * A new route can be allocated the next time
  970: 		 * output is attempted.
  971: 		 */
  972: 	}
  973: }
  974: 
  975: /*
  976:  * Lookup PCB in hash list.
  977:  */
  978: struct inpcb *
  979: in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
  980: 		   u_int fport_arg, struct in6_addr *laddr, u_int lport_arg,
  981: 		   int wildcard, struct ifnet *ifp)
  982: {
  983: 	struct inpcbhead *head;
  984: 	struct inpcb *inp;
  985: 	u_short fport = fport_arg, lport = lport_arg;
  986: 	int faith;
  987: 
  988: 	if (faithprefix_p != NULL)
  989: 		faith = (*faithprefix_p)(laddr);
  990: 	else
  991: 		faith = 0;
  992: 
  993: 	/*
  994: 	 * First look for an exact match.
  995: 	 */
  996: 	head = &pcbinfo->hashbase[INP_PCBCONNHASH(faddr->s6_addr32[3] /* XXX */,
  997: 					      fport,
  998: 					      laddr->s6_addr32[3], /* XXX JH */
  999: 					      lport,
 1000: 					      pcbinfo->hashmask)];
 1001: 	LIST_FOREACH(inp, head, inp_hash) {
 1002: 		if ((inp->inp_vflag & INP_IPV6) == 0)
 1003: 			continue;
 1004: 		if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
 1005: 		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
 1006: 		    inp->inp_fport == fport &&
 1007: 		    inp->inp_lport == lport) {
 1008: 			/*
 1009: 			 * Found.
 1010: 			 */
 1011: 			return (inp);
 1012: 		}
 1013: 	}
 1014: 	if (wildcard) {
 1015: 		struct inpcontainerhead *chead;
 1016: 		struct inpcontainer *ic;
 1017: 		struct inpcb *local_wild = NULL;
 1018: 
 1019: 		chead = &pcbinfo->wildcardhashbase[INP_PCBWILDCARDHASH(lport,
 1020: 		    pcbinfo->wildcardhashmask)];
 1021: 		LIST_FOREACH(ic, chead, ic_list) {
 1022: 			inp = ic->ic_inp;
 1023: 
 1024: 			if (!(inp->inp_vflag & INP_IPV6))
 1025: 				continue;
 1026: 			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
 1027: 			    inp->inp_lport == lport) {
 1028: 				if (faith && (inp->inp_flags & INP_FAITH) == 0)
 1029: 					continue;
 1030: 				if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
 1031: 						       laddr))
 1032: 					return (inp);
 1033: 				else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
 1034: 					local_wild = inp;
 1035: 			}
 1036: 		}
 1037: 		return (local_wild);
 1038: 	}
 1039: 
 1040: 	/*
 1041: 	 * Not found.
 1042: 	 */
 1043: 	return (NULL);
 1044: }
 1045: 
 1046: void
 1047: init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
 1048: {
 1049: 	struct ip6_hdr *ip;
 1050: 
 1051: 	ip = mtod(m, struct ip6_hdr *);
 1052: 	bzero(sin6, sizeof(*sin6));
 1053: 	sin6->sin6_len = sizeof(*sin6);
 1054: 	sin6->sin6_family = AF_INET6;
 1055: 	sin6->sin6_addr = ip->ip6_src;
 1056: 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1057: 		sin6->sin6_addr.s6_addr16[1] = 0;
 1058: 	sin6->sin6_scope_id =
 1059: 		(m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1060: 		? m->m_pkthdr.rcvif->if_index : 0;
 1061: 
 1062: 	return;
 1063: }