]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/icmp6.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / bsd / netinet6 / icmp6.c
1 /*
2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /* $FreeBSD: src/sys/netinet6/icmp6.c,v 1.6.2.6 2001/07/10 09:44:16 ume Exp $ */
30 /* $KAME: icmp6.c,v 1.211 2001/04/04 05:56:20 itojun Exp $ */
31
32 /*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61 /*
62 * Copyright (c) 1982, 1986, 1988, 1993
63 * The Regents of the University of California. All rights reserved.
64 *
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
67 * are met:
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. All advertising materials mentioning features or use of this software
74 * must display the following acknowledgement:
75 * This product includes software developed by the University of
76 * California, Berkeley and its contributors.
77 * 4. Neither the name of the University nor the names of its contributors
78 * may be used to endorse or promote products derived from this software
79 * without specific prior written permission.
80 *
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * SUCH DAMAGE.
92 *
93 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
94 */
95
96
97 #include <sys/param.h>
98 #include <sys/systm.h>
99 #include <sys/lock.h>
100 #include <sys/malloc.h>
101 #include <sys/mcache.h>
102 #include <sys/mbuf.h>
103 #include <sys/protosw.h>
104 #include <sys/socket.h>
105 #include <sys/socketvar.h>
106 #include <sys/time.h>
107 #include <sys/kernel.h>
108 #include <sys/syslog.h>
109 #include <sys/domain.h>
110 #include <sys/kauth.h>
111
112 #include <net/if.h>
113 #include <net/route.h>
114 #include <net/if_dl.h>
115 #include <net/if_types.h>
116
117 #include <netinet/in.h>
118 #include <netinet/in_var.h>
119 #include <netinet/ip6.h>
120 #include <netinet6/ip6_var.h>
121 #include <netinet/icmp6.h>
122 #include <netinet6/mld6_var.h>
123 #include <netinet/in_pcb.h>
124 #include <netinet6/in6_pcb.h>
125 #include <netinet6/in6_var.h>
126 #include <netinet6/nd6.h>
127 #include <netinet6/in6_ifattach.h>
128 #include <netinet6/ip6protosw.h>
129 #include <netinet6/scope6_var.h>
130
131 #if IPSEC
132 #include <netinet6/ipsec.h>
133 #include <netkey/key.h>
134 #endif
135
136 #include <net/net_osdep.h>
137
138 #if NECP
139 #include <net/necp.h>
140 #endif
141
142 extern struct ip6protosw *ip6_protox[];
143
144 extern uint32_t rip_sendspace;
145 extern uint32_t rip_recvspace;
146
147 struct icmp6stat icmp6stat;
148
149 extern struct inpcbhead ripcb;
150 extern int icmp6errppslim;
151 extern int icmp6rappslim;
152 static int icmp6errpps_count = 0;
153 static int icmp6rapps_count = 0;
154 static struct timeval icmp6errppslim_last;
155 static struct timeval icmp6rappslim_last;
156 extern int icmp6_nodeinfo;
157 extern struct inpcbinfo ripcbinfo;
158
159 static void icmp6_errcount(struct icmp6errstat *, int, int);
160 static int icmp6_rip6_input(struct mbuf **, int);
161 static int icmp6_ratelimit(const struct in6_addr *, const int, const int);
162 static const char *icmp6_redirect_diag(struct in6_addr *,
163 struct in6_addr *, struct in6_addr *);
164 static struct mbuf *ni6_input(struct mbuf *, int);
165 static struct mbuf *ni6_nametodns(const char *, int, int);
166 static int ni6_dnsmatch(const char *, int, const char *, int);
167 static int ni6_addrs(struct icmp6_nodeinfo *,
168 struct ifnet **, char *);
169 static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
170 struct ifnet *, int);
171 static int icmp6_notify_error(struct mbuf *, int, int, int);
172
173
174
175 void
176 icmp6_init(struct ip6protosw *pp, struct domain *dp)
177 {
178 #pragma unused(dp)
179 static int icmp6_initialized = 0;
180
181 /* Also called from ip6_init() without pp */
182 VERIFY(pp == NULL ||
183 (pp->pr_flags & (PR_INITIALIZED | PR_ATTACHED)) == PR_ATTACHED);
184
185 /* This gets called by more than one protocols, so initialize once */
186 if (!icmp6_initialized) {
187 icmp6_initialized = 1;
188 mld_init();
189 }
190 }
191
192 static void
193 icmp6_errcount(struct icmp6errstat *stat, int type, int code)
194 {
195 switch (type) {
196 case ICMP6_DST_UNREACH:
197 switch (code) {
198 case ICMP6_DST_UNREACH_NOROUTE:
199 stat->icp6errs_dst_unreach_noroute++;
200 return;
201 case ICMP6_DST_UNREACH_ADMIN:
202 stat->icp6errs_dst_unreach_admin++;
203 return;
204 case ICMP6_DST_UNREACH_BEYONDSCOPE:
205 stat->icp6errs_dst_unreach_beyondscope++;
206 return;
207 case ICMP6_DST_UNREACH_ADDR:
208 stat->icp6errs_dst_unreach_addr++;
209 return;
210 case ICMP6_DST_UNREACH_NOPORT:
211 stat->icp6errs_dst_unreach_noport++;
212 return;
213 }
214 break;
215 case ICMP6_PACKET_TOO_BIG:
216 stat->icp6errs_packet_too_big++;
217 return;
218 case ICMP6_TIME_EXCEEDED:
219 switch (code) {
220 case ICMP6_TIME_EXCEED_TRANSIT:
221 stat->icp6errs_time_exceed_transit++;
222 return;
223 case ICMP6_TIME_EXCEED_REASSEMBLY:
224 stat->icp6errs_time_exceed_reassembly++;
225 return;
226 }
227 break;
228 case ICMP6_PARAM_PROB:
229 switch (code) {
230 case ICMP6_PARAMPROB_HEADER:
231 stat->icp6errs_paramprob_header++;
232 return;
233 case ICMP6_PARAMPROB_NEXTHEADER:
234 stat->icp6errs_paramprob_nextheader++;
235 return;
236 case ICMP6_PARAMPROB_OPTION:
237 stat->icp6errs_paramprob_option++;
238 return;
239 }
240 break;
241 case ND_REDIRECT:
242 stat->icp6errs_redirect++;
243 return;
244 }
245 stat->icp6errs_unknown++;
246 }
247
248 /*
249 * A wrapper function for icmp6_error() necessary when the erroneous packet
250 * may not contain enough scope zone information.
251 */
252 void
253 icmp6_error2(struct mbuf *m, int type, int code, int param,
254 struct ifnet *ifp)
255 {
256 struct ip6_hdr *ip6;
257
258 if (ifp == NULL) {
259 return;
260 }
261
262 #ifndef PULLDOWN_TEST
263 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), return );
264 #else
265 if (m->m_len < sizeof(struct ip6_hdr)) {
266 m = m_pullup(m, sizeof(struct ip6_hdr));
267 if (m == NULL) {
268 return;
269 }
270 }
271 #endif
272
273 ip6 = mtod(m, struct ip6_hdr *);
274
275 if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0) {
276 return;
277 }
278 if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0) {
279 return;
280 }
281
282 icmp6_error(m, type, code, param);
283 }
284
285 /*
286 * Generate an error packet of type error in response to bad IP6 packet.
287 */
288 void
289 icmp6_error(struct mbuf *m, int type, int code, int param)
290 {
291 icmp6_error_flag(m, type, code, param, ICMP6_ERROR_RST_MRCVIF);
292 }
293
294 void
295 icmp6_error_flag(struct mbuf *m, int type, int code, int param, int flags)
296 {
297 struct ip6_hdr *oip6, *nip6;
298 struct icmp6_hdr *icmp6;
299 u_int preplen;
300 int off;
301 int nxt;
302
303 icmp6stat.icp6s_error++;
304
305 /* count per-type-code statistics */
306 icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code);
307
308 #ifdef M_DECRYPTED /*not openbsd*/
309 if (m->m_flags & M_DECRYPTED) {
310 icmp6stat.icp6s_canterror++;
311 goto freeit;
312 }
313 #endif
314
315 #ifndef PULLDOWN_TEST
316 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), return );
317 #else
318 if (m->m_len < sizeof(struct ip6_hdr)) {
319 m = m_pullup(m, sizeof(struct ip6_hdr));
320 if (m == NULL) {
321 return;
322 }
323 }
324 #endif
325 oip6 = mtod(m, struct ip6_hdr *);
326
327 /*
328 * If the destination address of the erroneous packet is a multicast
329 * address, or the packet was sent using link-layer multicast,
330 * we should basically suppress sending an error (RFC 2463, Section
331 * 2.4).
332 * We have two exceptions (the item e.2 in that section):
333 * - the Pakcet Too Big message can be sent for path MTU discovery.
334 * - the Parameter Problem Message that can be allowed an icmp6 error
335 * in the option type field. This check has been done in
336 * ip6_unknown_opt(), so we can just check the type and code.
337 */
338 if ((m->m_flags & (M_BCAST | M_MCAST) ||
339 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
340 (type != ICMP6_PACKET_TOO_BIG &&
341 (type != ICMP6_PARAM_PROB ||
342 code != ICMP6_PARAMPROB_OPTION))) {
343 goto freeit;
344 }
345
346 /*
347 * RFC 2463, 2.4 (e.5): source address check.
348 * XXX: the case of anycast source?
349 */
350 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
351 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) {
352 goto freeit;
353 }
354
355 /*
356 * If we are about to send ICMPv6 against ICMPv6 error/redirect,
357 * don't do it.
358 */
359 nxt = -1;
360 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
361 if (off >= 0 && nxt == IPPROTO_ICMPV6) {
362 struct icmp6_hdr *icp;
363
364 #ifndef PULLDOWN_TEST
365 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), return );
366 icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
367 #else
368 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
369 sizeof(*icp));
370 if (icp == NULL) {
371 icmp6stat.icp6s_tooshort++;
372 return;
373 }
374 #endif
375 if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
376 icp->icmp6_type == ND_REDIRECT) {
377 /*
378 * ICMPv6 error
379 * Special case: for redirect (which is
380 * informational) we must not send icmp6 error.
381 */
382 icmp6stat.icp6s_canterror++;
383 goto freeit;
384 } else {
385 /* ICMPv6 informational - send the error */
386 }
387 } else {
388 /* non-ICMPv6 - send the error */
389 }
390
391 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
392
393 /* Finally, do rate limitation check. */
394 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
395 icmp6stat.icp6s_toofreq++;
396 goto freeit;
397 }
398
399 /*
400 * OK, ICMP6 can be generated.
401 */
402
403 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) {
404 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
405 }
406
407 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
408 M_PREPEND(m, preplen, M_DONTWAIT, 1);
409 if (m && m->m_len < preplen) {
410 m = m_pullup(m, preplen);
411 }
412 if (m == NULL) {
413 nd6log(debug, "ENOBUFS in icmp6_error %d\n", __LINE__);
414 return;
415 }
416
417 nip6 = mtod(m, struct ip6_hdr *);
418 nip6->ip6_src = oip6->ip6_src;
419 nip6->ip6_dst = oip6->ip6_dst;
420
421 in6_clearscope(&oip6->ip6_src);
422 in6_clearscope(&oip6->ip6_dst);
423
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);
428
429 /*
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).
435 */
436 if (flags & ICMP6_ERROR_RST_MRCVIF) {
437 m->m_pkthdr.rcvif = NULL;
438 }
439
440 icmp6stat.icp6s_outhist[type]++;
441 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
442
443 return;
444
445 freeit:
446 /*
447 * If we can't tell whether or not we can generate ICMP6, free it.
448 */
449 m_freem(m);
450 }
451
452 /*
453 * Process a received ICMP6 message.
454 */
455 int
456 icmp6_input(struct mbuf **mp, int *offp, int proto)
457 {
458 #pragma unused(proto)
459 struct mbuf *m = *mp, *n;
460 struct ifnet *ifp;
461 struct ip6_hdr *ip6, *nip6;
462 struct icmp6_hdr *icmp6, *nicmp6;
463 int off = *offp;
464 int icmp6len = m->m_pkthdr.len - *offp;
465 int code, sum, noff, proxy = 0;
466
467 ifp = m->m_pkthdr.rcvif;
468
469 #ifndef PULLDOWN_TEST
470 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), return IPPROTO_DONE);
471 /* m might change if M_LOOP. So, call mtod after this */
472 #endif
473
474 /* Expect 32-bit aligned data pointer on strict-align platforms */
475 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
476
477 /*
478 * Locate icmp6 structure in mbuf, and check
479 * that not corrupted and of at least minimum length
480 */
481 ip6 = mtod(m, struct ip6_hdr *);
482 if (icmp6len < sizeof(struct icmp6_hdr)) {
483 icmp6stat.icp6s_tooshort++;
484 goto freeit;
485 }
486
487 #ifndef PULLDOWN_TEST
488 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
489 #else
490 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
491 if (icmp6 == NULL) {
492 icmp6stat.icp6s_tooshort++;
493 return IPPROTO_DONE;
494 }
495 #endif
496 code = icmp6->icmp6_code;
497
498 /*
499 * Early check for RFC 6980
500 * Drop certain NDP packets if they came in fragmented
501 */
502 switch (icmp6->icmp6_type) {
503 case ND_ROUTER_SOLICIT:
504 case ND_ROUTER_ADVERT:
505 case ND_NEIGHBOR_SOLICIT:
506 case ND_NEIGHBOR_ADVERT:
507 case ND_REDIRECT:
508 if (m->m_pkthdr.pkt_flags & PKTF_REASSEMBLED) {
509 icmp6stat.icp6s_rfc6980_drop++;
510 goto freeit;
511 }
512 break;
513 default:
514 break;
515 }
516
517 /* Apply rate limit before checksum validation. */
518 if (icmp6_ratelimit(&ip6->ip6_dst, icmp6->icmp6_type, code)) {
519 icmp6stat.icp6s_toofreq++;
520 goto freeit;
521 }
522
523 /*
524 * Check multicast group membership.
525 * Note: SSM filters are not applied for ICMPv6 traffic.
526 */
527 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
528 struct in6_multi *inm;
529
530 in6_multihead_lock_shared();
531 IN6_LOOKUP_MULTI(&ip6->ip6_dst, ifp, inm);
532 in6_multihead_lock_done();
533
534 if (inm == NULL) {
535 /*
536 * Don't discard if this is a Neighbor Solicitation
537 * that needs to be proxied (see check down below.)
538 */
539 if (!(m->m_pkthdr.pkt_flags & PKTF_PROXY_DST)) {
540 ip6stat.ip6s_notmember++;
541 in6_ifstat_inc(m->m_pkthdr.rcvif,
542 ifs6_in_discard);
543 goto freeit;
544 }
545 } else {
546 IN6M_REMREF(inm);
547 }
548 }
549
550 /*
551 * calculate the checksum
552 */
553 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
554 nd6log(error,
555 "ICMP6 checksum error(%d|%x) %s\n",
556 icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src));
557 icmp6stat.icp6s_checksum++;
558 goto freeit;
559 }
560
561 if (m->m_pkthdr.pkt_flags & PKTF_PROXY_DST) {
562 /*
563 * This is the special case of proxying NS (dst is either
564 * solicited-node multicast or unicast); process it locally
565 * but don't deliver it to sockets. It practically lets us
566 * steer the packet to nd6_prproxy_ns_input, where more
567 * specific tests and actions will be taken.
568 */
569 switch (icmp6->icmp6_type) {
570 case ND_NEIGHBOR_SOLICIT:
571 proxy = 1;
572 break;
573 default:
574 goto freeit;
575 }
576 }
577
578 icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
579 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
580 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) {
581 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
582 }
583
584 switch (icmp6->icmp6_type) {
585 case ICMP6_DST_UNREACH:
586 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
587 switch (code) {
588 case ICMP6_DST_UNREACH_NOROUTE:
589 case ICMP6_DST_UNREACH_ADDR: /* PRC_HOSTDEAD is a DOS */
590 code = PRC_UNREACH_NET;
591 break;
592 case ICMP6_DST_UNREACH_ADMIN:
593 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib);
594 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */
595 break;
596 case ICMP6_DST_UNREACH_BEYONDSCOPE:
597 /* I mean "source address was incorrect." */
598 code = PRC_PARAMPROB;
599 break;
600 case ICMP6_DST_UNREACH_NOPORT:
601 code = PRC_UNREACH_PORT;
602 break;
603 default:
604 goto badcode;
605 }
606 goto deliver;
607
608 case ICMP6_PACKET_TOO_BIG:
609 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
610
611 code = PRC_MSGSIZE;
612
613 /*
614 * Updating the path MTU will be done after examining
615 * intermediate extension headers.
616 */
617 goto deliver;
618
619 case ICMP6_TIME_EXCEEDED:
620 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
621 switch (code) {
622 case ICMP6_TIME_EXCEED_TRANSIT:
623 code = PRC_TIMXCEED_INTRANS;
624 break;
625 case ICMP6_TIME_EXCEED_REASSEMBLY:
626 code = PRC_TIMXCEED_REASS;
627 break;
628 default:
629 goto badcode;
630 }
631 goto deliver;
632
633 case ICMP6_PARAM_PROB:
634 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob);
635 switch (code) {
636 case ICMP6_PARAMPROB_NEXTHEADER:
637 code = PRC_UNREACH_PROTOCOL;
638 break;
639 case ICMP6_PARAMPROB_HEADER:
640 case ICMP6_PARAMPROB_OPTION:
641 code = PRC_PARAMPROB;
642 break;
643 default:
644 goto badcode;
645 }
646 goto deliver;
647
648 case ICMP6_ECHO_REQUEST:
649 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo);
650 if (code != 0) {
651 goto badcode;
652 }
653
654 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) {
655 /* Give up remote */
656 goto rate_limit_checked;
657 }
658 if ((n->m_flags & M_EXT) != 0
659 || n->m_len < off + sizeof(struct icmp6_hdr)) {
660 struct mbuf *n0 = n;
661 const int maxlen = sizeof(*nip6) + sizeof(*nicmp6);
662
663 /*
664 * Prepare an internal mbuf. m_pullup() doesn't
665 * always copy the length we specified.
666 */
667 if (maxlen >= MCLBYTES) {
668 /* Give up remote */
669 m_freem(n0);
670 goto rate_limit_checked;
671 }
672 MGETHDR(n, M_DONTWAIT, n0->m_type); /* MAC-OK */
673 if (n && maxlen >= MHLEN) {
674 MCLGET(n, M_DONTWAIT);
675 if ((n->m_flags & M_EXT) == 0) {
676 m_free(n);
677 n = NULL;
678 }
679 }
680 if (n == NULL) {
681 /* Give up remote */
682 m_freem(n0);
683 goto rate_limit_checked;
684 }
685 M_COPY_PKTHDR(n, n0);
686 /*
687 * Copy IPv6 and ICMPv6 only.
688 */
689 nip6 = mtod(n, struct ip6_hdr *);
690 bcopy(ip6, nip6, sizeof(struct ip6_hdr));
691 nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
692 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
693 noff = sizeof(struct ip6_hdr);
694 n->m_pkthdr.len = n->m_len =
695 noff + sizeof(struct icmp6_hdr);
696 /*
697 * Adjust mbuf. ip6_plen will be adjusted in
698 * ip6_output().
699 */
700 m_adj(n0, off + sizeof(struct icmp6_hdr));
701 n->m_pkthdr.len += n0->m_pkthdr.len;
702 n->m_next = n0;
703 n0->m_flags &= ~M_PKTHDR;
704 } else {
705 nip6 = mtod(n, struct ip6_hdr *);
706 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off,
707 sizeof(*nicmp6));
708 noff = off;
709 }
710 if (nicmp6 == NULL) {
711 panic("nicmp6 is NULL in %s, which isn't good!\n", __FUNCTION__);
712 } else {
713 nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
714 nicmp6->icmp6_code = 0;
715 }
716 if (n) {
717 icmp6stat.icp6s_reflect++;
718 icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
719 icmp6_reflect(n, noff);
720 }
721 goto rate_limit_checked;
722
723 case ICMP6_ECHO_REPLY:
724 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
725 if (code != 0) {
726 goto badcode;
727 }
728 break;
729
730 case MLD_LISTENER_QUERY:
731 case MLD_LISTENER_REPORT:
732
733 if (icmp6len < sizeof(struct mld_hdr)) {
734 goto badlen;
735 }
736 if (icmp6->icmp6_type == MLD_LISTENER_QUERY) { /* XXX: ugly... */
737 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery);
738 } else {
739 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport);
740 }
741
742 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
743 /* give up local */
744 if (mld_input(m, off, icmp6len) == IPPROTO_DONE) {
745 m = NULL;
746 }
747 goto freeit;
748 }
749 if (mld_input(n, off, icmp6len) != IPPROTO_DONE) {
750 m_freem(n);
751 }
752 /* m stays. */
753 goto rate_limit_checked;
754
755 case MLD_LISTENER_DONE:
756 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone);
757 if (icmp6len < sizeof(struct mld_hdr)) { /* necessary? */
758 goto badlen;
759 }
760 break; /* nothing to be done in kernel */
761
762 case MLD_MTRACE_RESP:
763 case MLD_MTRACE:
764 /* XXX: these two are experimental. not officially defined. */
765 /* XXX: per-interface statistics? */
766 break; /* just pass it to applications */
767
768 case ICMP6_NI_QUERY:
769 if (!icmp6_nodeinfo) {
770 break;
771 }
772 //### LD 10/20 Check fbsd differences here. Not sure we're more advanced or not.
773 /* By RFC 4620 refuse to answer queries from global scope addresses */
774 if ((icmp6_nodeinfo & 8) != 8 && in6_addrscope(&ip6->ip6_src) == IPV6_ADDR_SCOPE_GLOBAL) {
775 break;
776 }
777
778 if (icmp6len < sizeof(struct icmp6_nodeinfo)) {
779 goto badlen;
780 }
781
782 #ifndef PULLDOWN_TEST
783 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo),
784 return IPPROTO_DONE);
785 #endif
786
787 n = m_copy(m, 0, M_COPYALL);
788 if (n) {
789 n = ni6_input(n, off);
790 }
791 if (n) {
792 noff = sizeof(struct ip6_hdr);
793 icmp6stat.icp6s_reflect++;
794 icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
795 icmp6_reflect(n, noff);
796 }
797 goto rate_limit_checked;
798
799 case ICMP6_WRUREPLY:
800 if (code != 0) {
801 goto badcode;
802 }
803 break;
804
805 case ND_ROUTER_SOLICIT:
806 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit);
807 if (code != 0) {
808 goto badcode;
809 }
810 if (icmp6len < sizeof(struct nd_router_solicit)) {
811 goto badlen;
812 }
813
814 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
815 /* give up local */
816 nd6_rs_input(m, off, icmp6len);
817 m = NULL;
818 goto freeit;
819 }
820 nd6_rs_input(n, off, icmp6len);
821 /* m stays. */
822 goto rate_limit_checked;
823
824 case ND_ROUTER_ADVERT:
825 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert);
826 if (code != 0) {
827 goto badcode;
828 }
829 if (icmp6len < sizeof(struct nd_router_advert)) {
830 goto badlen;
831 }
832
833 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
834 /* give up local */
835 nd6_ra_input(m, off, icmp6len);
836 m = NULL;
837 goto freeit;
838 }
839 nd6_ra_input(n, off, icmp6len);
840 /* m stays. */
841 goto rate_limit_checked;
842
843 case ND_NEIGHBOR_SOLICIT:
844 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit);
845 if (code != 0) {
846 goto badcode;
847 }
848 if (icmp6len < sizeof(struct nd_neighbor_solicit)) {
849 goto badlen;
850 }
851
852 if (proxy ||
853 ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL)) {
854 /* give up local */
855 nd6_ns_input(m, off, icmp6len);
856 m = NULL;
857 goto freeit;
858 }
859 nd6_ns_input(n, off, icmp6len);
860 /* m stays. */
861 goto rate_limit_checked;
862
863 case ND_NEIGHBOR_ADVERT:
864 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert);
865 if (code != 0) {
866 goto badcode;
867 }
868 if (icmp6len < sizeof(struct nd_neighbor_advert)) {
869 goto badlen;
870 }
871
872 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
873 /* give up local */
874 nd6_na_input(m, off, icmp6len);
875 m = NULL;
876 goto freeit;
877 }
878 nd6_na_input(n, off, icmp6len);
879 /* m stays. */
880 goto rate_limit_checked;
881
882 case ND_REDIRECT:
883 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect);
884 if (code != 0) {
885 goto badcode;
886 }
887 if (icmp6len < sizeof(struct nd_redirect)) {
888 goto badlen;
889 }
890
891 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
892 /* give up local */
893 icmp6_redirect_input(m, off);
894 m = NULL;
895 goto freeit;
896 }
897 icmp6_redirect_input(n, off);
898 /* m stays. */
899 goto rate_limit_checked;
900
901 case ICMP6_ROUTER_RENUMBERING:
902 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
903 code != ICMP6_ROUTER_RENUMBERING_RESULT) {
904 goto badcode;
905 }
906 if (icmp6len < sizeof(struct icmp6_router_renum)) {
907 goto badlen;
908 }
909 break;
910
911 default:
912 nd6log(debug,
913 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
914 icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
915 ip6_sprintf(&ip6->ip6_dst),
916 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0);
917 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
918 /* ICMPv6 error: MUST deliver it by spec... */
919 code = PRC_NCMDS;
920 /* deliver */
921 } else {
922 /* ICMPv6 informational: MUST not deliver */
923 goto rate_limit_checked;
924 }
925 deliver:
926 if (icmp6_notify_error(m, off, icmp6len, code)) {
927 /* In this case, m should've been freed. */
928 return IPPROTO_DONE;
929 }
930 break;
931
932 badcode:
933 icmp6stat.icp6s_badcode++;
934 break;
935
936 badlen:
937 icmp6stat.icp6s_badlen++;
938 break;
939 }
940
941 rate_limit_checked:
942 icmp6_rip6_input(&m, *offp);
943 return IPPROTO_DONE;
944
945 freeit:
946 m_freem(m);
947 return IPPROTO_DONE;
948 }
949
950 static int
951 icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code)
952 {
953 struct icmp6_hdr *icmp6;
954 struct ip6_hdr *eip6;
955 u_int32_t notifymtu;
956 struct sockaddr_in6 icmp6src, icmp6dst;
957
958 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
959 icmp6stat.icp6s_tooshort++;
960 goto freeit;
961 }
962 #ifndef PULLDOWN_TEST
963 IP6_EXTHDR_CHECK(m, off,
964 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr),
965 return -1);
966 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
967 #else
968 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
969 sizeof(*icmp6) + sizeof(struct ip6_hdr));
970 if (icmp6 == NULL) {
971 icmp6stat.icp6s_tooshort++;
972 return -1;
973 }
974 #endif
975 eip6 = (struct ip6_hdr *)(icmp6 + 1);
976
977 /* Detect the upper level protocol */
978 {
979 void (*ctlfunc)(int, struct sockaddr *, void *, struct ifnet *);
980 u_int8_t nxt = eip6->ip6_nxt;
981 int eoff = off + sizeof(struct icmp6_hdr) +
982 sizeof(struct ip6_hdr);
983 struct ip6ctlparam ip6cp;
984 struct in6_addr *finaldst = NULL;
985 int icmp6type = icmp6->icmp6_type;
986 struct ip6_frag *fh;
987 struct ip6_rthdr *rth;
988 struct ip6_rthdr0 *rth0;
989 int rthlen;
990
991 while (1) { /* XXX: should avoid infinite loop explicitly? */
992 struct ip6_ext *eh;
993
994 switch (nxt) {
995 case IPPROTO_HOPOPTS:
996 case IPPROTO_DSTOPTS:
997 case IPPROTO_AH:
998 #ifndef PULLDOWN_TEST
999 IP6_EXTHDR_CHECK(m, 0,
1000 eoff + sizeof(struct ip6_ext), return -1);
1001 eh = (struct ip6_ext *)(mtod(m, caddr_t)
1002 + eoff);
1003 #else
1004 IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
1005 eoff, sizeof(*eh));
1006 if (eh == NULL) {
1007 icmp6stat.icp6s_tooshort++;
1008 return -1;
1009 }
1010 #endif
1011
1012 if (nxt == IPPROTO_AH) {
1013 eoff += (eh->ip6e_len + 2) << 2;
1014 } else {
1015 eoff += (eh->ip6e_len + 1) << 3;
1016 }
1017 nxt = eh->ip6e_nxt;
1018 break;
1019 case IPPROTO_ROUTING:
1020 /*
1021 * When the erroneous packet contains a
1022 * routing header, we should examine the
1023 * header to determine the final destination.
1024 * Otherwise, we can't properly update
1025 * information that depends on the final
1026 * destination (e.g. path MTU).
1027 */
1028 #ifndef PULLDOWN_TEST
1029 IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth),
1030 return -1);
1031 rth = (struct ip6_rthdr *)
1032 (mtod(m, caddr_t) + eoff);
1033 #else
1034 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
1035 eoff, sizeof(*rth));
1036 if (rth == NULL) {
1037 icmp6stat.icp6s_tooshort++;
1038 return -1;
1039 }
1040 #endif
1041 rthlen = (rth->ip6r_len + 1) << 3;
1042 /*
1043 * XXX: currently there is no
1044 * officially defined type other
1045 * than type-0.
1046 * Note that if the segment left field
1047 * is 0, all intermediate hops must
1048 * have been passed.
1049 */
1050 if (rth->ip6r_segleft &&
1051 rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
1052 int hops;
1053
1054 #ifndef PULLDOWN_TEST
1055 IP6_EXTHDR_CHECK(m, 0, eoff + rthlen,
1056 return -1);
1057 rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff);
1058 #else
1059 IP6_EXTHDR_GET(rth0,
1060 struct ip6_rthdr0 *, m,
1061 eoff, rthlen);
1062 if (rth0 == NULL) {
1063 icmp6stat.icp6s_tooshort++;
1064 return -1;
1065 }
1066 #endif
1067 /* just ignore a bogus header */
1068 if ((rth0->ip6r0_len % 2) == 0 &&
1069 (hops = rth0->ip6r0_len / 2)) {
1070 finaldst = (struct in6_addr *)(void *)(rth0 + 1) + (hops - 1);
1071 }
1072 }
1073 eoff += rthlen;
1074 nxt = rth->ip6r_nxt;
1075 break;
1076 case IPPROTO_FRAGMENT:
1077 #ifndef PULLDOWN_TEST
1078 IP6_EXTHDR_CHECK(m, 0, eoff +
1079 sizeof(struct ip6_frag),
1080 return -1);
1081 fh = (struct ip6_frag *)(mtod(m, caddr_t)
1082 + eoff);
1083 #else
1084 IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
1085 eoff, sizeof(*fh));
1086 if (fh == NULL) {
1087 icmp6stat.icp6s_tooshort++;
1088 return -1;
1089 }
1090 #endif
1091 /*
1092 * Data after a fragment header is meaningless
1093 * unless it is the first fragment, but
1094 * we'll go to the notify label for path MTU
1095 * discovery.
1096 */
1097 if (fh->ip6f_offlg & IP6F_OFF_MASK) {
1098 goto notify;
1099 }
1100
1101 eoff += sizeof(struct ip6_frag);
1102 nxt = fh->ip6f_nxt;
1103 break;
1104 default:
1105 /*
1106 * This case includes ESP and the No Next
1107 * Header. In such cases going to the notify
1108 * label does not have any meaning
1109 * (i.e. ctlfunc will be NULL), but we go
1110 * anyway since we might have to update
1111 * path MTU information.
1112 */
1113 goto notify;
1114 }
1115 }
1116 notify:
1117 #ifndef PULLDOWN_TEST
1118 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
1119 #else
1120 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
1121 sizeof(*icmp6) + sizeof(struct ip6_hdr));
1122 if (icmp6 == NULL) {
1123 icmp6stat.icp6s_tooshort++;
1124 return -1;
1125 }
1126 #endif
1127
1128 /*
1129 * retrieve parameters from the inner IPv6 header, and convert
1130 * them into sockaddr structures.
1131 * XXX: there is no guarantee that the source or destination
1132 * addresses of the inner packet are in the same scope as
1133 * the addresses of the icmp packet. But there is no other
1134 * way to determine the zone.
1135 */
1136 eip6 = (struct ip6_hdr *)(icmp6 + 1);
1137
1138 bzero(&icmp6dst, sizeof(icmp6dst));
1139 icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
1140 icmp6dst.sin6_family = AF_INET6;
1141 if (finaldst == NULL) {
1142 icmp6dst.sin6_addr = eip6->ip6_dst;
1143 } else {
1144 icmp6dst.sin6_addr = *finaldst;
1145 }
1146 if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL)) {
1147 goto freeit;
1148 }
1149 bzero(&icmp6src, sizeof(icmp6src));
1150 icmp6src.sin6_len = sizeof(struct sockaddr_in6);
1151 icmp6src.sin6_family = AF_INET6;
1152 icmp6src.sin6_addr = eip6->ip6_src;
1153 if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL)) {
1154 goto freeit;
1155 }
1156 icmp6src.sin6_flowinfo =
1157 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
1158
1159 if (finaldst == NULL) {
1160 finaldst = &eip6->ip6_dst;
1161 }
1162 ip6cp.ip6c_m = m;
1163 ip6cp.ip6c_icmp6 = icmp6;
1164 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
1165 ip6cp.ip6c_off = eoff;
1166 ip6cp.ip6c_finaldst = finaldst;
1167 ip6cp.ip6c_src = &icmp6src;
1168 ip6cp.ip6c_nxt = nxt;
1169
1170 if (icmp6type == ICMP6_PACKET_TOO_BIG) {
1171 notifymtu = ntohl(icmp6->icmp6_mtu);
1172 ip6cp.ip6c_cmdarg = (void *)&notifymtu;
1173 icmp6_mtudisc_update(&ip6cp, 1); /*XXX*/
1174 }
1175
1176 ctlfunc = ip6_protox[nxt]->pr_ctlinput;
1177 if (ctlfunc) {
1178 LCK_MTX_ASSERT(inet6_domain_mutex, LCK_MTX_ASSERT_OWNED);
1179
1180 lck_mtx_unlock(inet6_domain_mutex);
1181
1182 (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst,
1183 &ip6cp, m->m_pkthdr.rcvif);
1184
1185 lck_mtx_lock(inet6_domain_mutex);
1186 }
1187 }
1188 return 0;
1189
1190 freeit:
1191 m_freem(m);
1192 return -1;
1193 }
1194
1195 void
1196 icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
1197 {
1198 struct in6_addr *dst = ip6cp->ip6c_finaldst;
1199 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
1200 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
1201 u_int mtu = ntohl(icmp6->icmp6_mtu);
1202 struct rtentry *rt = NULL;
1203 struct sockaddr_in6 sin6;
1204 /*
1205 * we reject ICMPv6 too big with abnormally small value.
1206 * XXX what is the good definition of "abnormally small"?
1207 */
1208 if (mtu < sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + 8) {
1209 return;
1210 }
1211
1212 if (!validated) {
1213 return;
1214 }
1215
1216 /* Limit the MTU to the minimum IPv6 MTU */
1217 if (mtu < IPV6_MMTU) {
1218 mtu = IPV6_MMTU;
1219 }
1220
1221 bzero(&sin6, sizeof(sin6));
1222 sin6.sin6_family = PF_INET6;
1223 sin6.sin6_len = sizeof(struct sockaddr_in6);
1224 sin6.sin6_addr = *dst;
1225 /* XXX normally, this won't happen */
1226 if (IN6_IS_ADDR_LINKLOCAL(dst)) {
1227 sin6.sin6_addr.s6_addr16[1] =
1228 htons(m->m_pkthdr.rcvif->if_index);
1229 }
1230 /* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */
1231 /*
1232 * XXX On a side note, for asymmetric data-path
1233 * the lookup on receive interace is probably not
1234 * what we want to do.
1235 * That requires looking at the cached route for the
1236 * protocol control block.
1237 */
1238 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0,
1239 RTF_CLONING | RTF_PRCLONING, m->m_pkthdr.rcvif->if_index);
1240 if (rt != NULL) {
1241 RT_LOCK(rt);
1242 if ((rt->rt_flags & RTF_HOST) &&
1243 !(rt->rt_rmx.rmx_locks & RTV_MTU) &&
1244 mtu < IN6_LINKMTU(rt->rt_ifp) &&
1245 rt->rt_rmx.rmx_mtu > mtu) {
1246 icmp6stat.icp6s_pmtuchg++;
1247 rt->rt_rmx.rmx_mtu = mtu;
1248 }
1249 RT_UNLOCK(rt);
1250 rtfree(rt);
1251 }
1252 }
1253
1254 /*
1255 * Process a Node Information Query packet, based on
1256 * draft-ietf-ipngwg-icmp-name-lookups-07.
1257 *
1258 * Spec incompatibilities:
1259 * - IPv6 Subject address handling
1260 * - IPv4 Subject address handling support missing
1261 * - Proxy reply (answer even if it's not for me)
1262 * - joins NI group address at in6_ifattach() time only, does not cope
1263 * with hostname changes by sethostname(3)
1264 */
1265 #define hostnamelen strlen(hostname)
1266 static struct mbuf *
1267 ni6_input(struct mbuf *m, int off)
1268 {
1269 struct icmp6_nodeinfo *ni6, *nni6;
1270 struct mbuf *n = NULL;
1271 u_int16_t qtype;
1272 int subjlen;
1273 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1274 struct ni_reply_fqdn *fqdn;
1275 int addrs; /* for NI_QTYPE_NODEADDR */
1276 struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1277 struct sockaddr_in6 sin6; /* double meaning; ip6_dst and subjectaddr */
1278 struct sockaddr_in6 sin6_d; /* XXX: we should retrieve this from m_aux */
1279 struct ip6_hdr *ip6;
1280 int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
1281 char *subj = NULL;
1282
1283 ip6 = mtod(m, struct ip6_hdr *);
1284 #ifndef PULLDOWN_TEST
1285 ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1286 #else
1287 IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
1288 if (ni6 == NULL) {
1289 /* m is already reclaimed */
1290 return NULL;
1291 }
1292 #endif
1293
1294 /*
1295 * Validate IPv6 source address.
1296 * The default configuration MUST be to refuse answering queries from
1297 * global-scope addresses according to RFC4602.
1298 * Notes:
1299 * - it's not very clear what "refuse" means; this implementation
1300 * simply drops it.
1301 * - it's not very easy to identify global-scope (unicast) addresses
1302 * since there are many prefixes for them. It should be safer
1303 * and in practice sufficient to check "all" but loopback and
1304 * link-local (note that site-local unicast was deprecated and
1305 * ULA is defined as global scope-wise)
1306 */
1307 if ((icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1308 !IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1309 !IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
1310 goto bad;
1311 }
1312
1313 /*
1314 * Validate IPv6 destination address.
1315 *
1316 * The Responder must discard the Query without further processing
1317 * unless it is one of the Responder's unicast or anycast addresses, or
1318 * a link-local scope multicast address which the Responder has joined.
1319 * [RFC4602, Section 5.]
1320 */
1321 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
1322 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) {
1323 goto bad;
1324 }
1325 /* else it's a link-local multicast, fine */
1326 } else { /* unicast or anycast */
1327 uint32_t ia6_flags;
1328
1329 if (ip6_getdstifaddr_info(m, NULL, &ia6_flags) != 0) {
1330 goto bad; /* XXX impossible */
1331 }
1332 if ((ia6_flags & IN6_IFF_TEMPORARY) &&
1333 !(icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1334 nd6log(debug, "ni6_input: ignore node info to a temporary address in %s:%d",
1335 __func__, __LINE__);
1336 goto bad;
1337 }
1338 }
1339
1340 /* validate query Subject field. */
1341 qtype = ntohs(ni6->ni_qtype);
1342 subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1343 switch (qtype) {
1344 case NI_QTYPE_NOOP:
1345 case NI_QTYPE_SUPTYPES:
1346 /* 07 draft */
1347 if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0) {
1348 break;
1349 }
1350 /* FALLTHROUGH */
1351 case NI_QTYPE_FQDN:
1352 case NI_QTYPE_NODEADDR:
1353 case NI_QTYPE_IPV4ADDR:
1354 switch (ni6->ni_code) {
1355 case ICMP6_NI_SUBJ_IPV6:
1356 #if ICMP6_NI_SUBJ_IPV6 != 0
1357 case 0:
1358 #endif
1359 /*
1360 * backward compatibility - try to accept 03 draft
1361 * format, where no Subject is present.
1362 */
1363 if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
1364 subjlen == 0) {
1365 oldfqdn++;
1366 break;
1367 }
1368 #if ICMP6_NI_SUBJ_IPV6 != 0
1369 if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6) {
1370 goto bad;
1371 }
1372 #endif
1373
1374 if (subjlen != sizeof(struct in6_addr)) {
1375 goto bad;
1376 }
1377
1378 /*
1379 * Validate Subject address.
1380 *
1381 * Not sure what exactly "address belongs to the node"
1382 * means in the spec, is it just unicast, or what?
1383 *
1384 * At this moment we consider Subject address as
1385 * "belong to the node" if the Subject address equals
1386 * to the IPv6 destination address; validation for
1387 * IPv6 destination address should have done enough
1388 * check for us.
1389 *
1390 * We do not do proxy at this moment.
1391 */
1392 /* m_pulldown instead of copy? */
1393 m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1394 subjlen, (caddr_t)&sin6.sin6_addr);
1395 sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
1396 &sin6.sin6_addr);
1397 in6_embedscope(&sin6.sin6_addr, &sin6, NULL, NULL,
1398 NULL);
1399 bzero(&sin6_d, sizeof(sin6_d));
1400 sin6_d.sin6_family = AF_INET6; /* not used, actually */
1401 sin6_d.sin6_len = sizeof(sin6_d); /* ditto */
1402 sin6_d.sin6_addr = ip6->ip6_dst;
1403 sin6_d.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
1404 &ip6->ip6_dst);
1405 in6_embedscope(&sin6_d.sin6_addr, &sin6_d, NULL, NULL,
1406 NULL);
1407 subj = (char *)&sin6;
1408 if (SA6_ARE_ADDR_EQUAL(&sin6, &sin6_d)) {
1409 break;
1410 }
1411
1412 /*
1413 * XXX if we are to allow other cases, we should really
1414 * be careful about scope here.
1415 * basically, we should disallow queries toward IPv6
1416 * destination X with subject Y,
1417 * if scope(X) > scope(Y).
1418 * if we allow scope(X) > scope(Y), it will result in
1419 * information leakage across scope boundary.
1420 */
1421 goto bad;
1422
1423 case ICMP6_NI_SUBJ_FQDN:
1424 /*
1425 * Validate Subject name with gethostname(3).
1426 *
1427 * The behavior may need some debate, since:
1428 * - we are not sure if the node has FQDN as
1429 * hostname (returned by gethostname(3)).
1430 * - the code does wildcard match for truncated names.
1431 * however, we are not sure if we want to perform
1432 * wildcard match, if gethostname(3) side has
1433 * truncated hostname.
1434 */
1435 lck_mtx_lock(&hostname_lock);
1436 n = ni6_nametodns(hostname, hostnamelen, 0);
1437 lck_mtx_unlock(&hostname_lock);
1438 if (!n || n->m_next || n->m_len == 0) {
1439 goto bad;
1440 }
1441 IP6_EXTHDR_GET(subj, char *, m,
1442 off + sizeof(struct icmp6_nodeinfo), subjlen);
1443 if (subj == NULL) {
1444 goto bad;
1445 }
1446 if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1447 n->m_len)) {
1448 goto bad;
1449 }
1450 m_freem(n);
1451 n = NULL;
1452 break;
1453
1454 case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */
1455 default:
1456 goto bad;
1457 }
1458 break;
1459 }
1460
1461 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1462 switch (qtype) {
1463 case NI_QTYPE_FQDN:
1464 if ((icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0) {
1465 goto bad;
1466 }
1467 break;
1468 case NI_QTYPE_NODEADDR:
1469 case NI_QTYPE_IPV4ADDR:
1470 if ((icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0) {
1471 goto bad;
1472 }
1473 break;
1474 }
1475
1476 /* guess reply length */
1477 switch (qtype) {
1478 case NI_QTYPE_NOOP:
1479 break; /* no reply data */
1480 case NI_QTYPE_SUPTYPES:
1481 replylen += sizeof(u_int32_t);
1482 break;
1483 case NI_QTYPE_FQDN:
1484 /* XXX will append an mbuf */
1485 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1486 break;
1487 case NI_QTYPE_NODEADDR:
1488 addrs = ni6_addrs(ni6, &ifp, subj);
1489 if ((replylen += addrs * (sizeof(struct in6_addr) +
1490 sizeof(u_int32_t))) > MCLBYTES) {
1491 replylen = MCLBYTES; /* XXX: will truncate pkt later */
1492 }
1493 break;
1494 case NI_QTYPE_IPV4ADDR:
1495 /* unsupported - should respond with unknown Qtype? */
1496 break;
1497 default:
1498 /*
1499 * XXX: We must return a reply with the ICMP6 code
1500 * `unknown Qtype' in this case. However we regard the case
1501 * as an FQDN query for backward compatibility.
1502 * Older versions set a random value to this field,
1503 * so it rarely varies in the defined qtypes.
1504 * But the mechanism is not reliable...
1505 * maybe we should obsolete older versions.
1506 */
1507 qtype = NI_QTYPE_FQDN;
1508 /* XXX will append an mbuf */
1509 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1510 oldfqdn++;
1511 break;
1512 }
1513
1514 /* allocate an mbuf to reply. */
1515 MGETHDR(n, M_DONTWAIT, m->m_type); /* MAC-OK */
1516 if (n == NULL) {
1517 m_freem(m);
1518 if (ifp != NULL) {
1519 ifnet_release(ifp);
1520 }
1521 return NULL;
1522 }
1523 M_COPY_PKTHDR(n, m); /* just for recvif */
1524 if (replylen > MHLEN) {
1525 if (replylen > MCLBYTES) {
1526 /*
1527 * XXX: should we try to allocate more? But MCLBYTES
1528 * is probably much larger than IPV6_MMTU...
1529 */
1530 goto bad;
1531 }
1532 MCLGET(n, M_DONTWAIT);
1533 if ((n->m_flags & M_EXT) == 0) {
1534 goto bad;
1535 }
1536 }
1537 n->m_pkthdr.len = n->m_len = replylen;
1538
1539 /* copy mbuf header and IPv6 + Node Information base headers */
1540 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1541 nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1542 bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1543
1544 /* qtype dependent procedure */
1545 switch (qtype) {
1546 case NI_QTYPE_NOOP:
1547 nni6->ni_code = ICMP6_NI_SUCCESS;
1548 nni6->ni_flags = 0;
1549 break;
1550 case NI_QTYPE_SUPTYPES:
1551 {
1552 u_int32_t v;
1553 nni6->ni_code = ICMP6_NI_SUCCESS;
1554 nni6->ni_flags = htons(0x0000); /* raw bitmap */
1555 /* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
1556 v = (u_int32_t)htonl(0x0000000f);
1557 bcopy(&v, nni6 + 1, sizeof(u_int32_t));
1558 break;
1559 }
1560 case NI_QTYPE_FQDN:
1561 nni6->ni_code = ICMP6_NI_SUCCESS;
1562 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1563 sizeof(struct ip6_hdr) +
1564 sizeof(struct icmp6_nodeinfo));
1565 nni6->ni_flags = 0; /* XXX: meaningless TTL */
1566 fqdn->ni_fqdn_ttl = 0; /* ditto. */
1567 /*
1568 * XXX do we really have FQDN in variable "hostname"?
1569 */
1570 lck_mtx_lock(&hostname_lock);
1571 n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
1572 lck_mtx_unlock(&hostname_lock);
1573 if (n->m_next == NULL) {
1574 goto bad;
1575 }
1576 /* XXX we assume that n->m_next is not a chain */
1577 if (n->m_next->m_next != NULL) {
1578 goto bad;
1579 }
1580 n->m_pkthdr.len += n->m_next->m_len;
1581 break;
1582 case NI_QTYPE_NODEADDR:
1583 {
1584 int lenlim, copied;
1585
1586 nni6->ni_code = ICMP6_NI_SUCCESS;
1587 n->m_pkthdr.len = n->m_len =
1588 sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1589 lenlim = M_TRAILINGSPACE(n);
1590 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1591 /* XXX: reset mbuf length */
1592 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1593 sizeof(struct icmp6_nodeinfo) + copied;
1594 break;
1595 }
1596 default:
1597 break; /* XXX impossible! */
1598 }
1599
1600 nni6->ni_type = ICMP6_NI_REPLY;
1601 m_freem(m);
1602 if (ifp != NULL) {
1603 ifnet_release(ifp);
1604 }
1605 return n;
1606
1607 bad:
1608 m_freem(m);
1609 if (n) {
1610 m_freem(n);
1611 }
1612 if (ifp != NULL) {
1613 ifnet_release(ifp);
1614 }
1615 return NULL;
1616 }
1617 #undef hostnamelen
1618
1619 /*
1620 * make a mbuf with DNS-encoded string. no compression support.
1621 *
1622 * XXX names with less than 2 dots (like "foo" or "foo.section") will be
1623 * treated as truncated name (two \0 at the end). this is a wild guess.
1624 */
1625 static struct mbuf *
1626 ni6_nametodns(
1627 const char *name,
1628 int namelen,
1629 int old) /* return pascal string if non-zero */
1630 {
1631 struct mbuf *m;
1632 char *cp, *ep;
1633 const char *p, *q;
1634 int i, len, nterm;
1635
1636 if (old) {
1637 len = namelen + 1;
1638 } else {
1639 len = MCLBYTES;
1640 }
1641
1642 /* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
1643 MGET(m, M_DONTWAIT, MT_DATA);
1644 if (m && len > MLEN) {
1645 MCLGET(m, M_DONTWAIT);
1646 if ((m->m_flags & M_EXT) == 0) {
1647 goto fail;
1648 }
1649 }
1650 if (!m) {
1651 goto fail;
1652 }
1653 m->m_next = NULL;
1654
1655 if (old) {
1656 m->m_len = len;
1657 *mtod(m, char *) = namelen;
1658 bcopy(name, mtod(m, char *) + 1, namelen);
1659 return m;
1660 } else {
1661 m->m_len = 0;
1662 cp = mtod(m, char *);
1663 ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1664
1665 /* if not certain about my name, return empty buffer */
1666 if (namelen == 0) {
1667 return m;
1668 }
1669
1670 /*
1671 * guess if it looks like shortened hostname, or FQDN.
1672 * shortened hostname needs two trailing "\0".
1673 */
1674 i = 0;
1675 for (p = name; p < name + namelen; p++) {
1676 if (*p && *p == '.') {
1677 i++;
1678 }
1679 }
1680 if (i < 2) {
1681 nterm = 2;
1682 } else {
1683 nterm = 1;
1684 }
1685
1686 p = name;
1687 while (cp < ep && p < name + namelen) {
1688 i = 0;
1689 for (q = p; q < name + namelen && *q && *q != '.'; q++) {
1690 i++;
1691 }
1692 /* result does not fit into mbuf */
1693 if (cp + i + 1 >= ep) {
1694 goto fail;
1695 }
1696 /*
1697 * DNS label length restriction, RFC1035 page 8.
1698 * "i == 0" case is included here to avoid returning
1699 * 0-length label on "foo..bar".
1700 */
1701 if (i <= 0 || i >= 64) {
1702 goto fail;
1703 }
1704 *cp++ = i;
1705 bcopy(p, cp, i);
1706 cp += i;
1707 p = q;
1708 if (p < name + namelen && *p == '.') {
1709 p++;
1710 }
1711 }
1712 /* termination */
1713 if (cp + nterm >= ep) {
1714 goto fail;
1715 }
1716 while (nterm-- > 0) {
1717 *cp++ = '\0';
1718 }
1719 m->m_len = cp - mtod(m, char *);
1720 return m;
1721 }
1722
1723 panic("should not reach here");
1724 /* NOTREACHED */
1725
1726 fail:
1727 if (m) {
1728 m_freem(m);
1729 }
1730 return NULL;
1731 }
1732
1733 /*
1734 * check if two DNS-encoded string matches. takes care of truncated
1735 * form (with \0\0 at the end). no compression support.
1736 * XXX upper/lowercase match (see RFC2065)
1737 */
1738 static int
1739 ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
1740 {
1741 const char *a0, *b0;
1742 int l;
1743
1744 /* simplest case - need validation? */
1745 if (alen == blen && bcmp(a, b, alen) == 0) {
1746 return 1;
1747 }
1748
1749 a0 = a;
1750 b0 = b;
1751
1752 /* termination is mandatory */
1753 if (alen < 2 || blen < 2) {
1754 return 0;
1755 }
1756 if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0') {
1757 return 0;
1758 }
1759 alen--;
1760 blen--;
1761
1762 while (a - a0 < alen && b - b0 < blen) {
1763 if (a - a0 + 1 > alen || b - b0 + 1 > blen) {
1764 return 0;
1765 }
1766
1767 if ((signed char)a[0] < 0 || (signed char)b[0] < 0) {
1768 return 0;
1769 }
1770 /* we don't support compression yet */
1771 if (a[0] >= 64 || b[0] >= 64) {
1772 return 0;
1773 }
1774
1775 /* truncated case */
1776 if (a[0] == 0 && a - a0 == alen - 1) {
1777 return 1;
1778 }
1779 if (b[0] == 0 && b - b0 == blen - 1) {
1780 return 1;
1781 }
1782 if (a[0] == 0 || b[0] == 0) {
1783 return 0;
1784 }
1785
1786 if (a[0] != b[0]) {
1787 return 0;
1788 }
1789 l = a[0];
1790 if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen) {
1791 return 0;
1792 }
1793 if (bcmp(a + 1, b + 1, l) != 0) {
1794 return 0;
1795 }
1796
1797 a += 1 + l;
1798 b += 1 + l;
1799 }
1800
1801 if (a - a0 == alen && b - b0 == blen) {
1802 return 1;
1803 } else {
1804 return 0;
1805 }
1806 }
1807
1808 /*
1809 * calculate the number of addresses to be returned in the node info reply.
1810 */
1811 static int
1812 ni6_addrs(struct icmp6_nodeinfo *ni6, struct ifnet **ifpp, char *subj)
1813 {
1814 struct ifnet *ifp;
1815 struct in6_ifaddr *ifa6;
1816 struct ifaddr *ifa;
1817 struct sockaddr_in6 *subj_ip6 = NULL; /* XXX pedant */
1818 int addrs = 0, addrsofif, iffound = 0;
1819 int niflags = ni6->ni_flags;
1820
1821 if (ifpp != NULL) {
1822 *ifpp = NULL;
1823 }
1824
1825 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
1826 switch (ni6->ni_code) {
1827 case ICMP6_NI_SUBJ_IPV6:
1828 if (subj == NULL) { /* must be impossible... */
1829 return 0;
1830 }
1831 subj_ip6 = (struct sockaddr_in6 *)(void *)subj;
1832 break;
1833 default:
1834 /*
1835 * XXX: we only support IPv6 subject address for
1836 * this Qtype.
1837 */
1838 return 0;
1839 }
1840 }
1841
1842 ifnet_head_lock_shared();
1843 TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
1844 addrsofif = 0;
1845 ifnet_lock_shared(ifp);
1846 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1847 {
1848 IFA_LOCK(ifa);
1849 if (ifa->ifa_addr->sa_family != AF_INET6) {
1850 IFA_UNLOCK(ifa);
1851 continue;
1852 }
1853 ifa6 = (struct in6_ifaddr *)ifa;
1854
1855 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1856 IN6_ARE_ADDR_EQUAL(&subj_ip6->sin6_addr,
1857 &ifa6->ia_addr.sin6_addr)) {
1858 iffound = 1;
1859 }
1860
1861 /*
1862 * IPv4-mapped addresses can only be returned by a
1863 * Node Information proxy, since they represent
1864 * addresses of IPv4-only nodes, which perforce do
1865 * not implement this protocol.
1866 * [icmp-name-lookups-07, Section 5.4]
1867 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1868 * this function at this moment.
1869 */
1870
1871 /* What do we have to do about ::1? */
1872 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1873 case IPV6_ADDR_SCOPE_LINKLOCAL:
1874 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) {
1875 IFA_UNLOCK(ifa);
1876 continue;
1877 }
1878 break;
1879 case IPV6_ADDR_SCOPE_SITELOCAL:
1880 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) {
1881 IFA_UNLOCK(ifa);
1882 continue;
1883 }
1884 break;
1885 case IPV6_ADDR_SCOPE_GLOBAL:
1886 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) {
1887 IFA_UNLOCK(ifa);
1888 continue;
1889 }
1890 break;
1891 default:
1892 IFA_UNLOCK(ifa);
1893 continue;
1894 }
1895
1896 /*
1897 * check if anycast is okay.
1898 * XXX: just experimental. not in the spec.
1899 */
1900 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1901 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) {
1902 IFA_UNLOCK(ifa);
1903 continue; /* we need only unicast addresses */
1904 }
1905 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1906 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1907 IFA_UNLOCK(ifa);
1908 continue;
1909 }
1910 addrsofif++; /* count the address */
1911 IFA_UNLOCK(ifa);
1912 }
1913 ifnet_lock_done(ifp);
1914 if (iffound) {
1915 if (ifpp != NULL) {
1916 *ifpp = ifp;
1917 ifnet_reference(ifp);
1918 }
1919 ifnet_head_done();
1920 return addrsofif;
1921 }
1922
1923 addrs += addrsofif;
1924 }
1925 ifnet_head_done();
1926
1927 return addrs;
1928 }
1929
1930 static int
1931 ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1932 struct ifnet *ifp0, int resid)
1933 {
1934 struct ifnet *ifp = ifp0;
1935 struct in6_ifaddr *ifa6;
1936 struct ifaddr *ifa;
1937 struct ifnet *ifp_dep = NULL;
1938 int copied = 0, allow_deprecated = 0;
1939 u_char *cp = (u_char *)(nni6 + 1);
1940 int niflags = ni6->ni_flags;
1941 u_int32_t ltime;
1942 uint64_t now = net_uptime();
1943
1944 if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL)) {
1945 return 0; /* needless to copy */
1946 }
1947 again:
1948
1949 ifnet_head_lock_shared();
1950 if (ifp == NULL) {
1951 ifp = TAILQ_FIRST(&ifnet_head);
1952 }
1953
1954 for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
1955 ifnet_lock_shared(ifp);
1956 for (ifa = ifp->if_addrlist.tqh_first; ifa;
1957 ifa = ifa->ifa_list.tqe_next) {
1958 struct in6_addrlifetime_i *lt;
1959
1960 IFA_LOCK(ifa);
1961 if (ifa->ifa_addr->sa_family != AF_INET6) {
1962 IFA_UNLOCK(ifa);
1963 continue;
1964 }
1965 ifa6 = (struct in6_ifaddr *)ifa;
1966
1967 if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
1968 allow_deprecated == 0) {
1969 /*
1970 * prefererred address should be put before
1971 * deprecated addresses.
1972 */
1973
1974 /* record the interface for later search */
1975 if (ifp_dep == NULL) {
1976 ifp_dep = ifp;
1977 }
1978
1979 IFA_UNLOCK(ifa);
1980 continue;
1981 } else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
1982 allow_deprecated != 0) {
1983 IFA_UNLOCK(ifa);
1984 continue; /* we now collect deprecated addrs */
1985 }
1986 /* What do we have to do about ::1? */
1987 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1988 case IPV6_ADDR_SCOPE_LINKLOCAL:
1989 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) {
1990 IFA_UNLOCK(ifa);
1991 continue;
1992 }
1993 break;
1994 case IPV6_ADDR_SCOPE_SITELOCAL:
1995 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) {
1996 IFA_UNLOCK(ifa);
1997 continue;
1998 }
1999 break;
2000 case IPV6_ADDR_SCOPE_GLOBAL:
2001 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) {
2002 IFA_UNLOCK(ifa);
2003 continue;
2004 }
2005 break;
2006 default:
2007 IFA_UNLOCK(ifa);
2008 continue;
2009 }
2010
2011 /*
2012 * check if anycast is okay.
2013 * XXX: just experimental. not in the spec.
2014 */
2015 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
2016 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) {
2017 IFA_UNLOCK(ifa);
2018 continue;
2019 }
2020 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
2021 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
2022 IFA_UNLOCK(ifa);
2023 continue;
2024 }
2025
2026 /* now we can copy the address */
2027 if (resid < sizeof(struct in6_addr) +
2028 sizeof(u_int32_t)) {
2029 IFA_UNLOCK(ifa);
2030 /*
2031 * We give up much more copy.
2032 * Set the truncate flag and return.
2033 */
2034 nni6->ni_flags |=
2035 NI_NODEADDR_FLAG_TRUNCATE;
2036 ifnet_lock_done(ifp);
2037 ifnet_head_done();
2038 return copied;
2039 }
2040
2041 /*
2042 * Set the TTL of the address.
2043 * The TTL value should be one of the following
2044 * according to the specification:
2045 *
2046 * 1. The remaining lifetime of a DHCP lease on the
2047 * address, or
2048 * 2. The remaining Valid Lifetime of a prefix from
2049 * which the address was derived through Stateless
2050 * Autoconfiguration.
2051 *
2052 * Note that we currently do not support stateful
2053 * address configuration by DHCPv6, so the former
2054 * case can't happen.
2055 */
2056 lt = &ifa6->ia6_lifetime;
2057 if (lt->ia6ti_expire == 0) {
2058 ltime = ND6_INFINITE_LIFETIME;
2059 } else {
2060 if (lt->ia6ti_expire > now) {
2061 ltime = htonl(lt->ia6ti_expire - now);
2062 } else {
2063 ltime = 0;
2064 }
2065 }
2066
2067 bcopy(&ltime, cp, sizeof(u_int32_t));
2068 cp += sizeof(u_int32_t);
2069
2070 /* copy the address itself */
2071 bcopy(&ifa6->ia_addr.sin6_addr, cp,
2072 sizeof(struct in6_addr));
2073 /* XXX: KAME link-local hack; remove ifindex */
2074 if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr)) {
2075 ((struct in6_addr *)(void *)cp)->s6_addr16[1] = 0;
2076 }
2077 cp += sizeof(struct in6_addr);
2078
2079 resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
2080 copied += (sizeof(struct in6_addr) +
2081 sizeof(u_int32_t));
2082 IFA_UNLOCK(ifa);
2083 }
2084 ifnet_lock_done(ifp);
2085 if (ifp0) { /* we need search only on the specified IF */
2086 break;
2087 }
2088 }
2089 ifnet_head_done();
2090
2091 if (allow_deprecated == 0 && ifp_dep != NULL) {
2092 ifp = ifp_dep;
2093 allow_deprecated = 1;
2094
2095 goto again;
2096 }
2097
2098 return copied;
2099 }
2100
2101 /*
2102 * XXX almost dup'ed code with rip6_input.
2103 */
2104 static int
2105 icmp6_rip6_input(struct mbuf **mp, int off)
2106 {
2107 struct mbuf *m = *mp;
2108 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2109 struct in6pcb *in6p;
2110 struct in6pcb *last = NULL;
2111 struct sockaddr_in6 rip6src;
2112 struct icmp6_hdr *icmp6;
2113 struct mbuf *opts = NULL;
2114 int ret = 0;
2115 struct ifnet *ifp = m->m_pkthdr.rcvif;
2116
2117 #ifndef PULLDOWN_TEST
2118 /* this is assumed to be safe. */
2119 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
2120 #else
2121 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
2122 if (icmp6 == NULL) {
2123 /* m is already reclaimed */
2124 return IPPROTO_DONE;
2125 }
2126 #endif
2127
2128 /*
2129 * XXX: the address may have embedded scope zone ID, which should be
2130 * hidden from applications.
2131 */
2132 bzero(&rip6src, sizeof(rip6src));
2133 rip6src.sin6_family = AF_INET6;
2134 rip6src.sin6_len = sizeof(struct sockaddr_in6);
2135 rip6src.sin6_addr = ip6->ip6_src;
2136 if (sa6_recoverscope(&rip6src, TRUE)) {
2137 return IPPROTO_DONE;
2138 }
2139
2140 lck_rw_lock_shared(ripcbinfo.ipi_lock);
2141 LIST_FOREACH(in6p, &ripcb, inp_list)
2142 {
2143 if ((in6p->inp_vflag & INP_IPV6) == 0) {
2144 continue;
2145 }
2146 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6) {
2147 continue;
2148 }
2149 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
2150 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
2151 continue;
2152 }
2153 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
2154 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) {
2155 continue;
2156 }
2157 if (in6p->in6p_icmp6filt
2158 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
2159 in6p->in6p_icmp6filt)) {
2160 continue;
2161 }
2162
2163 if (inp_restricted_recv(in6p, ifp)) {
2164 continue;
2165 }
2166
2167 if (last) {
2168 struct mbuf *n;
2169 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
2170 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
2171 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
2172 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
2173 (last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
2174 ret = ip6_savecontrol(last, n, &opts);
2175 if (ret != 0) {
2176 m_freem(n);
2177 m_freem(opts);
2178 last = in6p;
2179 continue;
2180 }
2181 }
2182 /* strip intermediate headers */
2183 m_adj(n, off);
2184 so_recv_data_stat(last->in6p_socket, m, 0);
2185 if (sbappendaddr(&last->in6p_socket->so_rcv,
2186 (struct sockaddr *)&rip6src,
2187 n, opts, NULL) != 0) {
2188 sorwakeup(last->in6p_socket);
2189 }
2190 opts = NULL;
2191 }
2192 }
2193 last = in6p;
2194 }
2195 if (last) {
2196 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
2197 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
2198 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
2199 (last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
2200 ret = ip6_savecontrol(last, m, &opts);
2201 if (ret != 0) {
2202 goto error;
2203 }
2204 }
2205 /* strip intermediate headers */
2206 m_adj(m, off);
2207 so_recv_data_stat(last->in6p_socket, m, 0);
2208 if (sbappendaddr(&last->in6p_socket->so_rcv,
2209 (struct sockaddr *)&rip6src, m, opts, NULL) != 0) {
2210 sorwakeup(last->in6p_socket);
2211 }
2212 } else {
2213 goto error;
2214 }
2215 lck_rw_done(ripcbinfo.ipi_lock);
2216 return IPPROTO_DONE;
2217
2218 error:
2219 lck_rw_done(ripcbinfo.ipi_lock);
2220 m_freem(m);
2221 m_freem(opts);
2222 ip6stat.ip6s_delivered--;
2223 return IPPROTO_DONE;
2224 }
2225
2226 /*
2227 * Reflect the ip6 packet back to the source.
2228 * OFF points to the icmp6 header, counted from the top of the mbuf.
2229 */
2230 void
2231 icmp6_reflect(struct mbuf *m, size_t off)
2232 {
2233 struct mbuf *m_ip6hdr = m;
2234 struct ip6_hdr *ip6;
2235 struct icmp6_hdr *icmp6;
2236 struct in6_ifaddr *ia;
2237 struct in6_addr t, src_storage, *src = 0;
2238 int plen;
2239 int type, code;
2240 struct ifnet *outif = NULL;
2241 struct sockaddr_in6 sa6_src, sa6_dst;
2242 struct nd_ifinfo *ndi = NULL;
2243 u_int32_t oflow;
2244 struct ip6_out_args ip6oa;
2245
2246 bzero(&ip6oa, sizeof(ip6oa));
2247 ip6oa.ip6oa_boundif = IFSCOPE_NONE;
2248 ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR |
2249 IP6OAF_INTCOPROC_ALLOWED | IP6OAF_AWDL_UNRESTRICTED;
2250 ip6oa.ip6oa_sotc = SO_TC_UNSPEC;
2251 ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC;
2252
2253 if (!(m->m_pkthdr.pkt_flags & PKTF_LOOP) && m->m_pkthdr.rcvif != NULL) {
2254 ip6oa.ip6oa_boundif = m->m_pkthdr.rcvif->if_index;
2255 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
2256 }
2257
2258 /* too short to reflect */
2259 if (off < sizeof(struct ip6_hdr)) {
2260 nd6log(debug,
2261 "sanity fail: off=%x, sizeof(ip6)=%x in %s:%d\n",
2262 (u_int32_t)off, (u_int32_t)sizeof(struct ip6_hdr),
2263 __func__, __LINE__);
2264 goto bad;
2265 }
2266
2267 /*
2268 * If there are extra headers between IPv6 and ICMPv6, strip
2269 * off that header first.
2270 */
2271 if (off > sizeof(struct ip6_hdr)) {
2272 size_t l;
2273 struct ip6_hdr nip6;
2274
2275 l = off - sizeof(struct ip6_hdr);
2276 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
2277 m_adj(m, l);
2278 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2279 if (m->m_len < l) {
2280 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
2281 return;
2282 }
2283 }
2284 bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
2285 } else { /* off == sizeof(struct ip6_hdr) */
2286 size_t l;
2287 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2288 if (m->m_len < l) {
2289 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
2290 return;
2291 }
2292 }
2293 }
2294 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
2295 ip6 = mtod(m_ip6hdr, struct ip6_hdr *);
2296 ip6->ip6_nxt = IPPROTO_ICMPV6;
2297 icmp6 = (struct icmp6_hdr *)(ip6 + 1);
2298 type = icmp6->icmp6_type; /* keep type for statistics */
2299 code = icmp6->icmp6_code; /* ditto. */
2300
2301 t = ip6->ip6_dst;
2302 /*
2303 * ip6_input() drops a packet if its src is multicast.
2304 * So, the src is never multicast.
2305 */
2306 ip6->ip6_dst = ip6->ip6_src;
2307
2308 /*
2309 * XXX: make sure to embed scope zone information, using
2310 * already embedded IDs or the received interface (if any).
2311 * Note that rcvif may be NULL.
2312 */
2313 bzero(&sa6_src, sizeof(sa6_src));
2314 sa6_src.sin6_family = AF_INET6;
2315 sa6_src.sin6_len = sizeof(sa6_src);
2316 sa6_src.sin6_addr = ip6->ip6_dst;
2317 in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif);
2318 in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL, NULL);
2319 bzero(&sa6_dst, sizeof(sa6_dst));
2320 sa6_dst.sin6_family = AF_INET6;
2321 sa6_dst.sin6_len = sizeof(sa6_dst);
2322 sa6_dst.sin6_addr = t;
2323 in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif);
2324 in6_embedscope(&t, &sa6_dst, NULL, NULL, NULL);
2325
2326 /*
2327 * If the incoming packet was addressed directly to us(i.e. unicast),
2328 * use dst as the src for the reply.
2329 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2330 * (for example) when we encounter an error while forwarding procedure
2331 * destined to a duplicated address of ours.
2332 * Note that ip6_getdstifaddr() may fail if we are in an error handling
2333 * procedure of an outgoing packet of our own, in which case we need
2334 * to search in the ifaddr list.
2335 */
2336 lck_rw_lock_shared(&in6_ifaddr_rwlock);
2337 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
2338 IFA_LOCK(&ia->ia_ifa);
2339 if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
2340 (ia->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) == 0) {
2341 IFA_UNLOCK(&ia->ia_ifa);
2342 src = &t;
2343 break;
2344 }
2345 IFA_UNLOCK(&ia->ia_ifa);
2346 }
2347 lck_rw_done(&in6_ifaddr_rwlock);
2348 if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) &&
2349 ((m->m_flags & M_LOOP) || (m->m_pkthdr.pkt_flags & PKTF_LOOP))) {
2350 /*
2351 * This is the case if the dst is our link-local address
2352 * and the sender is also ourselves. Here we test for both
2353 * M_LOOP and PKTF_LOOP, since the former may have been set
2354 * in ip6_output() and that we get here as part of callling
2355 * ip6_process_hopopts(). See comments in <sys/mbuf.h>
2356 */
2357 src = &t;
2358 }
2359
2360 if (src == NULL) {
2361 int e;
2362 struct sockaddr_in6 sin6;
2363 struct route_in6 ro;
2364
2365 /*
2366 * This case matches to multicasts, our anycast, or unicasts
2367 * that we do not own. Select a source address based on the
2368 * source address of the erroneous packet.
2369 */
2370 bzero(&sin6, sizeof(sin6));
2371 sin6.sin6_family = AF_INET6;
2372 sin6.sin6_len = sizeof(sin6);
2373 sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
2374
2375 bzero(&ro, sizeof(ro));
2376 /*
2377 * in6_selectsrc() might return outif with its reference held
2378 * even in the error case, so we always need to release it
2379 * if non-NULL.
2380 */
2381 src = in6_selectsrc(&sin6, NULL, NULL, &ro, &outif,
2382 &src_storage, ip6oa.ip6oa_boundif, &e);
2383 ROUTE_RELEASE(&ro);
2384 if (src == NULL) {
2385 nd6log(debug,
2386 "icmp6_reflect: source can't be determined: "
2387 "dst=%s, error=%d\n",
2388 ip6_sprintf(&sa6_src.sin6_addr), e);
2389 goto bad;
2390 }
2391 }
2392 oflow = ip6->ip6_flow; /* Save for later */
2393 ip6->ip6_src = *src;
2394 ip6->ip6_flow = 0;
2395 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2396 ip6->ip6_vfc |= IPV6_VERSION;
2397 if (icmp6->icmp6_type == ICMP6_ECHO_REPLY && icmp6->icmp6_code == 0) {
2398 ip6->ip6_flow |= (oflow & htonl(0x0ff00000));
2399 }
2400 ip6->ip6_nxt = IPPROTO_ICMPV6;
2401 if (outif != NULL && (ndi = ND_IFINFO(outif)) != NULL &&
2402 ndi->initialized) {
2403 lck_mtx_lock(&ndi->lock);
2404 ip6->ip6_hlim = ndi->chlim;
2405 lck_mtx_unlock(&ndi->lock);
2406 }
2407 if (m->m_pkthdr.rcvif != NULL &&
2408 (ndi = ND_IFINFO(m->m_pkthdr.rcvif)) != NULL &&
2409 ndi->initialized) {
2410 /* XXX: This may not be the outgoing interface */
2411 lck_mtx_lock(&ndi->lock);
2412 ip6->ip6_hlim = ndi->chlim;
2413 lck_mtx_unlock(&ndi->lock);
2414 } else {
2415 ip6->ip6_hlim = ip6_defhlim;
2416 }
2417 /* Use the same traffic class as in the request to match IPv4 */
2418 icmp6->icmp6_cksum = 0;
2419 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2420 sizeof(struct ip6_hdr), plen);
2421
2422 /*
2423 * XXX option handling
2424 */
2425 m->m_flags &= ~(M_BCAST | M_MCAST);
2426
2427 if (outif != NULL) {
2428 ifnet_release(outif);
2429 outif = NULL;
2430 }
2431
2432 m->m_pkthdr.csum_data = 0;
2433 m->m_pkthdr.csum_flags = 0;
2434 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa);
2435 if (outif != NULL) {
2436 icmp6_ifoutstat_inc(outif, type, code);
2437 ifnet_release(outif);
2438 }
2439 return;
2440
2441 bad:
2442 m_freem(m);
2443 if (outif != NULL) {
2444 ifnet_release(outif);
2445 }
2446 return;
2447 }
2448
2449 static const char *
2450 icmp6_redirect_diag(struct in6_addr *src6,
2451 struct in6_addr *dst6,
2452 struct in6_addr *tgt6)
2453 {
2454 static char buf[1024];
2455 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
2456 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
2457 return buf;
2458 }
2459
2460 void
2461 icmp6_redirect_input(struct mbuf *m, int off)
2462 {
2463 struct ifnet *ifp = NULL;
2464 struct ip6_hdr *ip6 = NULL;
2465 struct nd_redirect *nd_rd = NULL;
2466 char *lladdr = NULL;
2467 int icmp6len = 0;
2468 int lladdrlen = 0;
2469 u_char *redirhdr = NULL;
2470 int redirhdrlen = 0;
2471 struct rtentry *rt = NULL;
2472 int is_router;
2473 int is_onlink;
2474 struct in6_addr src6;
2475 struct in6_addr redtgt6;
2476 struct in6_addr reddst6;
2477 union nd_opts ndopts;
2478
2479 if (m == NULL) {
2480 return;
2481 }
2482
2483 ifp = m->m_pkthdr.rcvif;
2484 if (ifp == NULL) {
2485 goto freeit;
2486 }
2487
2488 ip6 = mtod(m, struct ip6_hdr *);
2489 icmp6len = ntohs(ip6->ip6_plen);
2490 src6 = ip6->ip6_src;
2491
2492 /*
2493 * If we are an advertising router on this interface,
2494 * don't update route by icmp6 redirect.
2495 */
2496 if (ifp->if_eflags & IFEF_IPV6_ROUTER) {
2497 goto freeit;
2498 }
2499 if (!icmp6_rediraccept) {
2500 goto freeit;
2501 }
2502
2503 #ifndef PULLDOWN_TEST
2504 IP6_EXTHDR_CHECK(m, off, icmp6len, return );
2505 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2506 #else
2507 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2508 if (nd_rd == NULL) {
2509 icmp6stat.icp6s_tooshort++;
2510 goto freeit;
2511 }
2512 #endif
2513 redtgt6 = nd_rd->nd_rd_target;
2514 reddst6 = nd_rd->nd_rd_dst;
2515
2516 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) ||
2517 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) {
2518 goto freeit;
2519 }
2520
2521 /* validation */
2522 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2523 nd6log(error,
2524 "ICMP6 redirect sent from %s rejected; "
2525 "must be from linklocal\n", ip6_sprintf(&src6));
2526 goto bad;
2527 }
2528 if (ip6->ip6_hlim != IPV6_MAXHLIM) {
2529 nd6log(error,
2530 "ICMP6 redirect sent from %s rejected; "
2531 "hlim=%d (must be 255)\n",
2532 ip6_sprintf(&src6), ip6->ip6_hlim);
2533 goto bad;
2534 }
2535 {
2536 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2537 struct sockaddr_in6 sin6;
2538 struct in6_addr *gw6;
2539
2540 bzero(&sin6, sizeof(sin6));
2541 sin6.sin6_family = AF_INET6;
2542 sin6.sin6_len = sizeof(struct sockaddr_in6);
2543 bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
2544 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0, 0, ifp->if_index);
2545 if (rt) {
2546 RT_LOCK(rt);
2547 if (rt->rt_gateway == NULL ||
2548 rt->rt_gateway->sa_family != AF_INET6) {
2549 nd6log(error,
2550 "ICMP6 redirect rejected; no route "
2551 "with inet6 gateway found for redirect dst: %s\n",
2552 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2553 RT_UNLOCK(rt);
2554 rtfree(rt);
2555 goto bad;
2556 }
2557
2558 gw6 = &(((struct sockaddr_in6 *)(void *)
2559 rt->rt_gateway)->sin6_addr);
2560 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
2561 nd6log(error,
2562 "ICMP6 redirect rejected; "
2563 "not equal to gw-for-src=%s (must be same): "
2564 "%s\n",
2565 ip6_sprintf(gw6),
2566 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2567 RT_UNLOCK(rt);
2568 rtfree(rt);
2569 goto bad;
2570 }
2571 } else {
2572 nd6log(error,
2573 "ICMP6 redirect rejected; "
2574 "no route found for redirect dst: %s\n",
2575 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2576 goto bad;
2577 }
2578 RT_UNLOCK(rt);
2579 rtfree(rt);
2580 rt = NULL;
2581 }
2582 if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2583 nd6log(error,
2584 "ICMP6 redirect rejected; "
2585 "redirect dst must be unicast: %s\n",
2586 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2587 goto bad;
2588 }
2589
2590 is_router = is_onlink = 0;
2591 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) {
2592 is_router = 1; /* router case */
2593 }
2594 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) {
2595 is_onlink = 1; /* on-link destination case */
2596 }
2597 if (!is_router && !is_onlink) {
2598 nd6log(error,
2599 "ICMP6 redirect rejected; "
2600 "neither router case nor onlink case: %s\n",
2601 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2602 goto bad;
2603 }
2604 /* validation passed */
2605
2606 icmp6len -= sizeof(*nd_rd);
2607 nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2608 if (nd6_options(&ndopts) < 0) {
2609 nd6log(info, "icmp6_redirect_input: "
2610 "invalid ND option, rejected: %s\n",
2611 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2612 /* nd6_options have incremented stats */
2613 goto freeit;
2614 }
2615
2616 if (ndopts.nd_opts_tgt_lladdr) {
2617 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2618 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2619 }
2620
2621 if (ndopts.nd_opts_rh) {
2622 redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
2623 redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
2624 }
2625
2626 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2627 nd6log(info,
2628 "icmp6_redirect_input: lladdrlen mismatch for %s "
2629 "(if %d, icmp6 packet %d): %s\n",
2630 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
2631 icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2632 goto bad;
2633 }
2634
2635 /* RFC 2461 8.3 */
2636 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2637 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2638
2639 if (!is_onlink) { /* better router case. perform rtredirect. */
2640 /* perform rtredirect */
2641 struct sockaddr_in6 sdst;
2642 struct sockaddr_in6 sgw;
2643 struct sockaddr_in6 ssrc;
2644
2645 bzero(&sdst, sizeof(sdst));
2646 bzero(&sgw, sizeof(sgw));
2647 bzero(&ssrc, sizeof(ssrc));
2648 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
2649 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
2650 sizeof(struct sockaddr_in6);
2651 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
2652 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2653 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2654 rtredirect(ifp, (struct sockaddr *)&sdst,
2655 (struct sockaddr *)&sgw, NULL, RTF_GATEWAY | RTF_HOST,
2656 (struct sockaddr *)&ssrc, NULL);
2657 }
2658 /* finally update cached route in each socket via pfctlinput */
2659 {
2660 struct sockaddr_in6 sdst;
2661
2662 bzero(&sdst, sizeof(sdst));
2663 sdst.sin6_family = AF_INET6;
2664 sdst.sin6_len = sizeof(struct sockaddr_in6);
2665 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2666
2667 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
2668 #if IPSEC
2669 key_sa_routechange((struct sockaddr *)&sdst);
2670 #endif
2671 }
2672
2673 freeit:
2674 m_freem(m);
2675 return;
2676
2677 bad:
2678 icmp6stat.icp6s_badredirect++;
2679 m_freem(m);
2680 }
2681
2682 void
2683 icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
2684 {
2685 struct ifnet *ifp; /* my outgoing interface */
2686 struct in6_addr ifp_ll6;
2687 struct in6_addr *router_ll6;
2688 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2689 struct mbuf *m = NULL; /* newly allocated one */
2690 struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2691 struct nd_redirect *nd_rd;
2692 size_t maxlen;
2693 u_char *p;
2694 struct ifnet *outif = NULL;
2695 struct sockaddr_in6 src_sa;
2696 struct ip6_out_args ip6oa;
2697
2698 bzero(&ip6oa, sizeof(ip6oa));
2699 ip6oa.ip6oa_boundif = IFSCOPE_NONE;
2700 ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR;
2701 ip6oa.ip6oa_sotc = SO_TC_UNSPEC;
2702 ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC;
2703
2704 icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2705
2706 if (rt != NULL) {
2707 RT_LOCK(rt);
2708 }
2709
2710 /* sanity check */
2711 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) {
2712 goto fail;
2713 }
2714
2715 /*
2716 * If we are not a router to begin with, or not an advertising
2717 * router on this interface, don't send icmp6 redirect.
2718 */
2719 if (!ip6_forwarding || !(ifp->if_eflags & IFEF_IPV6_ROUTER)) {
2720 goto fail;
2721 }
2722
2723 /*
2724 * Address check:
2725 * the source address must identify a neighbor, and
2726 * the destination address must not be a multicast address
2727 * [RFC 2461, sec 8.2]
2728 */
2729 sip6 = mtod(m0, struct ip6_hdr *);
2730 bzero(&src_sa, sizeof(src_sa));
2731 src_sa.sin6_family = AF_INET6;
2732 src_sa.sin6_len = sizeof(src_sa);
2733 src_sa.sin6_addr = sip6->ip6_src;
2734 /* we don't currently use sin6_scope_id, but eventually use it */
2735 src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
2736 RT_UNLOCK(rt);
2737 if (nd6_is_addr_neighbor(&src_sa, ifp, 0) == 0) {
2738 /* already unlocked */
2739 rt = NULL;
2740 goto fail;
2741 }
2742 RT_LOCK(rt);
2743 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) {
2744 goto fail; /* what should we do here? */
2745 }
2746 /* rate limit */
2747 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) {
2748 goto fail;
2749 }
2750
2751 /*
2752 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2753 * we almost always ask for an mbuf cluster for simplicity.
2754 * (MHLEN < IPV6_MMTU is almost always true)
2755 */
2756 #if IPV6_MMTU >= MCLBYTES
2757 # error assumption failed about IPV6_MMTU and MCLBYTES
2758 #endif
2759 MGETHDR(m, M_DONTWAIT, MT_HEADER); /* MAC-OK */
2760 if (m && IPV6_MMTU >= MHLEN) {
2761 MCLGET(m, M_DONTWAIT);
2762 }
2763 if (!m) {
2764 goto fail;
2765 }
2766 m->m_pkthdr.rcvif = NULL;
2767 m->m_len = 0;
2768 maxlen = M_TRAILINGSPACE(m);
2769 maxlen = min(IPV6_MMTU, maxlen);
2770 /* just for safety */
2771 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2772 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2773 goto fail;
2774 }
2775
2776 {
2777 /* get ip6 linklocal address for ifp(my outgoing interface). */
2778 struct in6_ifaddr *ia;
2779 if ((ia = in6ifa_ifpforlinklocal(ifp,
2780 IN6_IFF_NOTREADY |
2781 IN6_IFF_ANYCAST)) == NULL) {
2782 goto fail;
2783 }
2784 IFA_LOCK(&ia->ia_ifa);
2785 ifp_ll6 = ia->ia_addr.sin6_addr;
2786 IFA_UNLOCK(&ia->ia_ifa);
2787 IFA_REMREF(&ia->ia_ifa);
2788 }
2789
2790 /* get ip6 linklocal address for the router. */
2791 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
2792 struct sockaddr_in6 *sin6;
2793 sin6 = (struct sockaddr_in6 *)(void *)rt->rt_gateway;
2794 router_ll6 = &sin6->sin6_addr;
2795 if (!IN6_IS_ADDR_LINKLOCAL(router_ll6)) {
2796 router_ll6 = (struct in6_addr *)NULL;
2797 }
2798 } else {
2799 router_ll6 = (struct in6_addr *)NULL;
2800 }
2801
2802 /* ip6 */
2803 ip6 = mtod(m, struct ip6_hdr *);
2804 ip6->ip6_flow = 0;
2805 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2806 ip6->ip6_vfc |= IPV6_VERSION;
2807 /* ip6->ip6_plen will be set later */
2808 ip6->ip6_nxt = IPPROTO_ICMPV6;
2809 ip6->ip6_hlim = IPV6_MAXHLIM;
2810 /* ip6->ip6_src must be linklocal addr for my outgoing if. */
2811 bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2812 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2813
2814 /* ND Redirect */
2815 nd_rd = (struct nd_redirect *)(ip6 + 1);
2816 nd_rd->nd_rd_type = ND_REDIRECT;
2817 nd_rd->nd_rd_code = 0;
2818 nd_rd->nd_rd_reserved = 0;
2819 if (rt->rt_flags & RTF_GATEWAY) {
2820 /*
2821 * nd_rd->nd_rd_target must be a link-local address in
2822 * better router cases.
2823 */
2824 if (!router_ll6) {
2825 goto fail;
2826 }
2827 bcopy(router_ll6, &nd_rd->nd_rd_target,
2828 sizeof(nd_rd->nd_rd_target));
2829 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2830 sizeof(nd_rd->nd_rd_dst));
2831 } else {
2832 /* make sure redtgt == reddst */
2833 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2834 sizeof(nd_rd->nd_rd_target));
2835 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2836 sizeof(nd_rd->nd_rd_dst));
2837 }
2838 RT_UNLOCK(rt);
2839 rt = NULL;
2840
2841 p = (u_char *)(nd_rd + 1);
2842
2843 if (!router_ll6) {
2844 goto nolladdropt;
2845 }
2846
2847 {
2848 /* target lladdr option */
2849 struct rtentry *rt_router = NULL;
2850 int len;
2851 struct sockaddr_dl *sdl;
2852 struct nd_opt_hdr *nd_opt;
2853 char *lladdr;
2854
2855 /* Callee returns a locked route upon success */
2856 rt_router = nd6_lookup(router_ll6, 0, ifp, 0);
2857 if (!rt_router) {
2858 goto nolladdropt;
2859 }
2860 RT_LOCK_ASSERT_HELD(rt_router);
2861 len = sizeof(*nd_opt) + ifp->if_addrlen;
2862 len = (len + 7) & ~7; /* round by 8 */
2863 /* safety check */
2864 if (len + (p - (u_char *)ip6) > maxlen) {
2865 RT_REMREF_LOCKED(rt_router);
2866 RT_UNLOCK(rt_router);
2867 goto nolladdropt;
2868 }
2869
2870 if (!(rt_router->rt_flags & RTF_GATEWAY) &&
2871 (rt_router->rt_flags & RTF_LLINFO) &&
2872 (rt_router->rt_gateway->sa_family == AF_LINK) &&
2873 (sdl = (struct sockaddr_dl *)(void *)
2874 rt_router->rt_gateway) && sdl->sdl_alen) {
2875 nd_opt = (struct nd_opt_hdr *)p;
2876 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2877 nd_opt->nd_opt_len = len >> 3;
2878 lladdr = (char *)(nd_opt + 1);
2879 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
2880 p += len;
2881 }
2882 RT_REMREF_LOCKED(rt_router);
2883 RT_UNLOCK(rt_router);
2884 }
2885
2886 nolladdropt:;
2887
2888 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2889
2890 /* just to be safe */
2891 #ifdef M_DECRYPTED /*not openbsd*/
2892 if (m0->m_flags & M_DECRYPTED) {
2893 goto noredhdropt;
2894 }
2895 #endif
2896 if (p - (u_char *)ip6 > maxlen) {
2897 goto noredhdropt;
2898 }
2899
2900 {
2901 /* redirected header option */
2902 int len;
2903 struct nd_opt_rd_hdr *nd_opt_rh;
2904
2905 /*
2906 * compute the maximum size for icmp6 redirect header option.
2907 * XXX room for auth header?
2908 */
2909 len = maxlen - (p - (u_char *)ip6);
2910 len &= ~7;
2911
2912 /* This is just for simplicity. */
2913 if (m0->m_pkthdr.len != m0->m_len) {
2914 if (m0->m_next) {
2915 m_freem(m0->m_next);
2916 m0->m_next = NULL;
2917 }
2918 m0->m_pkthdr.len = m0->m_len;
2919 }
2920
2921 /*
2922 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2923 * about padding/truncate rule for the original IP packet.
2924 * From the discussion on IPv6imp in Feb 1999, the consensus was:
2925 * - "attach as much as possible" is the goal
2926 * - pad if not aligned (original size can be guessed by original
2927 * ip6 header)
2928 * Following code adds the padding if it is simple enough,
2929 * and truncates if not.
2930 */
2931 if (m0->m_next || m0->m_pkthdr.len != m0->m_len) {
2932 panic("assumption failed in %s:%d\n", __func__, __LINE__);
2933 }
2934
2935 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2936 /* not enough room, truncate */
2937 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2938 } else {
2939 /* enough room, pad or truncate */
2940 size_t extra;
2941
2942 extra = m0->m_pkthdr.len % 8;
2943 if (extra) {
2944 /* pad if easy enough, truncate if not */
2945 if (8 - extra <= M_TRAILINGSPACE(m0)) {
2946 /* pad */
2947 m0->m_len += (8 - extra);
2948 m0->m_pkthdr.len += (8 - extra);
2949 } else {
2950 /* truncate */
2951 m0->m_pkthdr.len -= extra;
2952 m0->m_len -= extra;
2953 }
2954 }
2955 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2956 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2957 }
2958
2959 nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2960 bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2961 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2962 nd_opt_rh->nd_opt_rh_len = len >> 3;
2963 p += sizeof(*nd_opt_rh);
2964 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2965
2966 /* connect m0 to m */
2967 m->m_next = m0;
2968 m->m_pkthdr.len = m->m_len + m0->m_len;
2969 }
2970 noredhdropt:;
2971
2972 /* XXX: clear embedded link IDs in the inner header */
2973 in6_clearscope(&sip6->ip6_src);
2974 in6_clearscope(&sip6->ip6_dst);
2975 in6_clearscope(&nd_rd->nd_rd_target);
2976 in6_clearscope(&nd_rd->nd_rd_dst);
2977
2978 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2979
2980 nd_rd->nd_rd_cksum = 0;
2981 nd_rd->nd_rd_cksum
2982 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2983
2984 /* send the packet to outside... */
2985 ip6oa.ip6oa_boundif = ifp->if_index;
2986 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
2987
2988 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa);
2989 if (outif) {
2990 icmp6_ifstat_inc(outif, ifs6_out_msg);
2991 icmp6_ifstat_inc(outif, ifs6_out_redirect);
2992 ifnet_release(outif);
2993 }
2994 icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2995
2996 return;
2997
2998 fail:
2999 if (rt != NULL) {
3000 RT_UNLOCK(rt);
3001 }
3002 if (m) {
3003 m_freem(m);
3004 }
3005 if (m0) {
3006 m_freem(m0);
3007 }
3008 }
3009
3010 /*
3011 * ICMPv6 socket option processing.
3012 */
3013 int
3014 icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
3015 {
3016 int error = 0;
3017 int optlen;
3018 struct inpcb *inp = sotoinpcb(so);
3019 int level, op, optname;
3020
3021 if (sopt) {
3022 level = sopt->sopt_level;
3023 op = sopt->sopt_dir;
3024 optname = sopt->sopt_name;
3025 optlen = sopt->sopt_valsize;
3026 } else {
3027 level = op = optname = optlen = 0;
3028 }
3029
3030 if (level != IPPROTO_ICMPV6) {
3031 return EINVAL;
3032 }
3033
3034 switch (op) {
3035 case PRCO_SETOPT:
3036 switch (optname) {
3037 case ICMP6_FILTER:
3038 {
3039 struct icmp6_filter *p;
3040
3041 if (optlen != 0 && optlen != sizeof(*p)) {
3042 error = EMSGSIZE;
3043 break;
3044 }
3045 if (inp->in6p_icmp6filt == NULL) {
3046 error = EINVAL;
3047 break;
3048 }
3049
3050 if (optlen == 0) {
3051 /* According to RFC 3542, an installed filter can be
3052 * cleared by issuing a setsockopt for ICMP6_FILTER
3053 * with a zero length.
3054 */
3055 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
3056 } else {
3057 error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen,
3058 optlen);
3059 }
3060 break;
3061 }
3062
3063 default:
3064 error = ENOPROTOOPT;
3065 break;
3066 }
3067 break;
3068
3069 case PRCO_GETOPT:
3070 switch (optname) {
3071 case ICMP6_FILTER:
3072 {
3073 if (inp->in6p_icmp6filt == NULL) {
3074 error = EINVAL;
3075 break;
3076 }
3077 error = sooptcopyout(sopt, inp->in6p_icmp6filt,
3078 min(sizeof(struct icmp6_filter), optlen));
3079 break;
3080 }
3081
3082 default:
3083 error = ENOPROTOOPT;
3084 break;
3085 }
3086 break;
3087 }
3088
3089 return error;
3090 }
3091
3092 /*
3093 * ICMPv6 socket datagram option processing.
3094 */
3095 int
3096 icmp6_dgram_ctloutput(struct socket *so, struct sockopt *sopt)
3097 {
3098 if (kauth_cred_issuser(so->so_cred)) {
3099 return icmp6_ctloutput(so, sopt);
3100 }
3101
3102 if (sopt->sopt_level == IPPROTO_ICMPV6) {
3103 switch (sopt->sopt_name) {
3104 case ICMP6_FILTER:
3105 return icmp6_ctloutput(so, sopt);
3106 default:
3107 return EPERM;
3108 }
3109 }
3110
3111 if (sopt->sopt_level != IPPROTO_IPV6) {
3112 return EINVAL;
3113 }
3114
3115 switch (sopt->sopt_name) {
3116 case IPV6_UNICAST_HOPS:
3117 case IPV6_CHECKSUM:
3118 case IPV6_V6ONLY:
3119 case IPV6_USE_MIN_MTU:
3120 case IPV6_RECVRTHDR:
3121 case IPV6_RECVPKTINFO:
3122 case IPV6_RECVHOPLIMIT:
3123 case IPV6_PATHMTU:
3124 case IPV6_PKTINFO:
3125 case IPV6_HOPLIMIT:
3126 case IPV6_HOPOPTS:
3127 case IPV6_DSTOPTS:
3128 case IPV6_MULTICAST_IF:
3129 case IPV6_MULTICAST_HOPS:
3130 case IPV6_MULTICAST_LOOP:
3131 case IPV6_JOIN_GROUP:
3132 case IPV6_LEAVE_GROUP:
3133 case IPV6_PORTRANGE:
3134 case IPV6_IPSEC_POLICY:
3135 case IPV6_RECVTCLASS:
3136 case IPV6_TCLASS:
3137 case IPV6_2292PKTOPTIONS:
3138 case IPV6_2292PKTINFO:
3139 case IPV6_2292HOPLIMIT:
3140 case IPV6_2292HOPOPTS:
3141 case IPV6_2292DSTOPTS:
3142 case IPV6_2292RTHDR:
3143 case IPV6_BOUND_IF:
3144 case IPV6_NO_IFT_CELLULAR:
3145
3146 return ip6_ctloutput(so, sopt);
3147
3148 default:
3149 return EPERM;
3150 }
3151 }
3152
3153 __private_extern__ int
3154 icmp6_dgram_send(struct socket *so, int flags, struct mbuf *m,
3155 struct sockaddr *nam, struct mbuf *control, struct proc *p)
3156 {
3157 #pragma unused(flags, p)
3158 int error = 0;
3159 struct inpcb *inp = sotoinpcb(so);
3160 struct icmp6_hdr *icmp6;
3161
3162 if (inp == NULL
3163 #if NECP
3164 || (necp_socket_should_use_flow_divert(inp))
3165 #endif /* NECP */
3166 ) {
3167 error = (inp == NULL ? EINVAL : EPROTOTYPE);
3168 goto bad;
3169 }
3170
3171 if (kauth_cred_issuser(so->so_cred)) {
3172 return rip6_output(m, so, SIN6(nam), control, 0);
3173 }
3174
3175 /*
3176 * For an ICMPv6 packet, we should know its type and code
3177 */
3178 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) {
3179 if (m->m_len < sizeof(struct icmp6_hdr) &&
3180 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
3181 error = ENOBUFS;
3182 goto bad;
3183 }
3184 icmp6 = mtod(m, struct icmp6_hdr *);
3185
3186 /*
3187 * Allow only to send echo request and node information request
3188 * See RFC 2463 for Echo Request Message format
3189 */
3190 if ((icmp6->icmp6_type == ICMP6_ECHO_REQUEST &&
3191 icmp6->icmp6_code == 0) ||
3192 (icmp6->icmp6_type == ICMP6_NI_QUERY &&
3193 (icmp6->icmp6_code == ICMP6_NI_SUBJ_IPV6 ||
3194 icmp6->icmp6_code == ICMP6_NI_SUBJ_FQDN))) {
3195 /* Good */
3196 ;
3197 } else {
3198 error = EPERM;
3199 goto bad;
3200 }
3201 }
3202
3203 return rip6_output(m, so, SIN6(nam), control, 0);
3204 bad:
3205 VERIFY(error != 0);
3206
3207 if (m != NULL) {
3208 m_freem(m);
3209 }
3210 if (control != NULL) {
3211 m_freem(control);
3212 }
3213
3214 return error;
3215 }
3216
3217 /* Like rip6_attach but without root privilege enforcement */
3218 __private_extern__ int
3219 icmp6_dgram_attach(struct socket *so, int proto, struct proc *p)
3220 {
3221 struct inpcb *inp;
3222 int error;
3223
3224 inp = sotoinpcb(so);
3225 if (inp) {
3226 panic("icmp6_dgram_attach");
3227 }
3228
3229 if (proto != IPPROTO_ICMPV6) {
3230 return EINVAL;
3231 }
3232
3233 error = soreserve(so, rip_sendspace, rip_recvspace);
3234 if (error) {
3235 return error;
3236 }
3237 error = in_pcballoc(so, &ripcbinfo, p);
3238 if (error) {
3239 return error;
3240 }
3241 inp = (struct inpcb *)so->so_pcb;
3242 inp->inp_vflag |= INP_IPV6;
3243 inp->in6p_ip6_nxt = IPPROTO_ICMPV6;
3244 inp->in6p_hops = -1; /* use kernel default */
3245 inp->in6p_cksum = -1;
3246 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *,
3247 sizeof(struct icmp6_filter), M_PCB, M_WAITOK);
3248 if (inp->in6p_icmp6filt == NULL) {
3249 return ENOMEM;
3250 }
3251 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
3252 return 0;
3253 }
3254
3255
3256 /*
3257 * Perform rate limit check.
3258 * Returns 0 if it is okay to send the icmp6 packet.
3259 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
3260 * limitation.
3261 *
3262 * XXX per-destination check necessary?
3263 */
3264 static int
3265 icmp6_ratelimit(
3266 __unused const struct in6_addr *dst, /* not used at this moment */
3267 const int type,
3268 __unused const int code)
3269 {
3270 int ret;
3271
3272 ret = 0; /* okay to send */
3273
3274 /* PPS limit */
3275 if (type == ND_ROUTER_ADVERT) {
3276 if (!ppsratecheck(&icmp6rappslim_last, &icmp6rapps_count,
3277 icmp6rappslim)) {
3278 ret++;
3279 }
3280 } else if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
3281 icmp6errppslim)) {
3282 /* The packet is subject to rate limit */
3283 ret++;
3284 }
3285
3286 return ret;
3287 }