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