in6_pcb.c revision 55679
153541Sshin/*
253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
353541Sshin * All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 3. Neither the name of the project nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
2853541Sshin *
2953541Sshin * $FreeBSD: head/sys/netinet6/in6_pcb.c 55679 2000-01-09 19:17:30Z shin $
3053541Sshin */
3153541Sshin
3253541Sshin/*
3353541Sshin * Copyright (c) 1982, 1986, 1991, 1993
3453541Sshin *	The Regents of the University of California.  All rights reserved.
3553541Sshin *
3653541Sshin * Redistribution and use in source and binary forms, with or without
3753541Sshin * modification, are permitted provided that the following conditions
3853541Sshin * are met:
3953541Sshin * 1. Redistributions of source code must retain the above copyright
4053541Sshin *    notice, this list of conditions and the following disclaimer.
4153541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4253541Sshin *    notice, this list of conditions and the following disclaimer in the
4353541Sshin *    documentation and/or other materials provided with the distribution.
4453541Sshin * 3. All advertising materials mentioning features or use of this software
4553541Sshin *    must display the following acknowledgement:
4653541Sshin *	This product includes software developed by the University of
4753541Sshin *	California, Berkeley and its contributors.
4853541Sshin * 4. Neither the name of the University nor the names of its contributors
4953541Sshin *    may be used to endorse or promote products derived from this software
5053541Sshin *    without specific prior written permission.
5153541Sshin *
5253541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5353541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5453541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5553541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5653541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5753541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5853541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5953541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6053541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6153541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6253541Sshin * SUCH DAMAGE.
6353541Sshin *
6453541Sshin *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
6553541Sshin * $FreeBSD: head/sys/netinet6/in6_pcb.c 55679 2000-01-09 19:17:30Z shin $
6653541Sshin */
6753541Sshin
6855009Sshin#include "opt_ipsec.h"
6953541Sshin
7053541Sshin#include <sys/param.h>
7153541Sshin#include <sys/systm.h>
7253541Sshin#include <sys/malloc.h>
7353541Sshin#include <sys/mbuf.h>
7455679Sshin#include <sys/domain.h>
7553541Sshin#include <sys/protosw.h>
7653541Sshin#include <sys/socket.h>
7753541Sshin#include <sys/socketvar.h>
7853541Sshin#include <sys/sockio.h>
7953541Sshin#include <sys/errno.h>
8053541Sshin#include <sys/time.h>
8153541Sshin#include <sys/proc.h>
8253541Sshin#include <sys/jail.h>
8353541Sshin
8453541Sshin#include <vm/vm_zone.h>
8553541Sshin
8653541Sshin#include <net/if.h>
8753541Sshin#include <net/if_types.h>
8853541Sshin#include <net/route.h>
8953541Sshin
9053541Sshin#include <netinet/in.h>
9153541Sshin#include <netinet/in_var.h>
9253541Sshin#include <netinet/in_systm.h>
9353541Sshin#include <netinet6/ip6.h>
9455679Sshin#include <netinet/ip_var.h>
9553541Sshin#include <netinet6/ip6_var.h>
9653541Sshin#include <netinet6/nd6.h>
9753541Sshin#include <netinet/in_pcb.h>
9853541Sshin#include <netinet6/in6_pcb.h>
9953541Sshin
10054263Sshin#include "faith.h"
10153541Sshin
10253541Sshin#ifdef IPSEC
10353541Sshin#include <netinet6/ipsec.h>
10455009Sshin#include <netinet6/ah.h>
10553541Sshin#include <netinet6/ipsec6.h>
10655009Sshin#include <netinet6/ah6.h>
10753541Sshin#include <netkey/key.h>
10855009Sshin#ifdef IPSEC_DEBUG
10953541Sshin#include <netkey/key_debug.h>
11053541Sshin#else
11155009Sshin#define	KEYDEBUG(lev,arg)
11255009Sshin#endif /* IPSEC_DEBUG */
11353541Sshin#endif /* IPSEC */
11453541Sshin
11553541Sshinstruct	in6_addr zeroin6_addr;
11653541Sshin
11753541Sshinint
11853541Sshinin6_pcbbind(inp, nam, p)
11953541Sshin	register struct inpcb *inp;
12053541Sshin	struct sockaddr *nam;
12153541Sshin	struct proc *p;
12253541Sshin{
12353541Sshin	struct socket *so = inp->inp_socket;
12453541Sshin	unsigned short *lastport;
12553541Sshin	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
12653541Sshin	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
12753541Sshin	u_short	lport = 0;
12853541Sshin	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
12953541Sshin	int error;
13053541Sshin
13153541Sshin	if (!in6_ifaddr) /* XXX broken! */
13253541Sshin		return (EADDRNOTAVAIL);
13353541Sshin	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
13453541Sshin		return(EINVAL);
13553541Sshin	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
13653541Sshin		wild = 1;
13753541Sshin	if (nam) {
13853541Sshin		sin6 = (struct sockaddr_in6 *)nam;
13953541Sshin		if (nam->sa_len != sizeof(*sin6))
14053541Sshin			return(EINVAL);
14153541Sshin		/*
14253541Sshin		 * family check.
14353541Sshin		 */
14453541Sshin		if (nam->sa_family != AF_INET6)
14553541Sshin			return(EAFNOSUPPORT);
14653541Sshin
14753541Sshin		/*
14853541Sshin		 * If the scope of the destination is link-local, embed the
14953541Sshin		 * interface index in the address.
15053541Sshin		 */
15153541Sshin		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
15253541Sshin			/* XXX boundary check is assumed to be already done. */
15353541Sshin			/* XXX sin6_scope_id is weaker than advanced-api. */
15453541Sshin			struct in6_pktinfo *pi;
15553541Sshin			if (inp->in6p_outputopts &&
15653541Sshin			    (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
15753541Sshin			    pi->ipi6_ifindex) {
15853541Sshin				sin6->sin6_addr.s6_addr16[1]
15953541Sshin					= htons(pi->ipi6_ifindex);
16053541Sshin			} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)
16153541Sshin				&& inp->in6p_moptions
16253541Sshin				&& inp->in6p_moptions->im6o_multicast_ifp) {
16353541Sshin				sin6->sin6_addr.s6_addr16[1] =
16453541Sshin					htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
16553541Sshin			} else if (sin6->sin6_scope_id) {
16653541Sshin				/* boundary check */
16753541Sshin				if (sin6->sin6_scope_id < 0
16853541Sshin				 || if_index < sin6->sin6_scope_id) {
16953541Sshin					return ENXIO;  /* XXX EINVAL? */
17053541Sshin				}
17153541Sshin				sin6->sin6_addr.s6_addr16[1]
17253541Sshin					= htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
17353541Sshin				/* this must be cleared for ifa_ifwithaddr() */
17453541Sshin				sin6->sin6_scope_id = 0;
17553541Sshin			}
17653541Sshin		}
17753541Sshin
17853541Sshin		lport = sin6->sin6_port;
17953541Sshin		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
18053541Sshin			/*
18153541Sshin			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
18253541Sshin			 * allow compepte duplication of binding if
18353541Sshin			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
18453541Sshin			 * and a multicast address is bound on both
18553541Sshin			 * new and duplicated sockets.
18653541Sshin			 */
18753541Sshin			if (so->so_options & SO_REUSEADDR)
18853541Sshin				reuseport = SO_REUSEADDR|SO_REUSEPORT;
18953541Sshin		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
19053541Sshin			struct ifaddr *ia = NULL;
19153541Sshin
19253541Sshin			sin6->sin6_port = 0;		/* yech... */
19353541Sshin			if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
19453541Sshin				return(EADDRNOTAVAIL);
19553541Sshin
19653541Sshin			/*
19753541Sshin			 * XXX: bind to an anycast address might accidentally
19853541Sshin			 * cause sending a packet with anycast source address.
19953541Sshin			 */
20053541Sshin			if (ia &&
20153541Sshin			    ((struct in6_ifaddr *)ia)->ia6_flags &
20253541Sshin			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
20353541Sshin			     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
20453541Sshin				return(EADDRNOTAVAIL);
20553541Sshin			}
20653541Sshin		}
20753541Sshin		if (lport) {
20853541Sshin			struct inpcb *t;
20953541Sshin
21053541Sshin			/* GROSS */
21153541Sshin			if (ntohs(lport) < IPV6PORT_RESERVED && p &&
21253541Sshin			    suser_xxx(0, p, PRISON_ROOT))
21353541Sshin				return(EACCES);
21453541Sshin			if (so->so_cred->cr_uid != 0 &&
21553541Sshin			    !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
21655679Sshin				t = in6_pcblookup_local(pcbinfo,
21753541Sshin				    &sin6->sin6_addr, lport,
21853541Sshin				    INPLOOKUP_WILDCARD);
21953541Sshin				if (t &&
22053541Sshin				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
22153541Sshin				     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
22253541Sshin				     (t->inp_socket->so_options &
22353541Sshin				      SO_REUSEPORT) == 0) &&
22453541Sshin				    (so->so_cred->cr_uid !=
22553541Sshin				     t->inp_socket->so_cred->cr_uid))
22653541Sshin					return (EADDRINUSE);
22755679Sshin				if (ip6_mapped_addr_on != 0 &&
22855679Sshin				    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
22955679Sshin					struct sockaddr_in sin;
23055679Sshin
23155679Sshin					in6_sin6_2_sin(&sin, sin6);
23255679Sshin					t = in_pcblookup_local(pcbinfo,
23355679Sshin						sin.sin_addr, lport,
23455679Sshin						INPLOOKUP_WILDCARD);
23555679Sshin					if (t &&
23655679Sshin					    (so->so_cred->cr_uid !=
23755679Sshin					     t->inp_socket->so_cred->cr_uid) &&
23855679Sshin					    (ntohl(t->inp_laddr.s_addr) !=
23955679Sshin					     INADDR_ANY ||
24055679Sshin					     INP_SOCKAF(so) ==
24155679Sshin					     INP_SOCKAF(t->inp_socket)))
24255679Sshin						return (EADDRINUSE);
24355679Sshin				}
24453541Sshin			}
24553541Sshin			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
24653541Sshin						lport, wild);
24753541Sshin			if (t && (reuseport & t->inp_socket->so_options) == 0)
24853541Sshin				return(EADDRINUSE);
24955679Sshin			if (ip6_mapped_addr_on != 0 &&
25055679Sshin			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
25155679Sshin				struct sockaddr_in sin;
25255679Sshin
25355679Sshin				in6_sin6_2_sin(&sin, sin6);
25455679Sshin				t = in_pcblookup_local(pcbinfo, sin.sin_addr,
25555679Sshin						       lport, wild);
25655679Sshin				if (t &&
25755679Sshin				    (reuseport & t->inp_socket->so_options)
25855679Sshin				    == 0 &&
25955679Sshin				    (ntohl(t->inp_laddr.s_addr)
26055679Sshin				     != INADDR_ANY ||
26155679Sshin				     INP_SOCKAF(so) ==
26255679Sshin				     INP_SOCKAF(t->inp_socket)))
26355679Sshin					return (EADDRINUSE);
26455679Sshin			}
26553541Sshin		}
26653541Sshin		inp->in6p_laddr = sin6->sin6_addr;
26753541Sshin	}
26853541Sshin	if (lport == 0) {
26953541Sshin		ushort first, last;
27053541Sshin		int count;
27153541Sshin
27253541Sshin		inp->inp_flags |= INP_ANONPORT;
27353541Sshin
27453541Sshin		if (inp->inp_flags & INP_HIGHPORT) {
27553541Sshin			first = ipport_hifirstauto;	/* sysctl */
27653541Sshin			last  = ipport_hilastauto;
27753541Sshin			lastport = &pcbinfo->lasthi;
27853541Sshin		} else if (inp->inp_flags & INP_LOWPORT) {
27953541Sshin			if (p && (error = suser_xxx(0, p, PRISON_ROOT)))
28053541Sshin				return error;
28153541Sshin			first = ipport_lowfirstauto;	/* 1023 */
28253541Sshin			last  = ipport_lowlastauto;	/* 600 */
28353541Sshin			lastport = &pcbinfo->lastlow;
28453541Sshin		} else {
28553541Sshin			first = ipport_firstauto;	/* sysctl */
28653541Sshin			last  = ipport_lastauto;
28753541Sshin			lastport = &pcbinfo->lastport;
28853541Sshin		}
28953541Sshin		/*
29053541Sshin		 * Simple check to ensure all ports are not used up causing
29153541Sshin		 * a deadlock here.
29253541Sshin		 *
29353541Sshin		 * We split the two cases (up and down) so that the direction
29453541Sshin		 * is not being tested on each round of the loop.
29553541Sshin		 */
29653541Sshin		if (first > last) {
29753541Sshin			/*
29853541Sshin			 * counting down
29953541Sshin			 */
30053541Sshin			count = first - last;
30153541Sshin
30253541Sshin			do {
30353541Sshin				if (count-- < 0) {	/* completely used? */
30453541Sshin					/*
30553541Sshin					 * Undo any address bind that may have
30653541Sshin					 * occurred above.
30753541Sshin					 */
30853541Sshin					inp->in6p_laddr = in6addr_any;
30953541Sshin					return (EAGAIN);
31053541Sshin				}
31153541Sshin				--*lastport;
31253541Sshin				if (*lastport > first || *lastport < last)
31353541Sshin					*lastport = first;
31453541Sshin				lport = htons(*lastport);
31553541Sshin			} while (in6_pcblookup_local(pcbinfo,
31653541Sshin				 &inp->in6p_laddr, lport, wild));
31753541Sshin		} else {
31853541Sshin			/*
31953541Sshin			 * counting up
32053541Sshin			 */
32153541Sshin			count = last - first;
32253541Sshin
32353541Sshin			do {
32453541Sshin				if (count-- < 0) {	/* completely used? */
32553541Sshin					/*
32653541Sshin					 * Undo any address bind that may have
32753541Sshin					 * occurred above.
32853541Sshin					 */
32953541Sshin					inp->in6p_laddr = in6addr_any;
33053541Sshin					return (EAGAIN);
33153541Sshin				}
33253541Sshin				++*lastport;
33353541Sshin				if (*lastport < first || *lastport > last)
33453541Sshin					*lastport = first;
33553541Sshin				lport = htons(*lastport);
33653541Sshin			} while (in6_pcblookup_local(pcbinfo,
33753541Sshin				 &inp->in6p_laddr, lport, wild));
33853541Sshin		}
33953541Sshin	}
34053541Sshin	inp->inp_lport = lport;
34153541Sshin	if (in_pcbinshash(inp) != 0) {
34253541Sshin		inp->in6p_laddr = in6addr_any;
34353541Sshin		inp->inp_lport = 0;
34453541Sshin		return (EAGAIN);
34553541Sshin	}
34653541Sshin	inp->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0;	/*XXX*/
34753541Sshin	return(0);
34853541Sshin}
34953541Sshin
35053541Sshin/*
35153541Sshin *   Transform old in6_pcbconnect() into an inner subroutine for new
35253541Sshin *   in6_pcbconnect(): Do some validity-checking on the remote
35353541Sshin *   address (in mbuf 'nam') and then determine local host address
35453541Sshin *   (i.e., which interface) to use to access that remote host.
35553541Sshin *
35653541Sshin *   This preserves definition of in6_pcbconnect(), while supporting a
35753541Sshin *   slightly different version for T/TCP.  (This is more than
35853541Sshin *   a bit of a kludge, but cleaning up the internal interfaces would
35953541Sshin *   have forced minor changes in every protocol).
36053541Sshin */
36153541Sshin
36253541Sshinint
36353541Sshinin6_pcbladdr(inp, nam, plocal_addr6)
36453541Sshin	register struct inpcb *inp;
36553541Sshin	struct sockaddr *nam;
36653541Sshin	struct in6_addr **plocal_addr6;
36753541Sshin{
36853541Sshin	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
36953541Sshin	struct in6_pktinfo *pi;
37053541Sshin	struct ifnet *ifp = NULL;
37153541Sshin	int error = 0;
37253541Sshin
37353541Sshin	if (nam->sa_len != sizeof (*sin6))
37453541Sshin		return (EINVAL);
37553541Sshin	if (sin6->sin6_family != AF_INET6)
37653541Sshin		return (EAFNOSUPPORT);
37753541Sshin	if (sin6->sin6_port == 0)
37853541Sshin		return (EADDRNOTAVAIL);
37953541Sshin
38053541Sshin	/*
38153541Sshin	 * If the scope of the destination is link-local, embed the interface
38253541Sshin	 * index in the address.
38353541Sshin	 */
38453541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
38553541Sshin		/* XXX boundary check is assumed to be already done. */
38653541Sshin		/* XXX sin6_scope_id is weaker than advanced-api. */
38753541Sshin		if (inp->in6p_outputopts &&
38853541Sshin		    (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
38953541Sshin		    pi->ipi6_ifindex) {
39053541Sshin			sin6->sin6_addr.s6_addr16[1] = htons(pi->ipi6_ifindex);
39153541Sshin			ifp = ifindex2ifnet[pi->ipi6_ifindex];
39253541Sshin		} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
39353541Sshin			 inp->in6p_moptions &&
39453541Sshin			 inp->in6p_moptions->im6o_multicast_ifp) {
39553541Sshin			sin6->sin6_addr.s6_addr16[1] =
39653541Sshin				htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
39753541Sshin			ifp = ifindex2ifnet[inp->in6p_moptions->im6o_multicast_ifp->if_index];
39853541Sshin		} else if (sin6->sin6_scope_id) {
39953541Sshin			/* boundary check */
40053541Sshin			if (sin6->sin6_scope_id < 0
40153541Sshin			 || if_index < sin6->sin6_scope_id) {
40253541Sshin				return ENXIO;  /* XXX EINVAL? */
40353541Sshin			}
40453541Sshin			sin6->sin6_addr.s6_addr16[1]
40553541Sshin				= htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
40653541Sshin			ifp = ifindex2ifnet[sin6->sin6_scope_id];
40753541Sshin		}
40853541Sshin	}
40953541Sshin
41053541Sshin	if (in6_ifaddr) {
41153541Sshin		/*
41253541Sshin		 * If the destination address is UNSPECIFIED addr,
41353541Sshin		 * use the loopback addr, e.g ::1.
41453541Sshin		 */
41553541Sshin		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
41653541Sshin			sin6->sin6_addr = in6addr_loopback;
41753541Sshin	}
41853541Sshin	{
41953541Sshin		/*
42053541Sshin		 * XXX: in6_selectsrc might replace the bound local address
42153541Sshin		 * with the address specified by setsockopt(IPV6_PKTINFO).
42253541Sshin		 * Is it the intended behavior?
42353541Sshin		 */
42453541Sshin		*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
42553541Sshin					      inp->in6p_moptions,
42653541Sshin					      &inp->in6p_route,
42753541Sshin					      &inp->in6p_laddr, &error);
42853541Sshin		if (*plocal_addr6 == 0) {
42953541Sshin			if (error == 0)
43053541Sshin				error = EADDRNOTAVAIL;
43153541Sshin			return(error);
43253541Sshin		}
43353541Sshin		/*
43453541Sshin		 * Don't do pcblookup call here; return interface in
43553541Sshin		 * plocal_addr6
43653541Sshin		 * and exit to caller, that will do the lookup.
43753541Sshin		 */
43853541Sshin	}
43953541Sshin
44053541Sshin	if (inp->in6p_route.ro_rt)
44153541Sshin		ifp = inp->in6p_route.ro_rt->rt_ifp;
44253541Sshin
44353541Sshin	inp->in6p_ip6_hlim = (u_int8_t)in6_selecthlim(inp, ifp);
44453541Sshin
44553541Sshin	return(0);
44653541Sshin}
44753541Sshin
44853541Sshin/*
44953541Sshin * Outer subroutine:
45053541Sshin * Connect from a socket to a specified address.
45153541Sshin * Both address and port must be specified in argument sin.
45253541Sshin * If don't have a local address for this socket yet,
45353541Sshin * then pick one.
45453541Sshin */
45553541Sshinint
45653541Sshinin6_pcbconnect(inp, nam, p)
45753541Sshin	register struct inpcb *inp;
45853541Sshin	struct sockaddr *nam;
45953541Sshin	struct proc *p;
46053541Sshin{
46153541Sshin	struct in6_addr *addr6;
46253541Sshin	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
46353541Sshin	int error;
46453541Sshin
46553541Sshin	/*
46653541Sshin	 *   Call inner routine, to assign local interface address.
46753541Sshin	 */
46853541Sshin	if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
46953541Sshin		return(error);
47053541Sshin
47153541Sshin	if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
47253541Sshin			       sin6->sin6_port,
47353541Sshin			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
47453541Sshin			      ? addr6 : &inp->in6p_laddr,
47553541Sshin			      inp->inp_lport, 0, NULL) != NULL) {
47653541Sshin		return (EADDRINUSE);
47753541Sshin	}
47853541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
47953541Sshin		if (inp->inp_lport == 0) {
48053541Sshin			error = in6_pcbbind(inp, (struct sockaddr *)0, p);
48153541Sshin			if (error)
48253541Sshin				return (error);
48353541Sshin		}
48453541Sshin		inp->in6p_laddr = *addr6;
48553541Sshin	}
48653541Sshin	inp->in6p_faddr = sin6->sin6_addr;
48753541Sshin	inp->inp_fport = sin6->sin6_port;
48853541Sshin	/*
48953541Sshin	 * xxx kazu flowlabel is necessary for connect?
49053541Sshin	 * but if this line is missing, the garbage value remains.
49153541Sshin	 */
49253541Sshin	inp->in6p_flowinfo = sin6->sin6_flowinfo;
49355679Sshin#ifdef INET6
49455679Sshin	if ((inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) == 0 &&
49555679Sshin	    ip6_auto_flowlable != 0)
49655679Sshin		inp->in6p_flowinfo |=
49755679Sshin			(htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
49855679Sshin#endif
49953541Sshin
50053541Sshin	in_pcbrehash(inp);
50153541Sshin	return (0);
50253541Sshin}
50353541Sshin
50453541Sshin/*
50553541Sshin * Return an IPv6 address, which is the most appropriate for given
50653541Sshin * destination and user specified options.
50753541Sshin * If necessary, this function lookups the routing table and return
50853541Sshin * an entry to the caller for later use.
50953541Sshin */
51053541Sshinstruct in6_addr *
51153541Sshinin6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
51253541Sshin	struct sockaddr_in6 *dstsock;
51353541Sshin	struct ip6_pktopts *opts;
51453541Sshin	struct ip6_moptions *mopts;
51553541Sshin	struct route_in6 *ro;
51653541Sshin	struct in6_addr *laddr;
51753541Sshin	int *errorp;
51853541Sshin{
51953541Sshin	struct in6_addr *dst;
52053541Sshin	struct in6_ifaddr *ia6 = 0;
52153541Sshin	struct in6_pktinfo *pi = NULL;
52253541Sshin
52353541Sshin	dst = &dstsock->sin6_addr;
52453541Sshin	*errorp = 0;
52553541Sshin
52653541Sshin	/*
52753541Sshin	 * If the source address is explicitly specified by the caller,
52853541Sshin	 * use it.
52953541Sshin	 */
53053541Sshin	if (opts && (pi = opts->ip6po_pktinfo) &&
53153541Sshin	    !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
53253541Sshin		return(&pi->ipi6_addr);
53353541Sshin
53453541Sshin	/*
53553541Sshin	 * If the source address is not specified but the socket(if any)
53653541Sshin	 * is already bound, use the bound address.
53753541Sshin	 */
53853541Sshin	if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
53953541Sshin		return(laddr);
54053541Sshin
54153541Sshin	/*
54253541Sshin	 * If the caller doesn't specify the source address but
54353541Sshin	 * the outgoing interface, use an address associated with
54453541Sshin	 * the interface.
54553541Sshin	 */
54653541Sshin	if (pi && pi->ipi6_ifindex) {
54753541Sshin		/* XXX boundary check is assumed to be already done. */
54853541Sshin		ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
54953541Sshin				       dst);
55053541Sshin		if (ia6 == 0) {
55153541Sshin			*errorp = EADDRNOTAVAIL;
55253541Sshin			return(0);
55353541Sshin		}
55453541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
55553541Sshin	}
55653541Sshin
55753541Sshin	/*
55853541Sshin	 * If the destination address is a link-local unicast address or
55953541Sshin	 * a multicast address, and if the outgoing interface is specified
56053541Sshin	 * by the sin6_scope_id filed, use an address associated with the
56153541Sshin	 * interface.
56253541Sshin	 * XXX: We're now trying to define more specific semantics of
56353541Sshin	 *      sin6_scope_id field, so this part will be rewritten in
56453541Sshin	 *      the near future.
56553541Sshin	 */
56653541Sshin	if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
56753541Sshin	    dstsock->sin6_scope_id) {
56853541Sshin		/*
56953541Sshin		 * I'm not sure if boundary check for scope_id is done
57053541Sshin		 * somewhere...
57153541Sshin		 */
57253541Sshin		if (dstsock->sin6_scope_id < 0 ||
57353541Sshin		    if_index < dstsock->sin6_scope_id) {
57453541Sshin			*errorp = ENXIO; /* XXX: better error? */
57553541Sshin			return(0);
57653541Sshin		}
57753541Sshin		ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
57853541Sshin				       dst);
57953541Sshin		if (ia6 == 0) {
58053541Sshin			*errorp = EADDRNOTAVAIL;
58153541Sshin			return(0);
58253541Sshin		}
58353541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
58453541Sshin	}
58553541Sshin
58653541Sshin	/*
58753541Sshin	 * If the destination address is a multicast address and
58853541Sshin	 * the outgoing interface for the address is specified
58953541Sshin	 * by the caller, use an address associated with the interface.
59053541Sshin	 * There is a sanity check here; if the destination has node-local
59153541Sshin	 * scope, the outgoing interfacde should be a loopback address.
59253541Sshin	 * Even if the outgoing interface is not specified, we also
59353541Sshin	 * choose a loopback interface as the outgoing interface.
59453541Sshin	 */
59553541Sshin	if (IN6_IS_ADDR_MULTICAST(dst)) {
59653541Sshin		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
59753541Sshin
59853541Sshin		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
59953541Sshin			ifp = &loif[0];
60053541Sshin		}
60153541Sshin
60253541Sshin		if (ifp) {
60353541Sshin			ia6 = in6_ifawithscope(ifp, dst);
60453541Sshin			if (ia6 == 0) {
60553541Sshin				*errorp = EADDRNOTAVAIL;
60653541Sshin				return(0);
60753541Sshin			}
60853541Sshin			return(&ia6->ia_addr.sin6_addr);
60953541Sshin		}
61053541Sshin	}
61153541Sshin
61253541Sshin	/*
61353541Sshin	 * If the next hop address for the packet is specified
61453541Sshin	 * by caller, use an address associated with the route
61553541Sshin	 * to the next hop.
61653541Sshin	 */
61753541Sshin	{
61853541Sshin		struct sockaddr_in6 *sin6_next;
61953541Sshin		struct rtentry *rt;
62053541Sshin
62153541Sshin		if (opts && opts->ip6po_nexthop) {
62253541Sshin			sin6_next = satosin6(opts->ip6po_nexthop);
62353541Sshin			rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
62453541Sshin			if (rt) {
62553541Sshin				ia6 = in6_ifawithscope(rt->rt_ifp, dst);
62653541Sshin				if (ia6 == 0)
62753541Sshin					ia6 = ifatoia6(rt->rt_ifa);
62853541Sshin			}
62953541Sshin			if (ia6 == 0) {
63053541Sshin				*errorp = EADDRNOTAVAIL;
63153541Sshin				return(0);
63253541Sshin			}
63353541Sshin			return(&satosin6(&ia6->ia_addr)->sin6_addr);
63453541Sshin		}
63553541Sshin	}
63653541Sshin
63753541Sshin	/*
63853541Sshin	 * If route is known or can be allocated now,
63953541Sshin	 * our src addr is taken from the i/f, else punt.
64053541Sshin	 */
64153541Sshin	if (ro) {
64253541Sshin		if (ro->ro_rt &&
64353541Sshin		    !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
64453541Sshin			RTFREE(ro->ro_rt);
64553541Sshin			ro->ro_rt = (struct rtentry *)0;
64653541Sshin		}
64753541Sshin		if (ro->ro_rt == (struct rtentry *)0 ||
64853541Sshin		    ro->ro_rt->rt_ifp == (struct ifnet *)0) {
64953541Sshin			/* No route yet, so try to acquire one */
65053541Sshin			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
65153541Sshin			ro->ro_dst.sin6_family = AF_INET6;
65253541Sshin			ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
65353541Sshin			ro->ro_dst.sin6_addr = *dst;
65453541Sshin			if (IN6_IS_ADDR_MULTICAST(dst)) {
65553541Sshin				ro->ro_rt = rtalloc1(&((struct route *)ro)
65653541Sshin						     ->ro_dst, 0, 0UL);
65753541Sshin			} else {
65854350Sshin				rtalloc((struct route *)ro);
65953541Sshin			}
66053541Sshin		}
66153541Sshin
66253541Sshin		/*
66353541Sshin		 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
66453541Sshin		 * the address. But we don't know why it does so.
66553541Sshin		 * It is necessary to ensure the scope even for lo0
66653541Sshin		 * so doesn't check out IFF_LOOPBACK.
66753541Sshin		 */
66853541Sshin
66953541Sshin		if (ro->ro_rt) {
67053541Sshin			ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
67153541Sshin			if (ia6 == 0) /* xxx scope error ?*/
67253541Sshin				ia6 = ifatoia6(ro->ro_rt->rt_ifa);
67353541Sshin		}
67453541Sshin		if (ia6 == 0) {
67553541Sshin			*errorp = EHOSTUNREACH;	/* no route */
67653541Sshin			return(0);
67753541Sshin		}
67853541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
67953541Sshin	}
68053541Sshin
68153541Sshin	*errorp = EADDRNOTAVAIL;
68253541Sshin	return(0);
68353541Sshin}
68453541Sshin
68553541Sshin/*
68653541Sshin * Default hop limit selection. The precedence is as follows:
68753541Sshin * 1. Hoplimit valued specified via ioctl.
68853541Sshin * 2. (If the outgoing interface is detected) the current
68953541Sshin *     hop limit of the interface specified by router advertisement.
69053541Sshin * 3. The system default hoplimit.
69153541Sshin*/
69253541Sshinint
69353541Sshinin6_selecthlim(in6p, ifp)
69453541Sshin	struct in6pcb *in6p;
69553541Sshin	struct ifnet *ifp;
69653541Sshin{
69753541Sshin	if (in6p && in6p->in6p_hops >= 0)
69853541Sshin		return(in6p->in6p_hops);
69953541Sshin	else if (ifp)
70053541Sshin		return(nd_ifinfo[ifp->if_index].chlim);
70153541Sshin	else
70253541Sshin		return(ip6_defhlim);
70353541Sshin}
70453541Sshin
70553541Sshinvoid
70653541Sshinin6_pcbdisconnect(inp)
70753541Sshin	struct inpcb *inp;
70853541Sshin{
70953541Sshin	bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
71053541Sshin	inp->inp_fport = 0;
71153541Sshin	in_pcbrehash(inp);
71253541Sshin	if (inp->inp_socket->so_state & SS_NOFDREF)
71353541Sshin		in6_pcbdetach(inp);
71453541Sshin}
71553541Sshin
71653541Sshinvoid
71753541Sshinin6_pcbdetach(inp)
71853541Sshin	struct inpcb *inp;
71953541Sshin{
72053541Sshin	struct socket *so = inp->inp_socket;
72153541Sshin	struct inpcbinfo *ipi = inp->inp_pcbinfo;
72253541Sshin
72353541Sshin#ifdef IPSEC
72453541Sshin	if (sotoinpcb(so) != 0)
72553541Sshin		key_freeso(so);
72653541Sshin	ipsec6_delete_pcbpolicy(inp);
72753541Sshin#endif /* IPSEC */
72853541Sshin	inp->inp_gencnt = ++ipi->ipi_gencnt;
72953541Sshin	in_pcbremlists(inp);
73053541Sshin	sotoinpcb(so) = 0;
73153541Sshin	sofree(so);
73253541Sshin	if (inp->in6p_options)
73353541Sshin		m_freem(inp->in6p_options);
73453541Sshin	if (inp->in6p_outputopts) {
73553541Sshin		if (inp->in6p_outputopts->ip6po_rthdr &&
73653541Sshin		    inp->in6p_outputopts->ip6po_route.ro_rt)
73753541Sshin			RTFREE(inp->in6p_outputopts->ip6po_route.ro_rt);
73853541Sshin		if (inp->in6p_outputopts->ip6po_m)
73953541Sshin			(void)m_free(inp->in6p_outputopts->ip6po_m);
74053541Sshin		free(inp->in6p_outputopts, M_IP6OPT);
74153541Sshin	}
74253541Sshin	if (inp->in6p_route.ro_rt)
74353541Sshin		rtfree(inp->in6p_route.ro_rt);
74453541Sshin	ip6_freemoptions(inp->in6p_moptions);
74555679Sshin
74655679Sshin	/* Check and free IPv4 related resources in case of mapped addr */
74755679Sshin	if (inp->inp_options)
74855679Sshin		(void)m_free(inp->inp_options);
74955679Sshin	if (inp->inp_route.ro_rt)
75055679Sshin		rtfree(inp->inp_route.ro_rt);
75155679Sshin	ip_freemoptions(inp->inp_moptions);
75255679Sshin
75353541Sshin	inp->inp_vflag = 0;
75453541Sshin	zfreei(ipi->ipi_zone, inp);
75553541Sshin}
75653541Sshin
75753541Sshin/*
75853541Sshin * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
75953541Sshin * modified to match the pru_sockaddr() and pru_peeraddr() entry points
76053541Sshin * in struct pr_usrreqs, so that protocols can just reference then directly
76153541Sshin * without the need for a wrapper function.  The socket must have a valid
76253541Sshin * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
76353541Sshin * except through a kernel programming error, so it is acceptable to panic
76453541Sshin * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
76553541Sshin * because there actually /is/ a programming error somewhere... XXX)
76653541Sshin */
76753541Sshinint
76853541Sshinin6_setsockaddr(so, nam)
76953541Sshin	struct socket *so;
77053541Sshin	struct sockaddr **nam;
77153541Sshin{
77253541Sshin	int s;
77353541Sshin	register struct inpcb *inp;
77453541Sshin	register struct sockaddr_in6 *sin6;
77553541Sshin
77653541Sshin	/*
77753541Sshin	 * Do the malloc first in case it blocks.
77853541Sshin	 */
77953541Sshin	MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
78053541Sshin	bzero(sin6, sizeof *sin6);
78153541Sshin	sin6->sin6_family = AF_INET6;
78253541Sshin	sin6->sin6_len = sizeof(*sin6);
78353541Sshin
78453541Sshin	s = splnet();
78553541Sshin	inp = sotoinpcb(so);
78653541Sshin	if (!inp) {
78753541Sshin		splx(s);
78853541Sshin		free(sin6, M_SONAME);
78953541Sshin		return EINVAL;
79053541Sshin	}
79153541Sshin	sin6->sin6_port = inp->inp_lport;
79253541Sshin	sin6->sin6_addr = inp->in6p_laddr;
79353541Sshin	splx(s);
79453541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
79553541Sshin		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
79653541Sshin	else
79753541Sshin		sin6->sin6_scope_id = 0;	/*XXX*/
79853541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
79953541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
80053541Sshin
80153541Sshin	*nam = (struct sockaddr *)sin6;
80253541Sshin	return 0;
80353541Sshin}
80453541Sshin
80553541Sshinint
80653541Sshinin6_setpeeraddr(so, nam)
80753541Sshin	struct socket *so;
80853541Sshin	struct sockaddr **nam;
80953541Sshin{
81053541Sshin	int s;
81153541Sshin	struct inpcb *inp;
81253541Sshin	register struct sockaddr_in6 *sin6;
81353541Sshin
81453541Sshin	/*
81553541Sshin	 * Do the malloc first in case it blocks.
81653541Sshin	 */
81753541Sshin	MALLOC(sin6, struct sockaddr_in6 *, sizeof(*sin6), M_SONAME, M_WAITOK);
81853541Sshin	bzero((caddr_t)sin6, sizeof (*sin6));
81953541Sshin	sin6->sin6_family = AF_INET6;
82053541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
82153541Sshin
82253541Sshin	s = splnet();
82353541Sshin	inp = sotoinpcb(so);
82453541Sshin	if (!inp) {
82553541Sshin		splx(s);
82653541Sshin		free(sin6, M_SONAME);
82753541Sshin		return EINVAL;
82853541Sshin	}
82953541Sshin	sin6->sin6_port = inp->inp_fport;
83053541Sshin	sin6->sin6_addr = inp->in6p_faddr;
83153541Sshin	splx(s);
83253541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
83353541Sshin		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
83453541Sshin	else
83553541Sshin		sin6->sin6_scope_id = 0;	/*XXX*/
83653541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
83753541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
83853541Sshin
83953541Sshin	*nam = (struct sockaddr *)sin6;
84053541Sshin	return 0;
84153541Sshin}
84253541Sshin
84353541Sshinint
84453541Sshinin6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
84553541Sshin{
84653541Sshin	struct	inpcb *inp = sotoinpcb(so);
84753541Sshin	int	error;
84853541Sshin
84953541Sshin	if (inp == NULL)
85053541Sshin		return EINVAL;
85153541Sshin	if (inp->inp_vflag & INP_IPV4) {
85253541Sshin		error = in_setsockaddr(so, nam);
85354952Seivind		if (error == 0)
85453541Sshin			in6_sin_2_v4mapsin6_in_sock(nam);
85553541Sshin	} else
85653541Sshin	error = in6_setsockaddr(so, nam);
85753541Sshin
85853541Sshin	return error;
85953541Sshin}
86053541Sshin
86153541Sshinint
86253541Sshinin6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
86353541Sshin{
86453541Sshin	struct	inpcb *inp = sotoinpcb(so);
86553541Sshin	int	error;
86653541Sshin
86753541Sshin	if (inp == NULL)
86853541Sshin		return EINVAL;
86953541Sshin	if (inp->inp_vflag & INP_IPV4) {
87053541Sshin		error = in_setpeeraddr(so, nam);
87154952Seivind		if (error == 0)
87253541Sshin			in6_sin_2_v4mapsin6_in_sock(nam);
87353541Sshin	} else
87453541Sshin	error = in6_setpeeraddr(so, nam);
87553541Sshin
87653541Sshin	return error;
87753541Sshin}
87853541Sshin
87953541Sshin/*
88053541Sshin * Pass some notification to all connections of a protocol
88153541Sshin * associated with address dst.  The local address and/or port numbers
88253541Sshin * may be specified to limit the search.  The "usual action" will be
88353541Sshin * taken, depending on the ctlinput cmd.  The caller must filter any
88453541Sshin * cmds that are uninteresting (e.g., no error in the map).
88553541Sshin * Call the protocol specific routine (if any) to report
88653541Sshin * any errors for each matching socket.
88753541Sshin *
88853541Sshin * Must be called at splnet.
88953541Sshin */
89053541Sshinvoid
89153541Sshinin6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
89253541Sshin	struct inpcbhead *head;
89353541Sshin	struct sockaddr *dst;
89453541Sshin	u_int fport_arg, lport_arg;
89553541Sshin	struct in6_addr *laddr6;
89653541Sshin	int cmd;
89753541Sshin	void (*notify) __P((struct inpcb *, int));
89853541Sshin{
89953541Sshin	struct inpcb *inp, *oinp;
90053541Sshin	struct in6_addr faddr6;
90153541Sshin	u_short	fport = fport_arg, lport = lport_arg;
90253541Sshin	int errno, s;
90353541Sshin
90453541Sshin	if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
90553541Sshin		return;
90653541Sshin	faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
90753541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
90853541Sshin		return;
90953541Sshin
91053541Sshin	/*
91153541Sshin	 * Redirects go to all references to the destination,
91253541Sshin	 * and use in_rtchange to invalidate the route cache.
91353541Sshin	 * Dead host indications: notify all references to the destination.
91453541Sshin	 * Otherwise, if we have knowledge of the local port and address,
91553541Sshin	 * deliver only to that socket.
91653541Sshin	 */
91753541Sshin	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
91853541Sshin		fport = 0;
91953541Sshin		lport = 0;
92053541Sshin		bzero((caddr_t)laddr6, sizeof(*laddr6));
92153541Sshin		if (cmd != PRC_HOSTDEAD)
92253541Sshin			notify = in6_rtchange;
92353541Sshin	}
92453541Sshin	errno = inet6ctlerrmap[cmd];
92553541Sshin	s = splnet();
92653541Sshin	for (inp = LIST_FIRST(head); inp != NULL;) {
92754952Seivind		if ((inp->inp_vflag & INP_IPV6) == 0) {
92853541Sshin			inp = LIST_NEXT(inp, inp_list);
92953541Sshin			continue;
93053541Sshin		}
93153541Sshin		if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &faddr6) ||
93253541Sshin		   inp->inp_socket == 0 ||
93353541Sshin		   (lport && inp->inp_lport != lport) ||
93453541Sshin		   (!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
93553541Sshin		    !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr6)) ||
93653541Sshin		   (fport && inp->inp_fport != fport)) {
93753541Sshin			inp = LIST_NEXT(inp, inp_list);
93853541Sshin			continue;
93953541Sshin		}
94053541Sshin		oinp = inp;
94153541Sshin		inp = LIST_NEXT(inp, inp_list);
94253541Sshin		if (notify)
94353541Sshin			(*notify)(oinp, errno);
94453541Sshin	}
94553541Sshin	splx(s);
94653541Sshin}
94753541Sshin
94853541Sshin/*
94953541Sshin * Lookup a PCB based on the local address and port.
95053541Sshin */
95153541Sshinstruct inpcb *
95253541Sshinin6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
95353541Sshin	struct inpcbinfo *pcbinfo;
95453541Sshin	struct in6_addr *laddr;
95553541Sshin	u_int lport_arg;
95653541Sshin	int wild_okay;
95753541Sshin{
95853541Sshin	register struct inpcb *inp;
95953541Sshin	int matchwild = 3, wildcard;
96053541Sshin	u_short lport = lport_arg;
96153541Sshin
96253541Sshin	if (!wild_okay) {
96353541Sshin		struct inpcbhead *head;
96453541Sshin		/*
96553541Sshin		 * Look for an unconnected (wildcard foreign addr) PCB that
96653541Sshin		 * matches the local address and port we're looking for.
96753541Sshin		 */
96853541Sshin		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
96953541Sshin						      pcbinfo->hashmask)];
97053541Sshin		LIST_FOREACH(inp, head, inp_hash) {
97154952Seivind			if ((inp->inp_vflag & INP_IPV6) == 0)
97253541Sshin				continue;
97353541Sshin			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
97453541Sshin			    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
97553541Sshin			    inp->inp_lport == lport) {
97653541Sshin				/*
97753541Sshin				 * Found.
97853541Sshin				 */
97953541Sshin				return (inp);
98053541Sshin			}
98153541Sshin		}
98253541Sshin		/*
98353541Sshin		 * Not found.
98453541Sshin		 */
98553541Sshin		return (NULL);
98653541Sshin	} else {
98753541Sshin		struct inpcbporthead *porthash;
98853541Sshin		struct inpcbport *phd;
98953541Sshin		struct inpcb *match = NULL;
99053541Sshin		/*
99153541Sshin		 * Best fit PCB lookup.
99253541Sshin		 *
99353541Sshin		 * First see if this local port is in use by looking on the
99453541Sshin		 * port hash list.
99553541Sshin		 */
99653541Sshin		porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
99753541Sshin		    pcbinfo->porthashmask)];
99853541Sshin		LIST_FOREACH(phd, porthash, phd_hash) {
99953541Sshin			if (phd->phd_port == lport)
100053541Sshin				break;
100153541Sshin		}
100253541Sshin		if (phd != NULL) {
100353541Sshin			/*
100453541Sshin			 * Port is in use by one or more PCBs. Look for best
100553541Sshin			 * fit.
100653541Sshin			 */
100753541Sshin			LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
100853541Sshin				wildcard = 0;
100954952Seivind				if ((inp->inp_vflag & INP_IPV6) == 0)
101053541Sshin					continue;
101153541Sshin				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
101253541Sshin					wildcard++;
101353541Sshin				if (!IN6_IS_ADDR_UNSPECIFIED(
101453541Sshin					&inp->in6p_laddr)) {
101553541Sshin					if (IN6_IS_ADDR_UNSPECIFIED(laddr))
101653541Sshin						wildcard++;
101753541Sshin					else if (!IN6_ARE_ADDR_EQUAL(
101853541Sshin						&inp->in6p_laddr, laddr))
101953541Sshin						continue;
102053541Sshin				} else {
102153541Sshin					if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
102253541Sshin						wildcard++;
102353541Sshin				}
102453541Sshin				if (wildcard < matchwild) {
102553541Sshin					match = inp;
102653541Sshin					matchwild = wildcard;
102753541Sshin					if (matchwild == 0) {
102853541Sshin						break;
102953541Sshin					}
103053541Sshin				}
103153541Sshin			}
103253541Sshin		}
103353541Sshin		return (match);
103453541Sshin	}
103553541Sshin}
103653541Sshin
103753541Sshin/*
103853541Sshin * Check for alternatives when higher level complains
103953541Sshin * about service problems.  For now, invalidate cached
104053541Sshin * routing information.  If the route was created dynamically
104153541Sshin * (by a redirect), time to try a default gateway again.
104253541Sshin */
104353541Sshinvoid
104453541Sshinin6_losing(in6p)
104553541Sshin	struct inpcb *in6p;
104653541Sshin{
104753541Sshin	struct rtentry *rt;
104853541Sshin	struct rt_addrinfo info;
104953541Sshin
105053541Sshin	if ((rt = in6p->in6p_route.ro_rt) != NULL) {
105153541Sshin		in6p->in6p_route.ro_rt = 0;
105253541Sshin		bzero((caddr_t)&info, sizeof(info));
105353541Sshin		info.rti_info[RTAX_DST] =
105453541Sshin			(struct sockaddr *)&in6p->in6p_route.ro_dst;
105553541Sshin		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
105653541Sshin		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
105753541Sshin		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
105853541Sshin		if (rt->rt_flags & RTF_DYNAMIC)
105953541Sshin			(void)rtrequest(RTM_DELETE, rt_key(rt),
106053541Sshin					rt->rt_gateway, rt_mask(rt), rt->rt_flags,
106153541Sshin					(struct rtentry **)0);
106253541Sshin		else
106353541Sshin		/*
106453541Sshin		 * A new route can be allocated
106553541Sshin		 * the next time output is attempted.
106653541Sshin		 */
106753541Sshin			rtfree(rt);
106853541Sshin	}
106953541Sshin}
107053541Sshin
107153541Sshin/*
107253541Sshin * After a routing change, flush old routing
107353541Sshin * and allocate a (hopefully) better one.
107453541Sshin */
107553541Sshinvoid
107653541Sshinin6_rtchange(inp, errno)
107753541Sshin	struct inpcb *inp;
107853541Sshin	int errno;
107953541Sshin{
108053541Sshin	if (inp->in6p_route.ro_rt) {
108153541Sshin		rtfree(inp->in6p_route.ro_rt);
108253541Sshin		inp->in6p_route.ro_rt = 0;
108353541Sshin		/*
108453541Sshin		 * A new route can be allocated the next time
108553541Sshin		 * output is attempted.
108653541Sshin		 */
108753541Sshin	}
108853541Sshin}
108953541Sshin
109053541Sshin/*
109153541Sshin * Lookup PCB in hash list.
109253541Sshin */
109353541Sshinstruct inpcb *
109453541Sshinin6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
109553541Sshin	struct inpcbinfo *pcbinfo;
109653541Sshin	struct in6_addr *faddr, *laddr;
109753541Sshin	u_int fport_arg, lport_arg;
109853541Sshin	int wildcard;
109953541Sshin	struct ifnet *ifp;
110053541Sshin{
110153541Sshin	struct inpcbhead *head;
110253541Sshin	register struct inpcb *inp;
110353541Sshin	u_short fport = fport_arg, lport = lport_arg;
110453541Sshin
110553541Sshin	/*
110653541Sshin	 * First look for an exact match.
110753541Sshin	 */
110853541Sshin	head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
110953541Sshin					      lport, fport,
111053541Sshin					      pcbinfo->hashmask)];
111154263Sshin	LIST_FOREACH(inp, head, inp_hash) {
111254952Seivind		if ((inp->inp_vflag & INP_IPV6) == 0)
111353541Sshin			continue;
111453541Sshin		if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
111553541Sshin		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
111653541Sshin		    inp->inp_fport == fport &&
111753541Sshin		    inp->inp_lport == lport) {
111853541Sshin			/*
111953541Sshin			 * Found.
112053541Sshin			 */
112153541Sshin			return (inp);
112253541Sshin		}
112353541Sshin	}
112453541Sshin	if (wildcard) {
112553541Sshin		struct inpcb *local_wild = NULL;
112653541Sshin
112753541Sshin		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
112853541Sshin						      pcbinfo->hashmask)];
112954263Sshin		LIST_FOREACH(inp, head, inp_hash) {
113054952Seivind			if ((inp->inp_vflag & INP_IPV6) == 0)
113153541Sshin				continue;
113253541Sshin			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
113353541Sshin			    inp->inp_lport == lport) {
113453541Sshin#if defined(NFAITH) && NFAITH > 0
113553541Sshin				if (ifp && ifp->if_type == IFT_FAITH &&
113653541Sshin				    (inp->inp_flags & INP_FAITH) == 0)
113753541Sshin					continue;
113853541Sshin#endif
113953541Sshin				if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
114053541Sshin						       laddr))
114153541Sshin					return (inp);
114253541Sshin				else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
114353541Sshin					local_wild = inp;
114453541Sshin			}
114553541Sshin		}
114653541Sshin		return (local_wild);
114753541Sshin	}
114853541Sshin
114953541Sshin	/*
115053541Sshin	 * Not found.
115153541Sshin	 */
115253541Sshin	return (NULL);
115353541Sshin}
115453541Sshin
115553541Sshinvoid
115653541Sshininit_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
115753541Sshin{
115853541Sshin	struct ip6_hdr *ip;
115953541Sshin
116053541Sshin	ip = mtod(m, struct ip6_hdr *);
116153541Sshin	bzero(sin6, sizeof(*sin6));
116253541Sshin	sin6->sin6_len = sizeof(*sin6);
116353541Sshin	sin6->sin6_family = AF_INET6;
116453541Sshin	sin6->sin6_addr = ip->ip6_src;
116553541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
116653541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
116753541Sshin	sin6->sin6_scope_id =
116853541Sshin		(m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
116953541Sshin		? m->m_pkthdr.rcvif->if_index : 0;
117053541Sshin
117153541Sshin	return;
117253541Sshin}
1173