in6_pcb.c revision 171260
1/*	$FreeBSD: head/sys/netinet6/in6_pcb.c 171260 2007-07-05 16:29:40Z delphij $	*/
2/*	$KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $	*/
3
4/*-
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34/*-
35 * Copyright (c) 1982, 1986, 1991, 1993
36 *	The Regents of the University of California.  All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 4. Neither the name of the University nor the names of its contributors
47 *    may be used to endorse or promote products derived from this software
48 *    without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
63 */
64
65#include "opt_inet.h"
66#include "opt_inet6.h"
67#include "opt_ipsec.h"
68
69#include <sys/param.h>
70#include <sys/systm.h>
71#include <sys/malloc.h>
72#include <sys/mbuf.h>
73#include <sys/domain.h>
74#include <sys/protosw.h>
75#include <sys/socket.h>
76#include <sys/socketvar.h>
77#include <sys/sockio.h>
78#include <sys/errno.h>
79#include <sys/time.h>
80#include <sys/priv.h>
81#include <sys/proc.h>
82#include <sys/jail.h>
83
84#include <vm/uma.h>
85
86#include <net/if.h>
87#include <net/if_types.h>
88#include <net/route.h>
89
90#include <netinet/in.h>
91#include <netinet/in_var.h>
92#include <netinet/in_systm.h>
93#include <netinet/tcp_var.h>
94#include <netinet/ip6.h>
95#include <netinet/ip_var.h>
96#include <netinet6/ip6_var.h>
97#include <netinet6/nd6.h>
98#include <netinet/in_pcb.h>
99#include <netinet6/in6_pcb.h>
100#include <netinet6/scope6_var.h>
101
102#ifdef IPSEC
103#include <netipsec/ipsec.h>
104#include <netipsec/ipsec6.h>
105#include <netipsec/key.h>
106#endif /* IPSEC */
107
108struct	in6_addr zeroin6_addr;
109
110int
111in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
112    struct ucred *cred)
113{
114	struct socket *so = inp->inp_socket;
115	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
116	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
117	u_short	lport = 0;
118	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
119
120	INP_INFO_WLOCK_ASSERT(pcbinfo);
121	INP_LOCK_ASSERT(inp);
122
123	if (!in6_ifaddr) /* XXX broken! */
124		return (EADDRNOTAVAIL);
125	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
126		return (EINVAL);
127	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
128		wild = INPLOOKUP_WILDCARD;
129	if (nam) {
130		int error;
131
132		sin6 = (struct sockaddr_in6 *)nam;
133		if (nam->sa_len != sizeof(*sin6))
134			return (EINVAL);
135		/*
136		 * family check.
137		 */
138		if (nam->sa_family != AF_INET6)
139			return (EAFNOSUPPORT);
140
141		if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
142			return(error);
143
144		lport = sin6->sin6_port;
145		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
146			/*
147			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
148			 * allow compepte duplication of binding if
149			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
150			 * and a multicast address is bound on both
151			 * new and duplicated sockets.
152			 */
153			if (so->so_options & SO_REUSEADDR)
154				reuseport = SO_REUSEADDR|SO_REUSEPORT;
155		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
156			struct ifaddr *ia = NULL;
157
158			sin6->sin6_port = 0;		/* yech... */
159			if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
160				return (EADDRNOTAVAIL);
161
162			/*
163			 * XXX: bind to an anycast address might accidentally
164			 * cause sending a packet with anycast source address.
165			 * We should allow to bind to a deprecated address, since
166			 * the application dares to use it.
167			 */
168			if (ia &&
169			    ((struct in6_ifaddr *)ia)->ia6_flags &
170			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
171				return (EADDRNOTAVAIL);
172			}
173		}
174		if (lport) {
175			struct inpcb *t;
176
177			/* GROSS */
178			if (ntohs(lport) <= ipport_reservedhigh &&
179			    ntohs(lport) >= ipport_reservedlow &&
180			    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
181			    0))
182				return (EACCES);
183			if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
184			    priv_check_cred(so->so_cred,
185			    PRIV_NETINET_REUSEPORT, 0) != 0) {
186				t = in6_pcblookup_local(pcbinfo,
187				    &sin6->sin6_addr, lport,
188				    INPLOOKUP_WILDCARD);
189				if (t &&
190				    ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
191				    (so->so_type != SOCK_STREAM ||
192				     IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
193				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
194				     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
195				     (t->inp_socket->so_options & SO_REUSEPORT)
196				      == 0) && (so->so_cred->cr_uid !=
197				     t->inp_socket->so_cred->cr_uid))
198					return (EADDRINUSE);
199				if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
200				    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
201					struct sockaddr_in sin;
202
203					in6_sin6_2_sin(&sin, sin6);
204					t = in_pcblookup_local(pcbinfo,
205						sin.sin_addr, lport,
206						INPLOOKUP_WILDCARD);
207					if (t &&
208					    ((t->inp_vflag &
209					      INP_TIMEWAIT) == 0) &&
210					    (so->so_type != SOCK_STREAM ||
211					     ntohl(t->inp_faddr.s_addr) ==
212					      INADDR_ANY) &&
213					    (so->so_cred->cr_uid !=
214					     t->inp_socket->so_cred->cr_uid))
215						return (EADDRINUSE);
216				}
217			}
218			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
219						lport, wild);
220			if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ?
221			    intotw(t)->tw_so_options :
222			    t->inp_socket->so_options)) == 0)
223				return (EADDRINUSE);
224			if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
225			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
226				struct sockaddr_in sin;
227
228				in6_sin6_2_sin(&sin, sin6);
229				t = in_pcblookup_local(pcbinfo, sin.sin_addr,
230						       lport, wild);
231				if (t && t->inp_vflag & INP_TIMEWAIT) {
232					if ((reuseport &
233					    intotw(t)->tw_so_options) == 0 &&
234					    (ntohl(t->inp_laddr.s_addr) !=
235					     INADDR_ANY || ((inp->inp_vflag &
236					     INP_IPV6PROTO) ==
237					     (t->inp_vflag & INP_IPV6PROTO))))
238						return (EADDRINUSE);
239				}
240				else if (t &&
241				    (reuseport & t->inp_socket->so_options)
242				    == 0 && (ntohl(t->inp_laddr.s_addr) !=
243				    INADDR_ANY || INP_SOCKAF(so) ==
244				     INP_SOCKAF(t->inp_socket)))
245					return (EADDRINUSE);
246			}
247		}
248		inp->in6p_laddr = sin6->sin6_addr;
249	}
250	if (lport == 0) {
251		int e;
252		if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
253			return (e);
254	}
255	else {
256		inp->inp_lport = lport;
257		if (in_pcbinshash(inp) != 0) {
258			inp->in6p_laddr = in6addr_any;
259			inp->inp_lport = 0;
260			return (EAGAIN);
261		}
262	}
263	return (0);
264}
265
266/*
267 *   Transform old in6_pcbconnect() into an inner subroutine for new
268 *   in6_pcbconnect(): Do some validity-checking on the remote
269 *   address (in mbuf 'nam') and then determine local host address
270 *   (i.e., which interface) to use to access that remote host.
271 *
272 *   This preserves definition of in6_pcbconnect(), while supporting a
273 *   slightly different version for T/TCP.  (This is more than
274 *   a bit of a kludge, but cleaning up the internal interfaces would
275 *   have forced minor changes in every protocol).
276 */
277int
278in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
279    struct in6_addr **plocal_addr6)
280{
281	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
282	int error = 0;
283	struct ifnet *ifp = NULL;
284	int scope_ambiguous = 0;
285
286	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
287	INP_LOCK_ASSERT(inp);
288
289	if (nam->sa_len != sizeof (*sin6))
290		return (EINVAL);
291	if (sin6->sin6_family != AF_INET6)
292		return (EAFNOSUPPORT);
293	if (sin6->sin6_port == 0)
294		return (EADDRNOTAVAIL);
295
296	if (sin6->sin6_scope_id == 0 && !ip6_use_defzone)
297		scope_ambiguous = 1;
298	if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
299		return(error);
300
301	if (in6_ifaddr) {
302		/*
303		 * If the destination address is UNSPECIFIED addr,
304		 * use the loopback addr, e.g ::1.
305		 */
306		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
307			sin6->sin6_addr = in6addr_loopback;
308	}
309
310	/*
311	 * XXX: in6_selectsrc might replace the bound local address
312	 * with the address specified by setsockopt(IPV6_PKTINFO).
313	 * Is it the intended behavior?
314	 */
315	*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
316				      inp->in6p_moptions, NULL,
317				      &inp->in6p_laddr, &ifp, &error);
318	if (ifp && scope_ambiguous &&
319	    (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
320		return(error);
321	}
322
323	if (*plocal_addr6 == 0) {
324		if (error == 0)
325			error = EADDRNOTAVAIL;
326		return (error);
327	}
328	/*
329	 * Don't do pcblookup call here; return interface in
330	 * plocal_addr6
331	 * and exit to caller, that will do the lookup.
332	 */
333
334	return (0);
335}
336
337/*
338 * Outer subroutine:
339 * Connect from a socket to a specified address.
340 * Both address and port must be specified in argument sin.
341 * If don't have a local address for this socket yet,
342 * then pick one.
343 */
344int
345in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
346    struct ucred *cred)
347{
348	struct in6_addr *addr6;
349	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
350	int error;
351
352	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
353	INP_LOCK_ASSERT(inp);
354
355	/*
356	 * Call inner routine, to assign local interface address.
357	 * in6_pcbladdr() may automatically fill in sin6_scope_id.
358	 */
359	if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
360		return (error);
361
362	if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
363			       sin6->sin6_port,
364			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
365			      ? addr6 : &inp->in6p_laddr,
366			      inp->inp_lport, 0, NULL) != NULL) {
367		return (EADDRINUSE);
368	}
369	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
370		if (inp->inp_lport == 0) {
371			error = in6_pcbbind(inp, (struct sockaddr *)0, cred);
372			if (error)
373				return (error);
374		}
375		inp->in6p_laddr = *addr6;
376	}
377	inp->in6p_faddr = sin6->sin6_addr;
378	inp->inp_fport = sin6->sin6_port;
379	/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
380	inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
381	if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
382		inp->in6p_flowinfo |=
383		    (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
384
385	in_pcbrehash(inp);
386
387	return (0);
388}
389
390void
391in6_pcbdisconnect(struct inpcb *inp)
392{
393
394	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
395	INP_LOCK_ASSERT(inp);
396
397	bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
398	inp->inp_fport = 0;
399	/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
400	inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
401	in_pcbrehash(inp);
402}
403
404void
405in6_pcbdetach(struct inpcb *inp)
406{
407
408	KASSERT(inp->inp_socket != NULL, ("in6_pcbdetach: inp_socket == NULL"));
409	inp->inp_socket->so_pcb = NULL;
410	inp->inp_socket = NULL;
411}
412
413void
414in6_pcbfree(struct inpcb *inp)
415{
416	struct inpcbinfo *ipi = inp->inp_pcbinfo;
417
418	KASSERT(inp->inp_socket == NULL, ("in6_pcbfree: inp_socket != NULL"));
419	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
420	INP_LOCK_ASSERT(inp);
421
422#ifdef IPSEC
423	if (inp->in6p_sp != NULL)
424		ipsec6_delete_pcbpolicy(inp);
425#endif /* IPSEC */
426	inp->inp_gencnt = ++ipi->ipi_gencnt;
427	in_pcbremlists(inp);
428	ip6_freepcbopts(inp->in6p_outputopts);
429	ip6_freemoptions(inp->in6p_moptions);
430	/* Check and free IPv4 related resources in case of mapped addr */
431	if (inp->inp_options)
432		(void)m_free(inp->inp_options);
433	if (inp->inp_moptions != NULL)
434		inp_freemoptions(inp->inp_moptions);
435	inp->inp_vflag = 0;
436	INP_UNLOCK(inp);
437	uma_zfree(ipi->ipi_zone, inp);
438}
439
440struct sockaddr *
441in6_sockaddr(in_port_t port, struct in6_addr *addr_p)
442{
443	struct sockaddr_in6 *sin6;
444
445	MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
446	bzero(sin6, sizeof *sin6);
447	sin6->sin6_family = AF_INET6;
448	sin6->sin6_len = sizeof(*sin6);
449	sin6->sin6_port = port;
450	sin6->sin6_addr = *addr_p;
451	(void)sa6_recoverscope(sin6); /* XXX: should catch errors */
452
453	return (struct sockaddr *)sin6;
454}
455
456struct sockaddr *
457in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p)
458{
459	struct sockaddr_in sin;
460	struct sockaddr_in6 *sin6_p;
461
462	bzero(&sin, sizeof sin);
463	sin.sin_family = AF_INET;
464	sin.sin_len = sizeof(sin);
465	sin.sin_port = port;
466	sin.sin_addr = *addr_p;
467
468	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
469		M_WAITOK);
470	in6_sin_2_v4mapsin6(&sin, sin6_p);
471
472	return (struct sockaddr *)sin6_p;
473}
474
475int
476in6_getsockaddr(struct socket *so, struct sockaddr **nam)
477{
478	register struct inpcb *inp;
479	struct in6_addr addr;
480	in_port_t port;
481
482	inp = sotoinpcb(so);
483	KASSERT(inp != NULL, ("in6_getsockaddr: inp == NULL"));
484
485	INP_LOCK(inp);
486	port = inp->inp_lport;
487	addr = inp->in6p_laddr;
488	INP_UNLOCK(inp);
489
490	*nam = in6_sockaddr(port, &addr);
491	return 0;
492}
493
494int
495in6_getpeeraddr(struct socket *so, struct sockaddr **nam)
496{
497	struct inpcb *inp;
498	struct in6_addr addr;
499	in_port_t port;
500
501	inp = sotoinpcb(so);
502	KASSERT(inp != NULL, ("in6_getpeeraddr: inp == NULL"));
503
504	INP_LOCK(inp);
505	port = inp->inp_fport;
506	addr = inp->in6p_faddr;
507	INP_UNLOCK(inp);
508
509	*nam = in6_sockaddr(port, &addr);
510	return 0;
511}
512
513int
514in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
515{
516	struct	inpcb *inp;
517	int	error;
518
519	inp = sotoinpcb(so);
520	KASSERT(inp != NULL, ("in6_mapped_sockaddr: inp == NULL"));
521
522	if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
523		error = in_getsockaddr(so, nam);
524		if (error == 0)
525			in6_sin_2_v4mapsin6_in_sock(nam);
526	} else {
527		/* scope issues will be handled in in6_getsockaddr(). */
528		error = in6_getsockaddr(so, nam);
529	}
530
531	return error;
532}
533
534int
535in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
536{
537	struct	inpcb *inp;
538	int	error;
539
540	inp = sotoinpcb(so);
541	KASSERT(inp != NULL, ("in6_mapped_peeraddr: inp == NULL"));
542
543	if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
544		error = in_getpeeraddr(so, nam);
545		if (error == 0)
546			in6_sin_2_v4mapsin6_in_sock(nam);
547	} else
548	/* scope issues will be handled in in6_getpeeraddr(). */
549	error = in6_getpeeraddr(so, nam);
550
551	return error;
552}
553
554/*
555 * Pass some notification to all connections of a protocol
556 * associated with address dst.  The local address and/or port numbers
557 * may be specified to limit the search.  The "usual action" will be
558 * taken, depending on the ctlinput cmd.  The caller must filter any
559 * cmds that are uninteresting (e.g., no error in the map).
560 * Call the protocol specific routine (if any) to report
561 * any errors for each matching socket.
562 */
563void
564in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
565    u_int fport_arg, const struct sockaddr *src, u_int lport_arg,
566    int cmd, void *cmdarg,
567    struct inpcb *(*notify) __P((struct inpcb *, int)))
568{
569	struct inpcbhead *head;
570	struct inpcb *inp, *ninp;
571	struct sockaddr_in6 sa6_src, *sa6_dst;
572	u_short	fport = fport_arg, lport = lport_arg;
573	u_int32_t flowinfo;
574	int errno;
575
576	if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6)
577		return;
578
579	sa6_dst = (struct sockaddr_in6 *)dst;
580	if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
581		return;
582
583	/*
584	 * note that src can be NULL when we get notify by local fragmentation.
585	 */
586	sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
587	flowinfo = sa6_src.sin6_flowinfo;
588
589	/*
590	 * Redirects go to all references to the destination,
591	 * and use in6_rtchange to invalidate the route cache.
592	 * Dead host indications: also use in6_rtchange to invalidate
593	 * the cache, and deliver the error to all the sockets.
594	 * Otherwise, if we have knowledge of the local port and address,
595	 * deliver only to that socket.
596	 */
597	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
598		fport = 0;
599		lport = 0;
600		bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
601
602		if (cmd != PRC_HOSTDEAD)
603			notify = in6_rtchange;
604	}
605	errno = inet6ctlerrmap[cmd];
606	head = pcbinfo->ipi_listhead;
607	INP_INFO_WLOCK(pcbinfo);
608	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
609		INP_LOCK(inp);
610		ninp = LIST_NEXT(inp, inp_list);
611
612		if ((inp->inp_vflag & INP_IPV6) == 0) {
613			INP_UNLOCK(inp);
614			continue;
615		}
616
617		/*
618		 * If the error designates a new path MTU for a destination
619		 * and the application (associated with this socket) wanted to
620		 * know the value, notify. Note that we notify for all
621		 * disconnected sockets if the corresponding application
622		 * wanted. This is because some UDP applications keep sending
623		 * sockets disconnected.
624		 * XXX: should we avoid to notify the value to TCP sockets?
625		 */
626		if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
627		    (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
628		     IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
629			ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst,
630					(u_int32_t *)cmdarg);
631		}
632
633		/*
634		 * Detect if we should notify the error. If no source and
635		 * destination ports are specifed, but non-zero flowinfo and
636		 * local address match, notify the error. This is the case
637		 * when the error is delivered with an encrypted buffer
638		 * by ESP. Otherwise, just compare addresses and ports
639		 * as usual.
640		 */
641		if (lport == 0 && fport == 0 && flowinfo &&
642		    inp->inp_socket != NULL &&
643		    flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
644		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
645			goto do_notify;
646		else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
647					     &sa6_dst->sin6_addr) ||
648			 inp->inp_socket == 0 ||
649			 (lport && inp->inp_lport != lport) ||
650			 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
651			  !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
652					      &sa6_src.sin6_addr)) ||
653			 (fport && inp->inp_fport != fport)) {
654			INP_UNLOCK(inp);
655			continue;
656		}
657
658	  do_notify:
659		if (notify) {
660			if ((*notify)(inp, errno))
661				INP_UNLOCK(inp);
662		} else
663			INP_UNLOCK(inp);
664	}
665	INP_INFO_WUNLOCK(pcbinfo);
666}
667
668/*
669 * Lookup a PCB based on the local address and port.
670 */
671struct inpcb *
672in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
673    u_int lport_arg, int wild_okay)
674{
675	register struct inpcb *inp;
676	int matchwild = 3, wildcard;
677	u_short lport = lport_arg;
678
679	INP_INFO_WLOCK_ASSERT(pcbinfo);
680
681	if (!wild_okay) {
682		struct inpcbhead *head;
683		/*
684		 * Look for an unconnected (wildcard foreign addr) PCB that
685		 * matches the local address and port we're looking for.
686		 */
687		head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
688		    0, pcbinfo->ipi_hashmask)];
689		LIST_FOREACH(inp, head, inp_hash) {
690			if ((inp->inp_vflag & INP_IPV6) == 0)
691				continue;
692			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
693			    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
694			    inp->inp_lport == lport) {
695				/*
696				 * Found.
697				 */
698				return (inp);
699			}
700		}
701		/*
702		 * Not found.
703		 */
704		return (NULL);
705	} else {
706		struct inpcbporthead *porthash;
707		struct inpcbport *phd;
708		struct inpcb *match = NULL;
709		/*
710		 * Best fit PCB lookup.
711		 *
712		 * First see if this local port is in use by looking on the
713		 * port hash list.
714		 */
715		porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport,
716		    pcbinfo->ipi_porthashmask)];
717		LIST_FOREACH(phd, porthash, phd_hash) {
718			if (phd->phd_port == lport)
719				break;
720		}
721		if (phd != NULL) {
722			/*
723			 * Port is in use by one or more PCBs. Look for best
724			 * fit.
725			 */
726			LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
727				wildcard = 0;
728				if ((inp->inp_vflag & INP_IPV6) == 0)
729					continue;
730				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
731					wildcard++;
732				if (!IN6_IS_ADDR_UNSPECIFIED(
733					&inp->in6p_laddr)) {
734					if (IN6_IS_ADDR_UNSPECIFIED(laddr))
735						wildcard++;
736					else if (!IN6_ARE_ADDR_EQUAL(
737						&inp->in6p_laddr, laddr))
738						continue;
739				} else {
740					if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
741						wildcard++;
742				}
743				if (wildcard < matchwild) {
744					match = inp;
745					matchwild = wildcard;
746					if (matchwild == 0) {
747						break;
748					}
749				}
750			}
751		}
752		return (match);
753	}
754}
755
756void
757in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
758{
759	struct in6pcb *in6p;
760	struct ip6_moptions *im6o;
761	struct in6_multi_mship *imm, *nimm;
762
763	INP_INFO_RLOCK(pcbinfo);
764	LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
765		INP_LOCK(in6p);
766		im6o = in6p->in6p_moptions;
767		if ((in6p->inp_vflag & INP_IPV6) &&
768		    im6o) {
769			/*
770			 * Unselect the outgoing interface if it is being
771			 * detached.
772			 */
773			if (im6o->im6o_multicast_ifp == ifp)
774				im6o->im6o_multicast_ifp = NULL;
775
776			/*
777			 * Drop multicast group membership if we joined
778			 * through the interface being detached.
779			 * XXX controversial - is it really legal for kernel
780			 * to force this?
781			 */
782			for (imm = im6o->im6o_memberships.lh_first;
783			     imm != NULL; imm = nimm) {
784				nimm = imm->i6mm_chain.le_next;
785				if (imm->i6mm_maddr->in6m_ifp == ifp) {
786					LIST_REMOVE(imm, i6mm_chain);
787					in6_delmulti(imm->i6mm_maddr);
788					free(imm, M_IP6MADDR);
789				}
790			}
791		}
792		INP_UNLOCK(in6p);
793	}
794	INP_INFO_RUNLOCK(pcbinfo);
795}
796
797/*
798 * Check for alternatives when higher level complains
799 * about service problems.  For now, invalidate cached
800 * routing information.  If the route was created dynamically
801 * (by a redirect), time to try a default gateway again.
802 */
803void
804in6_losing(struct inpcb *in6p)
805{
806
807	/*
808	 * We don't store route pointers in the routing table anymore
809	 */
810	return;
811}
812
813/*
814 * After a routing change, flush old routing
815 * and allocate a (hopefully) better one.
816 */
817struct inpcb *
818in6_rtchange(struct inpcb *inp, int errno)
819{
820	/*
821	 * We don't store route pointers in the routing table anymore
822	 */
823	return inp;
824}
825
826/*
827 * Lookup PCB in hash list.
828 */
829struct inpcb *
830in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
831    u_int fport_arg, struct in6_addr *laddr, u_int lport_arg,
832    int wildcard, struct ifnet *ifp)
833{
834	struct inpcbhead *head;
835	register struct inpcb *inp;
836	u_short fport = fport_arg, lport = lport_arg;
837	int faith;
838
839	INP_INFO_RLOCK_ASSERT(pcbinfo);
840
841	if (faithprefix_p != NULL)
842		faith = (*faithprefix_p)(laddr);
843	else
844		faith = 0;
845
846	/*
847	 * First look for an exact match.
848	 */
849	head = &pcbinfo->ipi_hashbase[
850	    INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport,
851	    pcbinfo->ipi_hashmask)];
852	LIST_FOREACH(inp, head, inp_hash) {
853		if ((inp->inp_vflag & INP_IPV6) == 0)
854			continue;
855		if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
856		    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
857		    inp->inp_fport == fport &&
858		    inp->inp_lport == lport) {
859			/*
860			 * Found.
861			 */
862			return (inp);
863		}
864	}
865	if (wildcard) {
866		struct inpcb *local_wild = NULL;
867
868		head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
869		    0, pcbinfo->ipi_hashmask)];
870		LIST_FOREACH(inp, head, inp_hash) {
871			if ((inp->inp_vflag & INP_IPV6) == 0)
872				continue;
873			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
874			    inp->inp_lport == lport) {
875				if (faith && (inp->inp_flags & INP_FAITH) == 0)
876					continue;
877				if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
878						       laddr))
879					return (inp);
880				else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
881					local_wild = inp;
882			}
883		}
884		return (local_wild);
885	}
886
887	/*
888	 * Not found.
889	 */
890	return (NULL);
891}
892
893void
894init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
895{
896	struct ip6_hdr *ip;
897
898	ip = mtod(m, struct ip6_hdr *);
899	bzero(sin6, sizeof(*sin6));
900	sin6->sin6_len = sizeof(*sin6);
901	sin6->sin6_family = AF_INET6;
902	sin6->sin6_addr = ip->ip6_src;
903
904	(void)sa6_recoverscope(sin6); /* XXX: should catch errors... */
905
906	return;
907}
908