]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/in6_pcb.c
1b481b21fa1b32d59d2f8b364d4a51c35bdbc2c4
[apple/xnu.git] / bsd / netinet6 / in6_pcb.c
1 /*
2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
31 *
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.
43 *
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.
55 *
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
93 #include <sys/param.h>
94 #include <sys/systm.h>
95 #include <sys/malloc.h>
96 #include <sys/mbuf.h>
97 #include <sys/domain.h>
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>
114 #include <netinet/ip_var.h>
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
121 #include <kern/kern_types.h>
122 #include <kern/zalloc.h>
123
124 #if IPSEC
125 #include <netinet6/ipsec.h>
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
133 #include <netkey/key.h>
134 #endif /* IPSEC */
135
136 struct in6_addr zeroin6_addr;
137
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 */
147 static struct inpcb*
148 in6_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 }
176 int
177 in6_pcbbind(
178 struct inpcb *inp,
179 struct sockaddr *nam,
180 struct proc *p)
181 {
182 struct socket *so = inp->inp_socket;
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);
187
188 if (!in6_ifaddrs) /* XXX broken! */
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)
193 wild = 1;
194 socket_unlock(so, 0); /* keep reference */
195 lck_rw_lock_exclusive(pcbinfo->mtx);
196 if (nam) {
197 sin6 = (struct sockaddr_in6 *)nam;
198 if (nam->sa_len != sizeof(*sin6)) {
199 lck_rw_done(pcbinfo->mtx);
200 socket_lock(so, 0);
201 return(EINVAL);
202 }
203 /*
204 * family check.
205 */
206 if (nam->sa_family != AF_INET6) {
207 lck_rw_done(pcbinfo->mtx);
208 socket_lock(so, 0);
209 return(EAFNOSUPPORT);
210 }
211
212 /* KAME hack: embed scopeid */
213 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0) {
214 lck_rw_done(pcbinfo->mtx);
215 socket_lock(so, 0);
216 return EINVAL;
217 }
218 /* this must be cleared for ifa_ifwithaddr() */
219 sin6->sin6_scope_id = 0;
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... */
236 if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0) {
237 lck_rw_done(pcbinfo->mtx);
238 socket_lock(so, 0);
239 return(EADDRNOTAVAIL);
240 }
241
242 /*
243 * XXX: bind to an anycast address might accidentally
244 * cause sending a packet with anycast source address.
245 * We should allow to bind to a deprecated address, since
246 * the application dare to use it.
247 */
248 if (ia &&
249 ((struct in6_ifaddr *)ia)->ia6_flags &
250 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
251 ifafree(ia);
252 lck_rw_done(pcbinfo->mtx);
253 socket_lock(so, 0);
254 return(EADDRNOTAVAIL);
255 }
256 ifafree(ia);
257 ia = NULL;
258 }
259 if (lport) {
260 struct inpcb *t;
261
262 /* GROSS */
263 if (ntohs(lport) < IPV6PORT_RESERVED && p &&
264 ((so->so_state & SS_PRIV) == 0)) {
265 lck_rw_done(pcbinfo->mtx);
266 socket_lock(so, 0);
267 return(EACCES);
268 }
269
270 if (so->so_uid &&
271 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
272 t = in6_pcblookup_local_and_cleanup(pcbinfo,
273 &sin6->sin6_addr, lport,
274 INPLOOKUP_WILDCARD);
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) &&
280 (so->so_uid != t->inp_socket->so_uid) &&
281 ((t->inp_socket->so_flags & SOF_REUSESHAREUID) == 0)) {
282 lck_rw_done(pcbinfo->mtx);
283 socket_lock(so, 0);
284 return (EADDRINUSE);
285 }
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);
291 t = in_pcblookup_local_and_cleanup(pcbinfo,
292 sin.sin_addr, lport,
293 INPLOOKUP_WILDCARD);
294 if (t && (t->inp_socket->so_options & SO_REUSEPORT) == 0 &&
295 (so->so_uid !=
296 t->inp_socket->so_uid) &&
297 (ntohl(t->inp_laddr.s_addr) !=
298 INADDR_ANY ||
299 INP_SOCKAF(so) ==
300 INP_SOCKAF(t->inp_socket))) {
301
302 lck_rw_done(pcbinfo->mtx);
303 socket_lock(so, 0);
304 return (EADDRINUSE);
305 }
306 }
307 }
308 t = in6_pcblookup_local_and_cleanup(pcbinfo, &sin6->sin6_addr,
309 lport, wild);
310 if (t && (reuseport & t->inp_socket->so_options) == 0) {
311 lck_rw_done(pcbinfo->mtx);
312 socket_lock(so, 0);
313 return(EADDRINUSE);
314 }
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);
320 t = in_pcblookup_local_and_cleanup(pcbinfo, sin.sin_addr,
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) ==
328 INP_SOCKAF(t->inp_socket))) {
329 lck_rw_done(pcbinfo->mtx);
330 socket_lock(so, 0);
331 return (EADDRINUSE);
332 }
333 }
334 }
335 inp->in6p_laddr = sin6->sin6_addr;
336 }
337 socket_lock(so, 0);
338 if (lport == 0) {
339 int e;
340 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, p, 1)) != 0) {
341 lck_rw_done(pcbinfo->mtx);
342 return(e);
343 }
344 }
345 else {
346 inp->inp_lport = lport;
347 if (in_pcbinshash(inp, 1) != 0) {
348 inp->in6p_laddr = in6addr_any;
349 inp->inp_lport = 0;
350 lck_rw_done(pcbinfo->mtx);
351 return (EAGAIN);
352 }
353 }
354 lck_rw_done(pcbinfo->mtx);
355 sflt_notify(so, sock_evt_bound, NULL);
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
371 int
372 in6_pcbladdr(
373 struct inpcb *inp,
374 struct sockaddr *nam,
375 struct in6_addr *plocal_addr6)
376 {
377 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
378 struct in6_addr *addr6 = NULL;
379 struct in6_addr src_storage;
380
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
391 /* KAME hack: embed scopeid */
392 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
393 return EINVAL;
394
395 if (in6_ifaddrs) {
396 /*
397 * If the destination address is UNSPECIFIED addr,
398 * use the loopback addr, e.g ::1.
399 */
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 */
409 addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
410 inp->in6p_moptions,
411 &inp->in6p_route,
412 &inp->in6p_laddr, &src_storage, &error);
413 if (addr6 == 0) {
414 if (error == 0)
415 error = EADDRNOTAVAIL;
416 return(error);
417 }
418 *plocal_addr6 = *addr6;
419 /*
420 * Don't do pcblookup call here; return interface in
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 */
439 int
440 in6_pcbconnect(inp, nam, p)
441 struct inpcb *inp;
442 struct sockaddr *nam;
443 struct proc *p;
444 {
445 struct in6_addr addr6;
446 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
447 struct inpcb *pcb;
448 int error;
449
450 /*
451 * Call inner routine, to assign local interface address.
452 * in6_pcbladdr() may automatically fill in sin6_scope_id.
453 */
454 if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
455 return(error);
456 socket_unlock(inp->inp_socket, 0);
457 pcb = in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
458 sin6->sin6_port,
459 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
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);
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 }
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);
480 }
481 inp->in6p_faddr = sin6->sin6_addr;
482 inp->inp_fport = sin6->sin6_port;
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);
488
489 in_pcbrehash(inp);
490 lck_rw_done(inp->inp_pcbinfo->mtx);
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 */
501 struct in6_addr *
502 in6_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)
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 }
546 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
547 ifafree(&ia6->ia_ifa);
548 return(src_storage);
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 }
577 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
578 ifafree(&ia6->ia_ifa);
579 return(src_storage);
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;
593
594 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
595 ifp = lo_ifp;
596 }
597
598 if (ifp) {
599 ia6 = in6_ifawithscope(ifp, dst);
600 if (ia6 == 0) {
601 *errorp = EADDRNOTAVAIL;
602 return(0);
603 }
604 *src_storage = ia6->ia_addr.sin6_addr;
605 ifafree(&ia6->ia_ifa);
606 return(src_storage);
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);
621 rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL, 0);
622 if (rt) {
623 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
624 if (ia6 == 0) {
625 ifaref(&rt->rt_ifa);
626 ia6 = ifatoia6(rt->rt_ifa);
627 }
628 }
629 if (ia6 == 0) {
630 *errorp = EADDRNOTAVAIL;
631 return(0);
632 }
633 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
634 ifaref(&rt->rt_ifa);
635 return(src_storage);
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)) {
646 rtfree(ro->ro_rt);
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) {
651 struct sockaddr_in6 *dst6;
652
653 /* No route yet, so try to acquire one */
654 bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
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;
659 if (IN6_IS_ADDR_MULTICAST(dst)) {
660 ro->ro_rt =
661 rtalloc1(&((struct route *)ro)->ro_dst, 0, 0UL);
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);
676 if (ia6 == 0) { /* xxx scope error ?*/
677 ifaref(ro->ro_rt->rt_ifa);
678 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
679 }
680 }
681 if (ia6 == 0) {
682 *errorp = EHOSTUNREACH; /* no route */
683 return(0);
684 }
685 *src_storage = satosin6(&ia6->ia_addr)->sin6_addr;
686 ifaref(&rt->rt_ifa);
687 return(src_storage);
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 */
701 int
702 in6_selecthlim(
703 struct in6pcb *in6p,
704 struct ifnet *ifp)
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
715 void
716 in6_pcbdisconnect(inp)
717 struct inpcb *inp;
718 {
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 }
725 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
726 inp->inp_fport = 0;
727 /* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
728 inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
729 in_pcbrehash(inp);
730 lck_rw_done(inp->inp_pcbinfo->mtx);
731 if (inp->inp_socket->so_state & SS_NOFDREF)
732 in6_pcbdetach(inp);
733 }
734
735 void
736 in6_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
743 if (inp->in6p_sp != NULL) {
744 ipsec6_delete_pcbpolicy(inp);
745 }
746 #endif /* IPSEC */
747
748 if (in_pcb_checkstate(inp, WNT_STOPUSING, 1) != WNT_STOPUSING)
749 printf("in6_pcbdetach so=%p can't be marked dead ok\n", so);
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 inp->in6p_route.ro_rt = NULL;
764 }
765 /* Check and free IPv4 related resources in case of mapped addr */
766 if (inp->inp_options)
767 (void)m_free(inp->inp_options);
768 ip_freemoptions(inp->inp_moptions);
769 inp->inp_moptions = NULL;
770
771 }
772 }
773
774 struct sockaddr *
775 in6_sockaddr(port, addr_p)
776 in_port_t port;
777 struct in6_addr *addr_p;
778 {
779 struct sockaddr_in6 *sin6;
780
781 MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK);
782 bzero(sin6, sizeof *sin6);
783 sin6->sin6_family = AF_INET6;
784 sin6->sin6_len = sizeof(*sin6);
785 sin6->sin6_port = port;
786 sin6->sin6_addr = *addr_p;
787 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
788 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
789 else
790 sin6->sin6_scope_id = 0; /*XXX*/
791 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
792 sin6->sin6_addr.s6_addr16[1] = 0;
793
794 return (struct sockaddr *)sin6;
795 }
796
797 struct sockaddr *
798 in6_v4mapsin6_sockaddr(port, addr_p)
799 in_port_t port;
800 struct in_addr *addr_p;
801 {
802 struct sockaddr_in sin;
803 struct sockaddr_in6 *sin6_p;
804
805 bzero(&sin, sizeof sin);
806 sin.sin_family = AF_INET;
807 sin.sin_len = sizeof(sin);
808 sin.sin_port = port;
809 sin.sin_addr = *addr_p;
810
811 MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
812 M_WAITOK);
813 in6_sin_2_v4mapsin6(&sin, sin6_p);
814
815 return (struct sockaddr *)sin6_p;
816 }
817
818 /*
819 * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
820 * modified to match the pru_sockaddr() and pru_peeraddr() entry points
821 * in struct pr_usrreqs, so that protocols can just reference then directly
822 * without the need for a wrapper function. The socket must have a valid
823 * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
824 * except through a kernel programming error, so it is acceptable to panic
825 * (or in this case trap) if the PCB is invalid. (Actually, we don't trap
826 * because there actually /is/ a programming error somewhere... XXX)
827 */
828 int
829 in6_setsockaddr(so, nam)
830 struct socket *so;
831 struct sockaddr **nam;
832 {
833 struct inpcb *inp;
834 struct in6_addr addr;
835 in_port_t port;
836
837 inp = sotoinpcb(so);
838 if (!inp) {
839 return EINVAL;
840 }
841 port = inp->inp_lport;
842 addr = inp->in6p_laddr;
843
844 *nam = in6_sockaddr(port, &addr);
845 return 0;
846 }
847
848 int
849 in6_setpeeraddr(so, nam)
850 struct socket *so;
851 struct sockaddr **nam;
852 {
853 struct inpcb *inp;
854 struct in6_addr addr;
855 in_port_t port;
856
857 inp = sotoinpcb(so);
858 if (!inp) {
859 return EINVAL;
860 }
861 port = inp->inp_fport;
862 addr = inp->in6p_faddr;
863
864 *nam = in6_sockaddr(port, &addr);
865 return 0;
866 }
867
868 int
869 in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
870 {
871 struct inpcb *inp = sotoinpcb(so);
872 int error;
873
874 if (inp == NULL)
875 return EINVAL;
876 if (inp->inp_vflag & INP_IPV4) {
877 error = in_setsockaddr(so, nam);
878 if (error == 0)
879 in6_sin_2_v4mapsin6_in_sock(nam);
880 } else
881 /* scope issues will be handled in in6_setsockaddr(). */
882 error = in6_setsockaddr(so, nam);
883
884 return error;
885 }
886
887 int
888 in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
889 {
890 struct inpcb *inp = sotoinpcb(so);
891 int error;
892
893 if (inp == NULL)
894 return EINVAL;
895 if (inp->inp_vflag & INP_IPV4) {
896 error = in_setpeeraddr(so, nam);
897 if (error == 0)
898 in6_sin_2_v4mapsin6_in_sock(nam);
899 } else
900 /* scope issues will be handled in in6_setpeeraddr(). */
901 error = in6_setpeeraddr(so, nam);
902
903 return error;
904 }
905
906 /*
907 * Pass some notification to all connections of a protocol
908 * associated with address dst. The local address and/or port numbers
909 * may be specified to limit the search. The "usual action" will be
910 * taken, depending on the ctlinput cmd. The caller must filter any
911 * cmds that are uninteresting (e.g., no error in the map).
912 * Call the protocol specific routine (if any) to report
913 * any errors for each matching socket.
914 *
915 * Must be called at splnet.
916 */
917 void
918 in6_pcbnotify(pcbinfo, dst, fport_arg, src, lport_arg, cmd, notify)
919 struct inpcbinfo *pcbinfo;
920 struct sockaddr *dst;
921 const struct sockaddr *src;
922 u_int fport_arg, lport_arg;
923 int cmd;
924 // struct inpcb *(*notify)(struct inpcb *, int);
925 void (*notify)(struct inpcb *, int);
926 {
927 struct inpcb *inp, *ninp;
928 struct sockaddr_in6 sa6_src, *sa6_dst;
929 u_short fport = fport_arg, lport = lport_arg;
930 u_int32_t flowinfo;
931 int errno;
932 struct inpcbhead *head = pcbinfo->listhead;
933
934 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
935 return;
936
937 sa6_dst = (struct sockaddr_in6 *)dst;
938 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
939 return;
940
941 /*
942 * note that src can be NULL when we get notify by local fragmentation.
943 */
944 sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
945 flowinfo = sa6_src.sin6_flowinfo;
946
947 /*
948 * Redirects go to all references to the destination,
949 * and use in6_rtchange to invalidate the route cache.
950 * Dead host indications: also use in6_rtchange to invalidate
951 * the cache, and deliver the error to all the sockets.
952 * Otherwise, if we have knowledge of the local port and address,
953 * deliver only to that socket.
954 */
955 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
956 fport = 0;
957 lport = 0;
958 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
959
960 if (cmd != PRC_HOSTDEAD)
961 notify = in6_rtchange;
962 }
963 errno = inet6ctlerrmap[cmd];
964 lck_rw_lock_shared(pcbinfo->mtx);
965 for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
966 ninp = LIST_NEXT(inp, inp_list);
967
968 if ((inp->inp_vflag & INP_IPV6) == 0)
969 continue;
970
971 /*
972 * Detect if we should notify the error. If no source and
973 * destination ports are specifed, but non-zero flowinfo and
974 * local address match, notify the error. This is the case
975 * when the error is delivered with an encrypted buffer
976 * by ESP. Otherwise, just compare addresses and ports
977 * as usual.
978 */
979 if (lport == 0 && fport == 0 && flowinfo &&
980 inp->inp_socket != NULL &&
981 flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
982 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
983 goto do_notify;
984 else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
985 &sa6_dst->sin6_addr) ||
986 inp->inp_socket == 0 ||
987 (lport && inp->inp_lport != lport) ||
988 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
989 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
990 &sa6_src.sin6_addr)) ||
991 (fport && inp->inp_fport != fport))
992 continue;
993
994
995 do_notify:
996 if (notify) {
997 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING)
998 continue;
999 socket_lock(inp->inp_socket, 1);
1000 (*notify)(inp, errno);
1001 (void)in_pcb_checkstate(inp, WNT_RELEASE, 1);
1002 socket_unlock(inp->inp_socket, 1);
1003 }
1004 }
1005 lck_rw_done(pcbinfo->mtx);
1006 }
1007
1008 /*
1009 * Lookup a PCB based on the local address and port.
1010 */
1011 struct inpcb *
1012 in6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
1013 struct inpcbinfo *pcbinfo;
1014 struct in6_addr *laddr;
1015 u_int lport_arg;
1016 int wild_okay;
1017 {
1018 struct inpcb *inp;
1019 int matchwild = 3, wildcard;
1020 u_short lport = lport_arg;
1021
1022 if (!wild_okay) {
1023 struct inpcbhead *head;
1024 /*
1025 * Look for an unconnected (wildcard foreign addr) PCB that
1026 * matches the local address and port we're looking for.
1027 */
1028 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
1029 pcbinfo->hashmask)];
1030 LIST_FOREACH(inp, head, inp_hash) {
1031 if ((inp->inp_vflag & INP_IPV6) == 0)
1032 continue;
1033 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1034 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
1035 inp->inp_lport == lport) {
1036 /*
1037 * Found.
1038 */
1039 return (inp);
1040 }
1041 }
1042 /*
1043 * Not found.
1044 */
1045 return (NULL);
1046 } else {
1047 struct inpcbporthead *porthash;
1048 struct inpcbport *phd;
1049 struct inpcb *match = NULL;
1050 /*
1051 * Best fit PCB lookup.
1052 *
1053 * First see if this local port is in use by looking on the
1054 * port hash list.
1055 */
1056 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
1057 pcbinfo->porthashmask)];
1058 LIST_FOREACH(phd, porthash, phd_hash) {
1059 if (phd->phd_port == lport)
1060 break;
1061 }
1062 if (phd != NULL) {
1063 /*
1064 * Port is in use by one or more PCBs. Look for best
1065 * fit.
1066 */
1067 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
1068 wildcard = 0;
1069 if ((inp->inp_vflag & INP_IPV6) == 0)
1070 continue;
1071 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
1072 wildcard++;
1073 if (!IN6_IS_ADDR_UNSPECIFIED(
1074 &inp->in6p_laddr)) {
1075 if (IN6_IS_ADDR_UNSPECIFIED(laddr))
1076 wildcard++;
1077 else if (!IN6_ARE_ADDR_EQUAL(
1078 &inp->in6p_laddr, laddr))
1079 continue;
1080 } else {
1081 if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
1082 wildcard++;
1083 }
1084 if (wildcard < matchwild) {
1085 match = inp;
1086 matchwild = wildcard;
1087 if (matchwild == 0) {
1088 break;
1089 }
1090 }
1091 }
1092 }
1093 return (match);
1094 }
1095 }
1096 #ifndef APPLE
1097 /* this is not used in Darwin */
1098 void
1099 in6_pcbpurgeif0(
1100 struct in6pcb *head,
1101 struct ifnet *ifp)
1102 {
1103 struct in6pcb *in6p;
1104 struct ip6_moptions *im6o;
1105 struct in6_multi_mship *imm, *nimm;
1106
1107 for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) {
1108 im6o = in6p->in6p_moptions;
1109 if ((in6p->inp_vflag & INP_IPV6) &&
1110 im6o) {
1111 /*
1112 * Unselect the outgoing interface if it is being
1113 * detached.
1114 */
1115 if (im6o->im6o_multicast_ifp == ifp)
1116 im6o->im6o_multicast_ifp = NULL;
1117
1118 /*
1119 * Drop multicast group membership if we joined
1120 * through the interface being detached.
1121 * XXX controversial - is it really legal for kernel
1122 * to force this?
1123 */
1124 for (imm = im6o->im6o_memberships.lh_first;
1125 imm != NULL; imm = nimm) {
1126 nimm = imm->i6mm_chain.le_next;
1127 if (imm->i6mm_maddr->in6m_ifp == ifp) {
1128 LIST_REMOVE(imm, i6mm_chain);
1129 in6_delmulti(imm->i6mm_maddr);
1130 FREE(imm, M_IPMADDR);
1131 }
1132 }
1133 }
1134 }
1135 }
1136 #endif
1137
1138 /*
1139 * Check for alternatives when higher level complains
1140 * about service problems. For now, invalidate cached
1141 * routing information. If the route was created dynamically
1142 * (by a redirect), time to try a default gateway again.
1143 */
1144 void
1145 in6_losing(in6p)
1146 struct inpcb *in6p;
1147 {
1148 struct rtentry *rt;
1149 struct rt_addrinfo info;
1150
1151 if ((rt = in6p->in6p_route.ro_rt) != NULL) {
1152 in6p->in6p_route.ro_rt = 0;
1153 bzero((caddr_t)&info, sizeof(info));
1154 info.rti_info[RTAX_DST] =
1155 (struct sockaddr *)&in6p->in6p_route.ro_dst;
1156 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1157 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1158 lck_mtx_lock(rt_mtx);
1159 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
1160 if (rt->rt_flags & RTF_DYNAMIC)
1161 (void)rtrequest_locked(RTM_DELETE, rt_key(rt),
1162 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
1163 (struct rtentry **)0);
1164 else
1165 /*
1166 * A new route can be allocated
1167 * the next time output is attempted.
1168 */
1169 rtfree_locked(rt);
1170 lck_mtx_unlock(rt_mtx);
1171 }
1172 }
1173
1174 /*
1175 * After a routing change, flush old routing
1176 * and allocate a (hopefully) better one.
1177 */
1178 void
1179 in6_rtchange(
1180 struct inpcb *inp,
1181 __unused int errno)
1182 {
1183 if (inp->in6p_route.ro_rt) {
1184 rtfree(inp->in6p_route.ro_rt);
1185 inp->in6p_route.ro_rt = 0;
1186 /*
1187 * A new route can be allocated the next time
1188 * output is attempted.
1189 */
1190 }
1191 }
1192
1193 /*
1194 * Lookup PCB in hash list.
1195 */
1196 struct inpcb *
1197 in6_pcblookup_hash(
1198 struct inpcbinfo *pcbinfo,
1199 struct in6_addr *faddr,
1200 u_int fport_arg,
1201 struct in6_addr *laddr,
1202 u_int lport_arg,
1203 int wildcard,
1204 __unused struct ifnet *ifp)
1205 {
1206 struct inpcbhead *head;
1207 struct inpcb *inp;
1208 u_short fport = fport_arg, lport = lport_arg;
1209 int faith;
1210
1211 #if defined(NFAITH) && NFAITH > 0
1212 faith = faithprefix(laddr);
1213 #else
1214 faith = 0;
1215 #endif
1216
1217 lck_rw_lock_shared(pcbinfo->mtx);
1218
1219 /*
1220 * First look for an exact match.
1221 */
1222 head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
1223 lport, fport,
1224 pcbinfo->hashmask)];
1225 LIST_FOREACH(inp, head, inp_hash) {
1226 if ((inp->inp_vflag & INP_IPV6) == 0)
1227 continue;
1228 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
1229 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
1230 inp->inp_fport == fport &&
1231 inp->inp_lport == lport) {
1232 /*
1233 * Found. Check if pcb is still valid
1234 */
1235 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1236 lck_rw_done(pcbinfo->mtx);
1237 return (inp);
1238 }
1239 else { /* it's there but dead, say it isn't found */
1240 lck_rw_done(pcbinfo->mtx);
1241 return(NULL);
1242 }
1243 }
1244 }
1245 if (wildcard) {
1246 struct inpcb *local_wild = NULL;
1247
1248 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
1249 pcbinfo->hashmask)];
1250 LIST_FOREACH(inp, head, inp_hash) {
1251 if ((inp->inp_vflag & INP_IPV6) == 0)
1252 continue;
1253 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1254 inp->inp_lport == lport) {
1255 if (faith && (inp->inp_flags & INP_FAITH) == 0)
1256 continue;
1257 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
1258 laddr)) {
1259 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1260 lck_rw_done(pcbinfo->mtx);
1261 return (inp);
1262 }
1263 else { /* it's there but dead, say it isn't found */
1264 lck_rw_done(pcbinfo->mtx);
1265 return(NULL);
1266 }
1267 }
1268 else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
1269 local_wild = inp;
1270 }
1271 }
1272 if (local_wild && in_pcb_checkstate(local_wild, WNT_ACQUIRE, 0) != WNT_STOPUSING) {
1273 lck_rw_done(pcbinfo->mtx);
1274 return (local_wild);
1275 }
1276 else {
1277 lck_rw_done(pcbinfo->mtx);
1278 return (NULL);
1279 }
1280 }
1281
1282 /*
1283 * Not found.
1284 */
1285 lck_rw_done(pcbinfo->mtx);
1286 return (NULL);
1287 }
1288
1289 void
1290 init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
1291 {
1292 struct ip6_hdr *ip;
1293
1294 ip = mtod(m, struct ip6_hdr *);
1295 bzero(sin6, sizeof(*sin6));
1296 sin6->sin6_len = sizeof(*sin6);
1297 sin6->sin6_family = AF_INET6;
1298 sin6->sin6_addr = ip->ip6_src;
1299 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1300 sin6->sin6_addr.s6_addr16[1] = 0;
1301 sin6->sin6_scope_id =
1302 (m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1303 ? m->m_pkthdr.rcvif->if_index : 0;
1304
1305 return;
1306 }