1 /* $NetBSD: in6_pcb.c,v 1.109 2009/05/12 22:22:46 elad Exp $ */
2 /* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 1982, 1986, 1991, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
64 #include <sys/cdefs.h>
65 __KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.109 2009/05/12 22:22:46 elad Exp $");
68 #include "opt_ipsec.h"
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/malloc.h>
74 #include <sys/protosw.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/ioctl.h>
78 #include <sys/errno.h>
81 #include <sys/kauth.h>
82 #include <sys/domain.h>
86 #include <net/route.h>
88 #include <netinet/in.h>
89 #include <netinet/in_var.h>
90 #include <netinet/in_systm.h>
91 #include <netinet/ip.h>
92 #include <netinet/in_pcb.h>
93 #include <netinet/ip6.h>
94 #include <netinet6/ip6_var.h>
95 #include <netinet6/in6_pcb.h>
96 #include <netinet6/scope6_var.h>
97 #include <netinet6/nd6.h>
102 #include <netinet6/ipsec.h>
103 #include <netkey/key.h>
107 #include <netipsec/ipsec.h>
108 #include <netipsec/ipsec6.h>
109 #include <netipsec/key.h>
110 #endif /* FAST_IPSEC */
112 const struct in6_addr zeroin6_addr
;
114 #define IN6PCBHASH_PORT(table, lport) \
115 &(table)->inpt_porthashtbl[ntohs(lport) & (table)->inpt_porthash]
116 #define IN6PCBHASH_BIND(table, laddr, lport) \
117 &(table)->inpt_bindhashtbl[ \
118 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \
119 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + ntohs(lport)) & \
120 (table)->inpt_bindhash]
121 #define IN6PCBHASH_CONNECT(table, faddr, fport, laddr, lport) \
122 &(table)->inpt_bindhashtbl[ \
123 ((((faddr)->s6_addr32[0] ^ (faddr)->s6_addr32[1] ^ \
124 (faddr)->s6_addr32[2] ^ (faddr)->s6_addr32[3]) + ntohs(fport)) + \
125 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \
126 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + \
127 ntohs(lport))) & (table)->inpt_bindhash]
129 int ip6_anonportmin
= IPV6PORT_ANONMIN
;
130 int ip6_anonportmax
= IPV6PORT_ANONMAX
;
131 int ip6_lowportmin
= IPV6PORT_RESERVEDMIN
;
132 int ip6_lowportmax
= IPV6PORT_RESERVEDMAX
;
134 static struct pool in6pcb_pool
;
137 in6pcb_poolinit(void)
140 pool_init(&in6pcb_pool
, sizeof(struct in6pcb
), 0, 0, 0, "in6pcbpl",
146 in6_pcbinit(struct inpcbtable
*table
, int bindhashsize
, int connecthashsize
)
148 static ONCE_DECL(control
);
150 in_pcbinit(table
, bindhashsize
, connecthashsize
);
151 table
->inpt_lastport
= (u_int16_t
)ip6_anonportmax
;
153 RUN_ONCE(&control
, in6pcb_poolinit
);
157 in6_pcballoc(struct socket
*so
, void *v
)
159 struct inpcbtable
*table
= v
;
162 #if defined(IPSEC) || defined(FAST_IPSEC)
167 in6p
= pool_get(&in6pcb_pool
, PR_NOWAIT
);
171 memset((void *)in6p
, 0, sizeof(*in6p
));
172 in6p
->in6p_af
= AF_INET6
;
173 in6p
->in6p_table
= table
;
174 in6p
->in6p_socket
= so
;
175 in6p
->in6p_hops
= -1; /* use kernel default */
176 in6p
->in6p_icmp6filt
= NULL
;
177 #if defined(IPSEC) || defined(FAST_IPSEC)
178 error
= ipsec_init_pcbpolicy(so
, &in6p
->in6p_sp
);
181 pool_put(&in6pcb_pool
, in6p
);
187 CIRCLEQ_INSERT_HEAD(&table
->inpt_queue
, (struct inpcb_hdr
*)in6p
,
189 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table
, in6p
->in6p_lport
),
190 &in6p
->in6p_head
, inph_lhash
);
191 in6_pcbstate(in6p
, IN6P_ATTACHED
);
194 in6p
->in6p_flags
|= IN6P_IPV6_V6ONLY
;
195 so
->so_pcb
= (void *)in6p
;
200 * Bind address from sin6 to in6p.
203 in6_pcbbind_addr(struct in6pcb
*in6p
, struct sockaddr_in6
*sin6
, struct lwp
*l
)
208 * We should check the family, but old programs
209 * incorrectly fail to intialize it.
211 if (sin6
->sin6_family
!= AF_INET6
)
212 return (EAFNOSUPPORT
);
215 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
216 return (EADDRNOTAVAIL
);
219 if ((error
= sa6_embedscope(sin6
, ip6_use_defzone
)) != 0)
222 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
223 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
225 if (sin6
->sin6_addr
.s6_addr32
[3]) {
226 struct sockaddr_in sin
;
228 memset(&sin
, 0, sizeof(sin
));
229 sin
.sin_len
= sizeof(sin
);
230 sin
.sin_family
= AF_INET
;
231 bcopy(&sin6
->sin6_addr
.s6_addr32
[3],
232 &sin
.sin_addr
, sizeof(sin
.sin_addr
));
233 if (ifa_ifwithaddr((struct sockaddr
*)&sin
) == 0)
234 return EADDRNOTAVAIL
;
236 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
)) {
237 struct ifaddr
*ia
= NULL
;
239 if ((in6p
->in6p_flags
& IN6P_FAITH
) == 0 &&
240 (ia
= ifa_ifwithaddr((struct sockaddr
*)sin6
)) == 0)
241 return (EADDRNOTAVAIL
);
244 * bind to an anycast address might accidentally
245 * cause sending a packet with an anycast source
246 * address, so we forbid it.
248 * We should allow to bind to a deprecated address,
249 * since the application dare to use it.
250 * But, can we assume that they are careful enough
251 * to check if the address is deprecated or not?
252 * Maybe, as a safeguard, we should have a setsockopt
253 * flag to control the bind(2) behavior against
254 * deprecated addresses (default: forbid bind(2)).
257 ((struct in6_ifaddr
*)ia
)->ia6_flags
&
258 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
|IN6_IFF_DETACHED
))
259 return (EADDRNOTAVAIL
);
263 in6p
->in6p_laddr
= sin6
->sin6_addr
;
270 * Bind port from sin6 to in6p.
273 in6_pcbbind_port(struct in6pcb
*in6p
, struct sockaddr_in6
*sin6
, struct lwp
*l
)
275 struct inpcbtable
*table
= in6p
->in6p_table
;
276 struct socket
*so
= in6p
->in6p_socket
;
277 int wild
= 0, reuseport
= (so
->so_options
& SO_REUSEPORT
);
280 if ((so
->so_options
& (SO_REUSEADDR
|SO_REUSEPORT
)) == 0 &&
281 ((so
->so_proto
->pr_flags
& PR_CONNREQUIRED
) == 0 ||
282 (so
->so_options
& SO_ACCEPTCONN
) == 0))
285 if (sin6
->sin6_port
!= 0) {
286 enum kauth_network_req req
;
288 #ifndef IPNOPRIVPORTS
289 if (ntohs(sin6
->sin6_port
) < IPV6PORT_RESERVED
)
290 req
= KAUTH_REQ_NETWORK_BIND_PRIVPORT
;
292 #endif /* IPNOPRIVPORTS */
293 req
= KAUTH_REQ_NETWORK_BIND_PORT
;
295 error
= kauth_authorize_network(l
->l_cred
, KAUTH_NETWORK_BIND
,
296 req
, so
, sin6
, NULL
);
301 if (IN6_IS_ADDR_MULTICAST(&sin6
->sin6_addr
)) {
303 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
304 * allow compepte duplication of binding if
305 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
306 * and a multicast address is bound on both
307 * new and duplicated sockets.
309 if (so
->so_options
& SO_REUSEADDR
)
310 reuseport
= SO_REUSEADDR
|SO_REUSEPORT
;
313 if (sin6
->sin6_port
!= 0) {
314 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
318 t
= in_pcblookup_port(table
,
319 *(struct in_addr
*)&sin6
->sin6_addr
.s6_addr32
[3],
320 sin6
->sin6_port
, wild
);
321 if (t
&& (reuseport
& t
->inp_socket
->so_options
) == 0)
324 return (EADDRNOTAVAIL
);
331 t
= in6_pcblookup_port(table
, &sin6
->sin6_addr
,
332 sin6
->sin6_port
, wild
);
333 if (t
&& (reuseport
& t
->in6p_socket
->so_options
) == 0)
338 if (sin6
->sin6_port
== 0) {
340 e
= in6_pcbsetport(sin6
, in6p
, l
);
344 in6p
->in6p_lport
= sin6
->sin6_port
;
345 in6_pcbstate(in6p
, IN6P_BOUND
);
348 LIST_REMOVE(&in6p
->in6p_head
, inph_lhash
);
349 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table
, in6p
->in6p_lport
),
350 &in6p
->in6p_head
, inph_lhash
);
356 in6_pcbbind(void *v
, struct mbuf
*nam
, struct lwp
*l
)
358 struct in6pcb
*in6p
= v
;
359 struct sockaddr_in6 lsin6
;
360 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)NULL
;
363 if (in6p
->in6p_af
!= AF_INET6
)
367 * If we already have a local port or a local address it means we're
370 if (in6p
->in6p_lport
|| !IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
))
374 /* We were provided a sockaddr_in6 to use. */
375 sin6
= mtod(nam
, struct sockaddr_in6
*);
376 if (nam
->m_len
!= sizeof(*sin6
))
379 /* We always bind to *something*, even if it's "anything". */
380 lsin6
= *((const struct sockaddr_in6
*)
381 in6p
->in6p_socket
->so_proto
->pr_domain
->dom_sa_any
);
386 error
= in6_pcbbind_addr(in6p
, sin6
, l
);
391 error
= in6_pcbbind_port(in6p
, sin6
, l
);
394 * Reset the address here to "any" so we don't "leak" the
397 in6p
->in6p_laddr
= in6addr_any
;
404 in6p
->in6p_flowinfo
= 0; /* XXX */
410 * Connect from a socket to a specified address.
411 * Both address and port must be specified in argument sin6.
412 * If don't have a local address for this socket yet,
416 in6_pcbconnect(void *v
, struct mbuf
*nam
, struct lwp
*l
)
419 struct in6pcb
*in6p
= v
;
420 struct in6_addr
*in6a
= NULL
;
421 struct sockaddr_in6
*sin6
= mtod(nam
, struct sockaddr_in6
*);
422 struct ifnet
*ifp
= NULL
; /* outgoing interface */
424 int scope_ambiguous
= 0;
426 struct in6_addr mapped
;
428 struct sockaddr_in6 tmp
;
430 (void)&in6a
; /* XXX fool gcc */
432 if (in6p
->in6p_af
!= AF_INET6
)
435 if (nam
->m_len
!= sizeof(*sin6
))
437 if (sin6
->sin6_family
!= AF_INET6
)
438 return (EAFNOSUPPORT
);
439 if (sin6
->sin6_port
== 0)
440 return (EADDRNOTAVAIL
);
442 if (sin6
->sin6_scope_id
== 0 && !ip6_use_defzone
)
444 if ((error
= sa6_embedscope(sin6
, ip6_use_defzone
)) != 0)
447 /* sanity check for mapped address case */
448 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
449 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
451 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
))
452 in6p
->in6p_laddr
.s6_addr16
[5] = htons(0xffff);
453 if (!IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_laddr
))
457 if (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_laddr
))
461 /* protect *sin6 from overwrites */
465 /* Source address selection. */
466 if (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_laddr
) &&
467 in6p
->in6p_laddr
.s6_addr32
[3] == 0) {
469 struct sockaddr_in sin
, *sinp
;
471 memset(&sin
, 0, sizeof(sin
));
472 sin
.sin_len
= sizeof(sin
);
473 sin
.sin_family
= AF_INET
;
474 memcpy(&sin
.sin_addr
, &sin6
->sin6_addr
.s6_addr32
[3],
475 sizeof(sin
.sin_addr
));
476 sinp
= in_selectsrc(&sin
, &in6p
->in6p_route
,
477 in6p
->in6p_socket
->so_options
, NULL
, &error
);
480 error
= EADDRNOTAVAIL
;
483 memset(&mapped
, 0, sizeof(mapped
));
484 mapped
.s6_addr16
[5] = htons(0xffff);
485 memcpy(&mapped
.s6_addr32
[3], &sinp
->sin_addr
, sizeof(sinp
->sin_addr
));
488 return EADDRNOTAVAIL
;
492 * XXX: in6_selectsrc might replace the bound local address
493 * with the address specified by setsockopt(IPV6_PKTINFO).
494 * Is it the intended behavior?
496 in6a
= in6_selectsrc(sin6
, in6p
->in6p_outputopts
,
499 &in6p
->in6p_laddr
, &ifp
, &error
);
500 if (ifp
&& scope_ambiguous
&&
501 (error
= in6_setscope(&sin6
->sin6_addr
, ifp
, NULL
)) != 0) {
507 error
= EADDRNOTAVAIL
;
511 if (ifp
== NULL
&& (rt
= rtcache_validate(&in6p
->in6p_route
)) != NULL
)
514 in6p
->in6p_ip6
.ip6_hlim
= (u_int8_t
)in6_selecthlim(in6p
, ifp
);
516 if (in6_pcblookup_connect(in6p
->in6p_table
, &sin6
->sin6_addr
,
518 IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) ? in6a
: &in6p
->in6p_laddr
,
519 in6p
->in6p_lport
, 0))
521 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) ||
522 (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_laddr
) &&
523 in6p
->in6p_laddr
.s6_addr32
[3] == 0))
525 if (in6p
->in6p_lport
== 0) {
526 error
= in6_pcbbind(in6p
, (struct mbuf
*)0, l
);
530 in6p
->in6p_laddr
= *in6a
;
532 in6p
->in6p_faddr
= sin6
->sin6_addr
;
533 in6p
->in6p_fport
= sin6
->sin6_port
;
534 in6_pcbstate(in6p
, IN6P_CONNECTED
);
535 in6p
->in6p_flowinfo
&= ~IPV6_FLOWLABEL_MASK
;
536 if (ip6_auto_flowlabel
)
537 in6p
->in6p_flowinfo
|=
538 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK
);
539 #if defined(IPSEC) || defined(FAST_IPSEC)
540 if (in6p
->in6p_socket
->so_type
== SOCK_STREAM
)
541 ipsec_pcbconn(in6p
->in6p_sp
);
547 in6_pcbdisconnect(struct in6pcb
*in6p
)
549 memset((void *)&in6p
->in6p_faddr
, 0, sizeof(in6p
->in6p_faddr
));
550 in6p
->in6p_fport
= 0;
551 in6_pcbstate(in6p
, IN6P_BOUND
);
552 in6p
->in6p_flowinfo
&= ~IPV6_FLOWLABEL_MASK
;
553 #if defined(IPSEC) || defined(FAST_IPSEC)
554 ipsec_pcbdisconn(in6p
->in6p_sp
);
556 if (in6p
->in6p_socket
->so_state
& SS_NOFDREF
)
561 in6_pcbdetach(struct in6pcb
*in6p
)
563 struct socket
*so
= in6p
->in6p_socket
;
566 if (in6p
->in6p_af
!= AF_INET6
)
569 #if defined(IPSEC) || defined(FAST_IPSEC)
570 ipsec6_delete_pcbpolicy(in6p
);
573 if (in6p
->in6p_options
)
574 m_freem(in6p
->in6p_options
);
575 if (in6p
->in6p_outputopts
!= NULL
) {
576 ip6_clearpktopts(in6p
->in6p_outputopts
, -1);
577 free(in6p
->in6p_outputopts
, M_IP6OPT
);
579 rtcache_free(&in6p
->in6p_route
);
580 ip6_freemoptions(in6p
->in6p_moptions
);
582 in6_pcbstate(in6p
, IN6P_ATTACHED
);
583 LIST_REMOVE(&in6p
->in6p_head
, inph_lhash
);
584 CIRCLEQ_REMOVE(&in6p
->in6p_table
->inpt_queue
, &in6p
->in6p_head
,
586 pool_put(&in6pcb_pool
, in6p
);
588 sofree(so
); /* drops the socket's lock */
589 mutex_enter(softnet_lock
); /* reacquire it */
593 in6_setsockaddr(struct in6pcb
*in6p
, struct mbuf
*nam
)
595 struct sockaddr_in6
*sin6
;
597 if (in6p
->in6p_af
!= AF_INET6
)
600 nam
->m_len
= sizeof(*sin6
);
601 sin6
= mtod(nam
, struct sockaddr_in6
*);
602 sockaddr_in6_init(sin6
, &in6p
->in6p_laddr
, in6p
->in6p_lport
, 0, 0);
603 (void)sa6_recoverscope(sin6
); /* XXX: should catch errors */
607 in6_setpeeraddr(struct in6pcb
*in6p
, struct mbuf
*nam
)
609 struct sockaddr_in6
*sin6
;
611 if (in6p
->in6p_af
!= AF_INET6
)
614 nam
->m_len
= sizeof(*sin6
);
615 sin6
= mtod(nam
, struct sockaddr_in6
*);
616 sockaddr_in6_init(sin6
, &in6p
->in6p_faddr
, in6p
->in6p_fport
, 0, 0);
617 (void)sa6_recoverscope(sin6
); /* XXX: should catch errors */
621 * Pass some notification to all connections of a protocol
622 * associated with address dst. The local address and/or port numbers
623 * may be specified to limit the search. The "usual action" will be
624 * taken, depending on the ctlinput cmd. The caller must filter any
625 * cmds that are uninteresting (e.g., no error in the map).
626 * Call the protocol specific routine (if any) to report
627 * any errors for each matching socket.
629 * Must be called at splsoftnet.
631 * Note: src (4th arg) carries the flowlabel value on the original IPv6
632 * header, in sin6_flowinfo member.
635 in6_pcbnotify(struct inpcbtable
*table
, const struct sockaddr
*dst
,
636 u_int fport_arg
, const struct sockaddr
*src
, u_int lport_arg
, int cmd
,
637 void *cmdarg
, void (*notify
)(struct in6pcb
*, int))
640 struct in6pcb
*in6p
, *nin6p
;
641 struct sockaddr_in6 sa6_src
;
642 const struct sockaddr_in6
*sa6_dst
;
643 u_int16_t fport
= fport_arg
, lport
= lport_arg
;
648 if ((unsigned)cmd
>= PRC_NCMDS
|| dst
->sa_family
!= AF_INET6
)
651 sa6_dst
= (const struct sockaddr_in6
*)dst
;
652 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst
->sin6_addr
))
656 * note that src can be NULL when we get notify by local fragmentation.
658 sa6_src
= (src
== NULL
) ? sa6_any
: *(const struct sockaddr_in6
*)src
;
659 flowinfo
= sa6_src
.sin6_flowinfo
;
662 * Redirects go to all references to the destination,
663 * and use in6_rtchange to invalidate the route cache.
664 * Dead host indications: also use in6_rtchange to invalidate
665 * the cache, and deliver the error to all the sockets.
666 * Otherwise, if we have knowledge of the local port and address,
667 * deliver only to that socket.
669 if (PRC_IS_REDIRECT(cmd
) || cmd
== PRC_HOSTDEAD
) {
672 memset((void *)&sa6_src
.sin6_addr
, 0, sizeof(sa6_src
.sin6_addr
));
674 if (cmd
!= PRC_HOSTDEAD
)
675 notify
= in6_rtchange
;
678 errno
= inet6ctlerrmap
[cmd
];
679 for (in6p
= (struct in6pcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
680 in6p
!= (void *)&table
->inpt_queue
;
682 nin6p
= (struct in6pcb
*)CIRCLEQ_NEXT(in6p
, in6p_queue
);
684 if (in6p
->in6p_af
!= AF_INET6
)
688 * Under the following condition, notify of redirects
689 * to the pcb, without making address matches against inpcb.
690 * - redirect notification is arrived.
691 * - the inpcb is unconnected.
692 * - the inpcb is caching !RTF_HOST routing entry.
693 * - the ICMPv6 notification is from the gateway cached in the
694 * inpcb. i.e. ICMPv6 notification is from nexthop gateway
695 * the inpcb used very recently.
697 * This is to improve interaction between netbsd/openbsd
698 * redirect handling code, and inpcb route cache code.
699 * without the clause, !RTF_HOST routing entry (which carries
700 * gateway used by inpcb right before the ICMPv6 redirect)
701 * will be cached forever in unconnected inpcb.
703 * There still is a question regarding to what is TRT:
704 * - On bsdi/freebsd, RTF_HOST (cloned) routing entry will be
705 * generated on packet output. inpcb will always cache
706 * RTF_HOST routing entry so there's no need for the clause
707 * (ICMPv6 redirect will update RTF_HOST routing entry,
708 * and inpcb is caching it already).
709 * However, bsdi/freebsd are vulnerable to local DoS attacks
710 * due to the cloned routing entries.
711 * - Specwise, "destination cache" is mentioned in RFC2461.
712 * Jinmei says that it implies bsdi/freebsd behavior, itojun
713 * is not really convinced.
714 * - Having hiwat/lowat on # of cloned host route (redirect/
715 * pmtud) may be a good idea. netbsd/openbsd has it. see
716 * icmp6_mtudisc_update().
718 if ((PRC_IS_REDIRECT(cmd
) || cmd
== PRC_HOSTDEAD
) &&
719 IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
720 (rt
= rtcache_validate(&in6p
->in6p_route
)) != NULL
&&
721 !(rt
->rt_flags
& RTF_HOST
)) {
722 const struct sockaddr_in6
*dst6
;
724 dst6
= (const struct sockaddr_in6
*)
725 rtcache_getdst(&in6p
->in6p_route
);
728 else if (IN6_ARE_ADDR_EQUAL(&dst6
->sin6_addr
,
729 &sa6_dst
->sin6_addr
))
734 * If the error designates a new path MTU for a destination
735 * and the application (associated with this socket) wanted to
736 * know the value, notify. Note that we notify for all
737 * disconnected sockets if the corresponding application
738 * wanted. This is because some UDP applications keep sending
739 * sockets disconnected.
740 * XXX: should we avoid to notify the value to TCP sockets?
742 if (cmd
== PRC_MSGSIZE
&& (in6p
->in6p_flags
& IN6P_MTU
) != 0 &&
743 (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) ||
744 IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &sa6_dst
->sin6_addr
))) {
745 ip6_notify_pmtu(in6p
, (const struct sockaddr_in6
*)dst
,
746 (u_int32_t
*)cmdarg
);
750 * Detect if we should notify the error. If no source and
751 * destination ports are specified, but non-zero flowinfo and
752 * local address match, notify the error. This is the case
753 * when the error is delivered with an encrypted buffer
754 * by ESP. Otherwise, just compare addresses and ports
757 if (lport
== 0 && fport
== 0 && flowinfo
&&
758 in6p
->in6p_socket
!= NULL
&&
759 flowinfo
== (in6p
->in6p_flowinfo
& IPV6_FLOWLABEL_MASK
) &&
760 IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &sa6_src
.sin6_addr
))
762 else if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
763 &sa6_dst
->sin6_addr
) ||
764 in6p
->in6p_socket
== 0 ||
765 (lport
&& in6p
->in6p_lport
!= lport
) ||
766 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src
.sin6_addr
) &&
767 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
,
768 &sa6_src
.sin6_addr
)) ||
769 (fport
&& in6p
->in6p_fport
!= fport
))
774 (*notify
)(in6p
, errno
);
781 in6_pcbpurgeif0(struct inpcbtable
*table
, struct ifnet
*ifp
)
783 struct in6pcb
*in6p
, *nin6p
;
784 struct ip6_moptions
*im6o
;
785 struct in6_multi_mship
*imm
, *nimm
;
787 for (in6p
= (struct in6pcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
788 in6p
!= (void *)&table
->inpt_queue
;
790 nin6p
= (struct in6pcb
*)CIRCLEQ_NEXT(in6p
, in6p_queue
);
791 if (in6p
->in6p_af
!= AF_INET6
)
794 im6o
= in6p
->in6p_moptions
;
797 * Unselect the outgoing interface if it is being
800 if (im6o
->im6o_multicast_ifp
== ifp
)
801 im6o
->im6o_multicast_ifp
= NULL
;
804 * Drop multicast group membership if we joined
805 * through the interface being detached.
806 * XXX controversial - is it really legal for kernel
809 for (imm
= im6o
->im6o_memberships
.lh_first
;
810 imm
!= NULL
; imm
= nimm
) {
811 nimm
= imm
->i6mm_chain
.le_next
;
812 if (imm
->i6mm_maddr
->in6m_ifp
== ifp
) {
813 LIST_REMOVE(imm
, i6mm_chain
);
822 in6_pcbpurgeif(struct inpcbtable
*table
, struct ifnet
*ifp
)
825 struct in6pcb
*in6p
, *nin6p
;
827 for (in6p
= (struct in6pcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
828 in6p
!= (void *)&table
->inpt_queue
;
830 nin6p
= (struct in6pcb
*)CIRCLEQ_NEXT(in6p
, in6p_queue
);
831 if (in6p
->in6p_af
!= AF_INET6
)
833 if ((rt
= rtcache_validate(&in6p
->in6p_route
)) != NULL
&&
835 in6_rtchange(in6p
, 0);
840 * Check for alternatives when higher level complains
841 * about service problems. For now, invalidate cached
842 * routing information. If the route was created dynamically
843 * (by a redirect), time to try a default gateway again.
846 in6_losing(struct in6pcb
*in6p
)
849 struct rt_addrinfo info
;
851 if (in6p
->in6p_af
!= AF_INET6
)
854 if ((rt
= rtcache_validate(&in6p
->in6p_route
)) == NULL
)
857 memset(&info
, 0, sizeof(info
));
858 info
.rti_info
[RTAX_DST
] = rtcache_getdst(&in6p
->in6p_route
);
859 info
.rti_info
[RTAX_GATEWAY
] = rt
->rt_gateway
;
860 info
.rti_info
[RTAX_NETMASK
] = rt_mask(rt
);
861 rt_missmsg(RTM_LOSING
, &info
, rt
->rt_flags
, 0);
862 if (rt
->rt_flags
& RTF_DYNAMIC
) {
863 (void)rtrequest(RTM_DELETE
, rt_getkey(rt
),
864 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
, NULL
);
867 * A new route can be allocated
868 * the next time output is attempted.
870 rtcache_free(&in6p
->in6p_route
);
874 * After a routing change, flush old routing. A new route can be
875 * allocated the next time output is attempted.
878 in6_rtchange(struct in6pcb
*in6p
, int errno
)
880 if (in6p
->in6p_af
!= AF_INET6
)
883 rtcache_free(&in6p
->in6p_route
);
885 * A new route can be allocated the next time
886 * output is attempted.
891 in6_pcblookup_port(struct inpcbtable
*table
, struct in6_addr
*laddr6
,
892 u_int lport_arg
, int lookup_wildcard
)
894 struct inpcbhead
*head
;
895 struct inpcb_hdr
*inph
;
896 struct in6pcb
*in6p
, *match
= 0;
897 int matchwild
= 3, wildcard
;
898 u_int16_t lport
= lport_arg
;
900 head
= IN6PCBHASH_PORT(table
, lport
);
901 LIST_FOREACH(inph
, head
, inph_lhash
) {
902 in6p
= (struct in6pcb
*)inph
;
903 if (in6p
->in6p_af
!= AF_INET6
)
906 if (in6p
->in6p_lport
!= lport
)
909 if (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_faddr
)) {
910 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
913 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
))
915 if (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_laddr
)) {
916 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
918 if (!IN6_IS_ADDR_V4MAPPED(laddr6
))
921 /* duplicate of IPv4 logic */
923 if (IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_faddr
) &&
924 in6p
->in6p_faddr
.s6_addr32
[3])
926 if (!in6p
->in6p_laddr
.s6_addr32
[3]) {
927 if (laddr6
->s6_addr32
[3])
930 if (!laddr6
->s6_addr32
[3])
933 if (in6p
->in6p_laddr
.s6_addr32
[3] !=
934 laddr6
->s6_addr32
[3])
938 } else if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
)) {
939 if (IN6_IS_ADDR_V4MAPPED(laddr6
)) {
940 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
943 if (!IN6_IS_ADDR_UNSPECIFIED(laddr6
))
946 if (IN6_IS_ADDR_V4MAPPED(laddr6
)) {
947 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
950 if (IN6_IS_ADDR_UNSPECIFIED(laddr6
))
953 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
,
958 if (wildcard
&& !lookup_wildcard
)
960 if (wildcard
< matchwild
) {
962 matchwild
= wildcard
;
972 * WARNING: return value (rtentry) could be IPv4 one if in6pcb is connected to
973 * IPv4 mapped address.
976 in6_pcbrtentry(struct in6pcb
*in6p
)
981 const struct sockaddr
*sa
;
982 const struct sockaddr_in6
*sa6
;
984 const struct sockaddr_in
*sa4
;
988 ro
= &in6p
->in6p_route
;
990 if (in6p
->in6p_af
!= AF_INET6
)
993 cdst
.sa
= rtcache_getdst(ro
);
997 else if (cdst
.sa
->sa_family
== AF_INET
) {
998 KASSERT(IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_faddr
));
999 if (cdst
.sa4
->sin_addr
.s_addr
!= in6p
->in6p_faddr
.s6_addr32
[3])
1004 if (!IN6_ARE_ADDR_EQUAL(&cdst
.sa6
->sin6_addr
,
1008 if ((rt
= rtcache_validate(ro
)) == NULL
)
1009 rt
= rtcache_update(ro
, 1);
1011 if (rt
== NULL
&& IN6_IS_ADDR_V4MAPPED(&in6p
->in6p_faddr
)) {
1013 struct sockaddr dst
;
1014 struct sockaddr_in dst4
;
1016 struct in_addr addr
;
1018 addr
.s_addr
= in6p
->in6p_faddr
.s6_addr32
[3];
1020 sockaddr_in_init(&u
.dst4
, &addr
, 0);
1021 rtcache_setdst(ro
, &u
.dst
);
1023 rt
= rtcache_init(ro
);
1026 if (rt
== NULL
&& !IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
1028 struct sockaddr dst
;
1029 struct sockaddr_in6 dst6
;
1032 sockaddr_in6_init(&u
.dst6
, &in6p
->in6p_faddr
, 0, 0, 0);
1033 rtcache_setdst(ro
, &u
.dst
);
1035 rt
= rtcache_init(ro
);
1041 in6_pcblookup_connect(struct inpcbtable
*table
, const struct in6_addr
*faddr6
,
1042 u_int fport_arg
, const struct in6_addr
*laddr6
, u_int lport_arg
,
1045 struct inpcbhead
*head
;
1046 struct inpcb_hdr
*inph
;
1047 struct in6pcb
*in6p
;
1048 u_int16_t fport
= fport_arg
, lport
= lport_arg
;
1050 head
= IN6PCBHASH_CONNECT(table
, faddr6
, fport
, laddr6
, lport
);
1051 LIST_FOREACH(inph
, head
, inph_hash
) {
1052 in6p
= (struct in6pcb
*)inph
;
1053 if (in6p
->in6p_af
!= AF_INET6
)
1056 /* find exact match on both source and dest */
1057 if (in6p
->in6p_fport
!= fport
)
1059 if (in6p
->in6p_lport
!= lport
)
1061 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
))
1063 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, faddr6
))
1065 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
))
1067 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, laddr6
))
1069 if ((IN6_IS_ADDR_V4MAPPED(laddr6
) ||
1070 IN6_IS_ADDR_V4MAPPED(faddr6
)) &&
1071 (in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
))
1079 in6_pcblookup_bind(struct inpcbtable
*table
, const struct in6_addr
*laddr6
,
1080 u_int lport_arg
, int faith
)
1082 struct inpcbhead
*head
;
1083 struct inpcb_hdr
*inph
;
1084 struct in6pcb
*in6p
;
1085 u_int16_t lport
= lport_arg
;
1087 struct in6_addr zero_mapped
;
1090 head
= IN6PCBHASH_BIND(table
, laddr6
, lport
);
1091 LIST_FOREACH(inph
, head
, inph_hash
) {
1092 in6p
= (struct in6pcb
*)inph
;
1093 if (in6p
->in6p_af
!= AF_INET6
)
1096 if (faith
&& (in6p
->in6p_flags
& IN6P_FAITH
) == 0)
1098 if (in6p
->in6p_fport
!= 0)
1100 if (in6p
->in6p_lport
!= lport
)
1102 if (IN6_IS_ADDR_V4MAPPED(laddr6
) &&
1103 (in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
1105 if (IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, laddr6
))
1109 if (IN6_IS_ADDR_V4MAPPED(laddr6
)) {
1110 memset(&zero_mapped
, 0, sizeof(zero_mapped
));
1111 zero_mapped
.s6_addr16
[5] = 0xffff;
1112 head
= IN6PCBHASH_BIND(table
, &zero_mapped
, lport
);
1113 LIST_FOREACH(inph
, head
, inph_hash
) {
1114 in6p
= (struct in6pcb
*)inph
;
1115 if (in6p
->in6p_af
!= AF_INET6
)
1118 if (faith
&& (in6p
->in6p_flags
& IN6P_FAITH
) == 0)
1120 if (in6p
->in6p_fport
!= 0)
1122 if (in6p
->in6p_lport
!= lport
)
1124 if ((in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
1126 if (IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &zero_mapped
))
1131 head
= IN6PCBHASH_BIND(table
, &zeroin6_addr
, lport
);
1132 LIST_FOREACH(inph
, head
, inph_hash
) {
1133 in6p
= (struct in6pcb
*)inph
;
1134 if (in6p
->in6p_af
!= AF_INET6
)
1137 if (faith
&& (in6p
->in6p_flags
& IN6P_FAITH
) == 0)
1139 if (in6p
->in6p_fport
!= 0)
1141 if (in6p
->in6p_lport
!= lport
)
1143 if (IN6_IS_ADDR_V4MAPPED(laddr6
) &&
1144 (in6p
->in6p_flags
& IN6P_IPV6_V6ONLY
) != 0)
1146 if (IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &zeroin6_addr
))
1152 inph
= &in6p
->in6p_head
;
1153 if (inph
!= LIST_FIRST(head
)) {
1154 LIST_REMOVE(inph
, inph_hash
);
1155 LIST_INSERT_HEAD(head
, inph
, inph_hash
);
1161 in6_pcbstate(struct in6pcb
*in6p
, int state
)
1164 if (in6p
->in6p_af
!= AF_INET6
)
1167 if (in6p
->in6p_state
> IN6P_ATTACHED
)
1168 LIST_REMOVE(&in6p
->in6p_head
, inph_hash
);
1172 LIST_INSERT_HEAD(IN6PCBHASH_BIND(in6p
->in6p_table
,
1173 &in6p
->in6p_laddr
, in6p
->in6p_lport
), &in6p
->in6p_head
,
1176 case IN6P_CONNECTED
:
1177 LIST_INSERT_HEAD(IN6PCBHASH_CONNECT(in6p
->in6p_table
,
1178 &in6p
->in6p_faddr
, in6p
->in6p_fport
,
1179 &in6p
->in6p_laddr
, in6p
->in6p_lport
), &in6p
->in6p_head
,
1184 in6p
->in6p_state
= state
;