in6_pcb.c revision 54952
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 54952 1999-12-21 11:14:12Z eivind $
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 54952 1999-12-21 11:14:12Z eivind $
6653541Sshin */
6753541Sshin
6853541Sshin#include "opt_key.h"
6953541Sshin
7053541Sshin#include <sys/param.h>
7153541Sshin#include <sys/systm.h>
7253541Sshin#include <sys/malloc.h>
7353541Sshin#include <sys/mbuf.h>
7453541Sshin#include <sys/protosw.h>
7553541Sshin#include <sys/socket.h>
7653541Sshin#include <sys/socketvar.h>
7753541Sshin#include <sys/sockio.h>
7853541Sshin#include <sys/errno.h>
7953541Sshin#include <sys/time.h>
8053541Sshin#include <sys/proc.h>
8153541Sshin#include <sys/jail.h>
8253541Sshin
8353541Sshin#include <vm/vm_zone.h>
8453541Sshin
8553541Sshin#include <net/if.h>
8653541Sshin#include <net/if_types.h>
8753541Sshin#include <net/route.h>
8853541Sshin
8953541Sshin#include <netinet/in.h>
9053541Sshin#include <netinet/in_var.h>
9153541Sshin#include <netinet/in_systm.h>
9253541Sshin#include <netinet6/ip6.h>
9353541Sshin#include <netinet6/ip6_var.h>
9453541Sshin#include <netinet6/nd6.h>
9553541Sshin#include <netinet/in_pcb.h>
9653541Sshin#include <netinet6/in6_pcb.h>
9753541Sshin
9854263Sshin#include "faith.h"
9953541Sshin
10053541Sshin#ifdef IPSEC
10153541Sshin#include <netinet6/ipsec.h>
10253541Sshin#include <netinet6/ipsec6.h>
10353541Sshin#include <netkey/key.h>
10453541Sshin#ifdef KEY_DEBUG
10553541Sshin#include <netkey/key_debug.h>
10653541Sshin#else
10753541Sshin#define DPRINTF(lev,arg)
10853541Sshin#define DDO(lev, stmt)
10953541Sshin#define DP(x, y, z)
11053541Sshin#endif /* KEY_DEBUG */
11153541Sshin#endif /* IPSEC */
11253541Sshin
11353541Sshinstruct	in6_addr zeroin6_addr;
11453541Sshin
11553541Sshinint
11653541Sshinin6_pcbbind(inp, nam, p)
11753541Sshin	register struct inpcb *inp;
11853541Sshin	struct sockaddr *nam;
11953541Sshin	struct proc *p;
12053541Sshin{
12153541Sshin	struct socket *so = inp->inp_socket;
12253541Sshin	unsigned short *lastport;
12353541Sshin	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
12453541Sshin	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
12553541Sshin	u_short	lport = 0;
12653541Sshin	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
12753541Sshin	int error;
12853541Sshin
12953541Sshin	if (!in6_ifaddr) /* XXX broken! */
13053541Sshin		return (EADDRNOTAVAIL);
13153541Sshin	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
13253541Sshin		return(EINVAL);
13353541Sshin	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
13453541Sshin		wild = 1;
13553541Sshin	if (nam) {
13653541Sshin		sin6 = (struct sockaddr_in6 *)nam;
13753541Sshin		if (nam->sa_len != sizeof(*sin6))
13853541Sshin			return(EINVAL);
13953541Sshin		/*
14053541Sshin		 * family check.
14153541Sshin		 */
14253541Sshin		if (nam->sa_family != AF_INET6)
14353541Sshin			return(EAFNOSUPPORT);
14453541Sshin
14553541Sshin		/*
14653541Sshin		 * If the scope of the destination is link-local, embed the
14753541Sshin		 * interface index in the address.
14853541Sshin		 */
14953541Sshin		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
15053541Sshin			/* XXX boundary check is assumed to be already done. */
15153541Sshin			/* XXX sin6_scope_id is weaker than advanced-api. */
15253541Sshin			struct in6_pktinfo *pi;
15353541Sshin			if (inp->in6p_outputopts &&
15453541Sshin			    (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
15553541Sshin			    pi->ipi6_ifindex) {
15653541Sshin				sin6->sin6_addr.s6_addr16[1]
15753541Sshin					= htons(pi->ipi6_ifindex);
15853541Sshin			} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)
15953541Sshin				&& inp->in6p_moptions
16053541Sshin				&& inp->in6p_moptions->im6o_multicast_ifp) {
16153541Sshin				sin6->sin6_addr.s6_addr16[1] =
16253541Sshin					htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
16353541Sshin			} else if (sin6->sin6_scope_id) {
16453541Sshin				/* boundary check */
16553541Sshin				if (sin6->sin6_scope_id < 0
16653541Sshin				 || if_index < sin6->sin6_scope_id) {
16753541Sshin					return ENXIO;  /* XXX EINVAL? */
16853541Sshin				}
16953541Sshin				sin6->sin6_addr.s6_addr16[1]
17053541Sshin					= htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
17153541Sshin				/* this must be cleared for ifa_ifwithaddr() */
17253541Sshin				sin6->sin6_scope_id = 0;
17353541Sshin			}
17453541Sshin		}
17553541Sshin
17653541Sshin		lport = sin6->sin6_port;
17753541Sshin		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
17853541Sshin			/*
17953541Sshin			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
18053541Sshin			 * allow compepte duplication of binding if
18153541Sshin			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
18253541Sshin			 * and a multicast address is bound on both
18353541Sshin			 * new and duplicated sockets.
18453541Sshin			 */
18553541Sshin			if (so->so_options & SO_REUSEADDR)
18653541Sshin				reuseport = SO_REUSEADDR|SO_REUSEPORT;
18753541Sshin		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
18853541Sshin			struct ifaddr *ia = NULL;
18953541Sshin
19053541Sshin			sin6->sin6_port = 0;		/* yech... */
19153541Sshin			if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
19253541Sshin				return(EADDRNOTAVAIL);
19353541Sshin
19453541Sshin			/*
19553541Sshin			 * XXX: bind to an anycast address might accidentally
19653541Sshin			 * cause sending a packet with anycast source address.
19753541Sshin			 */
19853541Sshin			if (ia &&
19953541Sshin			    ((struct in6_ifaddr *)ia)->ia6_flags &
20053541Sshin			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
20153541Sshin			     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
20253541Sshin				return(EADDRNOTAVAIL);
20353541Sshin			}
20453541Sshin		}
20553541Sshin		if (lport) {
20653541Sshin			struct inpcb *t;
20753541Sshin
20853541Sshin			/* GROSS */
20953541Sshin			if (ntohs(lport) < IPV6PORT_RESERVED && p &&
21053541Sshin			    suser_xxx(0, p, PRISON_ROOT))
21153541Sshin				return(EACCES);
21253541Sshin			if (so->so_cred->cr_uid != 0 &&
21353541Sshin			    !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
21453541Sshin				t = in6_pcblookup_local(inp->inp_pcbinfo,
21553541Sshin				    &sin6->sin6_addr, lport,
21653541Sshin				    INPLOOKUP_WILDCARD);
21753541Sshin				if (t &&
21853541Sshin				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
21953541Sshin				     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
22053541Sshin				     (t->inp_socket->so_options &
22153541Sshin				      SO_REUSEPORT) == 0) &&
22253541Sshin				    (so->so_cred->cr_uid !=
22353541Sshin				     t->inp_socket->so_cred->cr_uid))
22453541Sshin					return (EADDRINUSE);
22553541Sshin			}
22653541Sshin			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
22753541Sshin						lport, wild);
22853541Sshin			if (t && (reuseport & t->inp_socket->so_options) == 0)
22953541Sshin				return(EADDRINUSE);
23053541Sshin		}
23153541Sshin		inp->in6p_laddr = sin6->sin6_addr;
23253541Sshin	}
23353541Sshin	if (lport == 0) {
23453541Sshin		ushort first, last;
23553541Sshin		int count;
23653541Sshin
23753541Sshin		inp->inp_flags |= INP_ANONPORT;
23853541Sshin
23953541Sshin		if (inp->inp_flags & INP_HIGHPORT) {
24053541Sshin			first = ipport_hifirstauto;	/* sysctl */
24153541Sshin			last  = ipport_hilastauto;
24253541Sshin			lastport = &pcbinfo->lasthi;
24353541Sshin		} else if (inp->inp_flags & INP_LOWPORT) {
24453541Sshin			if (p && (error = suser_xxx(0, p, PRISON_ROOT)))
24553541Sshin				return error;
24653541Sshin			first = ipport_lowfirstauto;	/* 1023 */
24753541Sshin			last  = ipport_lowlastauto;	/* 600 */
24853541Sshin			lastport = &pcbinfo->lastlow;
24953541Sshin		} else {
25053541Sshin			first = ipport_firstauto;	/* sysctl */
25153541Sshin			last  = ipport_lastauto;
25253541Sshin			lastport = &pcbinfo->lastport;
25353541Sshin		}
25453541Sshin		/*
25553541Sshin		 * Simple check to ensure all ports are not used up causing
25653541Sshin		 * a deadlock here.
25753541Sshin		 *
25853541Sshin		 * We split the two cases (up and down) so that the direction
25953541Sshin		 * is not being tested on each round of the loop.
26053541Sshin		 */
26153541Sshin		if (first > last) {
26253541Sshin			/*
26353541Sshin			 * counting down
26453541Sshin			 */
26553541Sshin			count = first - last;
26653541Sshin
26753541Sshin			do {
26853541Sshin				if (count-- < 0) {	/* completely used? */
26953541Sshin					/*
27053541Sshin					 * Undo any address bind that may have
27153541Sshin					 * occurred above.
27253541Sshin					 */
27353541Sshin					inp->in6p_laddr = in6addr_any;
27453541Sshin					return (EAGAIN);
27553541Sshin				}
27653541Sshin				--*lastport;
27753541Sshin				if (*lastport > first || *lastport < last)
27853541Sshin					*lastport = first;
27953541Sshin				lport = htons(*lastport);
28053541Sshin			} while (in6_pcblookup_local(pcbinfo,
28153541Sshin				 &inp->in6p_laddr, lport, wild));
28253541Sshin		} else {
28353541Sshin			/*
28453541Sshin			 * counting up
28553541Sshin			 */
28653541Sshin			count = last - first;
28753541Sshin
28853541Sshin			do {
28953541Sshin				if (count-- < 0) {	/* completely used? */
29053541Sshin					/*
29153541Sshin					 * Undo any address bind that may have
29253541Sshin					 * occurred above.
29353541Sshin					 */
29453541Sshin					inp->in6p_laddr = in6addr_any;
29553541Sshin					return (EAGAIN);
29653541Sshin				}
29753541Sshin				++*lastport;
29853541Sshin				if (*lastport < first || *lastport > last)
29953541Sshin					*lastport = first;
30053541Sshin				lport = htons(*lastport);
30153541Sshin			} while (in6_pcblookup_local(pcbinfo,
30253541Sshin				 &inp->in6p_laddr, lport, wild));
30353541Sshin		}
30453541Sshin	}
30553541Sshin	inp->inp_lport = lport;
30653541Sshin	if (in_pcbinshash(inp) != 0) {
30753541Sshin		inp->in6p_laddr = in6addr_any;
30853541Sshin		inp->inp_lport = 0;
30953541Sshin		return (EAGAIN);
31053541Sshin	}
31153541Sshin	inp->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0;	/*XXX*/
31253541Sshin	return(0);
31353541Sshin}
31453541Sshin
31553541Sshin/*
31653541Sshin *   Transform old in6_pcbconnect() into an inner subroutine for new
31753541Sshin *   in6_pcbconnect(): Do some validity-checking on the remote
31853541Sshin *   address (in mbuf 'nam') and then determine local host address
31953541Sshin *   (i.e., which interface) to use to access that remote host.
32053541Sshin *
32153541Sshin *   This preserves definition of in6_pcbconnect(), while supporting a
32253541Sshin *   slightly different version for T/TCP.  (This is more than
32353541Sshin *   a bit of a kludge, but cleaning up the internal interfaces would
32453541Sshin *   have forced minor changes in every protocol).
32553541Sshin */
32653541Sshin
32753541Sshinint
32853541Sshinin6_pcbladdr(inp, nam, plocal_addr6)
32953541Sshin	register struct inpcb *inp;
33053541Sshin	struct sockaddr *nam;
33153541Sshin	struct in6_addr **plocal_addr6;
33253541Sshin{
33353541Sshin	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
33453541Sshin	struct in6_pktinfo *pi;
33553541Sshin	struct ifnet *ifp = NULL;
33653541Sshin	int error = 0;
33753541Sshin
33853541Sshin	if (nam->sa_len != sizeof (*sin6))
33953541Sshin		return (EINVAL);
34053541Sshin	if (sin6->sin6_family != AF_INET6)
34153541Sshin		return (EAFNOSUPPORT);
34253541Sshin	if (sin6->sin6_port == 0)
34353541Sshin		return (EADDRNOTAVAIL);
34453541Sshin
34553541Sshin	/*
34653541Sshin	 * If the scope of the destination is link-local, embed the interface
34753541Sshin	 * index in the address.
34853541Sshin	 */
34953541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
35053541Sshin		/* XXX boundary check is assumed to be already done. */
35153541Sshin		/* XXX sin6_scope_id is weaker than advanced-api. */
35253541Sshin		if (inp->in6p_outputopts &&
35353541Sshin		    (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
35453541Sshin		    pi->ipi6_ifindex) {
35553541Sshin			sin6->sin6_addr.s6_addr16[1] = htons(pi->ipi6_ifindex);
35653541Sshin			ifp = ifindex2ifnet[pi->ipi6_ifindex];
35753541Sshin		} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
35853541Sshin			 inp->in6p_moptions &&
35953541Sshin			 inp->in6p_moptions->im6o_multicast_ifp) {
36053541Sshin			sin6->sin6_addr.s6_addr16[1] =
36153541Sshin				htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
36253541Sshin			ifp = ifindex2ifnet[inp->in6p_moptions->im6o_multicast_ifp->if_index];
36353541Sshin		} else if (sin6->sin6_scope_id) {
36453541Sshin			/* boundary check */
36553541Sshin			if (sin6->sin6_scope_id < 0
36653541Sshin			 || if_index < sin6->sin6_scope_id) {
36753541Sshin				return ENXIO;  /* XXX EINVAL? */
36853541Sshin			}
36953541Sshin			sin6->sin6_addr.s6_addr16[1]
37053541Sshin				= htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
37153541Sshin			ifp = ifindex2ifnet[sin6->sin6_scope_id];
37253541Sshin		}
37353541Sshin	}
37453541Sshin
37553541Sshin	if (in6_ifaddr) {
37653541Sshin		/*
37753541Sshin		 * If the destination address is UNSPECIFIED addr,
37853541Sshin		 * use the loopback addr, e.g ::1.
37953541Sshin		 */
38053541Sshin		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
38153541Sshin			sin6->sin6_addr = in6addr_loopback;
38253541Sshin	}
38353541Sshin	{
38453541Sshin		/*
38553541Sshin		 * XXX: in6_selectsrc might replace the bound local address
38653541Sshin		 * with the address specified by setsockopt(IPV6_PKTINFO).
38753541Sshin		 * Is it the intended behavior?
38853541Sshin		 */
38953541Sshin		*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
39053541Sshin					      inp->in6p_moptions,
39153541Sshin					      &inp->in6p_route,
39253541Sshin					      &inp->in6p_laddr, &error);
39353541Sshin		if (*plocal_addr6 == 0) {
39453541Sshin			if (error == 0)
39553541Sshin				error = EADDRNOTAVAIL;
39653541Sshin			return(error);
39753541Sshin		}
39853541Sshin		/*
39953541Sshin		 * Don't do pcblookup call here; return interface in
40053541Sshin		 * plocal_addr6
40153541Sshin		 * and exit to caller, that will do the lookup.
40253541Sshin		 */
40353541Sshin	}
40453541Sshin
40553541Sshin	if (inp->in6p_route.ro_rt)
40653541Sshin		ifp = inp->in6p_route.ro_rt->rt_ifp;
40753541Sshin
40853541Sshin	inp->in6p_ip6_hlim = (u_int8_t)in6_selecthlim(inp, ifp);
40953541Sshin
41053541Sshin	return(0);
41153541Sshin}
41253541Sshin
41353541Sshin/*
41453541Sshin * Outer subroutine:
41553541Sshin * Connect from a socket to a specified address.
41653541Sshin * Both address and port must be specified in argument sin.
41753541Sshin * If don't have a local address for this socket yet,
41853541Sshin * then pick one.
41953541Sshin */
42053541Sshinint
42153541Sshinin6_pcbconnect(inp, nam, p)
42253541Sshin	register struct inpcb *inp;
42353541Sshin	struct sockaddr *nam;
42453541Sshin	struct proc *p;
42553541Sshin{
42653541Sshin	struct in6_addr *addr6;
42753541Sshin	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
42853541Sshin	int error;
42953541Sshin
43053541Sshin	/*
43153541Sshin	 *   Call inner routine, to assign local interface address.
43253541Sshin	 */
43353541Sshin	if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
43453541Sshin		return(error);
43553541Sshin
43653541Sshin	if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
43753541Sshin			       sin6->sin6_port,
43853541Sshin			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
43953541Sshin			      ? addr6 : &inp->in6p_laddr,
44053541Sshin			      inp->inp_lport, 0, NULL) != NULL) {
44153541Sshin		return (EADDRINUSE);
44253541Sshin	}
44353541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
44453541Sshin		if (inp->inp_lport == 0) {
44553541Sshin			error = in6_pcbbind(inp, (struct sockaddr *)0, p);
44653541Sshin			if (error)
44753541Sshin				return (error);
44853541Sshin		}
44953541Sshin		inp->in6p_laddr = *addr6;
45053541Sshin	}
45153541Sshin	inp->in6p_faddr = sin6->sin6_addr;
45253541Sshin	inp->inp_fport = sin6->sin6_port;
45353541Sshin	/*
45453541Sshin	 * xxx kazu flowlabel is necessary for connect?
45553541Sshin	 * but if this line is missing, the garbage value remains.
45653541Sshin	 */
45753541Sshin	inp->in6p_flowinfo = sin6->sin6_flowinfo;
45853541Sshin
45953541Sshin	in_pcbrehash(inp);
46053541Sshin	return (0);
46153541Sshin}
46253541Sshin
46353541Sshin/*
46453541Sshin * Return an IPv6 address, which is the most appropriate for given
46553541Sshin * destination and user specified options.
46653541Sshin * If necessary, this function lookups the routing table and return
46753541Sshin * an entry to the caller for later use.
46853541Sshin */
46953541Sshinstruct in6_addr *
47053541Sshinin6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
47153541Sshin	struct sockaddr_in6 *dstsock;
47253541Sshin	struct ip6_pktopts *opts;
47353541Sshin	struct ip6_moptions *mopts;
47453541Sshin	struct route_in6 *ro;
47553541Sshin	struct in6_addr *laddr;
47653541Sshin	int *errorp;
47753541Sshin{
47853541Sshin	struct in6_addr *dst;
47953541Sshin	struct in6_ifaddr *ia6 = 0;
48053541Sshin	struct in6_pktinfo *pi = NULL;
48153541Sshin
48253541Sshin	dst = &dstsock->sin6_addr;
48353541Sshin	*errorp = 0;
48453541Sshin
48553541Sshin	/*
48653541Sshin	 * If the source address is explicitly specified by the caller,
48753541Sshin	 * use it.
48853541Sshin	 */
48953541Sshin	if (opts && (pi = opts->ip6po_pktinfo) &&
49053541Sshin	    !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
49153541Sshin		return(&pi->ipi6_addr);
49253541Sshin
49353541Sshin	/*
49453541Sshin	 * If the source address is not specified but the socket(if any)
49553541Sshin	 * is already bound, use the bound address.
49653541Sshin	 */
49753541Sshin	if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
49853541Sshin		return(laddr);
49953541Sshin
50053541Sshin	/*
50153541Sshin	 * If the caller doesn't specify the source address but
50253541Sshin	 * the outgoing interface, use an address associated with
50353541Sshin	 * the interface.
50453541Sshin	 */
50553541Sshin	if (pi && pi->ipi6_ifindex) {
50653541Sshin		/* XXX boundary check is assumed to be already done. */
50753541Sshin		ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
50853541Sshin				       dst);
50953541Sshin		if (ia6 == 0) {
51053541Sshin			*errorp = EADDRNOTAVAIL;
51153541Sshin			return(0);
51253541Sshin		}
51353541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
51453541Sshin	}
51553541Sshin
51653541Sshin	/*
51753541Sshin	 * If the destination address is a link-local unicast address or
51853541Sshin	 * a multicast address, and if the outgoing interface is specified
51953541Sshin	 * by the sin6_scope_id filed, use an address associated with the
52053541Sshin	 * interface.
52153541Sshin	 * XXX: We're now trying to define more specific semantics of
52253541Sshin	 *      sin6_scope_id field, so this part will be rewritten in
52353541Sshin	 *      the near future.
52453541Sshin	 */
52553541Sshin	if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
52653541Sshin	    dstsock->sin6_scope_id) {
52753541Sshin		/*
52853541Sshin		 * I'm not sure if boundary check for scope_id is done
52953541Sshin		 * somewhere...
53053541Sshin		 */
53153541Sshin		if (dstsock->sin6_scope_id < 0 ||
53253541Sshin		    if_index < dstsock->sin6_scope_id) {
53353541Sshin			*errorp = ENXIO; /* XXX: better error? */
53453541Sshin			return(0);
53553541Sshin		}
53653541Sshin		ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
53753541Sshin				       dst);
53853541Sshin		if (ia6 == 0) {
53953541Sshin			*errorp = EADDRNOTAVAIL;
54053541Sshin			return(0);
54153541Sshin		}
54253541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
54353541Sshin	}
54453541Sshin
54553541Sshin	/*
54653541Sshin	 * If the destination address is a multicast address and
54753541Sshin	 * the outgoing interface for the address is specified
54853541Sshin	 * by the caller, use an address associated with the interface.
54953541Sshin	 * There is a sanity check here; if the destination has node-local
55053541Sshin	 * scope, the outgoing interfacde should be a loopback address.
55153541Sshin	 * Even if the outgoing interface is not specified, we also
55253541Sshin	 * choose a loopback interface as the outgoing interface.
55353541Sshin	 */
55453541Sshin	if (IN6_IS_ADDR_MULTICAST(dst)) {
55553541Sshin		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
55653541Sshin
55753541Sshin		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
55853541Sshin			ifp = &loif[0];
55953541Sshin		}
56053541Sshin
56153541Sshin		if (ifp) {
56253541Sshin			ia6 = in6_ifawithscope(ifp, dst);
56353541Sshin			if (ia6 == 0) {
56453541Sshin				*errorp = EADDRNOTAVAIL;
56553541Sshin				return(0);
56653541Sshin			}
56753541Sshin			return(&ia6->ia_addr.sin6_addr);
56853541Sshin		}
56953541Sshin	}
57053541Sshin
57153541Sshin	/*
57253541Sshin	 * If the next hop address for the packet is specified
57353541Sshin	 * by caller, use an address associated with the route
57453541Sshin	 * to the next hop.
57553541Sshin	 */
57653541Sshin	{
57753541Sshin		struct sockaddr_in6 *sin6_next;
57853541Sshin		struct rtentry *rt;
57953541Sshin
58053541Sshin		if (opts && opts->ip6po_nexthop) {
58153541Sshin			sin6_next = satosin6(opts->ip6po_nexthop);
58253541Sshin			rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
58353541Sshin			if (rt) {
58453541Sshin				ia6 = in6_ifawithscope(rt->rt_ifp, dst);
58553541Sshin				if (ia6 == 0)
58653541Sshin					ia6 = ifatoia6(rt->rt_ifa);
58753541Sshin			}
58853541Sshin			if (ia6 == 0) {
58953541Sshin				*errorp = EADDRNOTAVAIL;
59053541Sshin				return(0);
59153541Sshin			}
59253541Sshin			return(&satosin6(&ia6->ia_addr)->sin6_addr);
59353541Sshin		}
59453541Sshin	}
59553541Sshin
59653541Sshin	/*
59753541Sshin	 * If route is known or can be allocated now,
59853541Sshin	 * our src addr is taken from the i/f, else punt.
59953541Sshin	 */
60053541Sshin	if (ro) {
60153541Sshin		if (ro->ro_rt &&
60253541Sshin		    !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
60353541Sshin			RTFREE(ro->ro_rt);
60453541Sshin			ro->ro_rt = (struct rtentry *)0;
60553541Sshin		}
60653541Sshin		if (ro->ro_rt == (struct rtentry *)0 ||
60753541Sshin		    ro->ro_rt->rt_ifp == (struct ifnet *)0) {
60853541Sshin			/* No route yet, so try to acquire one */
60953541Sshin			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
61053541Sshin			ro->ro_dst.sin6_family = AF_INET6;
61153541Sshin			ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
61253541Sshin			ro->ro_dst.sin6_addr = *dst;
61353541Sshin			if (IN6_IS_ADDR_MULTICAST(dst)) {
61453541Sshin				ro->ro_rt = rtalloc1(&((struct route *)ro)
61553541Sshin						     ->ro_dst, 0, 0UL);
61653541Sshin			} else {
61754350Sshin				rtalloc((struct route *)ro);
61853541Sshin			}
61953541Sshin		}
62053541Sshin
62153541Sshin		/*
62253541Sshin		 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
62353541Sshin		 * the address. But we don't know why it does so.
62453541Sshin		 * It is necessary to ensure the scope even for lo0
62553541Sshin		 * so doesn't check out IFF_LOOPBACK.
62653541Sshin		 */
62753541Sshin
62853541Sshin		if (ro->ro_rt) {
62953541Sshin			ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
63053541Sshin			if (ia6 == 0) /* xxx scope error ?*/
63153541Sshin				ia6 = ifatoia6(ro->ro_rt->rt_ifa);
63253541Sshin		}
63353541Sshin		if (ia6 == 0) {
63453541Sshin			*errorp = EHOSTUNREACH;	/* no route */
63553541Sshin			return(0);
63653541Sshin		}
63753541Sshin		return(&satosin6(&ia6->ia_addr)->sin6_addr);
63853541Sshin	}
63953541Sshin
64053541Sshin	*errorp = EADDRNOTAVAIL;
64153541Sshin	return(0);
64253541Sshin}
64353541Sshin
64453541Sshin/*
64553541Sshin * Default hop limit selection. The precedence is as follows:
64653541Sshin * 1. Hoplimit valued specified via ioctl.
64753541Sshin * 2. (If the outgoing interface is detected) the current
64853541Sshin *     hop limit of the interface specified by router advertisement.
64953541Sshin * 3. The system default hoplimit.
65053541Sshin*/
65153541Sshinint
65253541Sshinin6_selecthlim(in6p, ifp)
65353541Sshin	struct in6pcb *in6p;
65453541Sshin	struct ifnet *ifp;
65553541Sshin{
65653541Sshin	if (in6p && in6p->in6p_hops >= 0)
65753541Sshin		return(in6p->in6p_hops);
65853541Sshin	else if (ifp)
65953541Sshin		return(nd_ifinfo[ifp->if_index].chlim);
66053541Sshin	else
66153541Sshin		return(ip6_defhlim);
66253541Sshin}
66353541Sshin
66453541Sshinvoid
66553541Sshinin6_pcbdisconnect(inp)
66653541Sshin	struct inpcb *inp;
66753541Sshin{
66853541Sshin	bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
66953541Sshin	inp->inp_fport = 0;
67053541Sshin	in_pcbrehash(inp);
67153541Sshin	if (inp->inp_socket->so_state & SS_NOFDREF)
67253541Sshin		in6_pcbdetach(inp);
67353541Sshin}
67453541Sshin
67553541Sshinvoid
67653541Sshinin6_pcbdetach(inp)
67753541Sshin	struct inpcb *inp;
67853541Sshin{
67953541Sshin	struct socket *so = inp->inp_socket;
68053541Sshin	struct inpcbinfo *ipi = inp->inp_pcbinfo;
68153541Sshin
68253541Sshin#ifdef IPSEC
68353541Sshin	if (sotoinpcb(so) != 0)
68453541Sshin		key_freeso(so);
68553541Sshin	ipsec6_delete_pcbpolicy(inp);
68653541Sshin#endif /* IPSEC */
68753541Sshin	inp->inp_gencnt = ++ipi->ipi_gencnt;
68853541Sshin	in_pcbremlists(inp);
68953541Sshin	sotoinpcb(so) = 0;
69053541Sshin	sofree(so);
69153541Sshin	if (inp->in6p_options)
69253541Sshin		m_freem(inp->in6p_options);
69353541Sshin	if (inp->in6p_outputopts) {
69453541Sshin		if (inp->in6p_outputopts->ip6po_rthdr &&
69553541Sshin		    inp->in6p_outputopts->ip6po_route.ro_rt)
69653541Sshin			RTFREE(inp->in6p_outputopts->ip6po_route.ro_rt);
69753541Sshin		if (inp->in6p_outputopts->ip6po_m)
69853541Sshin			(void)m_free(inp->in6p_outputopts->ip6po_m);
69953541Sshin		free(inp->in6p_outputopts, M_IP6OPT);
70053541Sshin	}
70153541Sshin	if (inp->in6p_route.ro_rt)
70253541Sshin		rtfree(inp->in6p_route.ro_rt);
70353541Sshin	ip6_freemoptions(inp->in6p_moptions);
70453541Sshin	inp->inp_vflag = 0;
70553541Sshin	zfreei(ipi->ipi_zone, inp);
70653541Sshin}
70753541Sshin
70853541Sshin/*
70953541Sshin * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
71053541Sshin * modified to match the pru_sockaddr() and pru_peeraddr() entry points
71153541Sshin * in struct pr_usrreqs, so that protocols can just reference then directly
71253541Sshin * without the need for a wrapper function.  The socket must have a valid
71353541Sshin * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
71453541Sshin * except through a kernel programming error, so it is acceptable to panic
71553541Sshin * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
71653541Sshin * because there actually /is/ a programming error somewhere... XXX)
71753541Sshin */
71853541Sshinint
71953541Sshinin6_setsockaddr(so, nam)
72053541Sshin	struct socket *so;
72153541Sshin	struct sockaddr **nam;
72253541Sshin{
72353541Sshin	int s;
72453541Sshin	register struct inpcb *inp;
72553541Sshin	register struct sockaddr_in6 *sin6;
72653541Sshin
72753541Sshin	/*
72853541Sshin	 * Do the malloc first in case it blocks.
72953541Sshin	 */
73053541Sshin	MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
73153541Sshin	bzero(sin6, sizeof *sin6);
73253541Sshin	sin6->sin6_family = AF_INET6;
73353541Sshin	sin6->sin6_len = sizeof(*sin6);
73453541Sshin
73553541Sshin	s = splnet();
73653541Sshin	inp = sotoinpcb(so);
73753541Sshin	if (!inp) {
73853541Sshin		splx(s);
73953541Sshin		free(sin6, M_SONAME);
74053541Sshin		return EINVAL;
74153541Sshin	}
74253541Sshin	sin6->sin6_port = inp->inp_lport;
74353541Sshin	sin6->sin6_addr = inp->in6p_laddr;
74453541Sshin	splx(s);
74553541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
74653541Sshin		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
74753541Sshin	else
74853541Sshin		sin6->sin6_scope_id = 0;	/*XXX*/
74953541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
75053541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
75153541Sshin
75253541Sshin	*nam = (struct sockaddr *)sin6;
75353541Sshin	return 0;
75453541Sshin}
75553541Sshin
75653541Sshinint
75753541Sshinin6_setpeeraddr(so, nam)
75853541Sshin	struct socket *so;
75953541Sshin	struct sockaddr **nam;
76053541Sshin{
76153541Sshin	int s;
76253541Sshin	struct inpcb *inp;
76353541Sshin	register struct sockaddr_in6 *sin6;
76453541Sshin
76553541Sshin	/*
76653541Sshin	 * Do the malloc first in case it blocks.
76753541Sshin	 */
76853541Sshin	MALLOC(sin6, struct sockaddr_in6 *, sizeof(*sin6), M_SONAME, M_WAITOK);
76953541Sshin	bzero((caddr_t)sin6, sizeof (*sin6));
77053541Sshin	sin6->sin6_family = AF_INET6;
77153541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
77253541Sshin
77353541Sshin	s = splnet();
77453541Sshin	inp = sotoinpcb(so);
77553541Sshin	if (!inp) {
77653541Sshin		splx(s);
77753541Sshin		free(sin6, M_SONAME);
77853541Sshin		return EINVAL;
77953541Sshin	}
78053541Sshin	sin6->sin6_port = inp->inp_fport;
78153541Sshin	sin6->sin6_addr = inp->in6p_faddr;
78253541Sshin	splx(s);
78353541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
78453541Sshin		sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
78553541Sshin	else
78653541Sshin		sin6->sin6_scope_id = 0;	/*XXX*/
78753541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
78853541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
78953541Sshin
79053541Sshin	*nam = (struct sockaddr *)sin6;
79153541Sshin	return 0;
79253541Sshin}
79353541Sshin
79453541Sshinint
79553541Sshinin6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
79653541Sshin{
79753541Sshin	struct	inpcb *inp = sotoinpcb(so);
79853541Sshin	int	error;
79953541Sshin
80053541Sshin	if (inp == NULL)
80153541Sshin		return EINVAL;
80253541Sshin	if (inp->inp_vflag & INP_IPV4) {
80353541Sshin		error = in_setsockaddr(so, nam);
80454952Seivind		if (error == 0)
80553541Sshin			in6_sin_2_v4mapsin6_in_sock(nam);
80653541Sshin	} else
80753541Sshin	error = in6_setsockaddr(so, nam);
80853541Sshin
80953541Sshin	return error;
81053541Sshin}
81153541Sshin
81253541Sshinint
81353541Sshinin6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
81453541Sshin{
81553541Sshin	struct	inpcb *inp = sotoinpcb(so);
81653541Sshin	int	error;
81753541Sshin
81853541Sshin	if (inp == NULL)
81953541Sshin		return EINVAL;
82053541Sshin	if (inp->inp_vflag & INP_IPV4) {
82153541Sshin		error = in_setpeeraddr(so, nam);
82254952Seivind		if (error == 0)
82353541Sshin			in6_sin_2_v4mapsin6_in_sock(nam);
82453541Sshin	} else
82553541Sshin	error = in6_setpeeraddr(so, nam);
82653541Sshin
82753541Sshin	return error;
82853541Sshin}
82953541Sshin
83053541Sshin/*
83153541Sshin * Pass some notification to all connections of a protocol
83253541Sshin * associated with address dst.  The local address and/or port numbers
83353541Sshin * may be specified to limit the search.  The "usual action" will be
83453541Sshin * taken, depending on the ctlinput cmd.  The caller must filter any
83553541Sshin * cmds that are uninteresting (e.g., no error in the map).
83653541Sshin * Call the protocol specific routine (if any) to report
83753541Sshin * any errors for each matching socket.
83853541Sshin *
83953541Sshin * Must be called at splnet.
84053541Sshin */
84153541Sshinvoid
84253541Sshinin6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
84353541Sshin	struct inpcbhead *head;
84453541Sshin	struct sockaddr *dst;
84553541Sshin	u_int fport_arg, lport_arg;
84653541Sshin	struct in6_addr *laddr6;
84753541Sshin	int cmd;
84853541Sshin	void (*notify) __P((struct inpcb *, int));
84953541Sshin{
85053541Sshin	struct inpcb *inp, *oinp;
85153541Sshin	struct in6_addr faddr6;
85253541Sshin	u_short	fport = fport_arg, lport = lport_arg;
85353541Sshin	int errno, s;
85453541Sshin
85553541Sshin	if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
85653541Sshin		return;
85753541Sshin	faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
85853541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
85953541Sshin		return;
86053541Sshin
86153541Sshin	/*
86253541Sshin	 * Redirects go to all references to the destination,
86353541Sshin	 * and use in_rtchange to invalidate the route cache.
86453541Sshin	 * Dead host indications: notify all references to the destination.
86553541Sshin	 * Otherwise, if we have knowledge of the local port and address,
86653541Sshin	 * deliver only to that socket.
86753541Sshin	 */
86853541Sshin	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
86953541Sshin		fport = 0;
87053541Sshin		lport = 0;
87153541Sshin		bzero((caddr_t)laddr6, sizeof(*laddr6));
87253541Sshin		if (cmd != PRC_HOSTDEAD)
87353541Sshin			notify = in6_rtchange;
87453541Sshin	}
87553541Sshin	errno = inet6ctlerrmap[cmd];
87653541Sshin	s = splnet();
87753541Sshin	for (inp = LIST_FIRST(head); inp != NULL;) {
87854952Seivind		if ((inp->inp_vflag & INP_IPV6) == 0) {
87953541Sshin			inp = LIST_NEXT(inp, inp_list);
88053541Sshin			continue;
88153541Sshin		}
88253541Sshin		if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &faddr6) ||
88353541Sshin		   inp->inp_socket == 0 ||
88453541Sshin		   (lport && inp->inp_lport != lport) ||
88553541Sshin		   (!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
88653541Sshin		    !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr6)) ||
88753541Sshin		   (fport && inp->inp_fport != fport)) {
88853541Sshin			inp = LIST_NEXT(inp, inp_list);
88953541Sshin			continue;
89053541Sshin		}
89153541Sshin		oinp = inp;
89253541Sshin		inp = LIST_NEXT(inp, inp_list);
89353541Sshin		if (notify)
89453541Sshin			(*notify)(oinp, errno);
89553541Sshin	}
89653541Sshin	splx(s);
89753541Sshin}
89853541Sshin
89953541Sshin/*
90053541Sshin * Lookup a PCB based on the local address and port.
90153541Sshin */
90253541Sshinstruct inpcb *
90353541Sshinin6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
90453541Sshin	struct inpcbinfo *pcbinfo;
90553541Sshin	struct in6_addr *laddr;
90653541Sshin	u_int lport_arg;
90753541Sshin	int wild_okay;
90853541Sshin{
90953541Sshin	register struct inpcb *inp;
91053541Sshin	int matchwild = 3, wildcard;
91153541Sshin	u_short lport = lport_arg;
91253541Sshin
91353541Sshin	if (!wild_okay) {
91453541Sshin		struct inpcbhead *head;
91553541Sshin		/*
91653541Sshin		 * Look for an unconnected (wildcard foreign addr) PCB that
91753541Sshin		 * matches the local address and port we're looking for.
91853541Sshin		 */
91953541Sshin		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
92053541Sshin						      pcbinfo->hashmask)];
92153541Sshin		LIST_FOREACH(inp, head, inp_hash) {
92254952Seivind			if ((inp->inp_vflag & INP_IPV6) == 0)
92353541Sshin				continue;
92453541Sshin			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
92553541Sshin			    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
92653541Sshin			    inp->inp_lport == lport) {
92753541Sshin				/*
92853541Sshin				 * Found.
92953541Sshin				 */
93053541Sshin				return (inp);
93153541Sshin			}
93253541Sshin		}
93353541Sshin		/*
93453541Sshin		 * Not found.
93553541Sshin		 */
93653541Sshin		return (NULL);
93753541Sshin	} else {
93853541Sshin		struct inpcbporthead *porthash;
93953541Sshin		struct inpcbport *phd;
94053541Sshin		struct inpcb *match = NULL;
94153541Sshin		/*
94253541Sshin		 * Best fit PCB lookup.
94353541Sshin		 *
94453541Sshin		 * First see if this local port is in use by looking on the
94553541Sshin		 * port hash list.
94653541Sshin		 */
94753541Sshin		porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
94853541Sshin		    pcbinfo->porthashmask)];
94953541Sshin		LIST_FOREACH(phd, porthash, phd_hash) {
95053541Sshin			if (phd->phd_port == lport)
95153541Sshin				break;
95253541Sshin		}
95353541Sshin		if (phd != NULL) {
95453541Sshin			/*
95553541Sshin			 * Port is in use by one or more PCBs. Look for best
95653541Sshin			 * fit.
95753541Sshin			 */
95853541Sshin			LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
95953541Sshin				wildcard = 0;
96054952Seivind				if ((inp->inp_vflag & INP_IPV6) == 0)
96153541Sshin					continue;
96253541Sshin				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
96353541Sshin					wildcard++;
96453541Sshin				if (!IN6_IS_ADDR_UNSPECIFIED(
96553541Sshin					&inp->in6p_laddr)) {
96653541Sshin					if (IN6_IS_ADDR_UNSPECIFIED(laddr))
96753541Sshin						wildcard++;
96853541Sshin					else if (!IN6_ARE_ADDR_EQUAL(
96953541Sshin						&inp->in6p_laddr, laddr))
97053541Sshin						continue;
97153541Sshin				} else {
97253541Sshin					if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
97353541Sshin						wildcard++;
97453541Sshin				}
97553541Sshin				if (wildcard < matchwild) {
97653541Sshin					match = inp;
97753541Sshin					matchwild = wildcard;
97853541Sshin					if (matchwild == 0) {
97953541Sshin						break;
98053541Sshin					}
98153541Sshin				}
98253541Sshin			}
98353541Sshin		}
98453541Sshin		return (match);
98553541Sshin	}
98653541Sshin}
98753541Sshin
98853541Sshin/*
98953541Sshin * Check for alternatives when higher level complains
99053541Sshin * about service problems.  For now, invalidate cached
99153541Sshin * routing information.  If the route was created dynamically
99253541Sshin * (by a redirect), time to try a default gateway again.
99353541Sshin */
99453541Sshinvoid
99553541Sshinin6_losing(in6p)
99653541Sshin	struct inpcb *in6p;
99753541Sshin{
99853541Sshin	struct rtentry *rt;
99953541Sshin	struct rt_addrinfo info;
100053541Sshin
100153541Sshin	if ((rt = in6p->in6p_route.ro_rt) != NULL) {
100253541Sshin		in6p->in6p_route.ro_rt = 0;
100353541Sshin		bzero((caddr_t)&info, sizeof(info));
100453541Sshin		info.rti_info[RTAX_DST] =
100553541Sshin			(struct sockaddr *)&in6p->in6p_route.ro_dst;
100653541Sshin		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
100753541Sshin		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
100853541Sshin		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
100953541Sshin		if (rt->rt_flags & RTF_DYNAMIC)
101053541Sshin			(void)rtrequest(RTM_DELETE, rt_key(rt),
101153541Sshin					rt->rt_gateway, rt_mask(rt), rt->rt_flags,
101253541Sshin					(struct rtentry **)0);
101353541Sshin		else
101453541Sshin		/*
101553541Sshin		 * A new route can be allocated
101653541Sshin		 * the next time output is attempted.
101753541Sshin		 */
101853541Sshin			rtfree(rt);
101953541Sshin	}
102053541Sshin}
102153541Sshin
102253541Sshin/*
102353541Sshin * After a routing change, flush old routing
102453541Sshin * and allocate a (hopefully) better one.
102553541Sshin */
102653541Sshinvoid
102753541Sshinin6_rtchange(inp, errno)
102853541Sshin	struct inpcb *inp;
102953541Sshin	int errno;
103053541Sshin{
103153541Sshin	if (inp->in6p_route.ro_rt) {
103253541Sshin		rtfree(inp->in6p_route.ro_rt);
103353541Sshin		inp->in6p_route.ro_rt = 0;
103453541Sshin		/*
103553541Sshin		 * A new route can be allocated the next time
103653541Sshin		 * output is attempted.
103753541Sshin		 */
103853541Sshin	}
103953541Sshin}
104053541Sshin
104153541Sshin/*
104253541Sshin * Lookup PCB in hash list.
104353541Sshin */
104453541Sshinstruct inpcb *
104553541Sshinin6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
104653541Sshin	struct inpcbinfo *pcbinfo;
104753541Sshin	struct in6_addr *faddr, *laddr;
104853541Sshin	u_int fport_arg, lport_arg;
104953541Sshin	int wildcard;
105053541Sshin	struct ifnet *ifp;
105153541Sshin{
105253541Sshin	struct inpcbhead *head;
105353541Sshin	register struct inpcb *inp;
105453541Sshin	u_short fport = fport_arg, lport = lport_arg;
105553541Sshin
105653541Sshin	/*
105753541Sshin	 * First look for an exact match.
105853541Sshin	 */
105953541Sshin	head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
106053541Sshin					      lport, fport,
106153541Sshin					      pcbinfo->hashmask)];
106254263Sshin	LIST_FOREACH(inp, head, inp_hash) {
106354952Seivind		if ((inp->inp_vflag & INP_IPV6) == 0)
106453541Sshin			continue;
106553541Sshin		if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
106653541Sshin		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
106753541Sshin		    inp->inp_fport == fport &&
106853541Sshin		    inp->inp_lport == lport) {
106953541Sshin			/*
107053541Sshin			 * Found.
107153541Sshin			 */
107253541Sshin			return (inp);
107353541Sshin		}
107453541Sshin	}
107553541Sshin	if (wildcard) {
107653541Sshin		struct inpcb *local_wild = NULL;
107753541Sshin
107853541Sshin		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
107953541Sshin						      pcbinfo->hashmask)];
108054263Sshin		LIST_FOREACH(inp, head, inp_hash) {
108154952Seivind			if ((inp->inp_vflag & INP_IPV6) == 0)
108253541Sshin				continue;
108353541Sshin			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
108453541Sshin			    inp->inp_lport == lport) {
108553541Sshin#if defined(NFAITH) && NFAITH > 0
108653541Sshin				if (ifp && ifp->if_type == IFT_FAITH &&
108753541Sshin				    (inp->inp_flags & INP_FAITH) == 0)
108853541Sshin					continue;
108953541Sshin#endif
109053541Sshin				if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
109153541Sshin						       laddr))
109253541Sshin					return (inp);
109353541Sshin				else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
109453541Sshin					local_wild = inp;
109553541Sshin			}
109653541Sshin		}
109753541Sshin		return (local_wild);
109853541Sshin	}
109953541Sshin
110053541Sshin	/*
110153541Sshin	 * Not found.
110253541Sshin	 */
110353541Sshin	return (NULL);
110453541Sshin}
110553541Sshin
110653541Sshinvoid
110753541Sshininit_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
110853541Sshin{
110953541Sshin	struct ip6_hdr *ip;
111053541Sshin
111153541Sshin	ip = mtod(m, struct ip6_hdr *);
111253541Sshin	bzero(sin6, sizeof(*sin6));
111353541Sshin	sin6->sin6_len = sizeof(*sin6);
111453541Sshin	sin6->sin6_family = AF_INET6;
111553541Sshin	sin6->sin6_addr = ip->ip6_src;
111653541Sshin	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
111753541Sshin		sin6->sin6_addr.s6_addr16[1] = 0;
111853541Sshin	sin6->sin6_scope_id =
111953541Sshin		(m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
112053541Sshin		? m->m_pkthdr.rcvif->if_index : 0;
112153541Sshin
112253541Sshin	return;
112353541Sshin}
1124