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