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