]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/in6_pcb.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / bsd / netinet6 / in6_pcb.c
CommitLineData
91447636 1/*
2d21ac55 2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
91447636 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
91447636 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636 27 */
1c79356b
A
28/*
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
9bccf70c 31 *
1c79356b
A
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. Neither the name of the project nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
9bccf70c 43 *
1c79356b
A
44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
9bccf70c 55 *
1c79356b
A
56 */
57
58/*
59 * Copyright (c) 1982, 1986, 1991, 1993
60 * The Regents of the University of California. All rights reserved.
61 *
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions
64 * are met:
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in the
69 * documentation and/or other materials provided with the distribution.
70 * 3. All advertising materials mentioning features or use of this software
71 * must display the following acknowledgement:
72 * This product includes software developed by the University of
73 * California, Berkeley and its contributors.
74 * 4. Neither the name of the University nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 *
90 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
91 */
92
1c79356b
A
93#include <sys/param.h>
94#include <sys/systm.h>
95#include <sys/malloc.h>
96#include <sys/mbuf.h>
9bccf70c 97#include <sys/domain.h>
1c79356b
A
98#include <sys/protosw.h>
99#include <sys/socket.h>
100#include <sys/socketvar.h>
101#include <sys/sockio.h>
102#include <sys/errno.h>
103#include <sys/time.h>
104#include <sys/proc.h>
105
106#include <net/if.h>
107#include <net/if_types.h>
108#include <net/route.h>
109
110#include <netinet/in.h>
111#include <netinet/in_var.h>
112#include <netinet/in_systm.h>
113#include <netinet/ip6.h>
9bccf70c 114#include <netinet/ip_var.h>
1c79356b
A
115#include <netinet6/ip6_var.h>
116#include <netinet6/nd6.h>
117#include <netinet/in_pcb.h>
118#include <netinet6/in6_pcb.h>
119#include <net/if_types.h>
120
91447636
A
121#include <kern/kern_types.h>
122#include <kern/zalloc.h>
123
1c79356b
A
124#if IPSEC
125#include <netinet6/ipsec.h>
9bccf70c
A
126#if INET6
127#include <netinet6/ipsec6.h>
128#endif
129#include <netinet6/ah.h>
130#if INET6
131#include <netinet6/ah6.h>
132#endif
1c79356b 133#include <netkey/key.h>
1c79356b
A
134#endif /* IPSEC */
135
9bccf70c 136struct in6_addr zeroin6_addr;
1c79356b 137
2d21ac55
A
138/*
139 in6_pcblookup_local_and_cleanup does everything
140 in6_pcblookup_local does but it checks for a socket
141 that's going away. Since we know that the lock is
142 held read+write when this function is called, we
143 can safely dispose of this socket like the slow
144 timer would usually do and return NULL. This is
145 great for bind.
146*/
147static struct inpcb*
148in6_pcblookup_local_and_cleanup(
149 struct inpcbinfo *pcbinfo,
150 struct in6_addr *laddr,
151 u_int lport_arg,
152 int wild_okay)
153{
154 struct inpcb *inp;
155
156 /* Perform normal lookup */
157 inp = in6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay);
158
159 /* Check if we found a match but it's waiting to be disposed */
160 if (inp && inp->inp_wantcnt == WNT_STOPUSING) {
161 struct socket *so = inp->inp_socket;
162
163 lck_mtx_lock(inp->inpcb_mtx);
164
165 if (so->so_usecount == 0) {
166 in_pcbdispose(inp);
167 inp = NULL;
168 }
169 else {
170 lck_mtx_unlock(inp->inpcb_mtx);
171 }
172 }
173
174 return inp;
175}
1c79356b 176int
91447636
A
177in6_pcbbind(
178 struct inpcb *inp,
179 struct sockaddr *nam,
180 struct proc *p)
1c79356b
A
181{
182 struct socket *so = inp->inp_socket;
1c79356b
A
183 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
184 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
185 u_short lport = 0;
186 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
1c79356b 187
91447636 188 if (!in6_ifaddrs) /* XXX broken! */
1c79356b
A
189 return (EADDRNOTAVAIL);
190 if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
191 return(EINVAL);
192 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
9bccf70c 193 wild = 1;
91447636
A
194 socket_unlock(so, 0); /* keep reference */
195 lck_rw_lock_exclusive(pcbinfo->mtx);
1c79356b 196 if (nam) {
9bccf70c 197 sin6 = (struct sockaddr_in6 *)nam;
91447636
A
198 if (nam->sa_len != sizeof(*sin6)) {
199 lck_rw_done(pcbinfo->mtx);
200 socket_lock(so, 0);
1c79356b 201 return(EINVAL);
91447636 202 }
1c79356b 203 /*
9bccf70c 204 * family check.
1c79356b 205 */
91447636
A
206 if (nam->sa_family != AF_INET6) {
207 lck_rw_done(pcbinfo->mtx);
208 socket_lock(so, 0);
1c79356b 209 return(EAFNOSUPPORT);
91447636 210 }
1c79356b 211
9bccf70c 212 /* KAME hack: embed scopeid */
91447636
A
213 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0) {
214 lck_rw_done(pcbinfo->mtx);
215 socket_lock(so, 0);
9bccf70c 216 return EINVAL;
91447636 217 }
9bccf70c
A
218 /* this must be cleared for ifa_ifwithaddr() */
219 sin6->sin6_scope_id = 0;
1c79356b
A
220
221 lport = sin6->sin6_port;
222 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
223 /*
224 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
225 * allow compepte duplication of binding if
226 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
227 * and a multicast address is bound on both
228 * new and duplicated sockets.
229 */
230 if (so->so_options & SO_REUSEADDR)
231 reuseport = SO_REUSEADDR|SO_REUSEPORT;
232 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
233 struct ifaddr *ia = NULL;
234
235 sin6->sin6_port = 0; /* yech... */
91447636
A
236 if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0) {
237 lck_rw_done(pcbinfo->mtx);
238 socket_lock(so, 0);
1c79356b 239 return(EADDRNOTAVAIL);
91447636 240 }
1c79356b
A
241
242 /*
243 * XXX: bind to an anycast address might accidentally
244 * cause sending a packet with anycast source address.
9bccf70c
A
245 * We should allow to bind to a deprecated address, since
246 * the application dare to use it.
1c79356b
A
247 */
248 if (ia &&
249 ((struct in6_ifaddr *)ia)->ia6_flags &
9bccf70c 250 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
91447636
A
251 ifafree(ia);
252 lck_rw_done(pcbinfo->mtx);
253 socket_lock(so, 0);
1c79356b
A
254 return(EADDRNOTAVAIL);
255 }
91447636
A
256 ifafree(ia);
257 ia = NULL;
1c79356b
A
258 }
259 if (lport) {
260 struct inpcb *t;
261
262 /* GROSS */
263 if (ntohs(lport) < IPV6PORT_RESERVED && p &&
91447636
A
264 ((so->so_state & SS_PRIV) == 0)) {
265 lck_rw_done(pcbinfo->mtx);
266 socket_lock(so, 0);
1c79356b 267 return(EACCES);
91447636 268 }
1c79356b
A
269
270 if (so->so_uid &&
271 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
2d21ac55 272 t = in6_pcblookup_local_and_cleanup(pcbinfo,
9bccf70c
A
273 &sin6->sin6_addr, lport,
274 INPLOOKUP_WILDCARD);
1c79356b
A
275 if (t &&
276 (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
277 !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
278 (t->inp_socket->so_options &
279 SO_REUSEPORT) == 0) &&
2d21ac55
A
280 (so->so_uid != t->inp_socket->so_uid) &&
281 ((t->inp_socket->so_flags & SOF_REUSESHAREUID) == 0)) {
91447636
A
282 lck_rw_done(pcbinfo->mtx);
283 socket_lock(so, 0);
1c79356b 284 return (EADDRINUSE);
91447636 285 }
9bccf70c
A
286 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
287 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
288 struct sockaddr_in sin;
289
290 in6_sin6_2_sin(&sin, sin6);
2d21ac55 291 t = in_pcblookup_local_and_cleanup(pcbinfo,
9bccf70c
A
292 sin.sin_addr, lport,
293 INPLOOKUP_WILDCARD);
2d21ac55 294 if (t && (t->inp_socket->so_options & SO_REUSEPORT) == 0 &&
9bccf70c
A
295 (so->so_uid !=
296 t->inp_socket->so_uid) &&
297 (ntohl(t->inp_laddr.s_addr) !=
298 INADDR_ANY ||
299 INP_SOCKAF(so) ==
91447636
A
300 INP_SOCKAF(t->inp_socket))) {
301
302 lck_rw_done(pcbinfo->mtx);
303 socket_lock(so, 0);
9bccf70c 304 return (EADDRINUSE);
91447636 305 }
9bccf70c 306 }
1c79356b 307 }
2d21ac55 308 t = in6_pcblookup_local_and_cleanup(pcbinfo, &sin6->sin6_addr,
1c79356b 309 lport, wild);
91447636
A
310 if (t && (reuseport & t->inp_socket->so_options) == 0) {
311 lck_rw_done(pcbinfo->mtx);
312 socket_lock(so, 0);
1c79356b 313 return(EADDRINUSE);
91447636 314 }
9bccf70c
A
315 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
316 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
317 struct sockaddr_in sin;
318
319 in6_sin6_2_sin(&sin, sin6);
2d21ac55 320 t = in_pcblookup_local_and_cleanup(pcbinfo, sin.sin_addr,
9bccf70c
A
321 lport, wild);
322 if (t &&
323 (reuseport & t->inp_socket->so_options)
324 == 0 &&
325 (ntohl(t->inp_laddr.s_addr)
326 != INADDR_ANY ||
327 INP_SOCKAF(so) ==
91447636
A
328 INP_SOCKAF(t->inp_socket))) {
329 lck_rw_done(pcbinfo->mtx);
330 socket_lock(so, 0);
9bccf70c 331 return (EADDRINUSE);
91447636 332 }
9bccf70c 333 }
1c79356b
A
334 }
335 inp->in6p_laddr = sin6->sin6_addr;
336 }
91447636 337 socket_lock(so, 0);
1c79356b 338 if (lport == 0) {
9bccf70c 339 int e;
91447636
A
340 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, p, 1)) != 0) {
341 lck_rw_done(pcbinfo->mtx);
9bccf70c 342 return(e);
91447636 343 }
1c79356b 344 }
9bccf70c
A
345 else {
346 inp->inp_lport = lport;
91447636 347 if (in_pcbinshash(inp, 1) != 0) {
9bccf70c
A
348 inp->in6p_laddr = in6addr_any;
349 inp->inp_lport = 0;
91447636 350 lck_rw_done(pcbinfo->mtx);
9bccf70c
A
351 return (EAGAIN);
352 }
91447636
A
353 }
354 lck_rw_done(pcbinfo->mtx);
2d21ac55 355 sflt_notify(so, sock_evt_bound, NULL);
1c79356b
A
356 return(0);
357}
358
359/*
360 * Transform old in6_pcbconnect() into an inner subroutine for new
361 * in6_pcbconnect(): Do some validity-checking on the remote
362 * address (in mbuf 'nam') and then determine local host address
363 * (i.e., which interface) to use to access that remote host.
364 *
365 * This preserves definition of in6_pcbconnect(), while supporting a
366 * slightly different version for T/TCP. (This is more than
367 * a bit of a kludge, but cleaning up the internal interfaces would
368 * have forced minor changes in every protocol).
369 */
370
371int
91447636
A
372in6_pcbladdr(
373 struct inpcb *inp,
374 struct sockaddr *nam,
375 struct in6_addr *plocal_addr6)
1c79356b 376{
91447636
A
377 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
378 struct in6_addr *addr6 = NULL;
379 struct in6_addr src_storage;
380
1c79356b
A
381 struct ifnet *ifp = NULL;
382 int error = 0;
383
384 if (nam->sa_len != sizeof (*sin6))
385 return (EINVAL);
386 if (sin6->sin6_family != AF_INET6)
387 return (EAFNOSUPPORT);
388 if (sin6->sin6_port == 0)
389 return (EADDRNOTAVAIL);
390
9bccf70c
A
391 /* KAME hack: embed scopeid */
392 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
393 return EINVAL;
1c79356b 394
91447636 395 if (in6_ifaddrs) {
1c79356b
A
396 /*
397 * If the destination address is UNSPECIFIED addr,
398 * use the loopback addr, e.g ::1.
399 */
1c79356b
A
400 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
401 sin6->sin6_addr = in6addr_loopback;
402 }
403 {
404 /*
405 * XXX: in6_selectsrc might replace the bound local address
406 * with the address specified by setsockopt(IPV6_PKTINFO).
407 * Is it the intended behavior?
408 */
91447636 409 addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
1c79356b
A
410 inp->in6p_moptions,
411 &inp->in6p_route,
91447636
A
412 &inp->in6p_laddr, &src_storage, &error);
413 if (addr6 == 0) {
1c79356b
A
414 if (error == 0)
415 error = EADDRNOTAVAIL;
416 return(error);
417 }
91447636 418 *plocal_addr6 = *addr6;
1c79356b 419 /*
9bccf70c 420 * Don't do pcblookup call here; return interface in
1c79356b
A
421 * plocal_addr6
422 * and exit to caller, that will do the lookup.
423 */
424 }
425
426 if (inp->in6p_route.ro_rt)
427 ifp = inp->in6p_route.ro_rt->rt_ifp;
428
429 return(0);
430}
431
432/*
433 * Outer subroutine:
434 * Connect from a socket to a specified address.
435 * Both address and port must be specified in argument sin.
436 * If don't have a local address for this socket yet,
437 * then pick one.
438 */
439int
440in6_pcbconnect(inp, nam, p)
91447636 441 struct inpcb *inp;
1c79356b
A
442 struct sockaddr *nam;
443 struct proc *p;
444{
91447636
A
445 struct in6_addr addr6;
446 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
447 struct inpcb *pcb;
1c79356b
A
448 int error;
449
450 /*
55e303ae
A
451 * Call inner routine, to assign local interface address.
452 * in6_pcbladdr() may automatically fill in sin6_scope_id.
1c79356b 453 */
9bccf70c 454 if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
1c79356b 455 return(error);
91447636
A
456 socket_unlock(inp->inp_socket, 0);
457 pcb = in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
1c79356b
A
458 sin6->sin6_port,
459 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
91447636
A
460 ? &addr6 : &inp->in6p_laddr,
461 inp->inp_lport, 0, NULL);
462 socket_lock(inp->inp_socket, 0);
463 if (pcb != NULL) {
464 in_pcb_checkstate(pcb, WNT_RELEASE, 0);
1c79356b
A
465 return (EADDRINUSE);
466 }
467 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
468 if (inp->inp_lport == 0) {
469 error = in6_pcbbind(inp, (struct sockaddr *)0, p);
470 if (error)
471 return (error);
472 }
91447636
A
473 inp->in6p_laddr = addr6;
474 }
475 if (!lck_rw_try_lock_exclusive(inp->inp_pcbinfo->mtx)) {
476 /*lock inversion issue, mostly with udp multicast packets */
477 socket_unlock(inp->inp_socket, 0);
478 lck_rw_lock_exclusive(inp->inp_pcbinfo->mtx);
479 socket_lock(inp->inp_socket, 0);
1c79356b
A
480 }
481 inp->in6p_faddr = sin6->sin6_addr;
482 inp->inp_fport = sin6->sin6_port;
9bccf70c
A
483 /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
484 inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
485 if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
486 inp->in6p_flowinfo |=
487 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
1c79356b
A
488
489 in_pcbrehash(inp);
91447636 490 lck_rw_done(inp->inp_pcbinfo->mtx);
1c79356b
A
491 return (0);
492}
493
494#if 0
495/*
496 * Return an IPv6 address, which is the most appropriate for given
497 * destination and user specified options.
498 * If necessary, this function lookups the routing table and return
499 * an entry to the caller for later use.
500 */
501struct in6_addr *
91447636
A
502in6_selectsrc(
503 struct sockaddr_in6 *dstsock,
504 struct ip6_pktopts *opts,
505 struct ip6_moptions *mopts,
506 struct route_in6 *ro,
507 struct in6_addr *laddr,
508 struct in6_addr *src_storage,
509 int *errorp)
1c79356b
A
510{
511 struct in6_addr *dst;
512 struct in6_ifaddr *ia6 = 0;
513 struct in6_pktinfo *pi = NULL;
514
515 dst = &dstsock->sin6_addr;
516 *errorp = 0;
517
518 /*
519 * If the source address is explicitly specified by the caller,
520 * use it.
521 */
522 if (opts && (pi = opts->ip6po_pktinfo) &&
523 !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
524 return(&pi->ipi6_addr);
525
526 /*
527 * If the source address is not specified but the socket(if any)
528 * is already bound, use the bound address.
529 */
530 if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
531 return(laddr);
532
533 /*
534 * If the caller doesn't specify the source address but
535 * the outgoing interface, use an address associated with
536 * the interface.
537 */
538 if (pi && pi->ipi6_ifindex) {
539 /* XXX boundary check is assumed to be already done. */
540 ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
541 dst);
542 if (ia6 == 0) {
543 *errorp = EADDRNOTAVAIL;
544 return(0);
545 }
91447636
A
546 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
547 ifafree(&ia6->ia_ifa);
548 return(src_storage);
1c79356b
A
549 }
550
551 /*
552 * If the destination address is a link-local unicast address or
553 * a multicast address, and if the outgoing interface is specified
554 * by the sin6_scope_id filed, use an address associated with the
555 * interface.
556 * XXX: We're now trying to define more specific semantics of
557 * sin6_scope_id field, so this part will be rewritten in
558 * the near future.
559 */
560 if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
561 dstsock->sin6_scope_id) {
562 /*
563 * I'm not sure if boundary check for scope_id is done
564 * somewhere...
565 */
566 if (dstsock->sin6_scope_id < 0 ||
567 if_index < dstsock->sin6_scope_id) {
568 *errorp = ENXIO; /* XXX: better error? */
569 return(0);
570 }
571 ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
572 dst);
573 if (ia6 == 0) {
574 *errorp = EADDRNOTAVAIL;
575 return(0);
576 }
91447636
A
577 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
578 ifafree(&ia6->ia_ifa);
579 return(src_storage);
1c79356b
A
580 }
581
582 /*
583 * If the destination address is a multicast address and
584 * the outgoing interface for the address is specified
585 * by the caller, use an address associated with the interface.
586 * There is a sanity check here; if the destination has node-local
587 * scope, the outgoing interfacde should be a loopback address.
588 * Even if the outgoing interface is not specified, we also
589 * choose a loopback interface as the outgoing interface.
590 */
591 if (IN6_IS_ADDR_MULTICAST(dst)) {
592 struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
1c79356b
A
593
594 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
2d21ac55 595 ifp = lo_ifp;
1c79356b
A
596 }
597
598 if (ifp) {
599 ia6 = in6_ifawithscope(ifp, dst);
600 if (ia6 == 0) {
601 *errorp = EADDRNOTAVAIL;
602 return(0);
603 }
91447636
A
604 *src_storage = ia6->ia_addr.sin6_addr;
605 ifafree(&ia6->ia_ifa);
606 return(src_storage);
1c79356b
A
607 }
608 }
609
610 /*
611 * If the next hop address for the packet is specified
612 * by caller, use an address associated with the route
613 * to the next hop.
614 */
615 {
616 struct sockaddr_in6 *sin6_next;
617 struct rtentry *rt;
618
619 if (opts && opts->ip6po_nexthop) {
620 sin6_next = satosin6(opts->ip6po_nexthop);
91447636 621 rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL, 0);
1c79356b
A
622 if (rt) {
623 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
91447636
A
624 if (ia6 == 0) {
625 ifaref(&rt->rt_ifa);
1c79356b 626 ia6 = ifatoia6(rt->rt_ifa);
91447636 627 }
1c79356b
A
628 }
629 if (ia6 == 0) {
630 *errorp = EADDRNOTAVAIL;
631 return(0);
632 }
91447636
A
633 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
634 ifaref(&rt->rt_ifa);
635 return(src_storage);
1c79356b
A
636 }
637 }
638
639 /*
640 * If route is known or can be allocated now,
641 * our src addr is taken from the i/f, else punt.
642 */
643 if (ro) {
644 if (ro->ro_rt &&
645 !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
9bccf70c 646 rtfree(ro->ro_rt);
1c79356b
A
647 ro->ro_rt = (struct rtentry *)0;
648 }
649 if (ro->ro_rt == (struct rtentry *)0 ||
650 ro->ro_rt->rt_ifp == (struct ifnet *)0) {
9bccf70c
A
651 struct sockaddr_in6 *dst6;
652
1c79356b
A
653 /* No route yet, so try to acquire one */
654 bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
9bccf70c
A
655 dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
656 dst6->sin6_family = AF_INET6;
657 dst6->sin6_len = sizeof(struct sockaddr_in6);
658 dst6->sin6_addr = *dst;
1c79356b 659 if (IN6_IS_ADDR_MULTICAST(dst)) {
2d21ac55
A
660 ro->ro_rt =
661 rtalloc1(&((struct route *)ro)->ro_dst, 0, 0UL);
1c79356b
A
662 } else {
663 rtalloc((struct route *)ro);
664 }
665 }
666
667 /*
668 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
669 * the address. But we don't know why it does so.
670 * It is necessary to ensure the scope even for lo0
671 * so doesn't check out IFF_LOOPBACK.
672 */
673
674 if (ro->ro_rt) {
675 ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
91447636
A
676 if (ia6 == 0) { /* xxx scope error ?*/
677 ifaref(ro->ro_rt->rt_ifa);
1c79356b 678 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
91447636 679 }
1c79356b 680 }
1c79356b
A
681 if (ia6 == 0) {
682 *errorp = EHOSTUNREACH; /* no route */
683 return(0);
684 }
91447636
A
685 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
686 ifaref(&rt->rt_ifa);
687 return(src_storage);
1c79356b
A
688 }
689
690 *errorp = EADDRNOTAVAIL;
691 return(0);
692}
693
694/*
695 * Default hop limit selection. The precedence is as follows:
696 * 1. Hoplimit valued specified via ioctl.
697 * 2. (If the outgoing interface is detected) the current
698 * hop limit of the interface specified by router advertisement.
699 * 3. The system default hoplimit.
700*/
701int
91447636
A
702in6_selecthlim(
703 struct in6pcb *in6p,
704 struct ifnet *ifp)
1c79356b
A
705{
706 if (in6p && in6p->in6p_hops >= 0)
707 return(in6p->in6p_hops);
708 else if (ifp)
709 return(nd_ifinfo[ifp->if_index].chlim);
710 else
711 return(ip6_defhlim);
712}
713#endif
714
715void
716in6_pcbdisconnect(inp)
717 struct inpcb *inp;
718{
91447636
A
719 if (!lck_rw_try_lock_exclusive(inp->inp_pcbinfo->mtx)) {
720 /*lock inversion issue, mostly with udp multicast packets */
721 socket_unlock(inp->inp_socket, 0);
722 lck_rw_lock_exclusive(inp->inp_pcbinfo->mtx);
723 socket_lock(inp->inp_socket, 0);
724 }
1c79356b
A
725 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
726 inp->inp_fport = 0;
9bccf70c
A
727 /* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
728 inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
1c79356b 729 in_pcbrehash(inp);
91447636 730 lck_rw_done(inp->inp_pcbinfo->mtx);
1c79356b
A
731 if (inp->inp_socket->so_state & SS_NOFDREF)
732 in6_pcbdetach(inp);
733}
734
735void
736in6_pcbdetach(inp)
737 struct inpcb *inp;
738{
739 struct socket *so = inp->inp_socket;
740 struct inpcbinfo *ipi = inp->inp_pcbinfo;
741
742#if IPSEC
91447636 743 if (inp->in6p_sp != NULL) {
9bccf70c 744 ipsec6_delete_pcbpolicy(inp);
91447636 745 }
1c79356b 746#endif /* IPSEC */
9bccf70c 747
91447636 748 if (in_pcb_checkstate(inp, WNT_STOPUSING, 1) != WNT_STOPUSING)
2d21ac55 749 printf("in6_pcbdetach so=%p can't be marked dead ok\n", so);
91447636
A
750
751 inp->inp_state = INPCB_STATE_DEAD;
752
753 if ((so->so_flags & SOF_PCBCLEARING) == 0) {
754 inp->inp_vflag = 0;
755 so->so_flags |= SOF_PCBCLEARING;
756 inp->inp_gencnt = ++ipi->ipi_gencnt;
757 if (inp->in6p_options)
758 m_freem(inp->in6p_options);
759 ip6_freepcbopts(inp->in6p_outputopts);
760 ip6_freemoptions(inp->in6p_moptions);
761 if (inp->in6p_route.ro_rt)
762 rtfree(inp->in6p_route.ro_rt);
763 /* Check and free IPv4 related resources in case of mapped addr */
764 if (inp->inp_options)
765 (void)m_free(inp->inp_options);
766 ip_freemoptions(inp->inp_moptions);
767 inp->inp_moptions = NULL;
768
769 }
1c79356b
A
770}
771
55e303ae
A
772struct sockaddr *
773in6_sockaddr(port, addr_p)
774 in_port_t port;
775 struct in6_addr *addr_p;
776{
777 struct sockaddr_in6 *sin6;
778
779 MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
780 bzero(sin6, sizeof *sin6);
781 sin6->sin6_family = AF_INET6;
782 sin6->sin6_len = sizeof(*sin6);
783 sin6->sin6_port = port;
784 sin6->sin6_addr = *addr_p;
785 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
786 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
787 else
788 sin6->sin6_scope_id = 0; /*XXX*/
789 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
790 sin6->sin6_addr.s6_addr16[1] = 0;
791
792 return (struct sockaddr *)sin6;
793}
794
795struct sockaddr *
796in6_v4mapsin6_sockaddr(port, addr_p)
797 in_port_t port;
798 struct in_addr *addr_p;
799{
800 struct sockaddr_in sin;
801 struct sockaddr_in6 *sin6_p;
802
803 bzero(&sin, sizeof sin);
804 sin.sin_family = AF_INET;
805 sin.sin_len = sizeof(sin);
806 sin.sin_port = port;
807 sin.sin_addr = *addr_p;
808
809 MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
810 M_WAITOK);
811 in6_sin_2_v4mapsin6(&sin, sin6_p);
812
813 return (struct sockaddr *)sin6_p;
814}
815
1c79356b
A
816/*
817 * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
818 * modified to match the pru_sockaddr() and pru_peeraddr() entry points
819 * in struct pr_usrreqs, so that protocols can just reference then directly
820 * without the need for a wrapper function. The socket must have a valid
821 * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
822 * except through a kernel programming error, so it is acceptable to panic
823 * (or in this case trap) if the PCB is invalid. (Actually, we don't trap
824 * because there actually /is/ a programming error somewhere... XXX)
825 */
826int
827in6_setsockaddr(so, nam)
828 struct socket *so;
829 struct sockaddr **nam;
830{
91447636 831 struct inpcb *inp;
55e303ae
A
832 struct in6_addr addr;
833 in_port_t port;
1c79356b 834
1c79356b
A
835 inp = sotoinpcb(so);
836 if (!inp) {
1c79356b
A
837 return EINVAL;
838 }
55e303ae
A
839 port = inp->inp_lport;
840 addr = inp->in6p_laddr;
1c79356b 841
55e303ae 842 *nam = in6_sockaddr(port, &addr);
1c79356b
A
843 return 0;
844}
845
846int
847in6_setpeeraddr(so, nam)
848 struct socket *so;
849 struct sockaddr **nam;
850{
1c79356b 851 struct inpcb *inp;
55e303ae
A
852 struct in6_addr addr;
853 in_port_t port;
1c79356b 854
1c79356b
A
855 inp = sotoinpcb(so);
856 if (!inp) {
1c79356b
A
857 return EINVAL;
858 }
55e303ae
A
859 port = inp->inp_fport;
860 addr = inp->in6p_faddr;
1c79356b 861
55e303ae 862 *nam = in6_sockaddr(port, &addr);
1c79356b
A
863 return 0;
864}
865
866int
867in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
868{
869 struct inpcb *inp = sotoinpcb(so);
870 int error;
871
872 if (inp == NULL)
873 return EINVAL;
874 if (inp->inp_vflag & INP_IPV4) {
875 error = in_setsockaddr(so, nam);
876 if (error == 0)
877 in6_sin_2_v4mapsin6_in_sock(nam);
878 } else
55e303ae 879 /* scope issues will be handled in in6_setsockaddr(). */
1c79356b
A
880 error = in6_setsockaddr(so, nam);
881
882 return error;
883}
884
885int
886in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
887{
888 struct inpcb *inp = sotoinpcb(so);
889 int error;
890
891 if (inp == NULL)
892 return EINVAL;
893 if (inp->inp_vflag & INP_IPV4) {
894 error = in_setpeeraddr(so, nam);
895 if (error == 0)
896 in6_sin_2_v4mapsin6_in_sock(nam);
897 } else
55e303ae 898 /* scope issues will be handled in in6_setpeeraddr(). */
9bccf70c 899 error = in6_setpeeraddr(so, nam);
1c79356b
A
900
901 return error;
902}
903
904/*
905 * Pass some notification to all connections of a protocol
906 * associated with address dst. The local address and/or port numbers
907 * may be specified to limit the search. The "usual action" will be
908 * taken, depending on the ctlinput cmd. The caller must filter any
909 * cmds that are uninteresting (e.g., no error in the map).
910 * Call the protocol specific routine (if any) to report
911 * any errors for each matching socket.
912 *
913 * Must be called at splnet.
914 */
915void
91447636
A
916in6_pcbnotify(pcbinfo, dst, fport_arg, src, lport_arg, cmd, notify)
917 struct inpcbinfo *pcbinfo;
55e303ae
A
918 struct sockaddr *dst;
919 const struct sockaddr *src;
1c79356b 920 u_int fport_arg, lport_arg;
1c79356b 921 int cmd;
91447636
A
922// struct inpcb *(*notify)(struct inpcb *, int);
923 void (*notify)(struct inpcb *, int);
1c79356b
A
924{
925 struct inpcb *inp, *ninp;
9bccf70c 926 struct sockaddr_in6 sa6_src, *sa6_dst;
1c79356b 927 u_short fport = fport_arg, lport = lport_arg;
9bccf70c 928 u_int32_t flowinfo;
91447636
A
929 int errno;
930 struct inpcbhead *head = pcbinfo->listhead;
1c79356b
A
931
932 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
933 return;
9bccf70c
A
934
935 sa6_dst = (struct sockaddr_in6 *)dst;
936 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
1c79356b
A
937 return;
938
9bccf70c
A
939 /*
940 * note that src can be NULL when we get notify by local fragmentation.
941 */
55e303ae 942 sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
9bccf70c
A
943 flowinfo = sa6_src.sin6_flowinfo;
944
1c79356b
A
945 /*
946 * Redirects go to all references to the destination,
947 * and use in6_rtchange to invalidate the route cache.
948 * Dead host indications: also use in6_rtchange to invalidate
949 * the cache, and deliver the error to all the sockets.
950 * Otherwise, if we have knowledge of the local port and address,
951 * deliver only to that socket.
952 */
953 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
954 fport = 0;
955 lport = 0;
9bccf70c 956 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
1c79356b 957
9bccf70c
A
958 if (cmd != PRC_HOSTDEAD)
959 notify = in6_rtchange;
1c79356b
A
960 }
961 errno = inet6ctlerrmap[cmd];
91447636 962 lck_rw_lock_shared(pcbinfo->mtx);
9bccf70c
A
963 for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
964 ninp = LIST_NEXT(inp, inp_list);
1c79356b 965
9bccf70c 966 if ((inp->inp_vflag & INP_IPV6) == 0)
1c79356b
A
967 continue;
968
9bccf70c
A
969 /*
970 * Detect if we should notify the error. If no source and
971 * destination ports are specifed, but non-zero flowinfo and
972 * local address match, notify the error. This is the case
973 * when the error is delivered with an encrypted buffer
974 * by ESP. Otherwise, just compare addresses and ports
975 * as usual.
976 */
977 if (lport == 0 && fport == 0 && flowinfo &&
978 inp->inp_socket != NULL &&
979 flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
980 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
981 goto do_notify;
982 else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
983 &sa6_dst->sin6_addr) ||
984 inp->inp_socket == 0 ||
985 (lport && inp->inp_lport != lport) ||
986 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
987 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
988 &sa6_src.sin6_addr)) ||
91447636 989 (fport && inp->inp_fport != fport))
1c79356b 990 continue;
91447636 991
1c79356b 992
9bccf70c 993 do_notify:
91447636
A
994 if (notify) {
995 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING)
996 continue;
997 socket_lock(inp->inp_socket, 1);
1c79356b 998 (*notify)(inp, errno);
91447636
A
999 (void)in_pcb_checkstate(inp, WNT_RELEASE, 1);
1000 socket_unlock(inp->inp_socket, 1);
1001 }
1c79356b 1002 }
91447636 1003 lck_rw_done(pcbinfo->mtx);
1c79356b
A
1004}
1005
1006/*
1007 * Lookup a PCB based on the local address and port.
1008 */
1009struct inpcb *
1010in6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
1011 struct inpcbinfo *pcbinfo;
1012 struct in6_addr *laddr;
1013 u_int lport_arg;
1014 int wild_okay;
1015{
91447636 1016 struct inpcb *inp;
1c79356b
A
1017 int matchwild = 3, wildcard;
1018 u_short lport = lport_arg;
1019
1020 if (!wild_okay) {
1021 struct inpcbhead *head;
1022 /*
1023 * Look for an unconnected (wildcard foreign addr) PCB that
1024 * matches the local address and port we're looking for.
1025 */
1026 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
1027 pcbinfo->hashmask)];
1028 LIST_FOREACH(inp, head, inp_hash) {
1029 if ((inp->inp_vflag & INP_IPV6) == 0)
1030 continue;
1031 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1032 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
1033 inp->inp_lport == lport) {
1034 /*
1035 * Found.
1036 */
1037 return (inp);
1038 }
1039 }
1040 /*
1041 * Not found.
1042 */
1043 return (NULL);
1044 } else {
1045 struct inpcbporthead *porthash;
1046 struct inpcbport *phd;
1047 struct inpcb *match = NULL;
1048 /*
1049 * Best fit PCB lookup.
1050 *
1051 * First see if this local port is in use by looking on the
1052 * port hash list.
1053 */
1054 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
1055 pcbinfo->porthashmask)];
1056 LIST_FOREACH(phd, porthash, phd_hash) {
1057 if (phd->phd_port == lport)
1058 break;
1059 }
1060 if (phd != NULL) {
1061 /*
1062 * Port is in use by one or more PCBs. Look for best
1063 * fit.
1064 */
1065 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
1066 wildcard = 0;
1067 if ((inp->inp_vflag & INP_IPV6) == 0)
1068 continue;
1069 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
1070 wildcard++;
1071 if (!IN6_IS_ADDR_UNSPECIFIED(
1072 &inp->in6p_laddr)) {
1073 if (IN6_IS_ADDR_UNSPECIFIED(laddr))
1074 wildcard++;
1075 else if (!IN6_ARE_ADDR_EQUAL(
1076 &inp->in6p_laddr, laddr))
1077 continue;
1078 } else {
1079 if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
1080 wildcard++;
1081 }
1082 if (wildcard < matchwild) {
1083 match = inp;
1084 matchwild = wildcard;
1085 if (matchwild == 0) {
1086 break;
1087 }
1088 }
1089 }
1090 }
1091 return (match);
1092 }
1093}
91447636
A
1094#ifndef APPLE
1095/* this is not used in Darwin */
9bccf70c 1096void
91447636
A
1097in6_pcbpurgeif0(
1098 struct in6pcb *head,
1099 struct ifnet *ifp)
9bccf70c
A
1100{
1101 struct in6pcb *in6p;
1102 struct ip6_moptions *im6o;
1103 struct in6_multi_mship *imm, *nimm;
1104
1105 for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) {
1106 im6o = in6p->in6p_moptions;
1107 if ((in6p->inp_vflag & INP_IPV6) &&
1108 im6o) {
1109 /*
1110 * Unselect the outgoing interface if it is being
1111 * detached.
1112 */
1113 if (im6o->im6o_multicast_ifp == ifp)
1114 im6o->im6o_multicast_ifp = NULL;
1115
1116 /*
1117 * Drop multicast group membership if we joined
1118 * through the interface being detached.
1119 * XXX controversial - is it really legal for kernel
1120 * to force this?
1121 */
1122 for (imm = im6o->im6o_memberships.lh_first;
1123 imm != NULL; imm = nimm) {
1124 nimm = imm->i6mm_chain.le_next;
1125 if (imm->i6mm_maddr->in6m_ifp == ifp) {
1126 LIST_REMOVE(imm, i6mm_chain);
1127 in6_delmulti(imm->i6mm_maddr);
1128 FREE(imm, M_IPMADDR);
1129 }
1130 }
1131 }
1132 }
1133}
91447636 1134#endif
9bccf70c 1135
1c79356b
A
1136/*
1137 * Check for alternatives when higher level complains
1138 * about service problems. For now, invalidate cached
1139 * routing information. If the route was created dynamically
1140 * (by a redirect), time to try a default gateway again.
1141 */
1142void
1143in6_losing(in6p)
1144 struct inpcb *in6p;
1145{
1146 struct rtentry *rt;
1147 struct rt_addrinfo info;
1148
1149 if ((rt = in6p->in6p_route.ro_rt) != NULL) {
1150 in6p->in6p_route.ro_rt = 0;
1151 bzero((caddr_t)&info, sizeof(info));
1152 info.rti_info[RTAX_DST] =
1153 (struct sockaddr *)&in6p->in6p_route.ro_dst;
1154 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1155 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
91447636 1156 lck_mtx_lock(rt_mtx);
1c79356b
A
1157 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
1158 if (rt->rt_flags & RTF_DYNAMIC)
91447636 1159 (void)rtrequest_locked(RTM_DELETE, rt_key(rt),
1c79356b
A
1160 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
1161 (struct rtentry **)0);
1162 else
1163 /*
1164 * A new route can be allocated
1165 * the next time output is attempted.
1166 */
91447636
A
1167 rtfree_locked(rt);
1168 lck_mtx_unlock(rt_mtx);
1c79356b
A
1169 }
1170}
1171
1172/*
1173 * After a routing change, flush old routing
1174 * and allocate a (hopefully) better one.
1175 */
1176void
91447636
A
1177in6_rtchange(
1178 struct inpcb *inp,
2d21ac55 1179 __unused int errno)
1c79356b
A
1180{
1181 if (inp->in6p_route.ro_rt) {
1182 rtfree(inp->in6p_route.ro_rt);
1183 inp->in6p_route.ro_rt = 0;
1184 /*
1185 * A new route can be allocated the next time
1186 * output is attempted.
1187 */
1188 }
1189}
1190
1191/*
1192 * Lookup PCB in hash list.
1193 */
1194struct inpcb *
91447636
A
1195in6_pcblookup_hash(
1196 struct inpcbinfo *pcbinfo,
1197 struct in6_addr *faddr,
1198 u_int fport_arg,
1199 struct in6_addr *laddr,
1200 u_int lport_arg,
1201 int wildcard,
2d21ac55 1202 __unused struct ifnet *ifp)
1c79356b
A
1203{
1204 struct inpcbhead *head;
91447636 1205 struct inpcb *inp;
1c79356b 1206 u_short fport = fport_arg, lport = lport_arg;
9bccf70c
A
1207 int faith;
1208
1209#if defined(NFAITH) && NFAITH > 0
1210 faith = faithprefix(laddr);
1211#else
1212 faith = 0;
1213#endif
1c79356b 1214
91447636
A
1215 lck_rw_lock_shared(pcbinfo->mtx);
1216
1c79356b
A
1217 /*
1218 * First look for an exact match.
1219 */
1220 head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
1221 lport, fport,
1222 pcbinfo->hashmask)];
9bccf70c 1223 LIST_FOREACH(inp, head, inp_hash) {
1c79356b
A
1224 if ((inp->inp_vflag & INP_IPV6) == 0)
1225 continue;
1226 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
1227 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
1228 inp->inp_fport == fport &&
1229 inp->inp_lport == lport) {
1230 /*
91447636
A
1231 * Found. Check if pcb is still valid
1232 */
1233 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1234 lck_rw_done(pcbinfo->mtx);
1235 return (inp);
1236 }
1237 else { /* it's there but dead, say it isn't found */
1238 lck_rw_done(pcbinfo->mtx);
1239 return(NULL);
1240 }
1c79356b
A
1241 }
1242 }
1243 if (wildcard) {
1244 struct inpcb *local_wild = NULL;
1245
1246 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
1247 pcbinfo->hashmask)];
9bccf70c 1248 LIST_FOREACH(inp, head, inp_hash) {
1c79356b
A
1249 if ((inp->inp_vflag & INP_IPV6) == 0)
1250 continue;
1251 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1252 inp->inp_lport == lport) {
9bccf70c 1253 if (faith && (inp->inp_flags & INP_FAITH) == 0)
1c79356b 1254 continue;
1c79356b 1255 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
91447636
A
1256 laddr)) {
1257 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1258 lck_rw_done(pcbinfo->mtx);
1259 return (inp);
1260 }
1261 else { /* it's there but dead, say it isn't found */
1262 lck_rw_done(pcbinfo->mtx);
1263 return(NULL);
1264 }
1265 }
1c79356b
A
1266 else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
1267 local_wild = inp;
1268 }
1269 }
91447636
A
1270 if (local_wild && in_pcb_checkstate(local_wild, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1271 lck_rw_done(pcbinfo->mtx);
1272 return (local_wild);
1273 }
1274 else {
1275 lck_rw_done(pcbinfo->mtx);
1276 return (NULL);
1277 }
1c79356b
A
1278 }
1279
1280 /*
1281 * Not found.
1282 */
91447636 1283 lck_rw_done(pcbinfo->mtx);
1c79356b
A
1284 return (NULL);
1285}
1286
1287void
1288init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
1289{
1290 struct ip6_hdr *ip;
1291
1292 ip = mtod(m, struct ip6_hdr *);
1293 bzero(sin6, sizeof(*sin6));
1294 sin6->sin6_len = sizeof(*sin6);
1295 sin6->sin6_family = AF_INET6;
1296 sin6->sin6_addr = ip->ip6_src;
1297 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1298 sin6->sin6_addr.s6_addr16[1] = 0;
1299 sin6->sin6_scope_id =
1300 (m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1301 ? m->m_pkthdr.rcvif->if_index : 0;
1302
1303 return;
1304}