1 /* $NetBSD: icmp6.c,v 1.154 2009/10/12 22:32:23 christos Exp $ */
2 /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei 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, 1988, 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 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
64 #include <sys/cdefs.h>
65 __KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.154 2009/10/12 22:32:23 christos 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>
78 #include <sys/kernel.h>
79 #include <sys/syslog.h>
80 #include <sys/domain.h>
81 #include <sys/sysctl.h>
84 #include <net/route.h>
85 #include <net/if_dl.h>
86 #include <net/if_types.h>
88 #include <netinet/in.h>
89 #include <netinet/in_var.h>
90 #include <netinet/ip6.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/ip6_private.h>
93 #include <netinet/icmp6.h>
94 #include <netinet6/icmp6_private.h>
95 #include <netinet6/mld6_var.h>
96 #include <netinet6/in6_pcb.h>
97 #include <netinet6/nd6.h>
98 #include <netinet6/in6_ifattach.h>
99 #include <netinet6/ip6protosw.h>
100 #include <netinet6/scope6_var.h>
103 #include <netinet6/ipsec.h>
104 #include <netkey/key.h>
108 #include <netipsec/ipsec.h>
109 #include <netipsec/key.h>
114 #if defined(NFAITH) && 0 < NFAITH
115 #include <net/if_faith.h>
118 #include <net/net_osdep.h>
120 extern struct domain inet6domain
;
122 percpu_t
*icmp6stat_percpu
;
124 extern struct inpcbtable raw6cbtable
;
125 extern int icmp6errppslim
;
126 static int icmp6errpps_count
= 0;
127 static struct timeval icmp6errppslim_last
;
128 extern int icmp6_nodeinfo
;
131 * List of callbacks to notify when Path MTU changes are made.
133 struct icmp6_mtudisc_callback
{
134 LIST_ENTRY(icmp6_mtudisc_callback
) mc_list
;
135 void (*mc_func
)(struct in6_addr
*);
138 LIST_HEAD(, icmp6_mtudisc_callback
) icmp6_mtudisc_callbacks
=
139 LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks
);
141 static struct rttimer_queue
*icmp6_mtudisc_timeout_q
= NULL
;
142 extern int pmtu_expire
;
144 /* XXX do these values make any sense? */
145 static int icmp6_mtudisc_hiwat
= 1280;
146 static int icmp6_mtudisc_lowat
= 256;
149 * keep track of # of redirect routes.
151 static struct rttimer_queue
*icmp6_redirect_timeout_q
= NULL
;
153 /* XXX experimental, turned off */
154 static int icmp6_redirect_hiwat
= -1;
155 static int icmp6_redirect_lowat
= -1;
157 static void icmp6_errcount(u_int
, int, int);
158 static int icmp6_rip6_input(struct mbuf
**, int);
159 static int icmp6_ratelimit(const struct in6_addr
*, const int, const int);
160 static const char *icmp6_redirect_diag(struct in6_addr
*,
161 struct in6_addr
*, struct in6_addr
*);
162 static struct mbuf
*ni6_input(struct mbuf
*, int);
163 static struct mbuf
*ni6_nametodns(const char *, int, int);
164 static int ni6_dnsmatch(const char *, int, const char *, int);
165 static int ni6_addrs(struct icmp6_nodeinfo
*, struct mbuf
*,
166 struct ifnet
**, char *);
167 static int ni6_store_addrs(struct icmp6_nodeinfo
*, struct icmp6_nodeinfo
*,
168 struct ifnet
*, int);
169 static int icmp6_notify_error(struct mbuf
*, int, int, int);
170 static struct rtentry
*icmp6_mtudisc_clone(struct sockaddr
*);
171 static void icmp6_mtudisc_timeout(struct rtentry
*, struct rttimer
*);
172 static void icmp6_redirect_timeout(struct rtentry
*, struct rttimer
*);
173 static void sysctl_net_inet6_icmp6_setup(struct sysctllog
**);
180 sysctl_net_inet6_icmp6_setup(NULL
);
182 icmp6_mtudisc_timeout_q
= rt_timer_queue_create(pmtu_expire
);
183 icmp6_redirect_timeout_q
= rt_timer_queue_create(icmp6_redirtimeout
);
185 icmp6stat_percpu
= percpu_alloc(sizeof(uint64_t) * ICMP6_NSTATS
);
189 icmp6_errcount(u_int base
, int type
, int code
)
192 case ICMP6_DST_UNREACH
:
194 case ICMP6_DST_UNREACH_NOROUTE
:
195 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_DST_UNREACH_NOROUTE
);
197 case ICMP6_DST_UNREACH_ADMIN
:
198 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_DST_UNREACH_ADMIN
);
200 case ICMP6_DST_UNREACH_BEYONDSCOPE
:
202 ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE
);
204 case ICMP6_DST_UNREACH_ADDR
:
205 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_DST_UNREACH_ADDR
);
207 case ICMP6_DST_UNREACH_NOPORT
:
208 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_DST_UNREACH_NOPORT
);
212 case ICMP6_PACKET_TOO_BIG
:
213 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_PACKET_TOO_BIG
);
215 case ICMP6_TIME_EXCEEDED
:
217 case ICMP6_TIME_EXCEED_TRANSIT
:
218 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT
);
220 case ICMP6_TIME_EXCEED_REASSEMBLY
:
222 ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY
);
226 case ICMP6_PARAM_PROB
:
228 case ICMP6_PARAMPROB_HEADER
:
229 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_PARAMPROB_HEADER
);
231 case ICMP6_PARAMPROB_NEXTHEADER
:
233 ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER
);
235 case ICMP6_PARAMPROB_OPTION
:
236 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_PARAMPROB_OPTION
);
241 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_REDIRECT
);
244 ICMP6_STATINC(base
+ ICMP6_ERRSTAT_UNKNOWN
);
248 * Register a Path MTU Discovery callback.
251 icmp6_mtudisc_callback_register(void (*func
)(struct in6_addr
*))
253 struct icmp6_mtudisc_callback
*mc
;
255 for (mc
= LIST_FIRST(&icmp6_mtudisc_callbacks
); mc
!= NULL
;
256 mc
= LIST_NEXT(mc
, mc_list
)) {
257 if (mc
->mc_func
== func
)
261 mc
= malloc(sizeof(*mc
), M_PCB
, M_NOWAIT
);
263 panic("icmp6_mtudisc_callback_register");
266 LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks
, mc
, mc_list
);
270 * A wrapper function for icmp6_error() necessary when the erroneous packet
271 * may not contain enough scope zone information.
274 icmp6_error2(struct mbuf
*m
, int type
, int code
, int param
,
282 if (m
->m_len
< sizeof(struct ip6_hdr
)) {
283 m
= m_pullup(m
, sizeof(struct ip6_hdr
));
288 ip6
= mtod(m
, struct ip6_hdr
*);
290 if (in6_setscope(&ip6
->ip6_src
, ifp
, NULL
) != 0)
292 if (in6_setscope(&ip6
->ip6_dst
, ifp
, NULL
) != 0)
295 icmp6_error(m
, type
, code
, param
);
299 * Generate an error packet of type error in response to bad IP6 packet.
302 icmp6_error(struct mbuf
*m
, int type
, int code
, int param
)
304 struct ip6_hdr
*oip6
, *nip6
;
305 struct icmp6_hdr
*icmp6
;
310 ICMP6_STATINC(ICMP6_STAT_ERROR
);
312 /* count per-type-code statistics */
313 icmp6_errcount(ICMP6_STAT_OUTERRHIST
, type
, code
);
315 if (m
->m_flags
& M_DECRYPTED
) {
316 ICMP6_STATINC(ICMP6_STAT_CANTERROR
);
320 if (M_UNWRITABLE(m
, sizeof(struct ip6_hdr
)) &&
321 (m
= m_pullup(m
, sizeof(struct ip6_hdr
))) == NULL
)
323 oip6
= mtod(m
, struct ip6_hdr
*);
326 * If the destination address of the erroneous packet is a multicast
327 * address, or the packet was sent using link-layer multicast,
328 * we should basically suppress sending an error (RFC 2463, Section
330 * We have two exceptions (the item e.2 in that section):
331 * - the Pakcet Too Big message can be sent for path MTU discovery.
332 * - the Parameter Problem Message that can be allowed an icmp6 error
333 * in the option type field. This check has been done in
334 * ip6_unknown_opt(), so we can just check the type and code.
336 if ((m
->m_flags
& (M_BCAST
|M_MCAST
) ||
337 IN6_IS_ADDR_MULTICAST(&oip6
->ip6_dst
)) &&
338 (type
!= ICMP6_PACKET_TOO_BIG
&&
339 (type
!= ICMP6_PARAM_PROB
||
340 code
!= ICMP6_PARAMPROB_OPTION
)))
344 * RFC 2463, 2.4 (e.5): source address check.
345 * XXX: the case of anycast source?
347 if (IN6_IS_ADDR_UNSPECIFIED(&oip6
->ip6_src
) ||
348 IN6_IS_ADDR_MULTICAST(&oip6
->ip6_src
))
352 * If we are about to send ICMPv6 against ICMPv6 error/redirect,
356 off
= ip6_lasthdr(m
, 0, IPPROTO_IPV6
, &nxt
);
357 if (off
>= 0 && nxt
== IPPROTO_ICMPV6
) {
358 struct icmp6_hdr
*icp
;
360 IP6_EXTHDR_GET(icp
, struct icmp6_hdr
*, m
, off
,
363 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
366 if (icp
->icmp6_type
< ICMP6_ECHO_REQUEST
||
367 icp
->icmp6_type
== ND_REDIRECT
) {
370 * Special case: for redirect (which is
371 * informational) we must not send icmp6 error.
373 ICMP6_STATINC(ICMP6_STAT_CANTERROR
);
376 /* ICMPv6 informational - send the error */
379 #if 0 /* controversial */
380 else if (off
>= 0 && nxt
== IPPROTO_ESP
) {
382 * It could be ICMPv6 error inside ESP. Take a safer side,
385 ICMP6_STATINC(ICMP6_STAT_CANTERROR
);
390 /* non-ICMPv6 - send the error */
393 oip6
= mtod(m
, struct ip6_hdr
*); /* adjust pointer */
395 /* Finally, do rate limitation check. */
396 if (icmp6_ratelimit(&oip6
->ip6_src
, type
, code
)) {
397 ICMP6_STATINC(ICMP6_STAT_TOOFREQ
);
402 * OK, ICMP6 can be generated.
405 if (m
->m_pkthdr
.len
>= ICMPV6_PLD_MAXLEN
)
406 m_adj(m
, ICMPV6_PLD_MAXLEN
- m
->m_pkthdr
.len
);
408 preplen
= sizeof(struct ip6_hdr
) + sizeof(struct icmp6_hdr
);
409 M_PREPEND(m
, preplen
, M_DONTWAIT
);
410 if (m
&& M_UNWRITABLE(m
, preplen
))
411 m
= m_pullup(m
, preplen
);
413 nd6log((LOG_DEBUG
, "ENOBUFS in icmp6_error %d\n", __LINE__
));
417 nip6
= mtod(m
, struct ip6_hdr
*);
418 nip6
->ip6_src
= oip6
->ip6_src
;
419 nip6
->ip6_dst
= oip6
->ip6_dst
;
421 in6_clearscope(&oip6
->ip6_src
);
422 in6_clearscope(&oip6
->ip6_dst
);
424 icmp6
= (struct icmp6_hdr
*)(nip6
+ 1);
425 icmp6
->icmp6_type
= type
;
426 icmp6
->icmp6_code
= code
;
427 icmp6
->icmp6_pptr
= htonl((u_int32_t
)param
);
430 * icmp6_reflect() is designed to be in the input path.
431 * icmp6_error() can be called from both input and output path,
432 * and if we are in output path rcvif could contain bogus value.
433 * clear m->m_pkthdr.rcvif for safety, we should have enough scope
434 * information in ip header (nip6).
436 m
->m_pkthdr
.rcvif
= NULL
;
438 ICMP6_STATINC(ICMP6_STAT_OUTHIST
+ type
);
439 icmp6_reflect(m
, sizeof(struct ip6_hdr
)); /* header order: IPv6 - ICMPv6 */
445 * If we can't tell whether or not we can generate ICMP6, free it.
451 * Process a received ICMP6 message.
454 icmp6_input(struct mbuf
**mp
, int *offp
, int proto
)
456 struct mbuf
*m
= *mp
, *n
;
457 struct ip6_hdr
*ip6
, *nip6
;
458 struct icmp6_hdr
*icmp6
, *nicmp6
;
460 int icmp6len
= m
->m_pkthdr
.len
- *offp
;
461 int code
, sum
, noff
, i
;
463 #define ICMP6_MAXLEN (sizeof(*nip6) + sizeof(*nicmp6) + 4)
464 KASSERT(ICMP6_MAXLEN
< MCLBYTES
);
465 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_msg
);
468 * Locate icmp6 structure in mbuf, and check
469 * that not corrupted and of at least minimum length
472 if (icmp6len
< sizeof(struct icmp6_hdr
)) {
473 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
474 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_error
);
478 i
= off
+ sizeof(*icmp6
);
479 if ((m
->m_len
< i
|| M_READONLY(m
)) && (m
= m_pullup(m
, i
)) == 0) {
480 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
481 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_error
);
484 ip6
= mtod(m
, struct ip6_hdr
*);
486 * calculate the checksum
488 IP6_EXTHDR_GET(icmp6
, struct icmp6_hdr
*, m
, off
, sizeof(*icmp6
));
490 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
492 /*icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);*/
495 KASSERT(IP6_HDR_ALIGNED_P(icmp6
));
496 code
= icmp6
->icmp6_code
;
498 if ((sum
= in6_cksum(m
, IPPROTO_ICMPV6
, off
, icmp6len
)) != 0) {
500 "ICMP6 checksum error(%d|%x) %s\n",
501 icmp6
->icmp6_type
, sum
, ip6_sprintf(&ip6
->ip6_src
)));
502 ICMP6_STATINC(ICMP6_STAT_CHECKSUM
);
503 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_error
);
507 #if defined(NFAITH) && 0 < NFAITH
508 if (faithprefix(&ip6
->ip6_dst
)) {
510 * Deliver very specific ICMP6 type only.
511 * This is important to deliver TOOBIG. Otherwise PMTUD
514 switch (icmp6
->icmp6_type
) {
515 case ICMP6_DST_UNREACH
:
516 case ICMP6_PACKET_TOO_BIG
:
517 case ICMP6_TIME_EXCEEDED
:
525 ICMP6_STATINC(ICMP6_STAT_INHIST
+ icmp6
->icmp6_type
);
527 switch (icmp6
->icmp6_type
) {
528 case ICMP6_DST_UNREACH
:
529 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_dstunreach
);
531 case ICMP6_DST_UNREACH_NOROUTE
:
532 code
= PRC_UNREACH_NET
;
534 case ICMP6_DST_UNREACH_ADMIN
:
535 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_adminprohib
);
536 code
= PRC_UNREACH_PROTOCOL
; /* is this a good code? */
538 case ICMP6_DST_UNREACH_ADDR
:
541 #ifdef COMPAT_RFC1885
542 case ICMP6_DST_UNREACH_NOTNEIGHBOR
:
543 code
= PRC_UNREACH_SRCFAIL
;
546 case ICMP6_DST_UNREACH_BEYONDSCOPE
:
547 /* I mean "source address was incorrect." */
548 code
= PRC_UNREACH_NET
;
551 case ICMP6_DST_UNREACH_NOPORT
:
552 code
= PRC_UNREACH_PORT
;
559 case ICMP6_PACKET_TOO_BIG
:
560 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_pkttoobig
);
563 * MTU is checked in icmp6_mtudisc.
568 * Updating the path MTU will be done after examining
569 * intermediate extension headers.
573 case ICMP6_TIME_EXCEEDED
:
574 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_timeexceed
);
576 case ICMP6_TIME_EXCEED_TRANSIT
:
577 code
= PRC_TIMXCEED_INTRANS
;
579 case ICMP6_TIME_EXCEED_REASSEMBLY
:
580 code
= PRC_TIMXCEED_REASS
;
587 case ICMP6_PARAM_PROB
:
588 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_paramprob
);
590 case ICMP6_PARAMPROB_NEXTHEADER
:
591 code
= PRC_UNREACH_PROTOCOL
;
593 case ICMP6_PARAMPROB_HEADER
:
594 case ICMP6_PARAMPROB_OPTION
:
595 code
= PRC_PARAMPROB
;
602 case ICMP6_ECHO_REQUEST
:
603 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_echo
);
607 * Copy mbuf to send to two data paths: userland socket(s),
608 * and to the querier (echo reply).
609 * m: a copy for socket, n: a copy for querier
611 * If the first mbuf is shared, or the first mbuf is too short,
612 * copy the first part of the data into a fresh mbuf.
613 * Otherwise, we will wrongly overwrite both copies.
615 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
619 } else if (M_READONLY(n
) ||
620 n
->m_len
< off
+ sizeof(struct icmp6_hdr
)) {
624 * Prepare an internal mbuf. m_pullup() doesn't
625 * always copy the length we specified.
627 if ((n
= m_dup(n0
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
634 IP6_EXTHDR_GET(nicmp6
, struct icmp6_hdr
*, n
, off
,
636 nicmp6
->icmp6_type
= ICMP6_ECHO_REPLY
;
637 nicmp6
->icmp6_code
= 0;
639 uint64_t *icmp6s
= ICMP6_STAT_GETREF();
640 icmp6s
[ICMP6_STAT_REFLECT
]++;
641 icmp6s
[ICMP6_STAT_OUTHIST
+ ICMP6_ECHO_REPLY
]++;
643 icmp6_reflect(n
, off
);
649 case ICMP6_ECHO_REPLY
:
650 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_echoreply
);
655 case MLD_LISTENER_QUERY
:
656 case MLD_LISTENER_REPORT
:
657 if (icmp6len
< sizeof(struct mld_hdr
))
659 if (icmp6
->icmp6_type
== MLD_LISTENER_QUERY
) /* XXX: ugly... */
660 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_mldquery
);
662 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_mldreport
);
663 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
673 case MLD_LISTENER_DONE
:
674 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_mlddone
);
675 if (icmp6len
< sizeof(struct mld_hdr
)) /* necessary? */
677 break; /* nothing to be done in kernel */
679 case MLD_MTRACE_RESP
:
681 /* XXX: these two are experimental. not officially defined. */
682 /* XXX: per-interface statistics? */
683 break; /* just pass it to applications */
685 case ICMP6_WRUREQUEST
: /* ICMP6_FQDN_QUERY */
687 enum { WRU
, FQDN
} mode
;
692 if (icmp6len
== sizeof(struct icmp6_hdr
) + 4)
694 else if (icmp6len
>= sizeof(struct icmp6_nodeinfo
))
700 n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
);
702 n
= ni6_input(n
, off
);
703 /* XXX meaningless if n == NULL */
704 noff
= sizeof(struct ip6_hdr
);
709 if ((icmp6_nodeinfo
& 5) != 5)
714 MGETHDR(n
, M_DONTWAIT
, m
->m_type
);
715 if (n
&& ICMP6_MAXLEN
> MHLEN
) {
716 MCLGET(n
, M_DONTWAIT
);
717 if ((n
->m_flags
& M_EXT
) == 0) {
726 n
->m_pkthdr
.rcvif
= NULL
;
728 maxhlen
= M_TRAILINGSPACE(n
) - ICMP6_MAXLEN
;
729 if (maxhlen
> hostnamelen
)
730 maxhlen
= hostnamelen
;
732 * Copy IPv6 and ICMPv6 only.
734 nip6
= mtod(n
, struct ip6_hdr
*);
735 bcopy(ip6
, nip6
, sizeof(struct ip6_hdr
));
736 nicmp6
= (struct icmp6_hdr
*)(nip6
+ 1);
737 bcopy(icmp6
, nicmp6
, sizeof(struct icmp6_hdr
));
738 p
= (u_char
*)(nicmp6
+ 1);
740 bcopy(hostname
, p
+ 4, maxhlen
); /* meaningless TTL */
741 noff
= sizeof(struct ip6_hdr
);
742 M_COPY_PKTHDR(n
, m
); /* just for rcvif */
743 n
->m_pkthdr
.len
= n
->m_len
= sizeof(struct ip6_hdr
) +
744 sizeof(struct icmp6_hdr
) + 4 + maxhlen
;
745 nicmp6
->icmp6_type
= ICMP6_WRUREPLY
;
746 nicmp6
->icmp6_code
= 0;
750 uint64_t *icmp6s
= ICMP6_STAT_GETREF();
751 icmp6s
[ICMP6_STAT_REFLECT
]++;
752 icmp6s
[ICMP6_STAT_OUTHIST
+ ICMP6_WRUREPLY
]++;
754 icmp6_reflect(n
, noff
);
764 case ND_ROUTER_SOLICIT
:
765 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_routersolicit
);
768 if (icmp6len
< sizeof(struct nd_router_solicit
))
770 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
772 nd6_rs_input(m
, off
, icmp6len
);
776 nd6_rs_input(n
, off
, icmp6len
);
780 case ND_ROUTER_ADVERT
:
781 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_routeradvert
);
784 if (icmp6len
< sizeof(struct nd_router_advert
))
786 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
788 nd6_ra_input(m
, off
, icmp6len
);
792 nd6_ra_input(n
, off
, icmp6len
);
796 case ND_NEIGHBOR_SOLICIT
:
797 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_neighborsolicit
);
800 if (icmp6len
< sizeof(struct nd_neighbor_solicit
))
802 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
804 nd6_ns_input(m
, off
, icmp6len
);
808 nd6_ns_input(n
, off
, icmp6len
);
812 case ND_NEIGHBOR_ADVERT
:
813 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_neighboradvert
);
816 if (icmp6len
< sizeof(struct nd_neighbor_advert
))
818 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
820 nd6_na_input(m
, off
, icmp6len
);
824 nd6_na_input(n
, off
, icmp6len
);
829 icmp6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_redirect
);
832 if (icmp6len
< sizeof(struct nd_redirect
))
834 if ((n
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
)) == NULL
) {
836 icmp6_redirect_input(m
, off
);
840 icmp6_redirect_input(n
, off
);
844 case ICMP6_ROUTER_RENUMBERING
:
845 if (code
!= ICMP6_ROUTER_RENUMBERING_COMMAND
&&
846 code
!= ICMP6_ROUTER_RENUMBERING_RESULT
)
848 if (icmp6len
< sizeof(struct icmp6_router_renum
))
854 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
855 icmp6
->icmp6_type
, ip6_sprintf(&ip6
->ip6_src
),
856 ip6_sprintf(&ip6
->ip6_dst
),
857 m
->m_pkthdr
.rcvif
? m
->m_pkthdr
.rcvif
->if_index
: 0));
858 if (icmp6
->icmp6_type
< ICMP6_ECHO_REQUEST
) {
859 /* ICMPv6 error: MUST deliver it by spec... */
863 /* ICMPv6 informational: MUST not deliver */
867 if (icmp6_notify_error(m
, off
, icmp6len
, code
)) {
868 /* In this case, m should've been freed. */
869 return (IPPROTO_DONE
);
874 ICMP6_STATINC(ICMP6_STAT_BADCODE
);
878 ICMP6_STATINC(ICMP6_STAT_BADLEN
);
882 /* deliver the packet to appropriate sockets */
883 icmp6_rip6_input(&m
, *offp
);
893 icmp6_notify_error(struct mbuf
*m
, int off
, int icmp6len
, int code
)
895 struct icmp6_hdr
*icmp6
;
896 struct ip6_hdr
*eip6
;
898 struct sockaddr_in6 icmp6src
, icmp6dst
;
900 if (icmp6len
< sizeof(struct icmp6_hdr
) + sizeof(struct ip6_hdr
)) {
901 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
904 IP6_EXTHDR_GET(icmp6
, struct icmp6_hdr
*, m
, off
,
905 sizeof(*icmp6
) + sizeof(struct ip6_hdr
));
907 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
910 eip6
= (struct ip6_hdr
*)(icmp6
+ 1);
912 /* Detect the upper level protocol */
914 void (*ctlfunc
)(int, struct sockaddr
*, void *);
915 u_int8_t nxt
= eip6
->ip6_nxt
;
916 int eoff
= off
+ sizeof(struct icmp6_hdr
) +
917 sizeof(struct ip6_hdr
);
918 struct ip6ctlparam ip6cp
;
919 struct in6_addr
*finaldst
= NULL
;
920 int icmp6type
= icmp6
->icmp6_type
;
922 struct ip6_rthdr
*rth
;
923 struct ip6_rthdr0
*rth0
;
926 while (1) { /* XXX: should avoid infinite loop explicitly? */
930 case IPPROTO_HOPOPTS
:
931 case IPPROTO_DSTOPTS
:
933 IP6_EXTHDR_GET(eh
, struct ip6_ext
*, m
,
936 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
940 if (nxt
== IPPROTO_AH
)
941 eoff
+= (eh
->ip6e_len
+ 2) << 2;
943 eoff
+= (eh
->ip6e_len
+ 1) << 3;
946 case IPPROTO_ROUTING
:
948 * When the erroneous packet contains a
949 * routing header, we should examine the
950 * header to determine the final destination.
951 * Otherwise, we can't properly update
952 * information that depends on the final
953 * destination (e.g. path MTU).
955 IP6_EXTHDR_GET(rth
, struct ip6_rthdr
*, m
,
958 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
961 rthlen
= (rth
->ip6r_len
+ 1) << 3;
963 * XXX: currently there is no
964 * officially defined type other
966 * Note that if the segment left field
967 * is 0, all intermediate hops must
970 if (rth
->ip6r_segleft
&&
971 rth
->ip6r_type
== IPV6_RTHDR_TYPE_0
) {
975 struct ip6_rthdr0
*, m
,
978 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
981 /* just ignore a bogus header */
982 if ((rth0
->ip6r0_len
% 2) == 0 &&
983 (hops
= rth0
->ip6r0_len
/2))
984 finaldst
= (struct in6_addr
*)(rth0
+ 1) + (hops
- 1);
989 case IPPROTO_FRAGMENT
:
990 IP6_EXTHDR_GET(fh
, struct ip6_frag
*, m
,
993 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
997 * Data after a fragment header is meaningless
998 * unless it is the first fragment, but
999 * we'll go to the notify label for path MTU
1002 if (fh
->ip6f_offlg
& IP6F_OFF_MASK
)
1005 eoff
+= sizeof(struct ip6_frag
);
1010 * This case includes ESP and the No Next
1011 * Header. In such cases going to the notify
1012 * label does not have any meaning
1013 * (i.e. ctlfunc will be NULL), but we go
1014 * anyway since we might have to update
1015 * path MTU information.
1021 IP6_EXTHDR_GET(icmp6
, struct icmp6_hdr
*, m
, off
,
1022 sizeof(*icmp6
) + sizeof(struct ip6_hdr
));
1023 if (icmp6
== NULL
) {
1024 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
1029 * retrieve parameters from the inner IPv6 header, and convert
1030 * them into sockaddr structures.
1031 * XXX: there is no guarantee that the source or destination
1032 * addresses of the inner packet are in the same scope zone as
1033 * the addresses of the icmp packet. But there is no other
1034 * way to determine the zone.
1036 eip6
= (struct ip6_hdr
*)(icmp6
+ 1);
1038 sockaddr_in6_init(&icmp6dst
,
1039 (finaldst
== NULL
) ? &eip6
->ip6_dst
: finaldst
, 0, 0, 0);
1040 if (in6_setscope(&icmp6dst
.sin6_addr
, m
->m_pkthdr
.rcvif
, NULL
))
1042 sockaddr_in6_init(&icmp6src
, &eip6
->ip6_src
, 0, 0, 0);
1043 if (in6_setscope(&icmp6src
.sin6_addr
, m
->m_pkthdr
.rcvif
, NULL
))
1045 icmp6src
.sin6_flowinfo
=
1046 (eip6
->ip6_flow
& IPV6_FLOWLABEL_MASK
);
1048 if (finaldst
== NULL
)
1049 finaldst
= &eip6
->ip6_dst
;
1051 ip6cp
.ip6c_icmp6
= icmp6
;
1052 ip6cp
.ip6c_ip6
= (struct ip6_hdr
*)(icmp6
+ 1);
1053 ip6cp
.ip6c_off
= eoff
;
1054 ip6cp
.ip6c_finaldst
= finaldst
;
1055 ip6cp
.ip6c_src
= &icmp6src
;
1056 ip6cp
.ip6c_nxt
= nxt
;
1058 if (icmp6type
== ICMP6_PACKET_TOO_BIG
) {
1059 notifymtu
= ntohl(icmp6
->icmp6_mtu
);
1060 ip6cp
.ip6c_cmdarg
= (void *)¬ifymtu
;
1063 ctlfunc
= (void (*)(int, struct sockaddr
*, void *))
1064 (inet6sw
[ip6_protox
[nxt
]].pr_ctlinput
);
1066 (void) (*ctlfunc
)(code
, (struct sockaddr
*)&icmp6dst
,
1078 icmp6_mtudisc_update(struct ip6ctlparam
*ip6cp
, int validated
)
1080 unsigned long rtcount
;
1081 struct icmp6_mtudisc_callback
*mc
;
1082 struct in6_addr
*dst
= ip6cp
->ip6c_finaldst
;
1083 struct icmp6_hdr
*icmp6
= ip6cp
->ip6c_icmp6
;
1084 struct mbuf
*m
= ip6cp
->ip6c_m
; /* will be necessary for scope issue */
1085 u_int mtu
= ntohl(icmp6
->icmp6_mtu
);
1086 struct rtentry
*rt
= NULL
;
1087 struct sockaddr_in6 sin6
;
1090 * The MTU should not be less than the minimal IPv6 MTU except for the
1091 * hack in ip6_output/ip6_setpmtu where we always include a frag header.
1092 * In that one case, the MTU might be less than 1280.
1094 if (__predict_false(mtu
< IPV6_MMTU
- sizeof(struct ip6_frag
))) {
1095 /* is the mtu even sane? */
1096 if (mtu
< sizeof(struct ip6_hdr
) + sizeof(struct ip6_frag
) + 8)
1100 mtu
= IPV6_MMTU
- sizeof(struct ip6_frag
);
1104 * allow non-validated cases if memory is plenty, to make traffic
1105 * from non-connected pcb happy.
1107 rtcount
= rt_timer_count(icmp6_mtudisc_timeout_q
);
1109 if (0 <= icmp6_mtudisc_hiwat
&& rtcount
> icmp6_mtudisc_hiwat
)
1111 else if (0 <= icmp6_mtudisc_lowat
&&
1112 rtcount
> icmp6_mtudisc_lowat
) {
1114 * XXX nuke a victim, install the new one.
1118 if (0 <= icmp6_mtudisc_lowat
&& rtcount
> icmp6_mtudisc_lowat
)
1122 memset(&sin6
, 0, sizeof(sin6
));
1123 sin6
.sin6_family
= PF_INET6
;
1124 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
1125 sin6
.sin6_addr
= *dst
;
1126 if (in6_setscope(&sin6
.sin6_addr
, m
->m_pkthdr
.rcvif
, NULL
))
1129 rt
= icmp6_mtudisc_clone((struct sockaddr
*)&sin6
);
1131 if (rt
&& (rt
->rt_flags
& RTF_HOST
) &&
1132 !(rt
->rt_rmx
.rmx_locks
& RTV_MTU
) &&
1133 (rt
->rt_rmx
.rmx_mtu
> mtu
|| rt
->rt_rmx
.rmx_mtu
== 0)) {
1134 if (mtu
< IN6_LINKMTU(rt
->rt_ifp
)) {
1135 ICMP6_STATINC(ICMP6_STAT_PMTUCHG
);
1136 rt
->rt_rmx
.rmx_mtu
= mtu
;
1139 if (rt
) { /* XXX: need braces to avoid conflict with else in RTFREE. */
1144 * Notify protocols that the MTU for this destination
1147 for (mc
= LIST_FIRST(&icmp6_mtudisc_callbacks
); mc
!= NULL
;
1148 mc
= LIST_NEXT(mc
, mc_list
))
1149 (*mc
->mc_func
)(&sin6
.sin6_addr
);
1153 * Process a Node Information Query packet, based on
1154 * draft-ietf-ipngwg-icmp-name-lookups-07.
1156 * Spec incompatibilities:
1157 * - IPv6 Subject address handling
1158 * - IPv4 Subject address handling support missing
1159 * - Proxy reply (answer even if it's not for me)
1160 * - joins NI group address at in6_ifattach() time only, does not cope
1161 * with hostname changes by sethostname(3)
1163 #ifndef offsetof /* XXX */
1164 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
1166 static struct mbuf
*
1167 ni6_input(struct mbuf
*m
, int off
)
1169 struct icmp6_nodeinfo
*ni6
, *nni6
;
1170 struct mbuf
*n
= NULL
;
1173 int replylen
= sizeof(struct ip6_hdr
) + sizeof(struct icmp6_nodeinfo
);
1174 struct ni_reply_fqdn
*fqdn
;
1175 int addrs
; /* for NI_QTYPE_NODEADDR */
1176 struct ifnet
*ifp
= NULL
; /* for NI_QTYPE_NODEADDR */
1177 struct sockaddr_in6 sin6
; /* ip6_dst */
1178 struct in6_addr in6_subj
; /* subject address */
1179 struct ip6_hdr
*ip6
;
1180 int oldfqdn
= 0; /* if 1, return pascal string (03 draft) */
1183 ip6
= mtod(m
, struct ip6_hdr
*);
1184 IP6_EXTHDR_GET(ni6
, struct icmp6_nodeinfo
*, m
, off
, sizeof(*ni6
));
1186 /* m is already reclaimed */
1191 * Validate IPv6 destination address.
1193 * The Responder must discard the Query without further processing
1194 * unless it is one of the Responder's unicast or anycast addresses, or
1195 * a link-local scope multicast address which the Responder has joined.
1196 * [icmp-name-lookups-07, Section 4.]
1198 sockaddr_in6_init(&sin6
, &ip6
->ip6_dst
, 0, 0, 0);
1200 if (ifa_ifwithaddr((struct sockaddr
*)&sin6
))
1201 ; /* unicast/anycast, fine */
1202 else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
))
1203 ; /* link-local multicast, fine */
1207 /* validate query Subject field. */
1208 qtype
= ntohs(ni6
->ni_qtype
);
1209 subjlen
= m
->m_pkthdr
.len
- off
- sizeof(struct icmp6_nodeinfo
);
1212 case NI_QTYPE_SUPTYPES
:
1214 if (ni6
->ni_code
== ICMP6_NI_SUBJ_FQDN
&& subjlen
== 0)
1218 case NI_QTYPE_NODEADDR
:
1219 case NI_QTYPE_IPV4ADDR
:
1220 switch (ni6
->ni_code
) {
1221 case ICMP6_NI_SUBJ_IPV6
:
1222 #if ICMP6_NI_SUBJ_IPV6 != 0
1226 * backward compatibility - try to accept 03 draft
1227 * format, where no Subject is present.
1229 if (qtype
== NI_QTYPE_FQDN
&& ni6
->ni_code
== 0 &&
1234 #if ICMP6_NI_SUBJ_IPV6 != 0
1235 if (ni6
->ni_code
!= ICMP6_NI_SUBJ_IPV6
)
1239 if (subjlen
!= sizeof(sin6
.sin6_addr
))
1243 * Validate Subject address.
1245 * Not sure what exactly "address belongs to the node"
1246 * means in the spec, is it just unicast, or what?
1248 * At this moment we consider Subject address as
1249 * "belong to the node" if the Subject address equals
1250 * to the IPv6 destination address; validation for
1251 * IPv6 destination address should have done enough
1254 * We do not do proxy at this moment.
1256 /* m_pulldown instead of copy? */
1257 m_copydata(m
, off
+ sizeof(struct icmp6_nodeinfo
),
1258 subjlen
, (void *)&in6_subj
);
1259 if (in6_setscope(&in6_subj
, m
->m_pkthdr
.rcvif
, NULL
))
1262 subj
= (char *)&in6_subj
;
1263 if (IN6_ARE_ADDR_EQUAL(&ip6
->ip6_dst
, &in6_subj
))
1267 * XXX if we are to allow other cases, we should really
1268 * be careful about scope here.
1269 * basically, we should disallow queries toward IPv6
1270 * destination X with subject Y, if scope(X) > scope(Y).
1271 * if we allow scope(X) > scope(Y), it will result in
1272 * information leakage across scope boundary.
1276 case ICMP6_NI_SUBJ_FQDN
:
1278 * Validate Subject name with gethostname(3).
1280 * The behavior may need some debate, since:
1281 * - we are not sure if the node has FQDN as
1282 * hostname (returned by gethostname(3)).
1283 * - the code does wildcard match for truncated names.
1284 * however, we are not sure if we want to perform
1285 * wildcard match, if gethostname(3) side has
1286 * truncated hostname.
1288 n
= ni6_nametodns(hostname
, hostnamelen
, 0);
1289 if (!n
|| n
->m_next
|| n
->m_len
== 0)
1291 IP6_EXTHDR_GET(subj
, char *, m
,
1292 off
+ sizeof(struct icmp6_nodeinfo
), subjlen
);
1295 if (!ni6_dnsmatch(subj
, subjlen
, mtod(n
, const char *),
1303 case ICMP6_NI_SUBJ_IPV4
: /* XXX: to be implemented? */
1310 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1313 if ((icmp6_nodeinfo
& 1) == 0)
1316 case NI_QTYPE_NODEADDR
:
1317 case NI_QTYPE_IPV4ADDR
:
1318 if ((icmp6_nodeinfo
& 2) == 0)
1323 /* guess reply length */
1326 break; /* no reply data */
1327 case NI_QTYPE_SUPTYPES
:
1328 replylen
+= sizeof(u_int32_t
);
1331 /* XXX will append an mbuf */
1332 replylen
+= offsetof(struct ni_reply_fqdn
, ni_fqdn_namelen
);
1334 case NI_QTYPE_NODEADDR
:
1335 addrs
= ni6_addrs(ni6
, m
, &ifp
, subj
);
1336 if ((replylen
+= addrs
* (sizeof(struct in6_addr
) +
1337 sizeof(u_int32_t
))) > MCLBYTES
)
1338 replylen
= MCLBYTES
; /* XXX: will truncate pkt later */
1340 case NI_QTYPE_IPV4ADDR
:
1341 /* unsupported - should respond with unknown Qtype? */
1345 * XXX: We must return a reply with the ICMP6 code
1346 * `unknown Qtype' in this case. However we regard the case
1347 * as an FQDN query for backward compatibility.
1348 * Older versions set a random value to this field,
1349 * so it rarely varies in the defined qtypes.
1350 * But the mechanism is not reliable...
1351 * maybe we should obsolete older versions.
1353 qtype
= NI_QTYPE_FQDN
;
1354 /* XXX will append an mbuf */
1355 replylen
+= offsetof(struct ni_reply_fqdn
, ni_fqdn_namelen
);
1360 /* allocate an mbuf to reply. */
1361 MGETHDR(n
, M_DONTWAIT
, m
->m_type
);
1366 M_MOVE_PKTHDR(n
, m
); /* just for rcvif */
1367 if (replylen
> MHLEN
) {
1368 if (replylen
> MCLBYTES
) {
1370 * XXX: should we try to allocate more? But MCLBYTES
1371 * is probably much larger than IPV6_MMTU...
1375 MCLGET(n
, M_DONTWAIT
);
1376 if ((n
->m_flags
& M_EXT
) == 0) {
1380 n
->m_pkthdr
.len
= n
->m_len
= replylen
;
1382 /* copy mbuf header and IPv6 + Node Information base headers */
1383 bcopy(mtod(m
, void *), mtod(n
, void *), sizeof(struct ip6_hdr
));
1384 nni6
= (struct icmp6_nodeinfo
*)(mtod(n
, struct ip6_hdr
*) + 1);
1385 bcopy((void *)ni6
, (void *)nni6
, sizeof(struct icmp6_nodeinfo
));
1387 /* qtype dependent procedure */
1390 nni6
->ni_code
= ICMP6_NI_SUCCESS
;
1393 case NI_QTYPE_SUPTYPES
:
1396 nni6
->ni_code
= ICMP6_NI_SUCCESS
;
1397 nni6
->ni_flags
= htons(0x0000); /* raw bitmap */
1398 /* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
1399 v
= (u_int32_t
)htonl(0x0000000f);
1400 bcopy(&v
, nni6
+ 1, sizeof(u_int32_t
));
1404 nni6
->ni_code
= ICMP6_NI_SUCCESS
;
1405 fqdn
= (struct ni_reply_fqdn
*)(mtod(n
, char *) +
1406 sizeof(struct ip6_hdr
) +
1407 sizeof(struct icmp6_nodeinfo
));
1408 nni6
->ni_flags
= 0; /* XXX: meaningless TTL */
1409 fqdn
->ni_fqdn_ttl
= 0; /* ditto. */
1411 * XXX do we really have FQDN in variable "hostname"?
1413 n
->m_next
= ni6_nametodns(hostname
, hostnamelen
, oldfqdn
);
1414 if (n
->m_next
== NULL
)
1416 /* XXX we assume that n->m_next is not a chain */
1417 if (n
->m_next
->m_next
!= NULL
)
1419 n
->m_pkthdr
.len
+= n
->m_next
->m_len
;
1421 case NI_QTYPE_NODEADDR
:
1425 nni6
->ni_code
= ICMP6_NI_SUCCESS
;
1426 n
->m_pkthdr
.len
= n
->m_len
=
1427 sizeof(struct ip6_hdr
) + sizeof(struct icmp6_nodeinfo
);
1428 lenlim
= M_TRAILINGSPACE(n
);
1429 copied
= ni6_store_addrs(ni6
, nni6
, ifp
, lenlim
);
1430 /* XXX: reset mbuf length */
1431 n
->m_pkthdr
.len
= n
->m_len
= sizeof(struct ip6_hdr
) +
1432 sizeof(struct icmp6_nodeinfo
) + copied
;
1436 break; /* XXX impossible! */
1439 nni6
->ni_type
= ICMP6_NI_REPLY
;
1451 #define isupper(x) ('A' <= (x) && (x) <= 'Z')
1452 #define isalpha(x) (('A' <= (x) && (x) <= 'Z') || ('a' <= (x) && (x) <= 'z'))
1453 #define isalnum(x) (isalpha(x) || ('0' <= (x) && (x) <= '9'))
1454 #define tolower(x) (isupper(x) ? (x) + 'a' - 'A' : (x))
1457 * make a mbuf with DNS-encoded string. no compression support.
1459 * XXX names with less than 2 dots (like "foo" or "foo.section") will be
1460 * treated as truncated name (two \0 at the end). this is a wild guess.
1462 * old - return pascal string if non-zero
1464 static struct mbuf
*
1465 ni6_nametodns(const char *name
, int namelen
, int old
)
1477 /* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
1478 MGET(m
, M_DONTWAIT
, MT_DATA
);
1479 if (m
&& len
> MLEN
) {
1480 MCLGET(m
, M_DONTWAIT
);
1481 if ((m
->m_flags
& M_EXT
) == 0)
1490 *mtod(m
, char *) = namelen
;
1491 bcopy(name
, mtod(m
, char *) + 1, namelen
);
1495 cp
= mtod(m
, char *);
1496 ep
= mtod(m
, char *) + M_TRAILINGSPACE(m
);
1498 /* if not certain about my name, return empty buffer */
1503 * guess if it looks like shortened hostname, or FQDN.
1504 * shortened hostname needs two trailing "\0".
1507 for (p
= name
; p
< name
+ namelen
; p
++) {
1508 if (*p
&& *p
== '.')
1517 while (cp
< ep
&& p
< name
+ namelen
) {
1519 for (q
= p
; q
< name
+ namelen
&& *q
&& *q
!= '.'; q
++)
1521 /* result does not fit into mbuf */
1522 if (cp
+ i
+ 1 >= ep
)
1525 * DNS label length restriction, RFC1035 page 8.
1526 * "i == 0" case is included here to avoid returning
1527 * 0-length label on "foo..bar".
1529 if (i
<= 0 || i
>= 64)
1532 if (!isalpha(p
[0]) || !isalnum(p
[i
- 1]))
1535 if (!isalnum(*p
) && *p
!= '-')
1538 *cp
++ = tolower(*p
);
1545 if (p
< name
+ namelen
&& *p
== '.')
1549 if (cp
+ nterm
>= ep
)
1553 m
->m_len
= cp
- mtod(m
, char *);
1557 panic("should not reach here");
1567 * check if two DNS-encoded string matches. takes care of truncated
1568 * form (with \0\0 at the end). no compression support.
1569 * XXX upper/lowercase match (see RFC2065)
1572 ni6_dnsmatch(const char *a
, int alen
, const char *b
, int blen
)
1574 const char *a0
, *b0
;
1577 /* simplest case - need validation? */
1578 if (alen
== blen
&& memcmp(a
, b
, alen
) == 0)
1584 /* termination is mandatory */
1585 if (alen
< 2 || blen
< 2)
1587 if (a0
[alen
- 1] != '\0' || b0
[blen
- 1] != '\0')
1592 while (a
- a0
< alen
&& b
- b0
< blen
) {
1593 if (a
- a0
+ 1 > alen
|| b
- b0
+ 1 > blen
)
1596 if ((signed char)a
[0] < 0 || (signed char)b
[0] < 0)
1598 /* we don't support compression yet */
1599 if (a
[0] >= 64 || b
[0] >= 64)
1602 /* truncated case */
1603 if (a
[0] == 0 && a
- a0
== alen
- 1)
1605 if (b
[0] == 0 && b
- b0
== blen
- 1)
1607 if (a
[0] == 0 || b
[0] == 0)
1613 if (a
- a0
+ 1 + l
> alen
|| b
- b0
+ 1 + l
> blen
)
1615 if (memcmp(a
+ 1, b
+ 1, l
) != 0)
1622 if (a
- a0
== alen
&& b
- b0
== blen
)
1629 * calculate the number of addresses to be returned in the node info reply.
1632 ni6_addrs(struct icmp6_nodeinfo
*ni6
, struct mbuf
*m
,
1633 struct ifnet
**ifpp
, char *subj
)
1636 struct in6_ifaddr
*ifa6
;
1638 struct sockaddr_in6
*subj_ip6
= NULL
; /* XXX pedant */
1639 int addrs
= 0, addrsofif
, iffound
= 0;
1640 int niflags
= ni6
->ni_flags
;
1642 if ((niflags
& NI_NODEADDR_FLAG_ALL
) == 0) {
1643 switch (ni6
->ni_code
) {
1644 case ICMP6_NI_SUBJ_IPV6
:
1645 if (subj
== NULL
) /* must be impossible... */
1647 subj_ip6
= (struct sockaddr_in6
*)subj
;
1651 * XXX: we only support IPv6 subject address for
1658 IFNET_FOREACH(ifp
) {
1660 IFADDR_FOREACH(ifa
, ifp
) {
1661 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1663 ifa6
= (struct in6_ifaddr
*)ifa
;
1665 if ((niflags
& NI_NODEADDR_FLAG_ALL
) == 0 &&
1666 IN6_ARE_ADDR_EQUAL(&subj_ip6
->sin6_addr
,
1667 &ifa6
->ia_addr
.sin6_addr
))
1671 * IPv4-mapped addresses can only be returned by a
1672 * Node Information proxy, since they represent
1673 * addresses of IPv4-only nodes, which perforce do
1674 * not implement this protocol.
1675 * [icmp-name-lookups-07, Section 5.4]
1676 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1677 * this function at this moment.
1680 /* What do we have to do about ::1? */
1681 switch (in6_addrscope(&ifa6
->ia_addr
.sin6_addr
)) {
1682 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1683 if ((niflags
& NI_NODEADDR_FLAG_LINKLOCAL
) == 0)
1686 case IPV6_ADDR_SCOPE_SITELOCAL
:
1687 if ((niflags
& NI_NODEADDR_FLAG_SITELOCAL
) == 0)
1690 case IPV6_ADDR_SCOPE_GLOBAL
:
1691 if ((niflags
& NI_NODEADDR_FLAG_GLOBAL
) == 0)
1699 * check if anycast is okay.
1700 * XXX: just experimental. not in the spec.
1702 if ((ifa6
->ia6_flags
& IN6_IFF_ANYCAST
) != 0 &&
1703 (niflags
& NI_NODEADDR_FLAG_ANYCAST
) == 0)
1704 continue; /* we need only unicast addresses */
1706 addrsofif
++; /* count the address */
1720 ni6_store_addrs(struct icmp6_nodeinfo
*ni6
,
1721 struct icmp6_nodeinfo
*nni6
, struct ifnet
*ifp0
,
1724 struct ifnet
*ifp
= ifp0
? ifp0
: TAILQ_FIRST(&ifnet
);
1725 struct in6_ifaddr
*ifa6
;
1727 struct ifnet
*ifp_dep
= NULL
;
1728 int copied
= 0, allow_deprecated
= 0;
1729 u_char
*cp
= (u_char
*)(nni6
+ 1);
1730 int niflags
= ni6
->ni_flags
;
1733 if (ifp0
== NULL
&& !(niflags
& NI_NODEADDR_FLAG_ALL
))
1734 return (0); /* needless to copy */
1738 for (; ifp
; ifp
= TAILQ_NEXT(ifp
, if_list
))
1740 IFADDR_FOREACH(ifa
, ifp
) {
1741 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1743 ifa6
= (struct in6_ifaddr
*)ifa
;
1745 if ((ifa6
->ia6_flags
& IN6_IFF_DEPRECATED
) != 0 &&
1746 allow_deprecated
== 0) {
1748 * prefererred address should be put before
1749 * deprecated addresses.
1752 /* record the interface for later search */
1753 if (ifp_dep
== NULL
)
1758 else if ((ifa6
->ia6_flags
& IN6_IFF_DEPRECATED
) == 0 &&
1759 allow_deprecated
!= 0)
1760 continue; /* we now collect deprecated addrs */
1762 /* What do we have to do about ::1? */
1763 switch (in6_addrscope(&ifa6
->ia_addr
.sin6_addr
)) {
1764 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1765 if ((niflags
& NI_NODEADDR_FLAG_LINKLOCAL
) == 0)
1768 case IPV6_ADDR_SCOPE_SITELOCAL
:
1769 if ((niflags
& NI_NODEADDR_FLAG_SITELOCAL
) == 0)
1772 case IPV6_ADDR_SCOPE_GLOBAL
:
1773 if ((niflags
& NI_NODEADDR_FLAG_GLOBAL
) == 0)
1781 * check if anycast is okay.
1782 * XXX: just experimental. not in the spec.
1784 if ((ifa6
->ia6_flags
& IN6_IFF_ANYCAST
) != 0 &&
1785 (niflags
& NI_NODEADDR_FLAG_ANYCAST
) == 0)
1788 /* now we can copy the address */
1789 if (resid
< sizeof(struct in6_addr
) +
1790 sizeof(u_int32_t
)) {
1792 * We give up much more copy.
1793 * Set the truncate flag and return.
1795 nni6
->ni_flags
|= NI_NODEADDR_FLAG_TRUNCATE
;
1800 * Set the TTL of the address.
1801 * The TTL value should be one of the following
1802 * according to the specification:
1804 * 1. The remaining lifetime of a DHCP lease on the
1806 * 2. The remaining Valid Lifetime of a prefix from
1807 * which the address was derived through Stateless
1808 * Autoconfiguration.
1810 * Note that we currently do not support stateful
1811 * address configuration by DHCPv6, so the former
1812 * case can't happen.
1814 * TTL must be 2^31 > TTL >= 0.
1816 if (ifa6
->ia6_lifetime
.ia6t_expire
== 0)
1817 ltime
= ND6_INFINITE_LIFETIME
;
1819 if (ifa6
->ia6_lifetime
.ia6t_expire
>
1821 ltime
= ifa6
->ia6_lifetime
.ia6t_expire
-
1826 if (ltime
> 0x7fffffff)
1828 ltime
= htonl(ltime
);
1830 bcopy(<ime
, cp
, sizeof(u_int32_t
));
1831 cp
+= sizeof(u_int32_t
);
1833 /* copy the address itself */
1834 bcopy(&ifa6
->ia_addr
.sin6_addr
, cp
,
1835 sizeof(struct in6_addr
));
1836 in6_clearscope((struct in6_addr
*)cp
); /* XXX */
1837 cp
+= sizeof(struct in6_addr
);
1839 resid
-= (sizeof(struct in6_addr
) + sizeof(u_int32_t
));
1840 copied
+= (sizeof(struct in6_addr
) + sizeof(u_int32_t
));
1842 if (ifp0
) /* we need search only on the specified IF */
1846 if (allow_deprecated
== 0 && ifp_dep
!= NULL
) {
1848 allow_deprecated
= 1;
1857 * XXX almost dup'ed code with rip6_input.
1860 icmp6_rip6_input(struct mbuf
**mp
, int off
)
1862 struct mbuf
*m
= *mp
;
1863 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
1864 struct inpcb_hdr
*inph
;
1865 struct in6pcb
*in6p
;
1866 struct in6pcb
*last
= NULL
;
1867 struct sockaddr_in6 rip6src
;
1868 struct icmp6_hdr
*icmp6
;
1869 struct mbuf
*opts
= NULL
;
1871 IP6_EXTHDR_GET(icmp6
, struct icmp6_hdr
*, m
, off
, sizeof(*icmp6
));
1872 if (icmp6
== NULL
) {
1873 /* m is already reclaimed */
1874 return IPPROTO_DONE
;
1878 * XXX: the address may have embedded scope zone ID, which should be
1879 * hidden from applications.
1881 sockaddr_in6_init(&rip6src
, &ip6
->ip6_src
, 0, 0, 0);
1882 if (sa6_recoverscope(&rip6src
)) {
1884 return (IPPROTO_DONE
);
1887 CIRCLEQ_FOREACH(inph
, &raw6cbtable
.inpt_queue
, inph_queue
) {
1888 in6p
= (struct in6pcb
*)inph
;
1889 if (in6p
->in6p_af
!= AF_INET6
)
1891 if (in6p
->in6p_ip6
.ip6_nxt
!= IPPROTO_ICMPV6
)
1893 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
1894 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
))
1896 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
1897 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
))
1899 if (in6p
->in6p_icmp6filt
1900 && ICMP6_FILTER_WILLBLOCK(icmp6
->icmp6_type
,
1901 in6p
->in6p_icmp6filt
))
1905 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
1906 if (last
->in6p_flags
& IN6P_CONTROLOPTS
)
1907 ip6_savecontrol(last
, &opts
, ip6
, n
);
1908 /* strip intermediate headers */
1910 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
1911 (struct sockaddr
*)&rip6src
,
1913 /* should notify about lost packet */
1918 sorwakeup(last
->in6p_socket
);
1925 if (last
->in6p_flags
& IN6P_CONTROLOPTS
)
1926 ip6_savecontrol(last
, &opts
, ip6
, m
);
1927 /* strip intermediate headers */
1929 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
1930 (struct sockaddr
*)&rip6src
, m
, opts
) == 0) {
1935 sorwakeup(last
->in6p_socket
);
1938 IP6_STATDEC(IP6_STAT_DELIVERED
);
1940 return IPPROTO_DONE
;
1944 * Reflect the ip6 packet back to the source.
1945 * OFF points to the icmp6 header, counted from the top of the mbuf.
1947 * Note: RFC 1885 required that an echo reply should be truncated if it
1948 * did not fit in with (return) path MTU, and KAME code supported the
1949 * behavior. However, as a clarification after the RFC, this limitation
1950 * was removed in a revised version of the spec, RFC 2463. We had kept the
1951 * old behavior, with a (non-default) ifdef block, while the new version of
1952 * the spec was an internet-draft status, and even after the new RFC was
1953 * published. But it would rather make sense to clean the obsoleted part
1954 * up, and to make the code simpler at this stage.
1957 icmp6_reflect(struct mbuf
*m
, size_t off
)
1959 struct ip6_hdr
*ip6
;
1960 struct icmp6_hdr
*icmp6
;
1961 const struct in6_ifaddr
*ia
;
1962 const struct ip6aux
*ip6a
;
1965 struct ifnet
*outif
= NULL
;
1966 struct in6_addr origdst
;
1967 const struct in6_addr
*src
= NULL
;
1969 /* too short to reflect */
1970 if (off
< sizeof(struct ip6_hdr
)) {
1972 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
1973 (u_long
)off
, (u_long
)sizeof(struct ip6_hdr
),
1974 __FILE__
, __LINE__
));
1979 * If there are extra headers between IPv6 and ICMPv6, strip
1980 * off that header first.
1983 if (sizeof(struct ip6_hdr
) + sizeof(struct icmp6_hdr
) > MHLEN
)
1984 panic("assumption failed in icmp6_reflect");
1986 if (off
> sizeof(struct ip6_hdr
)) {
1988 struct ip6_hdr nip6
;
1990 l
= off
- sizeof(struct ip6_hdr
);
1991 m_copydata(m
, 0, sizeof(nip6
), (void *)&nip6
);
1993 l
= sizeof(struct ip6_hdr
) + sizeof(struct icmp6_hdr
);
1995 if ((m
= m_pullup(m
, l
)) == NULL
)
1998 bcopy((void *)&nip6
, mtod(m
, void *), sizeof(nip6
));
1999 } else /* off == sizeof(struct ip6_hdr) */ {
2001 l
= sizeof(struct ip6_hdr
) + sizeof(struct icmp6_hdr
);
2003 if ((m
= m_pullup(m
, l
)) == NULL
)
2007 plen
= m
->m_pkthdr
.len
- sizeof(struct ip6_hdr
);
2008 ip6
= mtod(m
, struct ip6_hdr
*);
2009 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
2010 icmp6
= (struct icmp6_hdr
*)(ip6
+ 1);
2011 type
= icmp6
->icmp6_type
; /* keep type for statistics */
2012 code
= icmp6
->icmp6_code
; /* ditto. */
2014 origdst
= ip6
->ip6_dst
;
2016 * ip6_input() drops a packet if its src is multicast.
2017 * So, the src is never multicast.
2019 ip6
->ip6_dst
= ip6
->ip6_src
;
2022 * If the incoming packet was addressed directly to us (i.e. unicast),
2023 * use dst as the src for the reply.
2024 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2025 * (for example) when we encounter an error while forwarding procedure
2026 * destined to a duplicated address of ours.
2027 * Note that ip6_getdstifaddr() may fail if we are in an error handling
2028 * procedure of an outgoing packet of our own, in which case we need
2029 * to search in the ifaddr list.
2031 if (IN6_IS_ADDR_MULTICAST(&origdst
))
2033 else if ((ip6a
= ip6_getdstifaddr(m
)) != NULL
) {
2034 if ((ip6a
->ip6a_flags
&
2035 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
)) == 0)
2036 src
= &ip6a
->ip6a_src
;
2039 struct sockaddr_in6 sin6
;
2043 sockaddr_in6_init(&u
.sin6
, &origdst
, 0, 0, 0);
2045 ia
= (struct in6_ifaddr
*)ifa_ifwithaddr(&u
.sa
);
2049 else if ((ia
->ia6_flags
&
2050 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
)) == 0)
2051 src
= &ia
->ia_addr
.sin6_addr
;
2056 struct sockaddr_in6 sin6
;
2060 * This case matches to multicasts, our anycast, or unicasts
2061 * that we do not own. Select a source address based on the
2062 * source address of the erroneous packet.
2064 /* zone ID should be embedded */
2065 sockaddr_in6_init(&sin6
, &ip6
->ip6_dst
, 0, 0, 0);
2067 memset(&ro
, 0, sizeof(ro
));
2068 src
= in6_selectsrc(&sin6
, NULL
, NULL
, &ro
, NULL
, &outif
, &e
);
2072 "icmp6_reflect: source can't be determined: "
2073 "dst=%s, error=%d\n",
2074 ip6_sprintf(&sin6
.sin6_addr
), e
));
2079 ip6
->ip6_src
= *src
;
2081 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
2082 ip6
->ip6_vfc
|= IPV6_VERSION
;
2083 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
2084 if (m
->m_pkthdr
.rcvif
) {
2085 /* XXX: This may not be the outgoing interface */
2086 ip6
->ip6_hlim
= ND_IFINFO(m
->m_pkthdr
.rcvif
)->chlim
;
2088 ip6
->ip6_hlim
= ip6_defhlim
;
2090 m
->m_pkthdr
.csum_flags
= 0;
2091 icmp6
->icmp6_cksum
= 0;
2092 icmp6
->icmp6_cksum
= in6_cksum(m
, IPPROTO_ICMPV6
,
2093 sizeof(struct ip6_hdr
), plen
);
2096 * XXX option handling
2099 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
2102 * To avoid a "too big" situation at an intermediate router
2103 * and the path MTU discovery process, specify the IPV6_MINMTU flag.
2104 * Note that only echo and node information replies are affected,
2105 * since the length of ICMP6 errors is limited to the minimum MTU.
2107 if (ip6_output(m
, NULL
, NULL
, IPV6_MINMTU
, NULL
, NULL
, &outif
) != 0 &&
2109 icmp6_ifstat_inc(outif
, ifs6_out_error
);
2112 icmp6_ifoutstat_inc(outif
, type
, code
);
2122 icmp6_redirect_diag(struct in6_addr
*src6
, struct in6_addr
*dst6
,
2123 struct in6_addr
*tgt6
)
2125 static char buf
[1024];
2126 snprintf(buf
, sizeof(buf
), "(src=%s dst=%s tgt=%s)",
2127 ip6_sprintf(src6
), ip6_sprintf(dst6
), ip6_sprintf(tgt6
));
2132 icmp6_redirect_input(struct mbuf
*m
, int off
)
2134 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
2135 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
2136 struct nd_redirect
*nd_rd
;
2137 int icmp6len
= ntohs(ip6
->ip6_plen
);
2138 char *lladdr
= NULL
;
2140 struct rtentry
*rt
= NULL
;
2143 struct in6_addr src6
= ip6
->ip6_src
;
2144 struct in6_addr redtgt6
;
2145 struct in6_addr reddst6
;
2146 union nd_opts ndopts
;
2151 /* XXX if we are router, we don't update route by icmp6 redirect */
2154 if (!icmp6_rediraccept
)
2157 IP6_EXTHDR_GET(nd_rd
, struct nd_redirect
*, m
, off
, icmp6len
);
2158 if (nd_rd
== NULL
) {
2159 ICMP6_STATINC(ICMP6_STAT_TOOSHORT
);
2162 redtgt6
= nd_rd
->nd_rd_target
;
2163 reddst6
= nd_rd
->nd_rd_dst
;
2165 if (in6_setscope(&redtgt6
, m
->m_pkthdr
.rcvif
, NULL
) ||
2166 in6_setscope(&reddst6
, m
->m_pkthdr
.rcvif
, NULL
)) {
2171 if (!IN6_IS_ADDR_LINKLOCAL(&src6
)) {
2173 "ICMP6 redirect sent from %s rejected; "
2174 "must be from linklocal\n", ip6_sprintf(&src6
)));
2177 if (ip6
->ip6_hlim
!= 255) {
2179 "ICMP6 redirect sent from %s rejected; "
2180 "hlim=%d (must be 255)\n",
2181 ip6_sprintf(&src6
), ip6
->ip6_hlim
));
2185 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2186 struct sockaddr_in6 sin6
;
2187 struct in6_addr
*gw6
;
2189 sockaddr_in6_init(&sin6
, &reddst6
, 0, 0, 0);
2190 rt
= rtalloc1((struct sockaddr
*)&sin6
, 0);
2192 if (rt
->rt_gateway
== NULL
||
2193 rt
->rt_gateway
->sa_family
!= AF_INET6
) {
2195 "ICMP6 redirect rejected; no route "
2196 "with inet6 gateway found for redirect dst: %s\n",
2197 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2202 gw6
= &(((struct sockaddr_in6
*)rt
->rt_gateway
)->sin6_addr
);
2203 if (memcmp(&src6
, gw6
, sizeof(struct in6_addr
)) != 0) {
2205 "ICMP6 redirect rejected; "
2206 "not equal to gw-for-src=%s (must be same): "
2209 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2215 "ICMP6 redirect rejected; "
2216 "no route found for redirect dst: %s\n",
2217 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2223 if (IN6_IS_ADDR_MULTICAST(&reddst6
)) {
2225 "ICMP6 redirect rejected; "
2226 "redirect dst must be unicast: %s\n",
2227 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2231 is_router
= is_onlink
= 0;
2232 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6
))
2233 is_router
= 1; /* router case */
2234 if (memcmp(&redtgt6
, &reddst6
, sizeof(redtgt6
)) == 0)
2235 is_onlink
= 1; /* on-link destination case */
2236 if (!is_router
&& !is_onlink
) {
2238 "ICMP6 redirect rejected; "
2239 "neither router case nor onlink case: %s\n",
2240 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2243 /* validation passed */
2245 icmp6len
-= sizeof(*nd_rd
);
2246 nd6_option_init(nd_rd
+ 1, icmp6len
, &ndopts
);
2247 if (nd6_options(&ndopts
) < 0) {
2248 nd6log((LOG_INFO
, "icmp6_redirect_input: "
2249 "invalid ND option, rejected: %s\n",
2250 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2251 /* nd6_options have incremented stats */
2255 if (ndopts
.nd_opts_tgt_lladdr
) {
2256 lladdr
= (char *)(ndopts
.nd_opts_tgt_lladdr
+ 1);
2257 lladdrlen
= ndopts
.nd_opts_tgt_lladdr
->nd_opt_len
<< 3;
2260 if (lladdr
&& ((ifp
->if_addrlen
+ 2 + 7) & ~7) != lladdrlen
) {
2262 "icmp6_redirect_input: lladdrlen mismatch for %s "
2263 "(if %d, icmp6 packet %d): %s\n",
2264 ip6_sprintf(&redtgt6
), ifp
->if_addrlen
, lladdrlen
- 2,
2265 icmp6_redirect_diag(&src6
, &reddst6
, &redtgt6
)));
2270 nd6_cache_lladdr(ifp
, &redtgt6
, lladdr
, lladdrlen
, ND_REDIRECT
,
2271 is_onlink
? ND_REDIRECT_ONLINK
: ND_REDIRECT_ROUTER
);
2273 if (!is_onlink
) { /* better router case. perform rtredirect. */
2274 /* perform rtredirect */
2275 struct sockaddr_in6 sdst
;
2276 struct sockaddr_in6 sgw
;
2277 struct sockaddr_in6 ssrc
;
2278 unsigned long rtcount
;
2279 struct rtentry
*newrt
= NULL
;
2282 * do not install redirect route, if the number of entries
2283 * is too much (> hiwat). note that, the node (= host) will
2284 * work just fine even if we do not install redirect route
2285 * (there will be additional hops, though).
2287 rtcount
= rt_timer_count(icmp6_redirect_timeout_q
);
2288 if (0 <= icmp6_redirect_hiwat
&& rtcount
> icmp6_redirect_hiwat
)
2290 else if (0 <= icmp6_redirect_lowat
&&
2291 rtcount
> icmp6_redirect_lowat
) {
2293 * XXX nuke a victim, install the new one.
2297 memset(&sdst
, 0, sizeof(sdst
));
2298 memset(&sgw
, 0, sizeof(sgw
));
2299 memset(&ssrc
, 0, sizeof(ssrc
));
2300 sdst
.sin6_family
= sgw
.sin6_family
= ssrc
.sin6_family
= AF_INET6
;
2301 sdst
.sin6_len
= sgw
.sin6_len
= ssrc
.sin6_len
=
2302 sizeof(struct sockaddr_in6
);
2303 bcopy(&redtgt6
, &sgw
.sin6_addr
, sizeof(struct in6_addr
));
2304 bcopy(&reddst6
, &sdst
.sin6_addr
, sizeof(struct in6_addr
));
2305 bcopy(&src6
, &ssrc
.sin6_addr
, sizeof(struct in6_addr
));
2306 rtredirect((struct sockaddr
*)&sdst
, (struct sockaddr
*)&sgw
,
2307 (struct sockaddr
*)NULL
, RTF_GATEWAY
| RTF_HOST
,
2308 (struct sockaddr
*)&ssrc
,
2312 (void)rt_timer_add(newrt
, icmp6_redirect_timeout
,
2313 icmp6_redirect_timeout_q
);
2317 /* finally update cached route in each socket via pfctlinput */
2319 struct sockaddr_in6 sdst
;
2321 sockaddr_in6_init(&sdst
, &reddst6
, 0, 0, 0);
2322 pfctlinput(PRC_REDIRECT_HOST
, (struct sockaddr
*)&sdst
);
2323 #if defined(IPSEC) || defined(FAST_IPSEC)
2324 key_sa_routechange((struct sockaddr
*)&sdst
);
2333 ICMP6_STATINC(ICMP6_STAT_BADREDIRECT
);
2338 icmp6_redirect_output(struct mbuf
*m0
, struct rtentry
*rt
)
2340 struct ifnet
*ifp
; /* my outgoing interface */
2341 struct in6_addr
*ifp_ll6
;
2342 struct in6_addr
*nexthop
;
2343 struct ip6_hdr
*sip6
; /* m0 as struct ip6_hdr */
2344 struct mbuf
*m
= NULL
; /* newly allocated one */
2345 struct ip6_hdr
*ip6
; /* m as struct ip6_hdr */
2346 struct nd_redirect
*nd_rd
;
2349 struct sockaddr_in6 src_sa
;
2351 icmp6_errcount(ICMP6_STAT_OUTERRHIST
, ND_REDIRECT
, 0);
2353 /* if we are not router, we don't send icmp6 redirect */
2354 if (!ip6_forwarding
)
2358 if (!m0
|| !rt
|| !(rt
->rt_flags
& RTF_UP
) || !(ifp
= rt
->rt_ifp
))
2363 * the source address must identify a neighbor, and
2364 * the destination address must not be a multicast address
2365 * [RFC 2461, sec 8.2]
2367 sip6
= mtod(m0
, struct ip6_hdr
*);
2368 sockaddr_in6_init(&src_sa
, &sip6
->ip6_src
, 0, 0, 0);
2369 if (nd6_is_addr_neighbor(&src_sa
, ifp
) == 0)
2371 if (IN6_IS_ADDR_MULTICAST(&sip6
->ip6_dst
))
2372 goto fail
; /* what should we do here? */
2375 if (icmp6_ratelimit(&sip6
->ip6_src
, ND_REDIRECT
, 0))
2379 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2380 * we almost always ask for an mbuf cluster for simplicity.
2381 * (MHLEN < IPV6_MMTU is almost always true)
2383 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
2384 if (m
&& IPV6_MMTU
>= MHLEN
) {
2385 #if IPV6_MMTU >= MCLBYTES
2386 _MCLGET(m
, mcl_cache
, IPV6_MMTU
, M_DONTWAIT
);
2388 MCLGET(m
, M_DONTWAIT
);
2394 m
->m_pkthdr
.rcvif
= NULL
;
2396 maxlen
= M_TRAILINGSPACE(m
);
2397 maxlen
= min(IPV6_MMTU
, maxlen
);
2398 /* just for safety */
2399 if (maxlen
< sizeof(struct ip6_hdr
) + sizeof(struct icmp6_hdr
) +
2400 ((sizeof(struct nd_opt_hdr
) + ifp
->if_addrlen
+ 7) & ~7)) {
2405 /* get ip6 linklocal address for ifp(my outgoing interface). */
2406 struct in6_ifaddr
*ia
;
2407 if ((ia
= in6ifa_ifpforlinklocal(ifp
,
2409 IN6_IFF_ANYCAST
)) == NULL
)
2411 ifp_ll6
= &ia
->ia_addr
.sin6_addr
;
2414 /* get ip6 linklocal address for the router. */
2415 if (rt
->rt_gateway
&& (rt
->rt_flags
& RTF_GATEWAY
)) {
2416 struct sockaddr_in6
*sin6
;
2417 sin6
= (struct sockaddr_in6
*)rt
->rt_gateway
;
2418 nexthop
= &sin6
->sin6_addr
;
2419 if (!IN6_IS_ADDR_LINKLOCAL(nexthop
))
2425 ip6
= mtod(m
, struct ip6_hdr
*);
2427 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
2428 ip6
->ip6_vfc
|= IPV6_VERSION
;
2429 /* ip6->ip6_plen will be set later */
2430 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
2431 ip6
->ip6_hlim
= 255;
2432 /* ip6->ip6_src must be linklocal addr for my outgoing if. */
2433 bcopy(ifp_ll6
, &ip6
->ip6_src
, sizeof(struct in6_addr
));
2434 bcopy(&sip6
->ip6_src
, &ip6
->ip6_dst
, sizeof(struct in6_addr
));
2437 nd_rd
= (struct nd_redirect
*)(ip6
+ 1);
2438 nd_rd
->nd_rd_type
= ND_REDIRECT
;
2439 nd_rd
->nd_rd_code
= 0;
2440 nd_rd
->nd_rd_reserved
= 0;
2441 if (rt
->rt_flags
& RTF_GATEWAY
) {
2443 * nd_rd->nd_rd_target must be a link-local address in
2444 * better router cases.
2448 bcopy(nexthop
, &nd_rd
->nd_rd_target
,
2449 sizeof(nd_rd
->nd_rd_target
));
2450 bcopy(&sip6
->ip6_dst
, &nd_rd
->nd_rd_dst
,
2451 sizeof(nd_rd
->nd_rd_dst
));
2453 /* make sure redtgt == reddst */
2454 nexthop
= &sip6
->ip6_dst
;
2455 bcopy(&sip6
->ip6_dst
, &nd_rd
->nd_rd_target
,
2456 sizeof(nd_rd
->nd_rd_target
));
2457 bcopy(&sip6
->ip6_dst
, &nd_rd
->nd_rd_dst
,
2458 sizeof(nd_rd
->nd_rd_dst
));
2461 p
= (u_char
*)(nd_rd
+ 1);
2464 /* target lladdr option */
2465 struct rtentry
*rt_nexthop
= NULL
;
2467 const struct sockaddr_dl
*sdl
;
2468 struct nd_opt_hdr
*nd_opt
;
2471 rt_nexthop
= nd6_lookup(nexthop
, 0, ifp
);
2474 len
= sizeof(*nd_opt
) + ifp
->if_addrlen
;
2475 len
= (len
+ 7) & ~7; /* round by 8 */
2477 if (len
+ (p
- (u_char
*)ip6
) > maxlen
)
2479 if (!(rt_nexthop
->rt_flags
& RTF_GATEWAY
) &&
2480 (rt_nexthop
->rt_flags
& RTF_LLINFO
) &&
2481 (rt_nexthop
->rt_gateway
->sa_family
== AF_LINK
) &&
2482 (sdl
= satocsdl(rt_nexthop
->rt_gateway
)) &&
2484 nd_opt
= (struct nd_opt_hdr
*)p
;
2485 nd_opt
->nd_opt_type
= ND_OPT_TARGET_LINKADDR
;
2486 nd_opt
->nd_opt_len
= len
>> 3;
2487 lladdr
= (char *)(nd_opt
+ 1);
2488 memcpy(lladdr
, CLLADDR(sdl
), ifp
->if_addrlen
);
2494 m
->m_pkthdr
.len
= m
->m_len
= p
- (u_char
*)ip6
;
2496 /* just to be safe */
2497 if (m0
->m_flags
& M_DECRYPTED
)
2499 if (p
- (u_char
*)ip6
> maxlen
)
2503 /* redirected header option */
2505 struct nd_opt_rd_hdr
*nd_opt_rh
;
2508 * compute the maximum size for icmp6 redirect header option.
2509 * XXX room for auth header?
2511 len
= maxlen
- (p
- (u_char
*)ip6
);
2515 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2516 * about padding/truncate rule for the original IP packet.
2517 * From the discussion on IPv6imp in Feb 1999,
2518 * the consensus was:
2519 * - "attach as much as possible" is the goal
2520 * - pad if not aligned (original size can be guessed by
2521 * original ip6 header)
2522 * Following code adds the padding if it is simple enough,
2523 * and truncates if not.
2525 if (len
- sizeof(*nd_opt_rh
) < m0
->m_pkthdr
.len
) {
2526 /* not enough room, truncate */
2527 m_adj(m0
, (len
- sizeof(*nd_opt_rh
)) -
2531 * enough room, truncate if not aligned.
2532 * we don't pad here for simplicity.
2536 extra
= m0
->m_pkthdr
.len
% 8;
2541 len
= m0
->m_pkthdr
.len
+ sizeof(*nd_opt_rh
);
2544 nd_opt_rh
= (struct nd_opt_rd_hdr
*)p
;
2545 memset(nd_opt_rh
, 0, sizeof(*nd_opt_rh
));
2546 nd_opt_rh
->nd_opt_rh_type
= ND_OPT_REDIRECTED_HEADER
;
2547 nd_opt_rh
->nd_opt_rh_len
= len
>> 3;
2548 p
+= sizeof(*nd_opt_rh
);
2549 m
->m_pkthdr
.len
= m
->m_len
= p
- (u_char
*)ip6
;
2551 /* connect m0 to m */
2552 m
->m_pkthdr
.len
+= m0
->m_pkthdr
.len
;
2562 /* XXX: clear embedded link IDs in the inner header */
2563 in6_clearscope(&sip6
->ip6_src
);
2564 in6_clearscope(&sip6
->ip6_dst
);
2565 in6_clearscope(&nd_rd
->nd_rd_target
);
2566 in6_clearscope(&nd_rd
->nd_rd_dst
);
2568 ip6
->ip6_plen
= htons(m
->m_pkthdr
.len
- sizeof(struct ip6_hdr
));
2570 nd_rd
->nd_rd_cksum
= 0;
2572 = in6_cksum(m
, IPPROTO_ICMPV6
, sizeof(*ip6
), ntohs(ip6
->ip6_plen
));
2574 /* send the packet to outside... */
2575 if (ip6_output(m
, NULL
, NULL
, 0,
2576 (struct ip6_moptions
*)NULL
, (struct socket
*)NULL
, NULL
) != 0)
2577 icmp6_ifstat_inc(ifp
, ifs6_out_error
);
2579 icmp6_ifstat_inc(ifp
, ifs6_out_msg
);
2580 icmp6_ifstat_inc(ifp
, ifs6_out_redirect
);
2581 ICMP6_STATINC(ICMP6_STAT_OUTHIST
+ ND_REDIRECT
);
2593 * ICMPv6 socket option processing.
2596 icmp6_ctloutput(int op
, struct socket
*so
, struct sockopt
*sopt
)
2599 struct in6pcb
*in6p
= sotoin6pcb(so
);
2601 if (sopt
->sopt_level
!= IPPROTO_ICMPV6
)
2602 return rip6_ctloutput(op
, so
, sopt
);
2606 switch (sopt
->sopt_name
) {
2609 struct icmp6_filter fil
;
2611 error
= sockopt_get(sopt
, &fil
, sizeof(fil
));
2614 memcpy(in6p
->in6p_icmp6filt
, &fil
,
2615 sizeof(struct icmp6_filter
));
2621 error
= ENOPROTOOPT
;
2627 switch (sopt
->sopt_name
) {
2630 if (in6p
->in6p_icmp6filt
== NULL
) {
2634 error
= sockopt_set(sopt
, in6p
->in6p_icmp6filt
,
2635 sizeof(struct icmp6_filter
));
2640 error
= ENOPROTOOPT
;
2650 * Perform rate limit check.
2651 * Returns 0 if it is okay to send the icmp6 packet.
2652 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2655 * XXX per-destination/type check necessary?
2659 const struct in6_addr
*dst
, /* not used at this moment */
2660 const int type
, /* not used at this moment */
2661 const int code
) /* not used at this moment */
2665 ret
= 0; /* okay to send */
2668 if (!ppsratecheck(&icmp6errppslim_last
, &icmp6errpps_count
,
2670 /* The packet is subject to rate limit */
2677 static struct rtentry
*
2678 icmp6_mtudisc_clone(struct sockaddr
*dst
)
2683 rt
= rtalloc1(dst
, 1);
2687 /* If we didn't get a host route, allocate one */
2688 if ((rt
->rt_flags
& RTF_HOST
) == 0) {
2689 struct rtentry
*nrt
;
2691 error
= rtrequest((int) RTM_ADD
, dst
,
2692 (struct sockaddr
*) rt
->rt_gateway
,
2693 (struct sockaddr
*) 0,
2694 RTF_GATEWAY
| RTF_HOST
| RTF_DYNAMIC
, &nrt
);
2699 nrt
->rt_rmx
= rt
->rt_rmx
;
2703 error
= rt_timer_add(rt
, icmp6_mtudisc_timeout
,
2704 icmp6_mtudisc_timeout_q
);
2710 return rt
; /* caller need to call rtfree() */
2714 icmp6_mtudisc_timeout(struct rtentry
*rt
, struct rttimer
*r
)
2717 panic("icmp6_mtudisc_timeout: bad route to timeout");
2718 if ((rt
->rt_flags
& (RTF_DYNAMIC
| RTF_HOST
)) ==
2719 (RTF_DYNAMIC
| RTF_HOST
)) {
2720 rtrequest((int) RTM_DELETE
, rt_getkey(rt
),
2721 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
, 0);
2723 if (!(rt
->rt_rmx
.rmx_locks
& RTV_MTU
))
2724 rt
->rt_rmx
.rmx_mtu
= 0;
2729 icmp6_redirect_timeout(struct rtentry
*rt
, struct rttimer
*r
)
2732 panic("icmp6_redirect_timeout: bad route to timeout");
2733 if ((rt
->rt_flags
& (RTF_GATEWAY
| RTF_DYNAMIC
| RTF_HOST
)) ==
2734 (RTF_GATEWAY
| RTF_DYNAMIC
| RTF_HOST
)) {
2735 rtrequest((int) RTM_DELETE
, rt_getkey(rt
),
2736 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
, 0);
2741 * sysctl helper routine for the net.inet6.icmp6.nd6 nodes. silly?
2744 sysctl_net_inet6_icmp6_nd6(SYSCTLFN_ARGS
)
2753 return (nd6_sysctl(rnode
->sysctl_num
, oldp
, oldlenp
,
2755 __UNCONST(newp
), newlen
));
2759 sysctl_net_inet6_icmp6_stats(SYSCTLFN_ARGS
)
2762 return (NETSTAT_SYSCTL(icmp6stat_percpu
, ICMP6_NSTATS
));
2766 sysctl_net_inet6_icmp6_setup(struct sysctllog
**clog
)
2768 extern int nd6_maxqueuelen
; /* defined in nd6.c */
2770 sysctl_createv(clog
, 0, NULL
, NULL
,
2772 CTLTYPE_NODE
, "net", NULL
,
2775 sysctl_createv(clog
, 0, NULL
, NULL
,
2777 CTLTYPE_NODE
, "inet6", NULL
,
2779 CTL_NET
, PF_INET6
, CTL_EOL
);
2780 sysctl_createv(clog
, 0, NULL
, NULL
,
2782 CTLTYPE_NODE
, "icmp6",
2783 SYSCTL_DESCR("ICMPv6 related settings"),
2785 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
, CTL_EOL
);
2787 sysctl_createv(clog
, 0, NULL
, NULL
,
2789 CTLTYPE_STRUCT
, "stats",
2790 SYSCTL_DESCR("ICMPv6 transmission statistics"),
2791 sysctl_net_inet6_icmp6_stats
, 0, NULL
, 0,
2792 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2793 ICMPV6CTL_STATS
, CTL_EOL
);
2794 sysctl_createv(clog
, 0, NULL
, NULL
,
2795 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2796 CTLTYPE_INT
, "rediraccept",
2797 SYSCTL_DESCR("Accept and process redirect messages"),
2798 NULL
, 0, &icmp6_rediraccept
, 0,
2799 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2800 ICMPV6CTL_REDIRACCEPT
, CTL_EOL
);
2801 sysctl_createv(clog
, 0, NULL
, NULL
,
2802 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2803 CTLTYPE_INT
, "redirtimeout",
2804 SYSCTL_DESCR("Redirect generated route lifetime"),
2805 NULL
, 0, &icmp6_redirtimeout
, 0,
2806 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2807 ICMPV6CTL_REDIRTIMEOUT
, CTL_EOL
);
2808 #if 0 /* obsoleted */
2809 sysctl_createv(clog
, 0, NULL
, NULL
,
2810 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2811 CTLTYPE_INT
, "errratelimit", NULL
,
2812 NULL
, 0, &icmp6_errratelimit
, 0,
2813 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2814 ICMPV6CTL_ERRRATELIMIT
, CTL_EOL
);
2816 sysctl_createv(clog
, 0, NULL
, NULL
,
2817 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2818 CTLTYPE_INT
, "nd6_prune",
2819 SYSCTL_DESCR("Neighbor discovery prune interval"),
2820 NULL
, 0, &nd6_prune
, 0,
2821 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2822 ICMPV6CTL_ND6_PRUNE
, CTL_EOL
);
2823 sysctl_createv(clog
, 0, NULL
, NULL
,
2824 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2825 CTLTYPE_INT
, "nd6_delay",
2826 SYSCTL_DESCR("First probe delay time"),
2827 NULL
, 0, &nd6_delay
, 0,
2828 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2829 ICMPV6CTL_ND6_DELAY
, CTL_EOL
);
2830 sysctl_createv(clog
, 0, NULL
, NULL
,
2831 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2832 CTLTYPE_INT
, "nd6_umaxtries",
2833 SYSCTL_DESCR("Number of unicast discovery attempts"),
2834 NULL
, 0, &nd6_umaxtries
, 0,
2835 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2836 ICMPV6CTL_ND6_UMAXTRIES
, CTL_EOL
);
2837 sysctl_createv(clog
, 0, NULL
, NULL
,
2838 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2839 CTLTYPE_INT
, "nd6_mmaxtries",
2840 SYSCTL_DESCR("Number of multicast discovery attempts"),
2841 NULL
, 0, &nd6_mmaxtries
, 0,
2842 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2843 ICMPV6CTL_ND6_MMAXTRIES
, CTL_EOL
);
2844 sysctl_createv(clog
, 0, NULL
, NULL
,
2845 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2846 CTLTYPE_INT
, "nd6_useloopback",
2847 SYSCTL_DESCR("Use loopback interface for local traffic"),
2848 NULL
, 0, &nd6_useloopback
, 0,
2849 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2850 ICMPV6CTL_ND6_USELOOPBACK
, CTL_EOL
);
2851 #if 0 /* obsoleted */
2852 sysctl_createv(clog
, 0, NULL
, NULL
,
2853 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2854 CTLTYPE_INT
, "nd6_proxyall", NULL
,
2855 NULL
, 0, &nd6_proxyall
, 0,
2856 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2857 ICMPV6CTL_ND6_PROXYALL
, CTL_EOL
);
2859 sysctl_createv(clog
, 0, NULL
, NULL
,
2860 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2861 CTLTYPE_INT
, "nodeinfo",
2862 SYSCTL_DESCR("Respond to node information requests"),
2863 NULL
, 0, &icmp6_nodeinfo
, 0,
2864 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2865 ICMPV6CTL_NODEINFO
, CTL_EOL
);
2866 sysctl_createv(clog
, 0, NULL
, NULL
,
2867 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2868 CTLTYPE_INT
, "errppslimit",
2869 SYSCTL_DESCR("Maximum ICMP errors sent per second"),
2870 NULL
, 0, &icmp6errppslim
, 0,
2871 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2872 ICMPV6CTL_ERRPPSLIMIT
, CTL_EOL
);
2873 sysctl_createv(clog
, 0, NULL
, NULL
,
2874 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2875 CTLTYPE_INT
, "nd6_maxnudhint",
2876 SYSCTL_DESCR("Maximum neighbor unreachable hint count"),
2877 NULL
, 0, &nd6_maxnudhint
, 0,
2878 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2879 ICMPV6CTL_ND6_MAXNUDHINT
, CTL_EOL
);
2880 sysctl_createv(clog
, 0, NULL
, NULL
,
2881 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2882 CTLTYPE_INT
, "mtudisc_hiwat",
2883 SYSCTL_DESCR("Low mark on MTU Discovery route timers"),
2884 NULL
, 0, &icmp6_mtudisc_hiwat
, 0,
2885 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2886 ICMPV6CTL_MTUDISC_HIWAT
, CTL_EOL
);
2887 sysctl_createv(clog
, 0, NULL
, NULL
,
2888 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2889 CTLTYPE_INT
, "mtudisc_lowat",
2890 SYSCTL_DESCR("Low mark on MTU Discovery route timers"),
2891 NULL
, 0, &icmp6_mtudisc_lowat
, 0,
2892 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2893 ICMPV6CTL_MTUDISC_LOWAT
, CTL_EOL
);
2894 sysctl_createv(clog
, 0, NULL
, NULL
,
2895 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2896 CTLTYPE_INT
, "nd6_debug",
2897 SYSCTL_DESCR("Enable neighbor discovery debug output"),
2898 NULL
, 0, &nd6_debug
, 0,
2899 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2900 ICMPV6CTL_ND6_DEBUG
, CTL_EOL
);
2901 sysctl_createv(clog
, 0, NULL
, NULL
,
2903 CTLTYPE_STRUCT
, "nd6_drlist",
2904 SYSCTL_DESCR("Default router list"),
2905 sysctl_net_inet6_icmp6_nd6
, 0, NULL
, 0,
2906 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2907 ICMPV6CTL_ND6_DRLIST
, CTL_EOL
);
2908 sysctl_createv(clog
, 0, NULL
, NULL
,
2910 CTLTYPE_STRUCT
, "nd6_prlist",
2911 SYSCTL_DESCR("Prefix list"),
2912 sysctl_net_inet6_icmp6_nd6
, 0, NULL
, 0,
2913 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2914 ICMPV6CTL_ND6_PRLIST
, CTL_EOL
);
2915 sysctl_createv(clog
, 0, NULL
, NULL
,
2916 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
2917 CTLTYPE_INT
, "maxqueuelen",
2918 SYSCTL_DESCR("max packet queue len for a unresolved ND"),
2919 NULL
, 1, &nd6_maxqueuelen
, 0,
2920 CTL_NET
, PF_INET6
, IPPROTO_ICMPV6
,
2921 ICMPV6CTL_ND6_MAXQLEN
, CTL_EOL
);
2925 icmp6_statinc(u_int stat
)
2928 KASSERT(stat
< ICMP6_NSTATS
);
2929 ICMP6_STATINC(stat
);