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