]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/icmp6.c
f1d66606e8947ba511fd5772d5e28a8d5a9d8c8e
[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((LOG_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((LOG_ERR,
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((LOG_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 /*
1217 * In case the suggested mtu is less than IPV6_MMTU, we
1218 * only need to remember that it was for above mentioned
1219 * "alwaysfrag" case.
1220 * Try to be as close to the spec as possible.
1221 */
1222 if (mtu < IPV6_MMTU) {
1223 mtu = IPV6_MMTU - 8;
1224 }
1225
1226 bzero(&sin6, sizeof(sin6));
1227 sin6.sin6_family = PF_INET6;
1228 sin6.sin6_len = sizeof(struct sockaddr_in6);
1229 sin6.sin6_addr = *dst;
1230 /* XXX normally, this won't happen */
1231 if (IN6_IS_ADDR_LINKLOCAL(dst)) {
1232 sin6.sin6_addr.s6_addr16[1] =
1233 htons(m->m_pkthdr.rcvif->if_index);
1234 }
1235 /* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */
1236 /*
1237 * XXX On a side note, for asymmetric data-path
1238 * the lookup on receive interace is probably not
1239 * what we want to do.
1240 * That requires looking at the cached route for the
1241 * protocol control block.
1242 */
1243 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0,
1244 RTF_CLONING | RTF_PRCLONING, m->m_pkthdr.rcvif->if_index);
1245 if (rt != NULL) {
1246 RT_LOCK(rt);
1247 if ((rt->rt_flags & RTF_HOST) &&
1248 !(rt->rt_rmx.rmx_locks & RTV_MTU) &&
1249 mtu < IN6_LINKMTU(rt->rt_ifp) &&
1250 rt->rt_rmx.rmx_mtu > mtu) {
1251 icmp6stat.icp6s_pmtuchg++;
1252 rt->rt_rmx.rmx_mtu = mtu;
1253 }
1254 RT_UNLOCK(rt);
1255 rtfree(rt);
1256 }
1257 }
1258
1259 /*
1260 * Process a Node Information Query packet, based on
1261 * draft-ietf-ipngwg-icmp-name-lookups-07.
1262 *
1263 * Spec incompatibilities:
1264 * - IPv6 Subject address handling
1265 * - IPv4 Subject address handling support missing
1266 * - Proxy reply (answer even if it's not for me)
1267 * - joins NI group address at in6_ifattach() time only, does not cope
1268 * with hostname changes by sethostname(3)
1269 */
1270 #define hostnamelen strlen(hostname)
1271 static struct mbuf *
1272 ni6_input(struct mbuf *m, int off)
1273 {
1274 struct icmp6_nodeinfo *ni6, *nni6;
1275 struct mbuf *n = NULL;
1276 u_int16_t qtype;
1277 int subjlen;
1278 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1279 struct ni_reply_fqdn *fqdn;
1280 int addrs; /* for NI_QTYPE_NODEADDR */
1281 struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1282 struct sockaddr_in6 sin6; /* double meaning; ip6_dst and subjectaddr */
1283 struct sockaddr_in6 sin6_d; /* XXX: we should retrieve this from m_aux */
1284 struct ip6_hdr *ip6;
1285 int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
1286 char *subj = NULL;
1287
1288 ip6 = mtod(m, struct ip6_hdr *);
1289 #ifndef PULLDOWN_TEST
1290 ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1291 #else
1292 IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
1293 if (ni6 == NULL) {
1294 /* m is already reclaimed */
1295 return NULL;
1296 }
1297 #endif
1298
1299 /*
1300 * Validate IPv6 source address.
1301 * The default configuration MUST be to refuse answering queries from
1302 * global-scope addresses according to RFC4602.
1303 * Notes:
1304 * - it's not very clear what "refuse" means; this implementation
1305 * simply drops it.
1306 * - it's not very easy to identify global-scope (unicast) addresses
1307 * since there are many prefixes for them. It should be safer
1308 * and in practice sufficient to check "all" but loopback and
1309 * link-local (note that site-local unicast was deprecated and
1310 * ULA is defined as global scope-wise)
1311 */
1312 if ((icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1313 !IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1314 !IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
1315 goto bad;
1316 }
1317
1318 /*
1319 * Validate IPv6 destination address.
1320 *
1321 * The Responder must discard the Query without further processing
1322 * unless it is one of the Responder's unicast or anycast addresses, or
1323 * a link-local scope multicast address which the Responder has joined.
1324 * [RFC4602, Section 5.]
1325 */
1326 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
1327 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) {
1328 goto bad;
1329 }
1330 /* else it's a link-local multicast, fine */
1331 } else { /* unicast or anycast */
1332 uint32_t ia6_flags;
1333
1334 if (ip6_getdstifaddr_info(m, NULL, &ia6_flags) != 0) {
1335 goto bad; /* XXX impossible */
1336 }
1337 if ((ia6_flags & IN6_IFF_TEMPORARY) &&
1338 !(icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1339 nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
1340 "a temporary address in %s:%d",
1341 __func__, __LINE__));
1342 goto bad;
1343 }
1344 }
1345
1346 /* validate query Subject field. */
1347 qtype = ntohs(ni6->ni_qtype);
1348 subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1349 switch (qtype) {
1350 case NI_QTYPE_NOOP:
1351 case NI_QTYPE_SUPTYPES:
1352 /* 07 draft */
1353 if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0) {
1354 break;
1355 }
1356 /* FALLTHROUGH */
1357 case NI_QTYPE_FQDN:
1358 case NI_QTYPE_NODEADDR:
1359 case NI_QTYPE_IPV4ADDR:
1360 switch (ni6->ni_code) {
1361 case ICMP6_NI_SUBJ_IPV6:
1362 #if ICMP6_NI_SUBJ_IPV6 != 0
1363 case 0:
1364 #endif
1365 /*
1366 * backward compatibility - try to accept 03 draft
1367 * format, where no Subject is present.
1368 */
1369 if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
1370 subjlen == 0) {
1371 oldfqdn++;
1372 break;
1373 }
1374 #if ICMP6_NI_SUBJ_IPV6 != 0
1375 if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6) {
1376 goto bad;
1377 }
1378 #endif
1379
1380 if (subjlen != sizeof(struct in6_addr)) {
1381 goto bad;
1382 }
1383
1384 /*
1385 * Validate Subject address.
1386 *
1387 * Not sure what exactly "address belongs to the node"
1388 * means in the spec, is it just unicast, or what?
1389 *
1390 * At this moment we consider Subject address as
1391 * "belong to the node" if the Subject address equals
1392 * to the IPv6 destination address; validation for
1393 * IPv6 destination address should have done enough
1394 * check for us.
1395 *
1396 * We do not do proxy at this moment.
1397 */
1398 /* m_pulldown instead of copy? */
1399 m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1400 subjlen, (caddr_t)&sin6.sin6_addr);
1401 sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
1402 &sin6.sin6_addr);
1403 in6_embedscope(&sin6.sin6_addr, &sin6, NULL, NULL,
1404 NULL);
1405 bzero(&sin6_d, sizeof(sin6_d));
1406 sin6_d.sin6_family = AF_INET6; /* not used, actually */
1407 sin6_d.sin6_len = sizeof(sin6_d); /* ditto */
1408 sin6_d.sin6_addr = ip6->ip6_dst;
1409 sin6_d.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
1410 &ip6->ip6_dst);
1411 in6_embedscope(&sin6_d.sin6_addr, &sin6_d, NULL, NULL,
1412 NULL);
1413 subj = (char *)&sin6;
1414 if (SA6_ARE_ADDR_EQUAL(&sin6, &sin6_d)) {
1415 break;
1416 }
1417
1418 /*
1419 * XXX if we are to allow other cases, we should really
1420 * be careful about scope here.
1421 * basically, we should disallow queries toward IPv6
1422 * destination X with subject Y,
1423 * if scope(X) > scope(Y).
1424 * if we allow scope(X) > scope(Y), it will result in
1425 * information leakage across scope boundary.
1426 */
1427 goto bad;
1428
1429 case ICMP6_NI_SUBJ_FQDN:
1430 /*
1431 * Validate Subject name with gethostname(3).
1432 *
1433 * The behavior may need some debate, since:
1434 * - we are not sure if the node has FQDN as
1435 * hostname (returned by gethostname(3)).
1436 * - the code does wildcard match for truncated names.
1437 * however, we are not sure if we want to perform
1438 * wildcard match, if gethostname(3) side has
1439 * truncated hostname.
1440 */
1441 n = ni6_nametodns(hostname, hostnamelen, 0);
1442 if (!n || n->m_next || n->m_len == 0) {
1443 goto bad;
1444 }
1445 IP6_EXTHDR_GET(subj, char *, m,
1446 off + sizeof(struct icmp6_nodeinfo), subjlen);
1447 if (subj == NULL) {
1448 goto bad;
1449 }
1450 if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1451 n->m_len)) {
1452 goto bad;
1453 }
1454 m_freem(n);
1455 n = NULL;
1456 break;
1457
1458 case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */
1459 default:
1460 goto bad;
1461 }
1462 break;
1463 }
1464
1465 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1466 switch (qtype) {
1467 case NI_QTYPE_FQDN:
1468 if ((icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0) {
1469 goto bad;
1470 }
1471 break;
1472 case NI_QTYPE_NODEADDR:
1473 case NI_QTYPE_IPV4ADDR:
1474 if ((icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0) {
1475 goto bad;
1476 }
1477 break;
1478 }
1479
1480 /* guess reply length */
1481 switch (qtype) {
1482 case NI_QTYPE_NOOP:
1483 break; /* no reply data */
1484 case NI_QTYPE_SUPTYPES:
1485 replylen += sizeof(u_int32_t);
1486 break;
1487 case NI_QTYPE_FQDN:
1488 /* XXX will append an mbuf */
1489 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1490 break;
1491 case NI_QTYPE_NODEADDR:
1492 addrs = ni6_addrs(ni6, &ifp, subj);
1493 if ((replylen += addrs * (sizeof(struct in6_addr) +
1494 sizeof(u_int32_t))) > MCLBYTES) {
1495 replylen = MCLBYTES; /* XXX: will truncate pkt later */
1496 }
1497 break;
1498 case NI_QTYPE_IPV4ADDR:
1499 /* unsupported - should respond with unknown Qtype? */
1500 break;
1501 default:
1502 /*
1503 * XXX: We must return a reply with the ICMP6 code
1504 * `unknown Qtype' in this case. However we regard the case
1505 * as an FQDN query for backward compatibility.
1506 * Older versions set a random value to this field,
1507 * so it rarely varies in the defined qtypes.
1508 * But the mechanism is not reliable...
1509 * maybe we should obsolete older versions.
1510 */
1511 qtype = NI_QTYPE_FQDN;
1512 /* XXX will append an mbuf */
1513 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1514 oldfqdn++;
1515 break;
1516 }
1517
1518 /* allocate an mbuf to reply. */
1519 MGETHDR(n, M_DONTWAIT, m->m_type); /* MAC-OK */
1520 if (n == NULL) {
1521 m_freem(m);
1522 if (ifp != NULL) {
1523 ifnet_release(ifp);
1524 }
1525 return NULL;
1526 }
1527 M_COPY_PKTHDR(n, m); /* just for recvif */
1528 if (replylen > MHLEN) {
1529 if (replylen > MCLBYTES) {
1530 /*
1531 * XXX: should we try to allocate more? But MCLBYTES
1532 * is probably much larger than IPV6_MMTU...
1533 */
1534 goto bad;
1535 }
1536 MCLGET(n, M_DONTWAIT);
1537 if ((n->m_flags & M_EXT) == 0) {
1538 goto bad;
1539 }
1540 }
1541 n->m_pkthdr.len = n->m_len = replylen;
1542
1543 /* copy mbuf header and IPv6 + Node Information base headers */
1544 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1545 nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1546 bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1547
1548 /* qtype dependent procedure */
1549 switch (qtype) {
1550 case NI_QTYPE_NOOP:
1551 nni6->ni_code = ICMP6_NI_SUCCESS;
1552 nni6->ni_flags = 0;
1553 break;
1554 case NI_QTYPE_SUPTYPES:
1555 {
1556 u_int32_t v;
1557 nni6->ni_code = ICMP6_NI_SUCCESS;
1558 nni6->ni_flags = htons(0x0000); /* raw bitmap */
1559 /* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
1560 v = (u_int32_t)htonl(0x0000000f);
1561 bcopy(&v, nni6 + 1, sizeof(u_int32_t));
1562 break;
1563 }
1564 case NI_QTYPE_FQDN:
1565 nni6->ni_code = ICMP6_NI_SUCCESS;
1566 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1567 sizeof(struct ip6_hdr) +
1568 sizeof(struct icmp6_nodeinfo));
1569 nni6->ni_flags = 0; /* XXX: meaningless TTL */
1570 fqdn->ni_fqdn_ttl = 0; /* ditto. */
1571 /*
1572 * XXX do we really have FQDN in variable "hostname"?
1573 */
1574 n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
1575 if (n->m_next == NULL) {
1576 goto bad;
1577 }
1578 /* XXX we assume that n->m_next is not a chain */
1579 if (n->m_next->m_next != NULL) {
1580 goto bad;
1581 }
1582 n->m_pkthdr.len += n->m_next->m_len;
1583 break;
1584 case NI_QTYPE_NODEADDR:
1585 {
1586 int lenlim, copied;
1587
1588 nni6->ni_code = ICMP6_NI_SUCCESS;
1589 n->m_pkthdr.len = n->m_len =
1590 sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1591 lenlim = M_TRAILINGSPACE(n);
1592 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1593 /* XXX: reset mbuf length */
1594 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1595 sizeof(struct icmp6_nodeinfo) + copied;
1596 break;
1597 }
1598 default:
1599 break; /* XXX impossible! */
1600 }
1601
1602 nni6->ni_type = ICMP6_NI_REPLY;
1603 m_freem(m);
1604 if (ifp != NULL) {
1605 ifnet_release(ifp);
1606 }
1607 return n;
1608
1609 bad:
1610 m_freem(m);
1611 if (n) {
1612 m_freem(n);
1613 }
1614 if (ifp != NULL) {
1615 ifnet_release(ifp);
1616 }
1617 return NULL;
1618 }
1619 #undef hostnamelen
1620
1621 /*
1622 * make a mbuf with DNS-encoded string. no compression support.
1623 *
1624 * XXX names with less than 2 dots (like "foo" or "foo.section") will be
1625 * treated as truncated name (two \0 at the end). this is a wild guess.
1626 */
1627 static struct mbuf *
1628 ni6_nametodns(
1629 const char *name,
1630 int namelen,
1631 int old) /* return pascal string if non-zero */
1632 {
1633 struct mbuf *m;
1634 char *cp, *ep;
1635 const char *p, *q;
1636 int i, len, nterm;
1637
1638 if (old) {
1639 len = namelen + 1;
1640 } else {
1641 len = MCLBYTES;
1642 }
1643
1644 /* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
1645 MGET(m, M_DONTWAIT, MT_DATA);
1646 if (m && len > MLEN) {
1647 MCLGET(m, M_DONTWAIT);
1648 if ((m->m_flags & M_EXT) == 0) {
1649 goto fail;
1650 }
1651 }
1652 if (!m) {
1653 goto fail;
1654 }
1655 m->m_next = NULL;
1656
1657 if (old) {
1658 m->m_len = len;
1659 *mtod(m, char *) = namelen;
1660 bcopy(name, mtod(m, char *) + 1, namelen);
1661 return m;
1662 } else {
1663 m->m_len = 0;
1664 cp = mtod(m, char *);
1665 ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1666
1667 /* if not certain about my name, return empty buffer */
1668 if (namelen == 0) {
1669 return m;
1670 }
1671
1672 /*
1673 * guess if it looks like shortened hostname, or FQDN.
1674 * shortened hostname needs two trailing "\0".
1675 */
1676 i = 0;
1677 for (p = name; p < name + namelen; p++) {
1678 if (*p && *p == '.') {
1679 i++;
1680 }
1681 }
1682 if (i < 2) {
1683 nterm = 2;
1684 } else {
1685 nterm = 1;
1686 }
1687
1688 p = name;
1689 while (cp < ep && p < name + namelen) {
1690 i = 0;
1691 for (q = p; q < name + namelen && *q && *q != '.'; q++) {
1692 i++;
1693 }
1694 /* result does not fit into mbuf */
1695 if (cp + i + 1 >= ep) {
1696 goto fail;
1697 }
1698 /*
1699 * DNS label length restriction, RFC1035 page 8.
1700 * "i == 0" case is included here to avoid returning
1701 * 0-length label on "foo..bar".
1702 */
1703 if (i <= 0 || i >= 64) {
1704 goto fail;
1705 }
1706 *cp++ = i;
1707 bcopy(p, cp, i);
1708 cp += i;
1709 p = q;
1710 if (p < name + namelen && *p == '.') {
1711 p++;
1712 }
1713 }
1714 /* termination */
1715 if (cp + nterm >= ep) {
1716 goto fail;
1717 }
1718 while (nterm-- > 0) {
1719 *cp++ = '\0';
1720 }
1721 m->m_len = cp - mtod(m, char *);
1722 return m;
1723 }
1724
1725 panic("should not reach here");
1726 /* NOTREACHED */
1727
1728 fail:
1729 if (m) {
1730 m_freem(m);
1731 }
1732 return NULL;
1733 }
1734
1735 /*
1736 * check if two DNS-encoded string matches. takes care of truncated
1737 * form (with \0\0 at the end). no compression support.
1738 * XXX upper/lowercase match (see RFC2065)
1739 */
1740 static int
1741 ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
1742 {
1743 const char *a0, *b0;
1744 int l;
1745
1746 /* simplest case - need validation? */
1747 if (alen == blen && bcmp(a, b, alen) == 0) {
1748 return 1;
1749 }
1750
1751 a0 = a;
1752 b0 = b;
1753
1754 /* termination is mandatory */
1755 if (alen < 2 || blen < 2) {
1756 return 0;
1757 }
1758 if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0') {
1759 return 0;
1760 }
1761 alen--;
1762 blen--;
1763
1764 while (a - a0 < alen && b - b0 < blen) {
1765 if (a - a0 + 1 > alen || b - b0 + 1 > blen) {
1766 return 0;
1767 }
1768
1769 if ((signed char)a[0] < 0 || (signed char)b[0] < 0) {
1770 return 0;
1771 }
1772 /* we don't support compression yet */
1773 if (a[0] >= 64 || b[0] >= 64) {
1774 return 0;
1775 }
1776
1777 /* truncated case */
1778 if (a[0] == 0 && a - a0 == alen - 1) {
1779 return 1;
1780 }
1781 if (b[0] == 0 && b - b0 == blen - 1) {
1782 return 1;
1783 }
1784 if (a[0] == 0 || b[0] == 0) {
1785 return 0;
1786 }
1787
1788 if (a[0] != b[0]) {
1789 return 0;
1790 }
1791 l = a[0];
1792 if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen) {
1793 return 0;
1794 }
1795 if (bcmp(a + 1, b + 1, l) != 0) {
1796 return 0;
1797 }
1798
1799 a += 1 + l;
1800 b += 1 + l;
1801 }
1802
1803 if (a - a0 == alen && b - b0 == blen) {
1804 return 1;
1805 } else {
1806 return 0;
1807 }
1808 }
1809
1810 /*
1811 * calculate the number of addresses to be returned in the node info reply.
1812 */
1813 static int
1814 ni6_addrs(struct icmp6_nodeinfo *ni6, struct ifnet **ifpp, char *subj)
1815 {
1816 struct ifnet *ifp;
1817 struct in6_ifaddr *ifa6;
1818 struct ifaddr *ifa;
1819 struct sockaddr_in6 *subj_ip6 = NULL; /* XXX pedant */
1820 int addrs = 0, addrsofif, iffound = 0;
1821 int niflags = ni6->ni_flags;
1822
1823 if (ifpp != NULL) {
1824 *ifpp = NULL;
1825 }
1826
1827 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
1828 switch (ni6->ni_code) {
1829 case ICMP6_NI_SUBJ_IPV6:
1830 if (subj == NULL) { /* must be impossible... */
1831 return 0;
1832 }
1833 subj_ip6 = (struct sockaddr_in6 *)(void *)subj;
1834 break;
1835 default:
1836 /*
1837 * XXX: we only support IPv6 subject address for
1838 * this Qtype.
1839 */
1840 return 0;
1841 }
1842 }
1843
1844 ifnet_head_lock_shared();
1845 TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
1846 addrsofif = 0;
1847 ifnet_lock_shared(ifp);
1848 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1849 {
1850 IFA_LOCK(ifa);
1851 if (ifa->ifa_addr->sa_family != AF_INET6) {
1852 IFA_UNLOCK(ifa);
1853 continue;
1854 }
1855 ifa6 = (struct in6_ifaddr *)ifa;
1856
1857 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1858 IN6_ARE_ADDR_EQUAL(&subj_ip6->sin6_addr,
1859 &ifa6->ia_addr.sin6_addr)) {
1860 iffound = 1;
1861 }
1862
1863 /*
1864 * IPv4-mapped addresses can only be returned by a
1865 * Node Information proxy, since they represent
1866 * addresses of IPv4-only nodes, which perforce do
1867 * not implement this protocol.
1868 * [icmp-name-lookups-07, Section 5.4]
1869 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1870 * this function at this moment.
1871 */
1872
1873 /* What do we have to do about ::1? */
1874 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1875 case IPV6_ADDR_SCOPE_LINKLOCAL:
1876 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) {
1877 IFA_UNLOCK(ifa);
1878 continue;
1879 }
1880 break;
1881 case IPV6_ADDR_SCOPE_SITELOCAL:
1882 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) {
1883 IFA_UNLOCK(ifa);
1884 continue;
1885 }
1886 break;
1887 case IPV6_ADDR_SCOPE_GLOBAL:
1888 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) {
1889 IFA_UNLOCK(ifa);
1890 continue;
1891 }
1892 break;
1893 default:
1894 IFA_UNLOCK(ifa);
1895 continue;
1896 }
1897
1898 /*
1899 * check if anycast is okay.
1900 * XXX: just experimental. not in the spec.
1901 */
1902 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1903 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) {
1904 IFA_UNLOCK(ifa);
1905 continue; /* we need only unicast addresses */
1906 }
1907 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1908 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1909 IFA_UNLOCK(ifa);
1910 continue;
1911 }
1912 addrsofif++; /* count the address */
1913 IFA_UNLOCK(ifa);
1914 }
1915 ifnet_lock_done(ifp);
1916 if (iffound) {
1917 if (ifpp != NULL) {
1918 *ifpp = ifp;
1919 ifnet_reference(ifp);
1920 }
1921 ifnet_head_done();
1922 return addrsofif;
1923 }
1924
1925 addrs += addrsofif;
1926 }
1927 ifnet_head_done();
1928
1929 return addrs;
1930 }
1931
1932 static int
1933 ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1934 struct ifnet *ifp0, int resid)
1935 {
1936 struct ifnet *ifp = ifp0;
1937 struct in6_ifaddr *ifa6;
1938 struct ifaddr *ifa;
1939 struct ifnet *ifp_dep = NULL;
1940 int copied = 0, allow_deprecated = 0;
1941 u_char *cp = (u_char *)(nni6 + 1);
1942 int niflags = ni6->ni_flags;
1943 u_int32_t ltime;
1944 uint64_t now = net_uptime();
1945
1946 if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL)) {
1947 return 0; /* needless to copy */
1948 }
1949 again:
1950
1951 ifnet_head_lock_shared();
1952 if (ifp == NULL) {
1953 ifp = TAILQ_FIRST(&ifnet_head);
1954 }
1955
1956 for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
1957 ifnet_lock_shared(ifp);
1958 for (ifa = ifp->if_addrlist.tqh_first; ifa;
1959 ifa = ifa->ifa_list.tqe_next) {
1960 struct in6_addrlifetime_i *lt;
1961
1962 IFA_LOCK(ifa);
1963 if (ifa->ifa_addr->sa_family != AF_INET6) {
1964 IFA_UNLOCK(ifa);
1965 continue;
1966 }
1967 ifa6 = (struct in6_ifaddr *)ifa;
1968
1969 if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
1970 allow_deprecated == 0) {
1971 /*
1972 * prefererred address should be put before
1973 * deprecated addresses.
1974 */
1975
1976 /* record the interface for later search */
1977 if (ifp_dep == NULL) {
1978 ifp_dep = ifp;
1979 }
1980
1981 IFA_UNLOCK(ifa);
1982 continue;
1983 } else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
1984 allow_deprecated != 0) {
1985 IFA_UNLOCK(ifa);
1986 continue; /* we now collect deprecated addrs */
1987 }
1988 /* What do we have to do about ::1? */
1989 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1990 case IPV6_ADDR_SCOPE_LINKLOCAL:
1991 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) {
1992 IFA_UNLOCK(ifa);
1993 continue;
1994 }
1995 break;
1996 case IPV6_ADDR_SCOPE_SITELOCAL:
1997 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) {
1998 IFA_UNLOCK(ifa);
1999 continue;
2000 }
2001 break;
2002 case IPV6_ADDR_SCOPE_GLOBAL:
2003 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) {
2004 IFA_UNLOCK(ifa);
2005 continue;
2006 }
2007 break;
2008 default:
2009 IFA_UNLOCK(ifa);
2010 continue;
2011 }
2012
2013 /*
2014 * check if anycast is okay.
2015 * XXX: just experimental. not in the spec.
2016 */
2017 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
2018 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) {
2019 IFA_UNLOCK(ifa);
2020 continue;
2021 }
2022 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
2023 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
2024 IFA_UNLOCK(ifa);
2025 continue;
2026 }
2027
2028 /* now we can copy the address */
2029 if (resid < sizeof(struct in6_addr) +
2030 sizeof(u_int32_t)) {
2031 IFA_UNLOCK(ifa);
2032 /*
2033 * We give up much more copy.
2034 * Set the truncate flag and return.
2035 */
2036 nni6->ni_flags |=
2037 NI_NODEADDR_FLAG_TRUNCATE;
2038 ifnet_lock_done(ifp);
2039 ifnet_head_done();
2040 return copied;
2041 }
2042
2043 /*
2044 * Set the TTL of the address.
2045 * The TTL value should be one of the following
2046 * according to the specification:
2047 *
2048 * 1. The remaining lifetime of a DHCP lease on the
2049 * address, or
2050 * 2. The remaining Valid Lifetime of a prefix from
2051 * which the address was derived through Stateless
2052 * Autoconfiguration.
2053 *
2054 * Note that we currently do not support stateful
2055 * address configuration by DHCPv6, so the former
2056 * case can't happen.
2057 */
2058 lt = &ifa6->ia6_lifetime;
2059 if (lt->ia6ti_expire == 0) {
2060 ltime = ND6_INFINITE_LIFETIME;
2061 } else {
2062 if (lt->ia6ti_expire > now) {
2063 ltime = htonl(lt->ia6ti_expire - now);
2064 } else {
2065 ltime = 0;
2066 }
2067 }
2068
2069 bcopy(&ltime, cp, sizeof(u_int32_t));
2070 cp += sizeof(u_int32_t);
2071
2072 /* copy the address itself */
2073 bcopy(&ifa6->ia_addr.sin6_addr, cp,
2074 sizeof(struct in6_addr));
2075 /* XXX: KAME link-local hack; remove ifindex */
2076 if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr)) {
2077 ((struct in6_addr *)(void *)cp)->s6_addr16[1] = 0;
2078 }
2079 cp += sizeof(struct in6_addr);
2080
2081 resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
2082 copied += (sizeof(struct in6_addr) +
2083 sizeof(u_int32_t));
2084 IFA_UNLOCK(ifa);
2085 }
2086 ifnet_lock_done(ifp);
2087 if (ifp0) { /* we need search only on the specified IF */
2088 break;
2089 }
2090 }
2091 ifnet_head_done();
2092
2093 if (allow_deprecated == 0 && ifp_dep != NULL) {
2094 ifp = ifp_dep;
2095 allow_deprecated = 1;
2096
2097 goto again;
2098 }
2099
2100 return copied;
2101 }
2102
2103 /*
2104 * XXX almost dup'ed code with rip6_input.
2105 */
2106 static int
2107 icmp6_rip6_input(struct mbuf **mp, int off)
2108 {
2109 struct mbuf *m = *mp;
2110 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2111 struct in6pcb *in6p;
2112 struct in6pcb *last = NULL;
2113 struct sockaddr_in6 rip6src;
2114 struct icmp6_hdr *icmp6;
2115 struct mbuf *opts = NULL;
2116 int ret = 0;
2117 struct ifnet *ifp = m->m_pkthdr.rcvif;
2118
2119 #ifndef PULLDOWN_TEST
2120 /* this is assumed to be safe. */
2121 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
2122 #else
2123 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
2124 if (icmp6 == NULL) {
2125 /* m is already reclaimed */
2126 return IPPROTO_DONE;
2127 }
2128 #endif
2129
2130 /*
2131 * XXX: the address may have embedded scope zone ID, which should be
2132 * hidden from applications.
2133 */
2134 bzero(&rip6src, sizeof(rip6src));
2135 rip6src.sin6_family = AF_INET6;
2136 rip6src.sin6_len = sizeof(struct sockaddr_in6);
2137 rip6src.sin6_addr = ip6->ip6_src;
2138 if (sa6_recoverscope(&rip6src, TRUE)) {
2139 return IPPROTO_DONE;
2140 }
2141
2142 lck_rw_lock_shared(ripcbinfo.ipi_lock);
2143 LIST_FOREACH(in6p, &ripcb, inp_list)
2144 {
2145 if ((in6p->inp_vflag & INP_IPV6) == 0) {
2146 continue;
2147 }
2148 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6) {
2149 continue;
2150 }
2151 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
2152 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
2153 continue;
2154 }
2155 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
2156 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) {
2157 continue;
2158 }
2159 if (in6p->in6p_icmp6filt
2160 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
2161 in6p->in6p_icmp6filt)) {
2162 continue;
2163 }
2164
2165 if (inp_restricted_recv(in6p, ifp)) {
2166 continue;
2167 }
2168
2169 if (last) {
2170 struct mbuf *n;
2171 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
2172 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
2173 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
2174 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
2175 (last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
2176 ret = ip6_savecontrol(last, n, &opts);
2177 if (ret != 0) {
2178 m_freem(n);
2179 m_freem(opts);
2180 last = in6p;
2181 continue;
2182 }
2183 }
2184 /* strip intermediate headers */
2185 m_adj(n, off);
2186 so_recv_data_stat(last->in6p_socket, m, 0);
2187 if (sbappendaddr(&last->in6p_socket->so_rcv,
2188 (struct sockaddr *)&rip6src,
2189 n, opts, NULL) != 0) {
2190 sorwakeup(last->in6p_socket);
2191 }
2192 opts = NULL;
2193 }
2194 }
2195 last = in6p;
2196 }
2197 if (last) {
2198 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
2199 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
2200 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
2201 (last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
2202 ret = ip6_savecontrol(last, m, &opts);
2203 if (ret != 0) {
2204 goto error;
2205 }
2206 }
2207 /* strip intermediate headers */
2208 m_adj(m, off);
2209 so_recv_data_stat(last->in6p_socket, m, 0);
2210 if (sbappendaddr(&last->in6p_socket->so_rcv,
2211 (struct sockaddr *)&rip6src, m, opts, NULL) != 0) {
2212 sorwakeup(last->in6p_socket);
2213 }
2214 } else {
2215 goto error;
2216 }
2217 lck_rw_done(ripcbinfo.ipi_lock);
2218 return IPPROTO_DONE;
2219
2220 error:
2221 lck_rw_done(ripcbinfo.ipi_lock);
2222 m_freem(m);
2223 m_freem(opts);
2224 ip6stat.ip6s_delivered--;
2225 return IPPROTO_DONE;
2226 }
2227
2228 /*
2229 * Reflect the ip6 packet back to the source.
2230 * OFF points to the icmp6 header, counted from the top of the mbuf.
2231 */
2232 void
2233 icmp6_reflect(struct mbuf *m, size_t off)
2234 {
2235 struct mbuf *m_ip6hdr = m;
2236 struct ip6_hdr *ip6;
2237 struct icmp6_hdr *icmp6;
2238 struct in6_ifaddr *ia;
2239 struct in6_addr t, src_storage, *src = 0;
2240 int plen;
2241 int type, code;
2242 struct ifnet *outif = NULL;
2243 struct sockaddr_in6 sa6_src, sa6_dst;
2244 struct nd_ifinfo *ndi = NULL;
2245 u_int32_t oflow;
2246 struct ip6_out_args ip6oa;
2247
2248 bzero(&ip6oa, sizeof(ip6oa));
2249 ip6oa.ip6oa_boundif = IFSCOPE_NONE;
2250 ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR |
2251 IP6OAF_INTCOPROC_ALLOWED | IP6OAF_AWDL_UNRESTRICTED;
2252 ip6oa.ip6oa_sotc = SO_TC_UNSPEC;
2253 ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC;
2254
2255 if (!(m->m_pkthdr.pkt_flags & PKTF_LOOP) && m->m_pkthdr.rcvif != NULL) {
2256 ip6oa.ip6oa_boundif = m->m_pkthdr.rcvif->if_index;
2257 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
2258 }
2259
2260 /* too short to reflect */
2261 if (off < sizeof(struct ip6_hdr)) {
2262 nd6log((LOG_DEBUG,
2263 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
2264 (u_int32_t)off, (u_int32_t)sizeof(struct ip6_hdr),
2265 __func__, __LINE__));
2266 goto bad;
2267 }
2268
2269 /*
2270 * If there are extra headers between IPv6 and ICMPv6, strip
2271 * off that header first.
2272 */
2273 if (off > sizeof(struct ip6_hdr)) {
2274 size_t l;
2275 struct ip6_hdr nip6;
2276
2277 l = off - sizeof(struct ip6_hdr);
2278 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
2279 m_adj(m, l);
2280 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2281 if (m->m_len < l) {
2282 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
2283 return;
2284 }
2285 }
2286 bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
2287 } else { /* off == sizeof(struct ip6_hdr) */
2288 size_t l;
2289 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2290 if (m->m_len < l) {
2291 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
2292 return;
2293 }
2294 }
2295 }
2296 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
2297 ip6 = mtod(m_ip6hdr, struct ip6_hdr *);
2298 ip6->ip6_nxt = IPPROTO_ICMPV6;
2299 icmp6 = (struct icmp6_hdr *)(ip6 + 1);
2300 type = icmp6->icmp6_type; /* keep type for statistics */
2301 code = icmp6->icmp6_code; /* ditto. */
2302
2303 t = ip6->ip6_dst;
2304 /*
2305 * ip6_input() drops a packet if its src is multicast.
2306 * So, the src is never multicast.
2307 */
2308 ip6->ip6_dst = ip6->ip6_src;
2309
2310 /*
2311 * XXX: make sure to embed scope zone information, using
2312 * already embedded IDs or the received interface (if any).
2313 * Note that rcvif may be NULL.
2314 */
2315 bzero(&sa6_src, sizeof(sa6_src));
2316 sa6_src.sin6_family = AF_INET6;
2317 sa6_src.sin6_len = sizeof(sa6_src);
2318 sa6_src.sin6_addr = ip6->ip6_dst;
2319 in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif);
2320 in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL, NULL);
2321 bzero(&sa6_dst, sizeof(sa6_dst));
2322 sa6_dst.sin6_family = AF_INET6;
2323 sa6_dst.sin6_len = sizeof(sa6_dst);
2324 sa6_dst.sin6_addr = t;
2325 in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif);
2326 in6_embedscope(&t, &sa6_dst, NULL, NULL, NULL);
2327
2328 /*
2329 * If the incoming packet was addressed directly to us(i.e. unicast),
2330 * use dst as the src for the reply.
2331 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2332 * (for example) when we encounter an error while forwarding procedure
2333 * destined to a duplicated address of ours.
2334 * Note that ip6_getdstifaddr() may fail if we are in an error handling
2335 * procedure of an outgoing packet of our own, in which case we need
2336 * to search in the ifaddr list.
2337 */
2338 lck_rw_lock_shared(&in6_ifaddr_rwlock);
2339 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
2340 IFA_LOCK(&ia->ia_ifa);
2341 if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
2342 (ia->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) == 0) {
2343 IFA_UNLOCK(&ia->ia_ifa);
2344 src = &t;
2345 break;
2346 }
2347 IFA_UNLOCK(&ia->ia_ifa);
2348 }
2349 lck_rw_done(&in6_ifaddr_rwlock);
2350 if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) &&
2351 ((m->m_flags & M_LOOP) || (m->m_pkthdr.pkt_flags & PKTF_LOOP))) {
2352 /*
2353 * This is the case if the dst is our link-local address
2354 * and the sender is also ourselves. Here we test for both
2355 * M_LOOP and PKTF_LOOP, since the former may have been set
2356 * in ip6_output() and that we get here as part of callling
2357 * ip6_process_hopopts(). See comments in <sys/mbuf.h>
2358 */
2359 src = &t;
2360 }
2361
2362 if (src == NULL) {
2363 int e;
2364 struct sockaddr_in6 sin6;
2365 struct route_in6 ro;
2366
2367 /*
2368 * This case matches to multicasts, our anycast, or unicasts
2369 * that we do not own. Select a source address based on the
2370 * source address of the erroneous packet.
2371 */
2372 bzero(&sin6, sizeof(sin6));
2373 sin6.sin6_family = AF_INET6;
2374 sin6.sin6_len = sizeof(sin6);
2375 sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
2376
2377 bzero(&ro, sizeof(ro));
2378 /*
2379 * in6_selectsrc() might return outif with its reference held
2380 * even in the error case, so we always need to release it
2381 * if non-NULL.
2382 */
2383 src = in6_selectsrc(&sin6, NULL, NULL, &ro, &outif,
2384 &src_storage, ip6oa.ip6oa_boundif, &e);
2385 ROUTE_RELEASE(&ro);
2386 if (src == NULL) {
2387 nd6log((LOG_DEBUG,
2388 "icmp6_reflect: source can't be determined: "
2389 "dst=%s, error=%d\n",
2390 ip6_sprintf(&sa6_src.sin6_addr), e));
2391 goto bad;
2392 }
2393 }
2394 oflow = ip6->ip6_flow; /* Save for later */
2395 ip6->ip6_src = *src;
2396 ip6->ip6_flow = 0;
2397 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2398 ip6->ip6_vfc |= IPV6_VERSION;
2399 if (icmp6->icmp6_type == ICMP6_ECHO_REPLY && icmp6->icmp6_code == 0) {
2400 ip6->ip6_flow |= (oflow & htonl(0x0ff00000));
2401 }
2402 ip6->ip6_nxt = IPPROTO_ICMPV6;
2403 if (outif != NULL && (ndi = ND_IFINFO(outif)) != NULL &&
2404 ndi->initialized) {
2405 lck_mtx_lock(&ndi->lock);
2406 ip6->ip6_hlim = ndi->chlim;
2407 lck_mtx_unlock(&ndi->lock);
2408 }
2409 if (m->m_pkthdr.rcvif != NULL &&
2410 (ndi = ND_IFINFO(m->m_pkthdr.rcvif)) != NULL &&
2411 ndi->initialized) {
2412 /* XXX: This may not be the outgoing interface */
2413 lck_mtx_lock(&ndi->lock);
2414 ip6->ip6_hlim = ndi->chlim;
2415 lck_mtx_unlock(&ndi->lock);
2416 } else {
2417 ip6->ip6_hlim = ip6_defhlim;
2418 }
2419 /* Use the same traffic class as in the request to match IPv4 */
2420 icmp6->icmp6_cksum = 0;
2421 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2422 sizeof(struct ip6_hdr), plen);
2423
2424 /*
2425 * XXX option handling
2426 */
2427 m->m_flags &= ~(M_BCAST | M_MCAST);
2428
2429 if (outif != NULL) {
2430 ifnet_release(outif);
2431 outif = NULL;
2432 }
2433
2434 m->m_pkthdr.csum_data = 0;
2435 m->m_pkthdr.csum_flags = 0;
2436 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa);
2437 if (outif != NULL) {
2438 icmp6_ifoutstat_inc(outif, type, code);
2439 ifnet_release(outif);
2440 }
2441 return;
2442
2443 bad:
2444 m_freem(m);
2445 if (outif != NULL) {
2446 ifnet_release(outif);
2447 }
2448 return;
2449 }
2450
2451 static const char *
2452 icmp6_redirect_diag(struct in6_addr *src6,
2453 struct in6_addr *dst6,
2454 struct in6_addr *tgt6)
2455 {
2456 static char buf[1024];
2457 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
2458 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
2459 return buf;
2460 }
2461
2462 void
2463 icmp6_redirect_input(struct mbuf *m, int off)
2464 {
2465 struct ifnet *ifp = m->m_pkthdr.rcvif;
2466 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2467 struct nd_redirect *nd_rd;
2468 int icmp6len = ntohs(ip6->ip6_plen);
2469 char *lladdr = NULL;
2470 int lladdrlen = 0;
2471 u_char *redirhdr = NULL;
2472 int redirhdrlen = 0;
2473 struct rtentry *rt = NULL;
2474 int is_router;
2475 int is_onlink;
2476 struct in6_addr src6 = ip6->ip6_src;
2477 struct in6_addr redtgt6;
2478 struct in6_addr reddst6;
2479 union nd_opts ndopts;
2480
2481 if (!m || !ifp) {
2482 return;
2483 }
2484
2485 /*
2486 * If we are an advertising router on this interface,
2487 * don't update route by icmp6 redirect.
2488 */
2489 if (ifp->if_eflags & IFEF_IPV6_ROUTER) {
2490 goto freeit;
2491 }
2492 if (!icmp6_rediraccept) {
2493 goto freeit;
2494 }
2495
2496 #ifndef PULLDOWN_TEST
2497 IP6_EXTHDR_CHECK(m, off, icmp6len, return );
2498 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2499 #else
2500 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2501 if (nd_rd == NULL) {
2502 icmp6stat.icp6s_tooshort++;
2503 return;
2504 }
2505 #endif
2506 redtgt6 = nd_rd->nd_rd_target;
2507 reddst6 = nd_rd->nd_rd_dst;
2508
2509 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) ||
2510 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) {
2511 goto freeit;
2512 }
2513
2514 /* validation */
2515 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2516 nd6log((LOG_ERR,
2517 "ICMP6 redirect sent from %s rejected; "
2518 "must be from linklocal\n", ip6_sprintf(&src6)));
2519 goto bad;
2520 }
2521 if (ip6->ip6_hlim != 255) {
2522 nd6log((LOG_ERR,
2523 "ICMP6 redirect sent from %s rejected; "
2524 "hlim=%d (must be 255)\n",
2525 ip6_sprintf(&src6), ip6->ip6_hlim));
2526 goto bad;
2527 }
2528 {
2529 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2530 struct sockaddr_in6 sin6;
2531 struct in6_addr *gw6;
2532
2533 bzero(&sin6, sizeof(sin6));
2534 sin6.sin6_family = AF_INET6;
2535 sin6.sin6_len = sizeof(struct sockaddr_in6);
2536 bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
2537 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0, 0, ifp->if_index);
2538 if (rt) {
2539 RT_LOCK(rt);
2540 if (rt->rt_gateway == NULL ||
2541 rt->rt_gateway->sa_family != AF_INET6) {
2542 nd6log((LOG_ERR,
2543 "ICMP6 redirect rejected; no route "
2544 "with inet6 gateway found for redirect dst: %s\n",
2545 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2546 RT_UNLOCK(rt);
2547 rtfree(rt);
2548 goto bad;
2549 }
2550
2551 gw6 = &(((struct sockaddr_in6 *)(void *)
2552 rt->rt_gateway)->sin6_addr);
2553 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
2554 nd6log((LOG_ERR,
2555 "ICMP6 redirect rejected; "
2556 "not equal to gw-for-src=%s (must be same): "
2557 "%s\n",
2558 ip6_sprintf(gw6),
2559 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2560 RT_UNLOCK(rt);
2561 rtfree(rt);
2562 goto bad;
2563 }
2564 } else {
2565 nd6log((LOG_ERR,
2566 "ICMP6 redirect rejected; "
2567 "no route found for redirect dst: %s\n",
2568 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2569 goto bad;
2570 }
2571 RT_UNLOCK(rt);
2572 rtfree(rt);
2573 rt = NULL;
2574 }
2575 if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2576 nd6log((LOG_ERR,
2577 "ICMP6 redirect rejected; "
2578 "redirect dst must be unicast: %s\n",
2579 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2580 goto bad;
2581 }
2582
2583 is_router = is_onlink = 0;
2584 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) {
2585 is_router = 1; /* router case */
2586 }
2587 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) {
2588 is_onlink = 1; /* on-link destination case */
2589 }
2590 if (!is_router && !is_onlink) {
2591 nd6log((LOG_ERR,
2592 "ICMP6 redirect rejected; "
2593 "neither router case nor onlink case: %s\n",
2594 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2595 goto bad;
2596 }
2597 /* validation passed */
2598
2599 icmp6len -= sizeof(*nd_rd);
2600 nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2601 if (nd6_options(&ndopts) < 0) {
2602 nd6log((LOG_INFO, "icmp6_redirect_input: "
2603 "invalid ND option, rejected: %s\n",
2604 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2605 /* nd6_options have incremented stats */
2606 goto freeit;
2607 }
2608
2609 if (ndopts.nd_opts_tgt_lladdr) {
2610 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2611 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2612 }
2613
2614 if (ndopts.nd_opts_rh) {
2615 redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
2616 redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
2617 }
2618
2619 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2620 nd6log((LOG_INFO,
2621 "icmp6_redirect_input: lladdrlen mismatch for %s "
2622 "(if %d, icmp6 packet %d): %s\n",
2623 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
2624 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2625 goto bad;
2626 }
2627
2628 /* RFC 2461 8.3 */
2629 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2630 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2631
2632 if (!is_onlink) { /* better router case. perform rtredirect. */
2633 /* perform rtredirect */
2634 struct sockaddr_in6 sdst;
2635 struct sockaddr_in6 sgw;
2636 struct sockaddr_in6 ssrc;
2637
2638 bzero(&sdst, sizeof(sdst));
2639 bzero(&sgw, sizeof(sgw));
2640 bzero(&ssrc, sizeof(ssrc));
2641 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
2642 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
2643 sizeof(struct sockaddr_in6);
2644 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
2645 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2646 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2647 rtredirect(ifp, (struct sockaddr *)&sdst,
2648 (struct sockaddr *)&sgw, NULL, RTF_GATEWAY | RTF_HOST,
2649 (struct sockaddr *)&ssrc, NULL);
2650 }
2651 /* finally update cached route in each socket via pfctlinput */
2652 {
2653 struct sockaddr_in6 sdst;
2654
2655 bzero(&sdst, sizeof(sdst));
2656 sdst.sin6_family = AF_INET6;
2657 sdst.sin6_len = sizeof(struct sockaddr_in6);
2658 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2659
2660 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
2661 #if IPSEC
2662 key_sa_routechange((struct sockaddr *)&sdst);
2663 #endif
2664 }
2665
2666 freeit:
2667 m_freem(m);
2668 return;
2669
2670 bad:
2671 icmp6stat.icp6s_badredirect++;
2672 m_freem(m);
2673 }
2674
2675 void
2676 icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
2677 {
2678 struct ifnet *ifp; /* my outgoing interface */
2679 struct in6_addr ifp_ll6;
2680 struct in6_addr *router_ll6;
2681 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2682 struct mbuf *m = NULL; /* newly allocated one */
2683 struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2684 struct nd_redirect *nd_rd;
2685 size_t maxlen;
2686 u_char *p;
2687 struct ifnet *outif = NULL;
2688 struct sockaddr_in6 src_sa;
2689 struct ip6_out_args ip6oa;
2690
2691 bzero(&ip6oa, sizeof(ip6oa));
2692 ip6oa.ip6oa_boundif = IFSCOPE_NONE;
2693 ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR;
2694 ip6oa.ip6oa_sotc = SO_TC_UNSPEC;
2695 ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC;
2696
2697 icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2698
2699 if (rt != NULL) {
2700 RT_LOCK(rt);
2701 }
2702
2703 /* sanity check */
2704 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) {
2705 goto fail;
2706 }
2707
2708 /*
2709 * If we are not a router to begin with, or not an advertising
2710 * router on this interface, don't send icmp6 redirect.
2711 */
2712 if (!ip6_forwarding || !(ifp->if_eflags & IFEF_IPV6_ROUTER)) {
2713 goto fail;
2714 }
2715
2716 /*
2717 * Address check:
2718 * the source address must identify a neighbor, and
2719 * the destination address must not be a multicast address
2720 * [RFC 2461, sec 8.2]
2721 */
2722 sip6 = mtod(m0, struct ip6_hdr *);
2723 bzero(&src_sa, sizeof(src_sa));
2724 src_sa.sin6_family = AF_INET6;
2725 src_sa.sin6_len = sizeof(src_sa);
2726 src_sa.sin6_addr = sip6->ip6_src;
2727 /* we don't currently use sin6_scope_id, but eventually use it */
2728 src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
2729 RT_UNLOCK(rt);
2730 if (nd6_is_addr_neighbor(&src_sa, ifp, 0) == 0) {
2731 /* already unlocked */
2732 rt = NULL;
2733 goto fail;
2734 }
2735 RT_LOCK(rt);
2736 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) {
2737 goto fail; /* what should we do here? */
2738 }
2739 /* rate limit */
2740 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) {
2741 goto fail;
2742 }
2743
2744 /*
2745 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2746 * we almost always ask for an mbuf cluster for simplicity.
2747 * (MHLEN < IPV6_MMTU is almost always true)
2748 */
2749 #if IPV6_MMTU >= MCLBYTES
2750 # error assumption failed about IPV6_MMTU and MCLBYTES
2751 #endif
2752 MGETHDR(m, M_DONTWAIT, MT_HEADER); /* MAC-OK */
2753 if (m && IPV6_MMTU >= MHLEN) {
2754 MCLGET(m, M_DONTWAIT);
2755 }
2756 if (!m) {
2757 goto fail;
2758 }
2759 m->m_pkthdr.rcvif = NULL;
2760 m->m_len = 0;
2761 maxlen = M_TRAILINGSPACE(m);
2762 maxlen = min(IPV6_MMTU, maxlen);
2763 /* just for safety */
2764 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2765 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2766 goto fail;
2767 }
2768
2769 {
2770 /* get ip6 linklocal address for ifp(my outgoing interface). */
2771 struct in6_ifaddr *ia;
2772 if ((ia = in6ifa_ifpforlinklocal(ifp,
2773 IN6_IFF_NOTREADY |
2774 IN6_IFF_ANYCAST)) == NULL) {
2775 goto fail;
2776 }
2777 IFA_LOCK(&ia->ia_ifa);
2778 ifp_ll6 = ia->ia_addr.sin6_addr;
2779 IFA_UNLOCK(&ia->ia_ifa);
2780 IFA_REMREF(&ia->ia_ifa);
2781 }
2782
2783 /* get ip6 linklocal address for the router. */
2784 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
2785 struct sockaddr_in6 *sin6;
2786 sin6 = (struct sockaddr_in6 *)(void *)rt->rt_gateway;
2787 router_ll6 = &sin6->sin6_addr;
2788 if (!IN6_IS_ADDR_LINKLOCAL(router_ll6)) {
2789 router_ll6 = (struct in6_addr *)NULL;
2790 }
2791 } else {
2792 router_ll6 = (struct in6_addr *)NULL;
2793 }
2794
2795 /* ip6 */
2796 ip6 = mtod(m, struct ip6_hdr *);
2797 ip6->ip6_flow = 0;
2798 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2799 ip6->ip6_vfc |= IPV6_VERSION;
2800 /* ip6->ip6_plen will be set later */
2801 ip6->ip6_nxt = IPPROTO_ICMPV6;
2802 ip6->ip6_hlim = 255;
2803 /* ip6->ip6_src must be linklocal addr for my outgoing if. */
2804 bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2805 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2806
2807 /* ND Redirect */
2808 nd_rd = (struct nd_redirect *)(ip6 + 1);
2809 nd_rd->nd_rd_type = ND_REDIRECT;
2810 nd_rd->nd_rd_code = 0;
2811 nd_rd->nd_rd_reserved = 0;
2812 if (rt->rt_flags & RTF_GATEWAY) {
2813 /*
2814 * nd_rd->nd_rd_target must be a link-local address in
2815 * better router cases.
2816 */
2817 if (!router_ll6) {
2818 goto fail;
2819 }
2820 bcopy(router_ll6, &nd_rd->nd_rd_target,
2821 sizeof(nd_rd->nd_rd_target));
2822 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2823 sizeof(nd_rd->nd_rd_dst));
2824 } else {
2825 /* make sure redtgt == reddst */
2826 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2827 sizeof(nd_rd->nd_rd_target));
2828 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2829 sizeof(nd_rd->nd_rd_dst));
2830 }
2831 RT_UNLOCK(rt);
2832 rt = NULL;
2833
2834 p = (u_char *)(nd_rd + 1);
2835
2836 if (!router_ll6) {
2837 goto nolladdropt;
2838 }
2839
2840 {
2841 /* target lladdr option */
2842 struct rtentry *rt_router = NULL;
2843 int len;
2844 struct sockaddr_dl *sdl;
2845 struct nd_opt_hdr *nd_opt;
2846 char *lladdr;
2847
2848 /* Callee returns a locked route upon success */
2849 rt_router = nd6_lookup(router_ll6, 0, ifp, 0);
2850 if (!rt_router) {
2851 goto nolladdropt;
2852 }
2853 RT_LOCK_ASSERT_HELD(rt_router);
2854 len = sizeof(*nd_opt) + ifp->if_addrlen;
2855 len = (len + 7) & ~7; /* round by 8 */
2856 /* safety check */
2857 if (len + (p - (u_char *)ip6) > maxlen) {
2858 RT_REMREF_LOCKED(rt_router);
2859 RT_UNLOCK(rt_router);
2860 goto nolladdropt;
2861 }
2862
2863 if (!(rt_router->rt_flags & RTF_GATEWAY) &&
2864 (rt_router->rt_flags & RTF_LLINFO) &&
2865 (rt_router->rt_gateway->sa_family == AF_LINK) &&
2866 (sdl = (struct sockaddr_dl *)(void *)
2867 rt_router->rt_gateway) && sdl->sdl_alen) {
2868 nd_opt = (struct nd_opt_hdr *)p;
2869 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2870 nd_opt->nd_opt_len = len >> 3;
2871 lladdr = (char *)(nd_opt + 1);
2872 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
2873 p += len;
2874 }
2875 RT_REMREF_LOCKED(rt_router);
2876 RT_UNLOCK(rt_router);
2877 }
2878
2879 nolladdropt:;
2880
2881 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2882
2883 /* just to be safe */
2884 #ifdef M_DECRYPTED /*not openbsd*/
2885 if (m0->m_flags & M_DECRYPTED) {
2886 goto noredhdropt;
2887 }
2888 #endif
2889 if (p - (u_char *)ip6 > maxlen) {
2890 goto noredhdropt;
2891 }
2892
2893 {
2894 /* redirected header option */
2895 int len;
2896 struct nd_opt_rd_hdr *nd_opt_rh;
2897
2898 /*
2899 * compute the maximum size for icmp6 redirect header option.
2900 * XXX room for auth header?
2901 */
2902 len = maxlen - (p - (u_char *)ip6);
2903 len &= ~7;
2904
2905 /* This is just for simplicity. */
2906 if (m0->m_pkthdr.len != m0->m_len) {
2907 if (m0->m_next) {
2908 m_freem(m0->m_next);
2909 m0->m_next = NULL;
2910 }
2911 m0->m_pkthdr.len = m0->m_len;
2912 }
2913
2914 /*
2915 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2916 * about padding/truncate rule for the original IP packet.
2917 * From the discussion on IPv6imp in Feb 1999, the consensus was:
2918 * - "attach as much as possible" is the goal
2919 * - pad if not aligned (original size can be guessed by original
2920 * ip6 header)
2921 * Following code adds the padding if it is simple enough,
2922 * and truncates if not.
2923 */
2924 if (m0->m_next || m0->m_pkthdr.len != m0->m_len) {
2925 panic("assumption failed in %s:%d\n", __func__, __LINE__);
2926 }
2927
2928 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2929 /* not enough room, truncate */
2930 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2931 } else {
2932 /* enough room, pad or truncate */
2933 size_t extra;
2934
2935 extra = m0->m_pkthdr.len % 8;
2936 if (extra) {
2937 /* pad if easy enough, truncate if not */
2938 if (8 - extra <= M_TRAILINGSPACE(m0)) {
2939 /* pad */
2940 m0->m_len += (8 - extra);
2941 m0->m_pkthdr.len += (8 - extra);
2942 } else {
2943 /* truncate */
2944 m0->m_pkthdr.len -= extra;
2945 m0->m_len -= extra;
2946 }
2947 }
2948 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2949 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2950 }
2951
2952 nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2953 bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2954 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2955 nd_opt_rh->nd_opt_rh_len = len >> 3;
2956 p += sizeof(*nd_opt_rh);
2957 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2958
2959 /* connect m0 to m */
2960 m->m_next = m0;
2961 m->m_pkthdr.len = m->m_len + m0->m_len;
2962 }
2963 noredhdropt:;
2964
2965 /* XXX: clear embedded link IDs in the inner header */
2966 in6_clearscope(&sip6->ip6_src);
2967 in6_clearscope(&sip6->ip6_dst);
2968 in6_clearscope(&nd_rd->nd_rd_target);
2969 in6_clearscope(&nd_rd->nd_rd_dst);
2970
2971 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2972
2973 nd_rd->nd_rd_cksum = 0;
2974 nd_rd->nd_rd_cksum
2975 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2976
2977 /* send the packet to outside... */
2978 ip6oa.ip6oa_boundif = ifp->if_index;
2979 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
2980
2981 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa);
2982 if (outif) {
2983 icmp6_ifstat_inc(outif, ifs6_out_msg);
2984 icmp6_ifstat_inc(outif, ifs6_out_redirect);
2985 ifnet_release(outif);
2986 }
2987 icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2988
2989 return;
2990
2991 fail:
2992 if (rt != NULL) {
2993 RT_UNLOCK(rt);
2994 }
2995 if (m) {
2996 m_freem(m);
2997 }
2998 if (m0) {
2999 m_freem(m0);
3000 }
3001 }
3002
3003 /*
3004 * ICMPv6 socket option processing.
3005 */
3006 int
3007 icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
3008 {
3009 int error = 0;
3010 int optlen;
3011 struct inpcb *inp = sotoinpcb(so);
3012 int level, op, optname;
3013
3014 if (sopt) {
3015 level = sopt->sopt_level;
3016 op = sopt->sopt_dir;
3017 optname = sopt->sopt_name;
3018 optlen = sopt->sopt_valsize;
3019 } else {
3020 level = op = optname = optlen = 0;
3021 }
3022
3023 if (level != IPPROTO_ICMPV6) {
3024 return EINVAL;
3025 }
3026
3027 switch (op) {
3028 case PRCO_SETOPT:
3029 switch (optname) {
3030 case ICMP6_FILTER:
3031 {
3032 struct icmp6_filter *p;
3033
3034 if (optlen != 0 && optlen != sizeof(*p)) {
3035 error = EMSGSIZE;
3036 break;
3037 }
3038 if (inp->in6p_icmp6filt == NULL) {
3039 error = EINVAL;
3040 break;
3041 }
3042
3043 if (optlen == 0) {
3044 /* According to RFC 3542, an installed filter can be
3045 * cleared by issuing a setsockopt for ICMP6_FILTER
3046 * with a zero length.
3047 */
3048 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
3049 } else {
3050 error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen,
3051 optlen);
3052 }
3053 break;
3054 }
3055
3056 default:
3057 error = ENOPROTOOPT;
3058 break;
3059 }
3060 break;
3061
3062 case PRCO_GETOPT:
3063 switch (optname) {
3064 case ICMP6_FILTER:
3065 {
3066 if (inp->in6p_icmp6filt == NULL) {
3067 error = EINVAL;
3068 break;
3069 }
3070 error = sooptcopyout(sopt, inp->in6p_icmp6filt,
3071 min(sizeof(struct icmp6_filter), optlen));
3072 break;
3073 }
3074
3075 default:
3076 error = ENOPROTOOPT;
3077 break;
3078 }
3079 break;
3080 }
3081
3082 return error;
3083 }
3084
3085 /*
3086 * ICMPv6 socket datagram option processing.
3087 */
3088 int
3089 icmp6_dgram_ctloutput(struct socket *so, struct sockopt *sopt)
3090 {
3091 if (kauth_cred_issuser(so->so_cred)) {
3092 return icmp6_ctloutput(so, sopt);
3093 }
3094
3095 if (sopt->sopt_level == IPPROTO_ICMPV6) {
3096 switch (sopt->sopt_name) {
3097 case ICMP6_FILTER:
3098 return icmp6_ctloutput(so, sopt);
3099 default:
3100 return EPERM;
3101 }
3102 }
3103
3104 if (sopt->sopt_level != IPPROTO_IPV6) {
3105 return EINVAL;
3106 }
3107
3108 switch (sopt->sopt_name) {
3109 case IPV6_UNICAST_HOPS:
3110 case IPV6_CHECKSUM:
3111 case IPV6_V6ONLY:
3112 case IPV6_USE_MIN_MTU:
3113 case IPV6_RECVRTHDR:
3114 case IPV6_RECVPKTINFO:
3115 case IPV6_RECVHOPLIMIT:
3116 case IPV6_PATHMTU:
3117 case IPV6_PKTINFO:
3118 case IPV6_HOPLIMIT:
3119 case IPV6_HOPOPTS:
3120 case IPV6_DSTOPTS:
3121 case IPV6_MULTICAST_IF:
3122 case IPV6_MULTICAST_HOPS:
3123 case IPV6_MULTICAST_LOOP:
3124 case IPV6_JOIN_GROUP:
3125 case IPV6_LEAVE_GROUP:
3126 case IPV6_PORTRANGE:
3127 case IPV6_IPSEC_POLICY:
3128 case IPV6_RECVTCLASS:
3129 case IPV6_TCLASS:
3130 case IPV6_2292PKTOPTIONS:
3131 case IPV6_2292PKTINFO:
3132 case IPV6_2292HOPLIMIT:
3133 case IPV6_2292HOPOPTS:
3134 case IPV6_2292DSTOPTS:
3135 case IPV6_2292RTHDR:
3136 case IPV6_BOUND_IF:
3137 case IPV6_NO_IFT_CELLULAR:
3138
3139 return ip6_ctloutput(so, sopt);
3140
3141 default:
3142 return EPERM;
3143 }
3144 }
3145
3146 __private_extern__ int
3147 icmp6_dgram_send(struct socket *so, int flags, struct mbuf *m,
3148 struct sockaddr *nam, struct mbuf *control, struct proc *p)
3149 {
3150 #pragma unused(flags, p)
3151 int error = 0;
3152 struct inpcb *inp = sotoinpcb(so);
3153 struct sockaddr_in6 tmp;
3154 struct sockaddr_in6 *dst = (struct sockaddr_in6 *)(void *)nam;
3155 struct icmp6_hdr *icmp6;
3156
3157 if (inp == NULL
3158 #if NECP
3159 || (necp_socket_should_use_flow_divert(inp))
3160 #endif /* NECP */
3161 ) {
3162 error = (inp == NULL ? EINVAL : EPROTOTYPE);
3163 goto bad;
3164 }
3165
3166 if (kauth_cred_issuser(so->so_cred)) {
3167 return rip6_output(m, so, SIN6(nam), control, 0);
3168 }
3169
3170 /* always copy sockaddr to avoid overwrites */
3171 if (so->so_state & SS_ISCONNECTED) {
3172 if (nam != NULL) {
3173 error = EISCONN;
3174 goto bad;
3175 }
3176 /* XXX */
3177 bzero(&tmp, sizeof(tmp));
3178 tmp.sin6_family = AF_INET6;
3179 tmp.sin6_len = sizeof(struct sockaddr_in6);
3180 bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
3181 sizeof(struct in6_addr));
3182 dst = &tmp;
3183 } else {
3184 if (nam == NULL) {
3185 error = ENOTCONN;
3186 goto bad;
3187 }
3188 tmp = *(struct sockaddr_in6 *)(void *)nam;
3189 dst = &tmp;
3190 }
3191
3192 /*
3193 * For an ICMPv6 packet, we should know its type and code
3194 */
3195 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) {
3196 if (m->m_len < sizeof(struct icmp6_hdr) &&
3197 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
3198 error = ENOBUFS;
3199 goto bad;
3200 }
3201 icmp6 = mtod(m, struct icmp6_hdr *);
3202
3203 /*
3204 * Allow only to send echo request and node information request
3205 * See RFC 2463 for Echo Request Message format
3206 */
3207 if ((icmp6->icmp6_type == ICMP6_ECHO_REQUEST &&
3208 icmp6->icmp6_code == 0) ||
3209 (icmp6->icmp6_type == ICMP6_NI_QUERY &&
3210 (icmp6->icmp6_code == ICMP6_NI_SUBJ_IPV6 ||
3211 icmp6->icmp6_code == ICMP6_NI_SUBJ_FQDN))) {
3212 /* Good */
3213 ;
3214 } else {
3215 error = EPERM;
3216 goto bad;
3217 }
3218 }
3219
3220 #if ENABLE_DEFAULT_SCOPE
3221 if (dst->sin6_scope_id == 0) { /* not change if specified */
3222 dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr);
3223 }
3224 #endif
3225
3226 return rip6_output(m, so, dst, control, 0);
3227 bad:
3228 VERIFY(error != 0);
3229
3230 if (m != NULL) {
3231 m_freem(m);
3232 }
3233 if (control != NULL) {
3234 m_freem(control);
3235 }
3236
3237 return error;
3238 }
3239
3240 /* Like rip6_attach but without root privilege enforcement */
3241 __private_extern__ int
3242 icmp6_dgram_attach(struct socket *so, int proto, struct proc *p)
3243 {
3244 struct inpcb *inp;
3245 int error;
3246
3247 inp = sotoinpcb(so);
3248 if (inp) {
3249 panic("icmp6_dgram_attach");
3250 }
3251
3252 if (proto != IPPROTO_ICMPV6) {
3253 return EINVAL;
3254 }
3255
3256 error = soreserve(so, rip_sendspace, rip_recvspace);
3257 if (error) {
3258 return error;
3259 }
3260 error = in_pcballoc(so, &ripcbinfo, p);
3261 if (error) {
3262 return error;
3263 }
3264 inp = (struct inpcb *)so->so_pcb;
3265 inp->inp_vflag |= INP_IPV6;
3266 inp->in6p_ip6_nxt = IPPROTO_ICMPV6;
3267 inp->in6p_hops = -1; /* use kernel default */
3268 inp->in6p_cksum = -1;
3269 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *,
3270 sizeof(struct icmp6_filter), M_PCB, M_WAITOK);
3271 if (inp->in6p_icmp6filt == NULL) {
3272 return ENOMEM;
3273 }
3274 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
3275 return 0;
3276 }
3277
3278
3279 /*
3280 * Perform rate limit check.
3281 * Returns 0 if it is okay to send the icmp6 packet.
3282 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
3283 * limitation.
3284 *
3285 * XXX per-destination check necessary?
3286 */
3287 static int
3288 icmp6_ratelimit(
3289 __unused const struct in6_addr *dst, /* not used at this moment */
3290 const int type,
3291 __unused const int code)
3292 {
3293 int ret;
3294
3295 ret = 0; /* okay to send */
3296
3297 /* PPS limit */
3298 if (type == ND_ROUTER_ADVERT) {
3299 if (!ppsratecheck(&icmp6rappslim_last, &icmp6rapps_count,
3300 icmp6rappslim)) {
3301 ret++;
3302 }
3303 } else if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
3304 icmp6errppslim)) {
3305 /* The packet is subject to rate limit */
3306 ret++;
3307 }
3308
3309 return ret;
3310 }