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