xref: /freebsd/sys/netinet6/icmp6.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /*	$FreeBSD$	*/
2 /*	$KAME: icmp6.c,v 1.119 2000/07/03 14:16:46 itojun Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1982, 1986, 1988, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Berkeley and its contributors.
49  * 4. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *	@(#)ip_icmp.c	8.2 (Berkeley) 1/4/94
66  */
67 
68 #include "opt_inet.h"
69 #include "opt_inet6.h"
70 #include "opt_ipsec.h"
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/mbuf.h>
75 #include <sys/protosw.h>
76 #include <sys/socket.h>
77 #include <sys/socketvar.h>
78 #include <sys/time.h>
79 #include <sys/kernel.h>
80 #include <sys/syslog.h>
81 #include <sys/domain.h>
82 
83 #include <net/if.h>
84 #include <net/route.h>
85 #include <net/if_dl.h>
86 #include <net/if_types.h>
87 
88 #include <netinet/in.h>
89 #include <netinet/in_var.h>
90 #include <netinet/ip6.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet/icmp6.h>
93 #include <netinet6/mld6_var.h>
94 #include <netinet/in_pcb.h>
95 #include <netinet6/in6_pcb.h>
96 #include <netinet6/nd6.h>
97 #include <netinet6/in6_ifattach.h>
98 #include <netinet6/ip6protosw.h>
99 
100 #ifdef IPSEC
101 #include <netinet6/ipsec.h>
102 #ifdef INET6
103 #include <netinet6/ipsec6.h>
104 #endif
105 #include <netkey/key.h>
106 #endif
107 
108 #include "faith.h"
109 
110 #include <net/net_osdep.h>
111 
112 extern struct domain inet6domain;
113 extern struct ip6protosw inet6sw[];
114 extern u_char ip6_protox[];
115 
116 struct icmp6stat icmp6stat;
117 
118 extern struct inpcbhead ripcb;
119 extern struct timeval icmp6errratelim;
120 static struct timeval icmp6errratelim_last;
121 extern int icmp6errppslim;
122 static int icmp6errpps_count = 0;
123 extern int icmp6_nodeinfo;
124 
125 static void icmp6_errcount __P((struct icmp6errstat *, int, int));
126 static int icmp6_rip6_input __P((struct mbuf **, int));
127 static void icmp6_mtudisc_update __P((struct in6_addr *, struct icmp6_hdr *,
128 				      struct mbuf *));
129 static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int));
130 static const char *icmp6_redirect_diag __P((struct in6_addr *,
131 	struct in6_addr *, struct in6_addr *));
132 #ifndef HAVE_RATECHECK
133 static int ratecheck __P((struct timeval *, struct timeval *));
134 #endif
135 static struct mbuf *ni6_input __P((struct mbuf *, int));
136 static struct mbuf *ni6_nametodns __P((const char *, int, int));
137 static int ni6_dnsmatch __P((const char *, int, const char *, int));
138 static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *,
139 			  struct ifnet **));
140 static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
141 				struct ifnet *, int));
142 
143 #ifdef COMPAT_RFC1885
144 static struct route_in6 icmp6_reflect_rt;
145 #endif
146 
147 void
148 icmp6_init()
149 {
150 	mld6_init();
151 }
152 
153 static void
154 icmp6_errcount(stat, type, code)
155 	struct icmp6errstat *stat;
156 	int type, code;
157 {
158 	switch(type) {
159 	case ICMP6_DST_UNREACH:
160 		switch (code) {
161 		case ICMP6_DST_UNREACH_NOROUTE:
162 			stat->icp6errs_dst_unreach_noroute++;
163 			return;
164 		case ICMP6_DST_UNREACH_ADMIN:
165 			stat->icp6errs_dst_unreach_admin++;
166 			return;
167 		case ICMP6_DST_UNREACH_BEYONDSCOPE:
168 			stat->icp6errs_dst_unreach_beyondscope++;
169 			return;
170 		case ICMP6_DST_UNREACH_ADDR:
171 			stat->icp6errs_dst_unreach_addr++;
172 			return;
173 		case ICMP6_DST_UNREACH_NOPORT:
174 			stat->icp6errs_dst_unreach_noport++;
175 			return;
176 		}
177 		break;
178 	case ICMP6_PACKET_TOO_BIG:
179 		stat->icp6errs_packet_too_big++;
180 		return;
181 	case ICMP6_TIME_EXCEEDED:
182 		switch(code) {
183 		case ICMP6_TIME_EXCEED_TRANSIT:
184 			stat->icp6errs_time_exceed_transit++;
185 			return;
186 		case ICMP6_TIME_EXCEED_REASSEMBLY:
187 			stat->icp6errs_time_exceed_reassembly++;
188 			return;
189 		}
190 		break;
191 	case ICMP6_PARAM_PROB:
192 		switch(code) {
193 		case ICMP6_PARAMPROB_HEADER:
194 			stat->icp6errs_paramprob_header++;
195 			return;
196 		case ICMP6_PARAMPROB_NEXTHEADER:
197 			stat->icp6errs_paramprob_nextheader++;
198 			return;
199 		case ICMP6_PARAMPROB_OPTION:
200 			stat->icp6errs_paramprob_option++;
201 			return;
202 		}
203 		break;
204 	case ND_REDIRECT:
205 		stat->icp6errs_redirect++;
206 		return;
207 	}
208 	stat->icp6errs_unknown++;
209 }
210 
211 /*
212  * Generate an error packet of type error in response to bad IP6 packet.
213  */
214 void
215 icmp6_error(m, type, code, param)
216 	struct mbuf *m;
217 	int type, code, param;
218 {
219 	struct ip6_hdr *oip6, *nip6;
220 	struct icmp6_hdr *icmp6;
221 	u_int preplen;
222 	int off;
223 	int nxt;
224 
225 	icmp6stat.icp6s_error++;
226 
227 	/* count per-type-code statistics */
228 	icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code);
229 
230 #ifdef M_DECRYPTED	/*not openbsd*/
231 	if (m->m_flags & M_DECRYPTED) {
232 		icmp6stat.icp6s_canterror++;
233 		goto freeit;
234 	}
235 #endif
236 
237 #ifndef PULLDOWN_TEST
238 	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );
239 #else
240 	if (m->m_len < sizeof(struct ip6_hdr)) {
241 		m = m_pullup(m, sizeof(struct ip6_hdr));
242 		if (m == NULL)
243 			return;
244 	}
245 #endif
246 	oip6 = mtod(m, struct ip6_hdr *);
247 
248 	/*
249 	 * Multicast destination check. For unrecognized option errors,
250 	 * this check has already done in ip6_unknown_opt(), so we can
251 	 * check only for other errors.
252 	 */
253 	if ((m->m_flags & (M_BCAST|M_MCAST) ||
254 	     IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
255 	    (type != ICMP6_PACKET_TOO_BIG &&
256 	     (type != ICMP6_PARAM_PROB ||
257 	      code != ICMP6_PARAMPROB_OPTION)))
258 		goto freeit;
259 
260 	/* Source address check. XXX: the case of anycast source? */
261 	if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
262 	    IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
263 		goto freeit;
264 
265 	/*
266 	 * If we are about to send ICMPv6 against ICMPv6 error/redirect,
267 	 * don't do it.
268 	 */
269 	nxt = -1;
270 	off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
271 	if (off >= 0 && nxt == IPPROTO_ICMPV6) {
272 		struct icmp6_hdr *icp;
273 
274 #ifndef PULLDOWN_TEST
275 		IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), );
276 		icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
277 #else
278 		IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
279 			sizeof(*icp));
280 		if (icp == NULL) {
281 			icmp6stat.icp6s_tooshort++;
282 			return;
283 		}
284 #endif
285 		if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
286 		    icp->icmp6_type == ND_REDIRECT) {
287 			/*
288 			 * ICMPv6 error
289 			 * Special case: for redirect (which is
290 			 * informational) we must not send icmp6 error.
291 			 */
292 			icmp6stat.icp6s_canterror++;
293 			goto freeit;
294 		} else {
295 			/* ICMPv6 informational - send the error */
296 		}
297 	} else {
298 		/* non-ICMPv6 - send the error */
299 	}
300 
301 	oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
302 
303 	/* Finally, do rate limitation check. */
304 	if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
305 		icmp6stat.icp6s_toofreq++;
306 		goto freeit;
307 	}
308 
309 	/*
310 	 * OK, ICMP6 can be generated.
311 	 */
312 
313 	if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
314 		m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
315 
316 	preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
317 	M_PREPEND(m, preplen, M_DONTWAIT);
318 	if (m && m->m_len < preplen)
319 		m = m_pullup(m, preplen);
320 	if (m == NULL) {
321 		printf("ENOBUFS in icmp6_error %d\n", __LINE__);
322 		return;
323 	}
324 
325 	nip6 = mtod(m, struct ip6_hdr *);
326 	nip6->ip6_src  = oip6->ip6_src;
327 	nip6->ip6_dst  = oip6->ip6_dst;
328 
329 	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
330 		oip6->ip6_src.s6_addr16[1] = 0;
331 	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
332 		oip6->ip6_dst.s6_addr16[1] = 0;
333 
334 	icmp6 = (struct icmp6_hdr *)(nip6 + 1);
335 	icmp6->icmp6_type = type;
336 	icmp6->icmp6_code = code;
337 	icmp6->icmp6_pptr = htonl((u_int32_t)param);
338 
339 	icmp6stat.icp6s_outhist[type]++;
340 	icmp6_reflect(m, sizeof(struct ip6_hdr)); /*header order: IPv6 - ICMPv6*/
341 
342 	return;
343 
344   freeit:
345 	/*
346 	 * If we can't tell wheter or not we can generate ICMP6, free it.
347 	 */
348 	m_freem(m);
349 }
350 
351 /*
352  * Process a received ICMP6 message.
353  */
354 int
355 icmp6_input(mp, offp, proto)
356 	struct mbuf **mp;
357 	int *offp, proto;
358 {
359 	struct mbuf *m = *mp, *n;
360 	struct ip6_hdr *ip6, *nip6;
361 	struct icmp6_hdr *icmp6, *nicmp6;
362 	int off = *offp;
363 	int icmp6len = m->m_pkthdr.len - *offp;
364 	int code, sum, noff;
365 	struct sockaddr_in6 icmp6src;
366 
367 #ifndef PULLDOWN_TEST
368 	IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE);
369 	/* m might change if M_LOOP. So, call mtod after this */
370 #endif
371 
372 	/*
373 	 * Locate icmp6 structure in mbuf, and check
374 	 * that not corrupted and of at least minimum length
375 	 */
376 
377 	ip6 = mtod(m, struct ip6_hdr *);
378 	if (icmp6len < sizeof(struct icmp6_hdr)) {
379 		icmp6stat.icp6s_tooshort++;
380 		goto freeit;
381 	}
382 
383 	/*
384 	 * calculate the checksum
385 	 */
386 #ifndef PULLDOWN_TEST
387 	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
388 #else
389 	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
390 	if (icmp6 == NULL) {
391 		icmp6stat.icp6s_tooshort++;
392 		return IPPROTO_DONE;
393 	}
394 #endif
395 	code = icmp6->icmp6_code;
396 
397 	if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
398 		log(LOG_ERR,
399 		    "ICMP6 checksum error(%d|%x) %s\n",
400 		    icmp6->icmp6_type,
401 		    sum,
402 		    ip6_sprintf(&ip6->ip6_src));
403 		icmp6stat.icp6s_checksum++;
404 		goto freeit;
405 	}
406 
407 #if defined(NFAITH) && 0 < NFAITH
408 	if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
409 		/*
410 		 * Deliver very specific ICMP6 type only.
411 		 * This is important to deilver TOOBIG.  Otherwise PMTUD
412 		 * will not work.
413 		 */
414 		switch (icmp6->icmp6_type) {
415 		case ICMP6_DST_UNREACH:
416 		case ICMP6_PACKET_TOO_BIG:
417 		case ICMP6_TIME_EXCEEDED:
418 			break;
419 		default:
420 			goto freeit;
421 		}
422 	}
423 #endif
424 
425 #ifdef IPSEC
426 	/* drop it if it does not match the default policy */
427 	if (ipsec6_in_reject(m, NULL)) {
428 		ipsecstat.in_polvio++;
429 		goto freeit;
430 	}
431 #endif
432 
433 	icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
434 	icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
435 	if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
436 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
437 
438 	switch (icmp6->icmp6_type) {
439 
440 	case ICMP6_DST_UNREACH:
441 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
442 		switch (code) {
443 		case ICMP6_DST_UNREACH_NOROUTE:
444 			code = PRC_UNREACH_NET;
445 			break;
446 		case ICMP6_DST_UNREACH_ADMIN:
447 			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib);
448 			code = PRC_UNREACH_PROTOCOL; /* is this a good code? */
449 			break;
450 		case ICMP6_DST_UNREACH_ADDR:
451 			code = PRC_HOSTDEAD;
452 			break;
453 #ifdef COMPAT_RFC1885
454 		case ICMP6_DST_UNREACH_NOTNEIGHBOR:
455 			code = PRC_UNREACH_SRCFAIL;
456 			break;
457 #else
458 		case ICMP6_DST_UNREACH_BEYONDSCOPE:
459 			/* I mean "source address was incorrect." */
460 			code = PRC_PARAMPROB;
461 			break;
462 #endif
463 		case ICMP6_DST_UNREACH_NOPORT:
464 			code = PRC_UNREACH_PORT;
465 			break;
466 		default:
467 			goto badcode;
468 		}
469 		goto deliver;
470 		break;
471 
472 	case ICMP6_PACKET_TOO_BIG:
473 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
474 		if (code != 0)
475 			goto badcode;
476 
477 		code = PRC_MSGSIZE;
478 
479 		/*
480 		 * Updating the path MTU will be done after examining
481 		 * intermediate extension headers.
482 		 */
483 		goto deliver;
484 		break;
485 
486 	case ICMP6_TIME_EXCEEDED:
487 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
488 		switch (code) {
489 		case ICMP6_TIME_EXCEED_TRANSIT:
490 		case ICMP6_TIME_EXCEED_REASSEMBLY:
491 			code += PRC_TIMXCEED_INTRANS;
492 			break;
493 		default:
494 			goto badcode;
495 		}
496 		goto deliver;
497 		break;
498 
499 	case ICMP6_PARAM_PROB:
500 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob);
501 		switch (code) {
502 		case ICMP6_PARAMPROB_NEXTHEADER:
503 			code = PRC_UNREACH_PROTOCOL;
504 			break;
505 		case ICMP6_PARAMPROB_HEADER:
506 		case ICMP6_PARAMPROB_OPTION:
507 			code = PRC_PARAMPROB;
508 			break;
509 		default:
510 			goto badcode;
511 		}
512 		goto deliver;
513 		break;
514 
515 	case ICMP6_ECHO_REQUEST:
516 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo);
517 		if (code != 0)
518 			goto badcode;
519 		if ((n = m_copy(m, 0, M_COPYALL)) == NULL) {
520 			/* Give up remote */
521 			break;
522 		}
523 		if ((n->m_flags & M_EXT) != 0
524 		 || n->m_len < off + sizeof(struct icmp6_hdr)) {
525 			struct mbuf *n0 = n;
526 			const int maxlen = sizeof(*nip6) + sizeof(*nicmp6);
527 
528 			/*
529 			 * Prepare an internal mbuf. m_pullup() doesn't
530 			 * always copy the length we specified.
531 			 */
532 			if (maxlen >= MCLBYTES) {
533 #ifdef DIAGNOSTIC
534 				printf("MCLBYTES too small\n");
535 #endif
536 				/* Give up remote */
537 				m_freem(n0);
538 				break;
539 			}
540 			MGETHDR(n, M_DONTWAIT, n0->m_type);
541 			if (n && maxlen >= MHLEN) {
542 				MCLGET(n, M_DONTWAIT);
543 				if ((n->m_flags & M_EXT) == 0) {
544 					m_free(n);
545 					n = NULL;
546 				}
547 			}
548 			if (n == NULL) {
549 				/* Give up remote */
550 				m_freem(n0);
551 				break;
552 			}
553 			M_COPY_PKTHDR(n, n0);
554 			/*
555 			 * Copy IPv6 and ICMPv6 only.
556 			 */
557 			nip6 = mtod(n, struct ip6_hdr *);
558 			bcopy(ip6, nip6, sizeof(struct ip6_hdr));
559 			nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
560 			bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
561 			noff = sizeof(struct ip6_hdr);
562 			n->m_pkthdr.len = n->m_len =
563 				noff + sizeof(struct icmp6_hdr);
564 			/*
565 			 * Adjust mbuf. ip6_plen will be adjusted in
566 			 * ip6_output().
567 			 */
568 			m_adj(n0, off + sizeof(struct icmp6_hdr));
569 			n->m_pkthdr.len += n0->m_pkthdr.len;
570 			n->m_next = n0;
571 			n0->m_flags &= ~M_PKTHDR;
572 		} else {
573 			nip6 = mtod(n, struct ip6_hdr *);
574 			nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off);
575 			noff = off;
576 		}
577 		nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
578 		nicmp6->icmp6_code = 0;
579 		if (n) {
580 			icmp6stat.icp6s_reflect++;
581 			icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
582 			icmp6_reflect(n, noff);
583 		}
584 		break;
585 
586 	case ICMP6_ECHO_REPLY:
587 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
588 		if (code != 0)
589 			goto badcode;
590 		break;
591 
592 	case MLD6_LISTENER_QUERY:
593 	case MLD6_LISTENER_REPORT:
594 		if (icmp6len < sizeof(struct mld6_hdr))
595 			goto badlen;
596 		if (icmp6->icmp6_type == MLD6_LISTENER_QUERY) /* XXX: ugly... */
597 			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery);
598 		else
599 			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport);
600 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
601 			/* give up local */
602 			mld6_input(m, off);
603 			m = NULL;
604 			goto freeit;
605 		}
606 		mld6_input(n, off);
607 		/* m stays. */
608 		break;
609 
610 	case MLD6_LISTENER_DONE:
611 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone);
612 		if (icmp6len < sizeof(struct mld6_hdr))	/* necessary? */
613 			goto badlen;
614 		break;		/* nothing to be done in kernel */
615 
616 	case MLD6_MTRACE_RESP:
617 	case MLD6_MTRACE:
618 		/* XXX: these two are experimental. not officially defind. */
619 		/* XXX: per-interface statistics? */
620 		break;		/* just pass it to applications */
621 
622 	case ICMP6_WRUREQUEST:	/* ICMP6_FQDN_QUERY */
623 	    {
624 		enum { WRU, FQDN } mode;
625 
626 		if (!icmp6_nodeinfo)
627 			break;
628 
629 		if (icmp6len == sizeof(struct icmp6_hdr) + 4)
630 			mode = WRU;
631 		else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
632 			mode = FQDN;
633 		else
634 			goto badlen;
635 
636 #define hostnamelen	strlen(hostname)
637 		if (mode == FQDN) {
638 #ifndef PULLDOWN_TEST
639 			IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo),
640 					 IPPROTO_DONE);
641 #endif
642 			n = m_copy(m, 0, M_COPYALL);
643 			if (n)
644 				n = ni6_input(n, off);
645 			/* XXX meaningless if n == NULL */
646 			noff = sizeof(struct ip6_hdr);
647 		} else {
648 			u_char *p;
649 			int maxlen, maxhlen;
650 
651 			if (code != 0)
652 				goto badcode;
653 			maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4;
654 			if (maxlen >= MCLBYTES) {
655 #ifdef DIAGNOSTIC
656 				printf("MCLBYTES too small\n");
657 #endif
658 				/* Give up remote */
659 				break;
660 			}
661 			MGETHDR(n, M_DONTWAIT, m->m_type);
662 			if (n && maxlen > MHLEN) {
663 				MCLGET(n, M_DONTWAIT);
664 				if ((n->m_flags & M_EXT) == 0) {
665 					m_free(n);
666 					n = NULL;
667 				}
668 			}
669 			if (n == NULL) {
670 				/* Give up remote */
671 				break;
672 			}
673 			n->m_len = 0;
674 			maxhlen = M_TRAILINGSPACE(n) - maxlen;
675 			if (maxhlen > hostnamelen)
676 				maxhlen = hostnamelen;
677 			/*
678 			 * Copy IPv6 and ICMPv6 only.
679 			 */
680 			nip6 = mtod(n, struct ip6_hdr *);
681 			bcopy(ip6, nip6, sizeof(struct ip6_hdr));
682 			nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
683 			bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
684 			p = (u_char *)(nicmp6 + 1);
685 			bzero(p, 4);
686 			bcopy(hostname, p + 4, maxhlen); /*meaningless TTL*/
687 			noff = sizeof(struct ip6_hdr);
688 			M_COPY_PKTHDR(n, m); /* just for recvif */
689 			n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
690 				sizeof(struct icmp6_hdr) + 4 + maxhlen;
691 			nicmp6->icmp6_type = ICMP6_WRUREPLY;
692 			nicmp6->icmp6_code = 0;
693 		}
694 #undef hostnamelen
695 		if (n) {
696 			icmp6stat.icp6s_reflect++;
697 			icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
698 			icmp6_reflect(n, noff);
699 		}
700 		break;
701 	    }
702 
703 	case ICMP6_WRUREPLY:
704 		if (code != 0)
705 			goto badcode;
706 		break;
707 
708 	case ND_ROUTER_SOLICIT:
709 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit);
710 		if (code != 0)
711 			goto badcode;
712 		if (icmp6len < sizeof(struct nd_router_solicit))
713 			goto badlen;
714 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
715 			/* give up local */
716 			nd6_rs_input(m, off, icmp6len);
717 			m = NULL;
718 			goto freeit;
719 		}
720 		nd6_rs_input(n, off, icmp6len);
721 		/* m stays. */
722 		break;
723 
724 	case ND_ROUTER_ADVERT:
725 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert);
726 		if (code != 0)
727 			goto badcode;
728 		if (icmp6len < sizeof(struct nd_router_advert))
729 			goto badlen;
730 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
731 			/* give up local */
732 			nd6_ra_input(m, off, icmp6len);
733 			m = NULL;
734 			goto freeit;
735 		}
736 		nd6_ra_input(n, off, icmp6len);
737 		/* m stays. */
738 		break;
739 
740 	case ND_NEIGHBOR_SOLICIT:
741 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit);
742 		if (code != 0)
743 			goto badcode;
744 		if (icmp6len < sizeof(struct nd_neighbor_solicit))
745 			goto badlen;
746 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
747 			/* give up local */
748 			nd6_ns_input(m, off, icmp6len);
749 			m = NULL;
750 			goto freeit;
751 		}
752 		nd6_ns_input(n, off, icmp6len);
753 		/* m stays. */
754 		break;
755 
756 	case ND_NEIGHBOR_ADVERT:
757 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert);
758 		if (code != 0)
759 			goto badcode;
760 		if (icmp6len < sizeof(struct nd_neighbor_advert))
761 			goto badlen;
762 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
763 			/* give up local */
764 			nd6_na_input(m, off, icmp6len);
765 			m = NULL;
766 			goto freeit;
767 		}
768 		nd6_na_input(n, off, icmp6len);
769 		/* m stays. */
770 		break;
771 
772 	case ND_REDIRECT:
773 		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect);
774 		if (code != 0)
775 			goto badcode;
776 		if (icmp6len < sizeof(struct nd_redirect))
777 			goto badlen;
778 		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
779 			/* give up local */
780 			icmp6_redirect_input(m, off);
781 			m = NULL;
782 			goto freeit;
783 		}
784 		icmp6_redirect_input(n, off);
785 		/* m stays. */
786 		break;
787 
788 	case ICMP6_ROUTER_RENUMBERING:
789 		if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
790 		    code != ICMP6_ROUTER_RENUMBERING_RESULT)
791 			goto badcode;
792 		if (icmp6len < sizeof(struct icmp6_router_renum))
793 			goto badlen;
794 		break;
795 
796 	default:
797 		printf("icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
798 		       icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
799 		       ip6_sprintf(&ip6->ip6_dst),
800 		       m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0);
801 		if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
802 			/* ICMPv6 error: MUST deliver it by spec... */
803 			code = PRC_NCMDS;
804 			/* deliver */
805 		} else {
806 			/* ICMPv6 informational: MUST not deliver */
807 			break;
808 		}
809 	deliver:
810 		if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
811 			icmp6stat.icp6s_tooshort++;
812 			goto freeit;
813 		}
814 #ifndef PULLDOWN_TEST
815 		IP6_EXTHDR_CHECK(m, off,
816 			sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr),
817 			IPPROTO_DONE);
818 		icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
819 #else
820 		IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
821 			sizeof(*icmp6) + sizeof(struct ip6_hdr));
822 		if (icmp6 == NULL) {
823 			icmp6stat.icp6s_tooshort++;
824 			return IPPROTO_DONE;
825 		}
826 #endif
827 		bzero(&icmp6src, sizeof(icmp6src));
828 		icmp6src.sin6_len = sizeof(struct sockaddr_in6);
829 		icmp6src.sin6_family = AF_INET6;
830 		icmp6src.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
831 
832 		/* Detect the upper level protocol */
833 	    {
834 		void (*ctlfunc) __P((int, struct sockaddr *, void *));
835 		struct ip6_hdr *eip6 = (struct ip6_hdr *)(icmp6 + 1);
836 		u_int8_t nxt = eip6->ip6_nxt;
837 		int eoff = off + sizeof(struct icmp6_hdr) +
838 			sizeof(struct ip6_hdr);
839 		struct ip6ctlparam ip6cp;
840 		struct in6_addr *finaldst = NULL;
841 		int icmp6type = icmp6->icmp6_type;
842 		struct ip6_frag *fh;
843 		struct ip6_rthdr *rth;
844 		struct ip6_rthdr0 *rth0;
845 		int rthlen;
846 
847 		while (1) { /* XXX: should avoid inf. loop explicitly? */
848 			struct ip6_ext *eh;
849 
850 			switch(nxt) {
851 			case IPPROTO_HOPOPTS:
852 			case IPPROTO_DSTOPTS:
853 			case IPPROTO_AH:
854 #ifndef PULLDOWN_TEST
855 				IP6_EXTHDR_CHECK(m, 0, eoff +
856 						 sizeof(struct ip6_ext),
857 						 IPPROTO_DONE);
858 				eh = (struct ip6_ext *)(mtod(m, caddr_t)
859 							+ eoff);
860 #else
861 				IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
862 					eoff, sizeof(*eh));
863 				if (eh == NULL) {
864 					icmp6stat.icp6s_tooshort++;
865 					return IPPROTO_DONE;
866 				}
867 #endif
868 
869 				if (nxt == IPPROTO_AH)
870 					eoff += (eh->ip6e_len + 2) << 2;
871 				else
872 					eoff += (eh->ip6e_len + 1) << 3;
873 				nxt = eh->ip6e_nxt;
874 				break;
875 			case IPPROTO_ROUTING:
876 				/*
877 				 * When the erroneous packet contains a
878 				 * routing header, we should examine the
879 				 * header to determine the final destination.
880 				 * Otherwise, we can't properly update
881 				 * information that depends on the final
882 				 * destination (e.g. path MTU).
883 				 */
884 #ifndef PULLDOWN_TEST
885 				IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth),
886 						 IPPROTO_DONE);
887 				rth = (struct ip6_rthdr *)(mtod(m, caddr_t)
888 							   + eoff);
889 #else
890 				IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
891 					eoff, sizeof(*rth));
892 				if (rth == NULL) {
893 					icmp6stat.icp6s_tooshort++;
894 					return IPPROTO_DONE;
895 				}
896 #endif
897 				rthlen = (rth->ip6r_len + 1) << 3;
898 				/*
899 				 * XXX: currently there is no
900 				 * officially defined type other
901 				 * than type-0.
902 				 * Note that if the segment left field
903 				 * is 0, all intermediate hops must
904 				 * have been passed.
905 				 */
906 				if (rth->ip6r_segleft &&
907 				    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
908 					int hops;
909 
910 #ifndef PULLDOWN_TEST
911 					IP6_EXTHDR_CHECK(m, 0, eoff + rthlen,
912 							 IPPROTO_DONE);
913 					rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff);
914 #else
915 					IP6_EXTHDR_GET(rth0,
916 						       struct ip6_rthdr0 *, m,
917 						       eoff, rthlen);
918 					if (rth0 == NULL) {
919 						icmp6stat.icp6s_tooshort++;
920 						return IPPROTO_DONE;
921 					}
922 #endif
923 					/* just ignore a bogus header */
924 					if ((rth0->ip6r0_len % 2) == 0 &&
925 					    (hops = rth0->ip6r0_len/2))
926 						finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
927 				}
928 				eoff += rthlen;
929 				nxt = rth->ip6r_nxt;
930 				break;
931 			case IPPROTO_FRAGMENT:
932 #ifndef PULLDOWN_TEST
933 				IP6_EXTHDR_CHECK(m, 0, eoff +
934 						 sizeof(struct ip6_frag),
935 						 IPPROTO_DONE);
936 				fh = (struct ip6_frag *)(mtod(m, caddr_t)
937 							 + eoff);
938 #else
939 				IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
940 					eoff, sizeof(*fh));
941 				if (fh == NULL) {
942 					icmp6stat.icp6s_tooshort++;
943 					return IPPROTO_DONE;
944 				}
945 #endif
946 				/*
947 				 * Data after a fragment header is meaningless
948 				 * unless it is the first fragment, but
949 				 * we'll go to the notify label for path MTU
950 				 * discovery.
951 				 */
952 				if (fh->ip6f_offlg & IP6F_OFF_MASK)
953 					goto notify;
954 
955 				eoff += sizeof(struct ip6_frag);
956 				nxt = fh->ip6f_nxt;
957 				break;
958 			default:
959 				/*
960 				 * This case includes ESP and the No Next
961 				 * Header. In such cases going to the notify
962 				 * label does not have any meaning
963 				 * (i.e. ctlfunc will be NULL), but we go
964 				 * anyway since we might have to update
965 				 * path MTU information.
966 				 */
967 				goto notify;
968 			}
969 		}
970 	    notify:
971 #ifndef PULLDOWN_TEST
972 		icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
973 #else
974 		IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
975 			sizeof(*icmp6) + sizeof(struct ip6_hdr));
976 		if (icmp6 == NULL) {
977 			icmp6stat.icp6s_tooshort++;
978 			return IPPROTO_DONE;
979 		}
980 #endif
981 		if (icmp6type == ICMP6_PACKET_TOO_BIG) {
982 			if (finaldst == NULL)
983 				finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
984 			icmp6_mtudisc_update(finaldst, icmp6, m);
985 		}
986 
987 		ctlfunc = (void (*) __P((int, struct sockaddr *, void *)))
988 			(inet6sw[ip6_protox[nxt]].pr_ctlinput);
989 		if (ctlfunc) {
990 			ip6cp.ip6c_m = m;
991 			ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
992 			ip6cp.ip6c_off = eoff;
993 			(*ctlfunc)(code, (struct sockaddr *)&icmp6src, &ip6cp);
994 		}
995 	    }
996 		break;
997 
998 	badcode:
999 		icmp6stat.icp6s_badcode++;
1000 		break;
1001 
1002 	badlen:
1003 		icmp6stat.icp6s_badlen++;
1004 		break;
1005 	}
1006 
1007 #ifdef HAVE_NRL_INPCB
1008 	rip6_input(&m, offp, IPPROTO_ICMPV6);
1009 #else
1010 	icmp6_rip6_input(&m, *offp);
1011 #endif
1012 	return IPPROTO_DONE;
1013 
1014  freeit:
1015 	m_freem(m);
1016 	return IPPROTO_DONE;
1017 }
1018 
1019 static void
1020 icmp6_mtudisc_update(dst, icmp6, m)
1021 	struct in6_addr *dst;
1022 	struct icmp6_hdr *icmp6;/* we can assume the validity of the pointer */
1023 	struct mbuf *m;	/* currently unused but added for scoped addrs */
1024 {
1025 	u_int mtu = ntohl(icmp6->icmp6_mtu);
1026 	struct rtentry *rt = NULL;
1027 	struct sockaddr_in6 sin6;
1028 
1029 	bzero(&sin6, sizeof(sin6));
1030 	sin6.sin6_family = PF_INET6;
1031 	sin6.sin6_len = sizeof(struct sockaddr_in6);
1032 	sin6.sin6_addr = *dst;
1033 	/* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */
1034 	rt = rtalloc1((struct sockaddr *)&sin6, 0,
1035 		      RTF_CLONING | RTF_PRCLONING);
1036 
1037 	if (rt && (rt->rt_flags & RTF_HOST)
1038 	    && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
1039 		if (mtu < IPV6_MMTU) {
1040 				/* xxx */
1041 			rt->rt_rmx.rmx_locks |= RTV_MTU;
1042 		} else if (mtu < rt->rt_ifp->if_mtu &&
1043 			   rt->rt_rmx.rmx_mtu > mtu) {
1044 			rt->rt_rmx.rmx_mtu = mtu;
1045 		}
1046 	}
1047 	if (rt)
1048 		RTFREE(rt);
1049 }
1050 
1051 /*
1052  * Process a Node Information Query packet, (roughly) based on
1053  * draft-ietf-ipngwg-icmp-name-lookups-05.
1054  *
1055  * Spec incompatibilities:
1056  * - IPv6 Subject address handling
1057  * - IPv4 Subject address handling support missing
1058  * - Proxy reply (answer even if it's not for me)
1059  * - "Supported Qtypes" support missing
1060  * - joins NI group address at in6_ifattach() time only, does not cope
1061  *   with hostname changes by sethostname(3)
1062  */
1063 #define hostnamelen	strlen(hostname)
1064 #ifndef offsetof		/* XXX */
1065 #define	offsetof(type, member)	((size_t)(&((type *)0)->member))
1066 #endif
1067 static struct mbuf *
1068 ni6_input(m, off)
1069 	struct mbuf *m;
1070 	int off;
1071 {
1072 	struct icmp6_nodeinfo *ni6, *nni6;
1073 	struct mbuf *n = NULL;
1074 	u_int16_t qtype;
1075 	int subjlen;
1076 	int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1077 	struct ni_reply_fqdn *fqdn;
1078 	int addrs;		/* for NI_QTYPE_NODEADDR */
1079 	struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1080 	struct sockaddr_in6 sin6;
1081 	struct ip6_hdr *ip6;
1082 	int oldfqdn = 0;	/* if 1, return pascal string (03 draft) */
1083 	char *subj;
1084 
1085 	ip6 = mtod(m, struct ip6_hdr *);
1086 #ifndef PULLDOWN_TEST
1087 	ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1088 #else
1089 	IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
1090 	if (ni6 == NULL) {
1091 		/* m is already reclaimed */
1092 		return NULL;
1093 	}
1094 #endif
1095 
1096 	/*
1097 	 * Validate IPv6 destination address.
1098 	 *
1099 	 * We accept packets with the following IPv6 destination address:
1100 	 * - Responder's unicast/anycast address,
1101 	 * - link-local multicast address
1102 	 * This is a violation to last paragraph in icmp-name-lookups-05
1103 	 * page 4, which restricts IPv6 destination address of a query to:
1104 	 * - Responder's unicast/anycast address,
1105 	 * - NI group address for a name belongs to the Responder, or
1106 	 * - NI group address for a name for which the Responder is providing
1107 	 *   proxy service.
1108 	 * (note: NI group address is a link-local multicast address)
1109 	 *
1110 	 * We allow any link-local multicast address, since "ping6 -w ff02::1"
1111 	 * has been really useful for us debugging our network.  Also this is
1112 	 * still questionable if the restriction in spec buy us security at all,
1113 	 * since RFC2463 permits echo packet to multicast destination.
1114 	 * Even if we forbid NI query to ff02::1, we can effectively get the
1115 	 * same result as "ping6 -w ff02::1" by the following steps:
1116 	 * - run "ping6 ff02::1", then
1117 	 * - run "ping6 -w" for all addresses replied.
1118 	 */
1119 	bzero(&sin6, sizeof(sin6));
1120 	sin6.sin6_family = AF_INET6;
1121 	sin6.sin6_len = sizeof(struct sockaddr_in6);
1122 	bcopy(&ip6->ip6_dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
1123 	/* XXX scopeid */
1124 	if (ifa_ifwithaddr((struct sockaddr *)&sin6))
1125 		; /*unicast/anycast, fine*/
1126 	else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr))
1127 		; /*violates spec slightly, see above*/
1128 	else
1129 		goto bad;
1130 
1131 	/* guess reply length */
1132 	qtype = ntohs(ni6->ni_qtype);
1133 	switch (qtype) {
1134 	case NI_QTYPE_NOOP:
1135 		break;		/* no reply data */
1136 	case NI_QTYPE_SUPTYPES:
1137 		goto bad;	/* xxx: to be implemented */
1138 		break;
1139 	case NI_QTYPE_FQDN:
1140 		/* XXX will append a mbuf */
1141 		replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1142 		break;
1143 	case NI_QTYPE_NODEADDR:
1144 		addrs = ni6_addrs(ni6, m, &ifp);
1145 		if ((replylen += addrs * sizeof(struct in6_addr)) > MCLBYTES)
1146 			replylen = MCLBYTES; /* XXX: we'll truncate later */
1147 		break;
1148 	default:
1149 		/*
1150 		 * XXX: We must return a reply with the ICMP6 code
1151 		 * `unknown Qtype' in this case. However we regard the case
1152 		 * as an FQDN query for backward compatibility.
1153 		 * Older versions set a random value to this field,
1154 		 * so it rarely varies in the defined qtypes.
1155 		 * But the mechanism is not reliable...
1156 		 * maybe we should obsolete older versions.
1157 		 */
1158 		qtype = NI_QTYPE_FQDN;
1159 		/* XXX will append a mbuf */
1160 		replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1161 		oldfqdn++;
1162 		break;
1163 	}
1164 
1165 	/* validate query Subject field. */
1166 	subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1167 	switch (qtype) {
1168 	case NI_QTYPE_NOOP:
1169 	case NI_QTYPE_SUPTYPES:
1170 		if (subjlen != 0)
1171 			goto bad;
1172 		break;
1173 
1174 	case NI_QTYPE_FQDN:
1175 	case NI_QTYPE_NODEADDR:
1176 		switch (ni6->ni_code) {
1177 		case ICMP6_NI_SUBJ_IPV6:
1178 #if ICMP6_NI_SUBJ_IPV6 != 0
1179 		case 0:
1180 #endif
1181 			/*
1182 			 * backward compatibility - try to accept 03 draft
1183 			 * format, where no Subject is present.
1184 			 */
1185 			if (subjlen == 0) {
1186 				oldfqdn++;
1187 				break;
1188 			}
1189 
1190 			if (subjlen != sizeof(sin6.sin6_addr))
1191 				goto bad;
1192 
1193 			/*
1194 			 * Validate Subject address.
1195 			 *
1196 			 * Not sure what exactly does "address belongs to the
1197 			 * node" mean in the spec, is it just unicast, or what?
1198 			 *
1199 			 * At this moment we consider Subject address as
1200 			 * "belong to the node" if the Subject address equals
1201 			 * to the IPv6 destination address; validation for
1202 			 * IPv6 destination address should have done enough
1203 			 * check for us.
1204 			 *
1205 			 * We do not do proxy at this moment.
1206 			 */
1207 			/* m_pulldown instead of copy? */
1208 			m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1209 			    subjlen, (caddr_t)&sin6.sin6_addr);
1210 			/* XXX kame scope hack */
1211 			if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
1212 #ifdef FAKE_LOOPBACK_IF
1213 				if ((m->m_flags & M_PKTHDR) != 0 &&
1214 				    m->m_pkthdr.rcvif) {
1215 					sin6.sin6_addr.s6_addr16[1] =
1216 					    htons(m->m_pkthdr.rcvif->if_index);
1217 				}
1218 #else
1219 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
1220 					sin6.sin6_addr.s6_addr16[1] =
1221 					    ip6->ip6_dst.s6_addr16[1];
1222 				}
1223 #endif
1224 			}
1225 			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &sin6.sin6_addr))
1226 				break;
1227 			/*
1228 			 * XXX if we are to allow other cases, we should really
1229 			 * be careful about scope here.
1230 			 * basically, we should disallow queries toward IPv6
1231 			 * destination X with subject Y, if scope(X) > scope(Y).
1232 			 * if we allow scope(X) > scope(Y), it will result in
1233 			 * information leakage across scope boundary.
1234 			 */
1235 			goto bad;
1236 
1237 		case ICMP6_NI_SUBJ_FQDN:
1238 			/*
1239 			 * Validate Subject name with gethostname(3).
1240 			 *
1241 			 * The behavior may need some debate, since:
1242 			 * - we are not sure if the node has FQDN as
1243 			 *   hostname (returned by gethostname(3)).
1244 			 * - the code does wildcard match for truncated names.
1245 			 *   however, we are not sure if we want to perform
1246 			 *   wildcard match, if gethostname(3) side has
1247 			 *   truncated hostname.
1248 			 */
1249 			n = ni6_nametodns(hostname, hostnamelen, 0);
1250 			if (!n || n->m_next || n->m_len == 0)
1251 				goto bad;
1252 			IP6_EXTHDR_GET(subj, char *, m,
1253 			    off + sizeof(struct icmp6_nodeinfo), subjlen);
1254 			if (subj == NULL)
1255 				goto bad;
1256 			if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1257 					n->m_len)) {
1258 				goto bad;
1259 			}
1260 			m_freem(n);
1261 			n = NULL;
1262 			break;
1263 
1264 		case ICMP6_NI_SUBJ_IPV4:	/* xxx: to be implemented? */
1265 		default:
1266 			goto bad;
1267 		}
1268 		break;
1269 
1270 	default:
1271 		/* should never be here due to "switch (qtype)" above */
1272 		goto bad;
1273 	}
1274 
1275 	/* allocate a mbuf to reply. */
1276 	MGETHDR(n, M_DONTWAIT, m->m_type);
1277 	if (n == NULL) {
1278 		m_freem(m);
1279 		return(NULL);
1280 	}
1281 	M_COPY_PKTHDR(n, m); /* just for recvif */
1282 	if (replylen > MHLEN) {
1283 		if (replylen > MCLBYTES) {
1284 			 /*
1285 			  * XXX: should we try to allocate more? But MCLBYTES is
1286 			  * probably much larger than IPV6_MMTU...
1287 			  */
1288 			goto bad;
1289 		}
1290 		MCLGET(n, M_DONTWAIT);
1291 		if ((n->m_flags & M_EXT) == 0) {
1292 			goto bad;
1293 		}
1294 	}
1295 	n->m_pkthdr.len = n->m_len = replylen;
1296 
1297 	/* copy mbuf header and IPv6 + Node Information base headers */
1298 	bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1299 	nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1300 	bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1301 
1302 	/* qtype dependent procedure */
1303 	switch (qtype) {
1304 	case NI_QTYPE_NOOP:
1305 		nni6->ni_flags = 0;
1306 		break;
1307 	case NI_QTYPE_SUPTYPES:
1308 		goto bad;	/* xxx: to be implemented */
1309 		break;
1310 	case NI_QTYPE_FQDN:
1311 		fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1312 						sizeof(struct ip6_hdr) +
1313 						sizeof(struct icmp6_nodeinfo));
1314 		nni6->ni_flags = 0; /* XXX: meaningless TTL */
1315 		fqdn->ni_fqdn_ttl = 0;	/* ditto. */
1316 		/*
1317 		 * XXX do we really have FQDN in variable "hostname"?
1318 		 */
1319 		n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
1320 		if (n->m_next == NULL)
1321 			goto bad;
1322 		/* XXX we assume that n->m_next is not a chain */
1323 		if (n->m_next->m_next != NULL)
1324 			goto bad;
1325 		n->m_pkthdr.len += n->m_next->m_len;
1326 		break;
1327 	case NI_QTYPE_NODEADDR:
1328 	{
1329 		int lenlim, copied;
1330 
1331 		if (n->m_flags & M_EXT)
1332 			lenlim = MCLBYTES - sizeof(struct ip6_hdr) -
1333 				sizeof(struct icmp6_nodeinfo);
1334 		else
1335 			lenlim = MHLEN - sizeof(struct ip6_hdr) -
1336 				sizeof(struct icmp6_nodeinfo);
1337 		copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1338 		/* XXX: reset mbuf length */
1339 		n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1340 			sizeof(struct icmp6_nodeinfo) + copied;
1341 		break;
1342 	}
1343 	default:
1344 		break;		/* XXX impossible! */
1345 	}
1346 
1347 	nni6->ni_type = ICMP6_NI_REPLY;
1348 	nni6->ni_code = ICMP6_NI_SUCESS;
1349 	m_freem(m);
1350 	return(n);
1351 
1352   bad:
1353 	m_freem(m);
1354 	if (n)
1355 		m_freem(n);
1356 	return(NULL);
1357 }
1358 #undef hostnamelen
1359 
1360 /*
1361  * make a mbuf with DNS-encoded string.  no compression support.
1362  *
1363  * XXX names with less than 2 dots (like "foo" or "foo.section") will be
1364  * treated as truncated name (two \0 at the end).  this is a wild guess.
1365  */
1366 static struct mbuf *
1367 ni6_nametodns(name, namelen, old)
1368 	const char *name;
1369 	int namelen;
1370 	int old;	/* return pascal string if non-zero */
1371 {
1372 	struct mbuf *m;
1373 	char *cp, *ep;
1374 	const char *p, *q;
1375 	int i, len, nterm;
1376 
1377 	if (old)
1378 		len = namelen + 1;
1379 	else
1380 		len = MCLBYTES;
1381 
1382 	/* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
1383 	MGET(m, M_DONTWAIT, MT_DATA);
1384 	if (m && len > MLEN) {
1385 		MCLGET(m, M_DONTWAIT);
1386 		if ((m->m_flags & M_EXT) == 0)
1387 			goto fail;
1388 	}
1389 	if (!m)
1390 		goto fail;
1391 	m->m_next = NULL;
1392 
1393 	if (old) {
1394 		m->m_len = len;
1395 		*mtod(m, char *) = namelen;
1396 		bcopy(name, mtod(m, char *) + 1, namelen);
1397 		return m;
1398 	} else {
1399 		m->m_len = 0;
1400 		cp = mtod(m, char *);
1401 		ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1402 
1403 		/* if not certain about my name, return empty buffer */
1404 		if (namelen == 0)
1405 			return m;
1406 
1407 		/*
1408 		 * guess if it looks like shortened hostname, or FQDN.
1409 		 * shortened hostname needs two trailing "\0".
1410 		 */
1411 		i = 0;
1412 		for (p = name; p < name + namelen; p++) {
1413 			if (*p && *p == '.')
1414 				i++;
1415 		}
1416 		if (i < 2)
1417 			nterm = 2;
1418 		else
1419 			nterm = 1;
1420 
1421 		p = name;
1422 		while (cp < ep && p < name + namelen) {
1423 			i = 0;
1424 			for (q = p; q < name + namelen && *q && *q != '.'; q++)
1425 				i++;
1426 			/* result does not fit into mbuf */
1427 			if (cp + i + 1 >= ep)
1428 				goto fail;
1429 			/* DNS label length restriction, RFC1035 page 8 */
1430 			if (i >= 64)
1431 				goto fail;
1432 			*cp++ = i;
1433 			bcopy(p, cp, i);
1434 			cp += i;
1435 			p = q;
1436 			if (p < name + namelen && *p == '.')
1437 				p++;
1438 		}
1439 		/* termination */
1440 		if (cp + nterm >= ep)
1441 			goto fail;
1442 		while (nterm-- > 0)
1443 			*cp++ = '\0';
1444 		m->m_len = cp - mtod(m, char *);
1445 		return m;
1446 	}
1447 
1448 	panic("should not reach here");
1449 	/*NOTREACHED*/
1450 
1451  fail:
1452 	if (m)
1453 		m_freem(m);
1454 	return NULL;
1455 }
1456 
1457 /*
1458  * check if two DNS-encoded string matches.  takes care of truncated
1459  * form (with \0\0 at the end).  no compression support.
1460  */
1461 static int
1462 ni6_dnsmatch(a, alen, b, blen)
1463 	const char *a;
1464 	int alen;
1465 	const char *b;
1466 	int blen;
1467 {
1468 	const char *a0, *b0;
1469 	int l;
1470 
1471 	/* simplest case - need validation? */
1472 	if (alen == blen && bcmp(a, b, alen) == 0)
1473 		return 1;
1474 
1475 	a0 = a;
1476 	b0 = b;
1477 
1478 	/* termination is mandatory */
1479 	if (alen < 2 || blen < 2)
1480 		return 0;
1481 	if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
1482 		return 0;
1483 	alen--;
1484 	blen--;
1485 
1486 	while (a - a0 < alen && b - b0 < blen) {
1487 		if (a - a0 + 1 > alen || b - b0 + 1 > blen)
1488 			return 0;
1489 
1490 		if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
1491 			return 0;
1492 		/* we don't support compression yet */
1493 		if (a[0] >= 64 || b[0] >= 64)
1494 			return 0;
1495 
1496 		/* truncated case */
1497 		if (a[0] == 0 && a - a0 == alen - 1)
1498 			return 1;
1499 		if (b[0] == 0 && b - b0 == blen - 1)
1500 			return 1;
1501 		if (a[0] == 0 || b[0] == 0)
1502 			return 0;
1503 
1504 		if (a[0] != b[0])
1505 			return 0;
1506 		l = a[0];
1507 		if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
1508 			return 0;
1509 		if (bcmp(a + 1, b + 1, l) != 0)
1510 			return 0;
1511 
1512 		a += 1 + l;
1513 		b += 1 + l;
1514 	}
1515 
1516 	if (a - a0 == alen && b - b0 == blen)
1517 		return 1;
1518 	else
1519 		return 0;
1520 }
1521 
1522 /*
1523  * calculate the number of addresses to be returned in the node info reply.
1524  */
1525 static int
1526 ni6_addrs(ni6, m, ifpp)
1527 	struct icmp6_nodeinfo *ni6;
1528 	struct mbuf *m;
1529 	struct ifnet **ifpp;
1530 {
1531 	register struct ifnet *ifp;
1532 	register struct in6_ifaddr *ifa6;
1533 	register struct ifaddr *ifa;
1534 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1535 	int addrs = 0, addrsofif, iffound = 0;
1536 
1537 	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1538 	{
1539 		addrsofif = 0;
1540 		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1541 		     ifa = ifa->ifa_list.tqe_next)
1542 		{
1543 			if (ifa->ifa_addr->sa_family != AF_INET6)
1544 				continue;
1545 			ifa6 = (struct in6_ifaddr *)ifa;
1546 
1547 			if (!(ni6->ni_flags & NI_NODEADDR_FLAG_ALL) &&
1548 			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1549 					       &ifa6->ia_addr.sin6_addr))
1550 				iffound = 1;
1551 
1552 			/*
1553 			 * IPv4-mapped addresses can only be returned by a
1554 			 * Node Information proxy, since they represent
1555 			 * addresses of IPv4-only nodes, which perforce do
1556 			 * not implement this protocol.
1557 			 * [icmp-name-lookups-05]
1558 			 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1559 			 * this function at this moment.
1560 			 */
1561 
1562 			if (ifa6->ia6_flags & IN6_IFF_ANYCAST)
1563 				continue; /* we need only unicast addresses */
1564 
1565 			if ((ni6->ni_flags & (NI_NODEADDR_FLAG_LINKLOCAL |
1566 					      NI_NODEADDR_FLAG_SITELOCAL |
1567 					      NI_NODEADDR_FLAG_GLOBAL)) == 0)
1568 				continue;
1569 
1570 			/* What do we have to do about ::1? */
1571 			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1572 			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1573 				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1574 					addrsofif++;
1575 				break;
1576 			 case IPV6_ADDR_SCOPE_SITELOCAL:
1577 				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1578 					addrsofif++;
1579 				break;
1580 			 case IPV6_ADDR_SCOPE_GLOBAL:
1581 				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1582 					 addrsofif++;
1583 				 break;
1584 			 default:
1585 				 continue;
1586 			}
1587 		}
1588 		if (iffound) {
1589 			*ifpp = ifp;
1590 			return(addrsofif);
1591 		}
1592 
1593 		addrs += addrsofif;
1594 	}
1595 
1596 	return(addrs);
1597 }
1598 
1599 static int
1600 ni6_store_addrs(ni6, nni6, ifp0, resid)
1601 	struct icmp6_nodeinfo *ni6, *nni6;
1602 	struct ifnet *ifp0;
1603 	int resid;
1604 {
1605 	register struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
1606 	register struct in6_ifaddr *ifa6;
1607 	register struct ifaddr *ifa;
1608 	int docopy, copied = 0;
1609 	u_char *cp = (u_char *)(nni6 + 1);
1610 
1611 	if (ifp0 == NULL && !(ni6->ni_flags & NI_NODEADDR_FLAG_ALL))
1612 		return(0);	/* needless to copy */
1613 
1614 	for (; ifp; ifp = TAILQ_NEXT(ifp, if_list))
1615 	{
1616 		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1617 		     ifa = ifa->ifa_list.tqe_next)
1618 		{
1619 			docopy = 0;
1620 
1621 			if (ifa->ifa_addr->sa_family != AF_INET6)
1622 				continue;
1623 			ifa6 = (struct in6_ifaddr *)ifa;
1624 
1625 			if (ifa6->ia6_flags & IN6_IFF_ANYCAST) {
1626 				/* just experimental. not in the spec. */
1627 				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1628 					docopy = 1;
1629 				else
1630 					continue;
1631 			}
1632 			else {	/* unicast address */
1633 				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1634 					continue;
1635 				else
1636 					docopy = 1;
1637 			}
1638 
1639 			/* What do we have to do about ::1? */
1640 			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1641 			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1642 				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1643 					docopy = 1;
1644 				break;
1645 			 case IPV6_ADDR_SCOPE_SITELOCAL:
1646 				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1647 					docopy = 1;
1648 				break;
1649 			 case IPV6_ADDR_SCOPE_GLOBAL:
1650 				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1651 					 docopy = 1;
1652 				 break;
1653 			 default:
1654 				 continue;
1655 			}
1656 
1657 			if (docopy) {
1658 				if (resid < sizeof(struct in6_addr)) {
1659 					/*
1660 					 * We give up much more copy.
1661 					 * Set the truncate flag and return.
1662 					 */
1663 					nni6->ni_flags |=
1664 						NI_NODEADDR_FLAG_TRUNCATE;
1665 					return(copied);
1666 				}
1667 				bcopy(&ifa6->ia_addr.sin6_addr, cp,
1668 				      sizeof(struct in6_addr));
1669 				/* XXX: KAME link-local hack; remove ifindex */
1670 				if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))
1671 					((struct in6_addr *)cp)->s6_addr16[1] = 0;
1672 				cp += sizeof(struct in6_addr);
1673 				resid -= sizeof(struct in6_addr);
1674 				copied += sizeof(struct in6_addr);
1675 			}
1676 		}
1677 		if (ifp0)	/* we need search only on the specified IF */
1678 			break;
1679 	}
1680 
1681 	return(copied);
1682 }
1683 
1684 /*
1685  * XXX almost dup'ed code with rip6_input.
1686  */
1687 static int
1688 icmp6_rip6_input(mp, off)
1689 	struct	mbuf **mp;
1690 	int	off;
1691 {
1692 	struct mbuf *m = *mp;
1693 	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1694 	register struct in6pcb *in6p;
1695 	struct in6pcb *last = NULL;
1696 	struct sockaddr_in6 rip6src;
1697 	struct icmp6_hdr *icmp6;
1698 	struct mbuf *opts = NULL;
1699 
1700 #ifndef PULLDOWN_TEST
1701 	/* this is assumed to be safe. */
1702 	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
1703 #else
1704 	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
1705 	if (icmp6 == NULL) {
1706 		/* m is already reclaimed */
1707 		return IPPROTO_DONE;
1708 	}
1709 #endif
1710 
1711 	bzero(&rip6src, sizeof(rip6src));
1712 	rip6src.sin6_len = sizeof(struct sockaddr_in6);
1713 	rip6src.sin6_family = AF_INET6;
1714 	/* KAME hack: recover scopeid */
1715 	(void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);
1716 
1717 	LIST_FOREACH(in6p, &ripcb, inp_list)
1718 	{
1719 		if ((in6p->inp_vflag & INP_IPV6) == NULL)
1720 			continue;
1721 		if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
1722 			continue;
1723 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1724 		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1725 			continue;
1726 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1727 		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
1728 			continue;
1729 		if (in6p->in6p_icmp6filt
1730 		    && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1731 				 in6p->in6p_icmp6filt))
1732 			continue;
1733 		if (last) {
1734 			struct	mbuf *n;
1735 			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1736 				if (last->in6p_flags & IN6P_CONTROLOPTS)
1737 					ip6_savecontrol(last, &opts, ip6, n);
1738 				/* strip intermediate headers */
1739 				m_adj(n, off);
1740 				if (sbappendaddr(&last->in6p_socket->so_rcv,
1741 						 (struct sockaddr *)&rip6src,
1742 						 n, opts) == 0) {
1743 					/* should notify about lost packet */
1744 					m_freem(n);
1745 					if (opts)
1746 						m_freem(opts);
1747 				} else
1748 					sorwakeup(last->in6p_socket);
1749 				opts = NULL;
1750 			}
1751 		}
1752 		last = in6p;
1753 	}
1754 	if (last) {
1755 		if (last->in6p_flags & IN6P_CONTROLOPTS)
1756 			ip6_savecontrol(last, &opts, ip6, m);
1757 		/* strip intermediate headers */
1758 		m_adj(m, off);
1759 		if (sbappendaddr(&last->in6p_socket->so_rcv,
1760 				(struct sockaddr *)&rip6src, m, opts) == 0) {
1761 			m_freem(m);
1762 			if (opts)
1763 				m_freem(opts);
1764 		} else
1765 			sorwakeup(last->in6p_socket);
1766 	} else {
1767 		m_freem(m);
1768 		ip6stat.ip6s_delivered--;
1769 	}
1770 	return IPPROTO_DONE;
1771 }
1772 
1773 /*
1774  * Reflect the ip6 packet back to the source.
1775  * OFF points to the icmp6 header, counted from the top of the mbuf.
1776  */
1777 void
1778 icmp6_reflect(m, off)
1779 	struct	mbuf *m;
1780 	size_t off;
1781 {
1782 	struct ip6_hdr *ip6;
1783 	struct icmp6_hdr *icmp6;
1784 	struct in6_ifaddr *ia;
1785 	struct in6_addr t, *src = 0;
1786 	int plen;
1787 	int type, code;
1788 	struct ifnet *outif = NULL;
1789 #ifdef COMPAT_RFC1885
1790 	int mtu = IPV6_MMTU;
1791 	struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst;
1792 #endif
1793 
1794 	/* too short to reflect */
1795 	if (off < sizeof(struct ip6_hdr)) {
1796 		printf("sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
1797 		       (u_long)off, (u_long)sizeof(struct ip6_hdr),
1798 		       __FILE__, __LINE__);
1799 		goto bad;
1800 	}
1801 
1802 	/*
1803 	 * If there are extra headers between IPv6 and ICMPv6, strip
1804 	 * off that header first.
1805 	 */
1806 #ifdef DIAGNOSTIC
1807 	if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
1808 		panic("assumption failed in icmp6_reflect");
1809 #endif
1810 	if (off > sizeof(struct ip6_hdr)) {
1811 		size_t l;
1812 		struct ip6_hdr nip6;
1813 
1814 		l = off - sizeof(struct ip6_hdr);
1815 		m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
1816 		m_adj(m, l);
1817 		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1818 		if (m->m_len < l) {
1819 			if ((m = m_pullup(m, l)) == NULL)
1820 				return;
1821 		}
1822 		bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
1823 	} else /* off == sizeof(struct ip6_hdr) */ {
1824 		size_t l;
1825 		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1826 		if (m->m_len < l) {
1827 			if ((m = m_pullup(m, l)) == NULL)
1828 				return;
1829 		}
1830 	}
1831 	plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
1832 	ip6 = mtod(m, struct ip6_hdr *);
1833 	ip6->ip6_nxt = IPPROTO_ICMPV6;
1834 	icmp6 = (struct icmp6_hdr *)(ip6 + 1);
1835 	type = icmp6->icmp6_type; /* keep type for statistics */
1836 	code = icmp6->icmp6_code; /* ditto. */
1837 
1838 	t = ip6->ip6_dst;
1839 	/*
1840 	 * ip6_input() drops a packet if its src is multicast.
1841 	 * So, the src is never multicast.
1842 	 */
1843 	ip6->ip6_dst = ip6->ip6_src;
1844 
1845 	/* XXX hack for link-local addresses */
1846 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
1847 		ip6->ip6_dst.s6_addr16[1] =
1848 			htons(m->m_pkthdr.rcvif->if_index);
1849 	if (IN6_IS_ADDR_LINKLOCAL(&t))
1850 		t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
1851 
1852 #ifdef COMPAT_RFC1885
1853 	/*
1854 	 * xxx guess MTU
1855 	 * RFC 1885 requires that echo reply should be truncated if it
1856 	 * does not fit in with (return) path MTU, but the description was
1857 	 * removed in the new spec.
1858 	 */
1859 	if (icmp6_reflect_rt.ro_rt == 0 ||
1860 	    ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) {
1861 		if (icmp6_reflect_rt.ro_rt) {
1862 			RTFREE(icmp6_reflect_rt.ro_rt);
1863 			icmp6_reflect_rt.ro_rt = 0;
1864 		}
1865 		bzero(sin6, sizeof(*sin6));
1866 		sin6->sin6_family = PF_INET6;
1867 		sin6->sin6_len = sizeof(struct sockaddr_in6);
1868 		sin6->sin6_addr = ip6->ip6_dst;
1869 
1870 		rtalloc_ign((struct route *)&icmp6_reflect_rt.ro_rt,
1871 			    RTF_PRCLONING);
1872 	}
1873 
1874 	if (icmp6_reflect_rt.ro_rt == 0)
1875 		goto bad;
1876 
1877 	if ((icmp6_reflect_rt.ro_rt->rt_flags & RTF_HOST)
1878 	    && mtu < icmp6_reflect_rt.ro_rt->rt_ifp->if_mtu)
1879 		mtu = icmp6_reflect_rt.ro_rt->rt_rmx.rmx_mtu;
1880 
1881 	if (mtu < m->m_pkthdr.len) {
1882 		plen -= (m->m_pkthdr.len - mtu);
1883 		m_adj(m, mtu - m->m_pkthdr.len);
1884 	}
1885 #endif
1886 	/*
1887 	 * If the incoming packet was addressed directly to us(i.e. unicast),
1888 	 * use dst as the src for the reply.
1889 	 * The IN6_IFF_NOTREADY case would be VERY rare, but is possible
1890 	 * (for example) when we encounter an error while forwarding procedure
1891 	 * destined to a duplicated address of ours.
1892 	 */
1893 	for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1894 		if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
1895 		    (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) {
1896 			src = &t;
1897 			break;
1898 		}
1899 	if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) {
1900 		/*
1901 		 * This is the case if the dst is our link-local address
1902 		 * and the sender is also ourseleves.
1903 		 */
1904 		src = &t;
1905 	}
1906 
1907 	if (src == 0)
1908 		/*
1909 		 * This case matches to multicasts, our anycast, or unicasts
1910 		 * that we do not own. Select a source address which has the
1911 		 * same scope.
1912 		 * XXX: for (non link-local) multicast addresses, this might
1913 		 * not be a good choice.
1914 		 */
1915 		if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0)
1916 			src = &IA6_SIN6(ia)->sin6_addr;
1917 
1918 	if (src == 0)
1919 		goto bad;
1920 
1921 	ip6->ip6_src = *src;
1922 
1923 	ip6->ip6_flow = 0;
1924 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1925 	ip6->ip6_vfc |= IPV6_VERSION;
1926 	ip6->ip6_nxt = IPPROTO_ICMPV6;
1927 	if (m->m_pkthdr.rcvif) {
1928 		/* XXX: This may not be the outgoing interface */
1929 		ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim;
1930 	}
1931 
1932 	icmp6->icmp6_cksum = 0;
1933 	icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
1934 					sizeof(struct ip6_hdr), plen);
1935 
1936 	/*
1937 	 * xxx option handling
1938 	 */
1939 
1940 	m->m_flags &= ~(M_BCAST|M_MCAST);
1941 #ifdef IPSEC
1942 	/* Don't lookup socket */
1943 	ipsec_setsocket(m, NULL);
1944 #endif /*IPSEC*/
1945 
1946 #ifdef COMPAT_RFC1885
1947 	ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL, &outif);
1948 #else
1949 	ip6_output(m, NULL, NULL, 0, NULL, &outif);
1950 #endif
1951 	if (outif)
1952 		icmp6_ifoutstat_inc(outif, type, code);
1953 
1954 	return;
1955 
1956  bad:
1957 	m_freem(m);
1958 	return;
1959 }
1960 
1961 void
1962 icmp6_fasttimo()
1963 {
1964 
1965 	mld6_fasttimeo();
1966 
1967 	/* reset ICMPv6 pps limit */
1968 	icmp6errpps_count = 0;
1969 }
1970 
1971 static const char *
1972 icmp6_redirect_diag(src6, dst6, tgt6)
1973 	struct in6_addr *src6;
1974 	struct in6_addr *dst6;
1975 	struct in6_addr *tgt6;
1976 {
1977 	static char buf[1024];
1978 	snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
1979 		ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
1980 	return buf;
1981 }
1982 
1983 void
1984 icmp6_redirect_input(m, off)
1985 	register struct mbuf *m;
1986 	int off;
1987 {
1988 	struct ifnet *ifp = m->m_pkthdr.rcvif;
1989 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1990 	struct nd_redirect *nd_rd;
1991 	int icmp6len = ntohs(ip6->ip6_plen);
1992 	char *lladdr = NULL;
1993 	int lladdrlen = 0;
1994 	u_char *redirhdr = NULL;
1995 	int redirhdrlen = 0;
1996 	struct rtentry *rt = NULL;
1997 	int is_router;
1998 	int is_onlink;
1999 	struct in6_addr src6 = ip6->ip6_src;
2000 	struct in6_addr redtgt6;
2001 	struct in6_addr reddst6;
2002 	union nd_opts ndopts;
2003 
2004 	if (!m || !ifp)
2005 		return;
2006 
2007 	/* XXX if we are router, we don't update route by icmp6 redirect */
2008 	if (ip6_forwarding)
2009 		goto freeit;
2010 	if (!icmp6_rediraccept)
2011 		goto freeit;
2012 
2013 #ifndef PULLDOWN_TEST
2014 	IP6_EXTHDR_CHECK(m, off, icmp6len,);
2015 	nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2016 #else
2017 	IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2018 	if (nd_rd == NULL) {
2019 		icmp6stat.icp6s_tooshort++;
2020 		return;
2021 	}
2022 #endif
2023 	redtgt6 = nd_rd->nd_rd_target;
2024 	reddst6 = nd_rd->nd_rd_dst;
2025 
2026 	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2027 		redtgt6.s6_addr16[1] = htons(ifp->if_index);
2028 	if (IN6_IS_ADDR_LINKLOCAL(&reddst6))
2029 		reddst6.s6_addr16[1] = htons(ifp->if_index);
2030 
2031 	/* validation */
2032 	if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2033 		log(LOG_ERR,
2034 			"ICMP6 redirect sent from %s rejected; "
2035 			"must be from linklocal\n", ip6_sprintf(&src6));
2036 		goto freeit;
2037 	}
2038 	if (ip6->ip6_hlim != 255) {
2039 		log(LOG_ERR,
2040 			"ICMP6 redirect sent from %s rejected; "
2041 			"hlim=%d (must be 255)\n",
2042 			ip6_sprintf(&src6), ip6->ip6_hlim);
2043 		goto freeit;
2044 	}
2045     {
2046 	/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2047 	struct sockaddr_in6 sin6;
2048 	struct in6_addr *gw6;
2049 
2050 	bzero(&sin6, sizeof(sin6));
2051 	sin6.sin6_family = AF_INET6;
2052 	sin6.sin6_len = sizeof(struct sockaddr_in6);
2053 	bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
2054 	rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
2055 	if (rt) {
2056 		gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
2057 		if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
2058 			log(LOG_ERR,
2059 				"ICMP6 redirect rejected; "
2060 				"not equal to gw-for-src=%s (must be same): "
2061 				"%s\n",
2062 				ip6_sprintf(gw6),
2063 				icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2064 			RTFREE(rt);
2065 			goto freeit;
2066 		}
2067 	} else {
2068 		log(LOG_ERR,
2069 			"ICMP6 redirect rejected; "
2070 			"no route found for redirect dst: %s\n",
2071 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2072 		goto freeit;
2073 	}
2074 	RTFREE(rt);
2075 	rt = NULL;
2076     }
2077 	if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2078 		log(LOG_ERR,
2079 			"ICMP6 redirect rejected; "
2080 			"redirect dst must be unicast: %s\n",
2081 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2082 		goto freeit;
2083 	}
2084 
2085 	is_router = is_onlink = 0;
2086 	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2087 		is_router = 1;	/* router case */
2088 	if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
2089 		is_onlink = 1;	/* on-link destination case */
2090 	if (!is_router && !is_onlink) {
2091 		log(LOG_ERR,
2092 			"ICMP6 redirect rejected; "
2093 			"neither router case nor onlink case: %s\n",
2094 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2095 		goto freeit;
2096 	}
2097 	/* validation passed */
2098 
2099 	icmp6len -= sizeof(*nd_rd);
2100 	nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2101 	if (nd6_options(&ndopts) < 0) {
2102 		log(LOG_INFO, "icmp6_redirect_input: "
2103 			"invalid ND option, rejected: %s\n",
2104 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2105 		goto freeit;
2106 	}
2107 
2108 	if (ndopts.nd_opts_tgt_lladdr) {
2109 		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2110 		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2111 	}
2112 
2113 	if (ndopts.nd_opts_rh) {
2114 		redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
2115 		redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
2116 	}
2117 
2118 	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2119 		log(LOG_INFO,
2120 			"icmp6_redirect_input: lladdrlen mismatch for %s "
2121 			"(if %d, icmp6 packet %d): %s\n",
2122 			ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
2123 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2124 	}
2125 
2126 	/* RFC 2461 8.3 */
2127 	nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2128 			 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2129 
2130 	if (!is_onlink) {	/* better router case. perform rtredirect. */
2131 		/* perform rtredirect */
2132 		struct sockaddr_in6 sdst;
2133 		struct sockaddr_in6 sgw;
2134 		struct sockaddr_in6 ssrc;
2135 
2136 		bzero(&sdst, sizeof(sdst));
2137 		bzero(&sgw, sizeof(sgw));
2138 		bzero(&ssrc, sizeof(ssrc));
2139 		sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
2140 		sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
2141 			sizeof(struct sockaddr_in6);
2142 		bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
2143 		bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2144 		bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2145 		rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
2146 			   (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
2147 			   (struct sockaddr *)&ssrc,
2148 			   (struct rtentry **)NULL);
2149 	}
2150 	/* finally update cached route in each socket via pfctlinput */
2151     {
2152 	struct sockaddr_in6 sdst;
2153 
2154 	bzero(&sdst, sizeof(sdst));
2155 	sdst.sin6_family = AF_INET6;
2156 	sdst.sin6_len = sizeof(struct sockaddr_in6);
2157 	bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2158 	pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
2159 #ifdef IPSEC
2160 	key_sa_routechange((struct sockaddr *)&sdst);
2161 #endif
2162     }
2163 
2164  freeit:
2165 	m_freem(m);
2166 }
2167 
2168 void
2169 icmp6_redirect_output(m0, rt)
2170 	struct mbuf *m0;
2171 	struct rtentry *rt;
2172 {
2173 	struct ifnet *ifp;	/* my outgoing interface */
2174 	struct in6_addr *ifp_ll6;
2175 	struct in6_addr *router_ll6;
2176 	struct ip6_hdr *sip6;	/* m0 as struct ip6_hdr */
2177 	struct mbuf *m = NULL;	/* newly allocated one */
2178 	struct ip6_hdr *ip6;	/* m as struct ip6_hdr */
2179 	struct nd_redirect *nd_rd;
2180 	size_t maxlen;
2181 	u_char *p;
2182 	struct ifnet *outif = NULL;
2183 	struct sockaddr_in6 src_sa;
2184 
2185 	icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2186 
2187 	/* if we are not router, we don't send icmp6 redirect */
2188 	if (!ip6_forwarding || ip6_accept_rtadv)
2189 		goto fail;
2190 
2191 	/* sanity check */
2192 	if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
2193 		goto fail;
2194 
2195 	/*
2196 	 * Address check:
2197 	 *  the source address must identify a neighbor, and
2198 	 *  the destination address must not be a multicast address
2199 	 *  [RFC 2461, sec 8.2]
2200 	 */
2201 	sip6 = mtod(m0, struct ip6_hdr *);
2202 	bzero(&src_sa, sizeof(src_sa));
2203 	src_sa.sin6_family = AF_INET6;
2204 	src_sa.sin6_len = sizeof(src_sa);
2205 	src_sa.sin6_addr = sip6->ip6_src;
2206 	/* we don't currently use sin6_scope_id, but eventually use it */
2207 	src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
2208 	if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
2209 		goto fail;
2210 	if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
2211 		goto fail;	/* what should we do here? */
2212 
2213 	/* rate limit */
2214 	if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
2215 		goto fail;
2216 
2217 	/*
2218 	 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2219 	 * we almost always ask for an mbuf cluster for simplicity.
2220 	 * (MHLEN < IPV6_MMTU is almost always true)
2221 	 */
2222 #if IPV6_MMTU >= MCLBYTES
2223 # error assumption failed about IPV6_MMTU and MCLBYTES
2224 #endif
2225 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
2226 	if (m && IPV6_MMTU >= MHLEN)
2227 		MCLGET(m, M_DONTWAIT);
2228 	if (!m)
2229 		goto fail;
2230 	maxlen = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
2231 	maxlen = min(IPV6_MMTU, maxlen);
2232 	/* just for safety */
2233 	if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2234 	    ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2235 		goto fail;
2236 	}
2237 
2238 	{
2239 		/* get ip6 linklocal address for ifp(my outgoing interface). */
2240 		struct in6_ifaddr *ia;
2241 		if ((ia = in6ifa_ifpforlinklocal(ifp,
2242 						 IN6_IFF_NOTREADY|
2243 						 IN6_IFF_ANYCAST)) == NULL)
2244 			goto fail;
2245 		ifp_ll6 = &ia->ia_addr.sin6_addr;
2246 	}
2247 
2248 	/* get ip6 linklocal address for the router. */
2249 	if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
2250 		struct sockaddr_in6 *sin6;
2251 		sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
2252 		router_ll6 = &sin6->sin6_addr;
2253 		if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
2254 			router_ll6 = (struct in6_addr *)NULL;
2255 	} else
2256 		router_ll6 = (struct in6_addr *)NULL;
2257 
2258 	/* ip6 */
2259 	ip6 = mtod(m, struct ip6_hdr *);
2260 	ip6->ip6_flow = 0;
2261 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2262 	ip6->ip6_vfc |= IPV6_VERSION;
2263 	/* ip6->ip6_plen will be set later */
2264 	ip6->ip6_nxt = IPPROTO_ICMPV6;
2265 	ip6->ip6_hlim = 255;
2266 	/* ip6->ip6_src must be linklocal addr for my outgoing if. */
2267 	bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2268 	bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2269 
2270 	/* ND Redirect */
2271 	nd_rd = (struct nd_redirect *)(ip6 + 1);
2272 	nd_rd->nd_rd_type = ND_REDIRECT;
2273 	nd_rd->nd_rd_code = 0;
2274 	nd_rd->nd_rd_reserved = 0;
2275 	if (rt->rt_flags & RTF_GATEWAY) {
2276 		/*
2277 		 * nd_rd->nd_rd_target must be a link-local address in
2278 		 * better router cases.
2279 		 */
2280 		if (!router_ll6)
2281 			goto fail;
2282 		bcopy(router_ll6, &nd_rd->nd_rd_target,
2283 		      sizeof(nd_rd->nd_rd_target));
2284 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2285 		      sizeof(nd_rd->nd_rd_dst));
2286 	} else {
2287 		/* make sure redtgt == reddst */
2288 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2289 		      sizeof(nd_rd->nd_rd_target));
2290 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2291 		      sizeof(nd_rd->nd_rd_dst));
2292 	}
2293 
2294 	p = (u_char *)(nd_rd + 1);
2295 
2296 	if (!router_ll6)
2297 		goto nolladdropt;
2298 
2299     {
2300 	/* target lladdr option */
2301 	struct rtentry *rt_router = NULL;
2302 	int len;
2303 	struct sockaddr_dl *sdl;
2304 	struct nd_opt_hdr *nd_opt;
2305 	char *lladdr;
2306 
2307 	rt_router = nd6_lookup(router_ll6, 0, ifp);
2308 	if (!rt_router)
2309 		goto nolladdropt;
2310 	len = sizeof(*nd_opt) + ifp->if_addrlen;
2311 	len = (len + 7) & ~7;	/*round by 8*/
2312 	/* safety check */
2313 	if (len + (p - (u_char *)ip6) > maxlen)
2314 		goto nolladdropt;
2315 	if (!(rt_router->rt_flags & RTF_GATEWAY) &&
2316 	    (rt_router->rt_flags & RTF_LLINFO) &&
2317 	    (rt_router->rt_gateway->sa_family == AF_LINK) &&
2318 	    (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) &&
2319 	    sdl->sdl_alen) {
2320 		nd_opt = (struct nd_opt_hdr *)p;
2321 		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2322 		nd_opt->nd_opt_len = len >> 3;
2323 		lladdr = (char *)(nd_opt + 1);
2324 		bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
2325 		p += len;
2326 	}
2327     }
2328 nolladdropt:;
2329 
2330 	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2331 
2332 	/* just to be safe */
2333 #ifdef M_DECRYPTED	/*not openbsd*/
2334 	if (m0->m_flags & M_DECRYPTED)
2335 		goto noredhdropt;
2336 #endif
2337 	if (p - (u_char *)ip6 > maxlen)
2338 		goto noredhdropt;
2339 
2340     {
2341 	/* redirected header option */
2342 	int len;
2343 	struct nd_opt_rd_hdr *nd_opt_rh;
2344 
2345 	/*
2346 	 * compute the maximum size for icmp6 redirect header option.
2347 	 * XXX room for auth header?
2348 	 */
2349 	len = maxlen - (p - (u_char *)ip6);
2350 	len &= ~7;
2351 
2352 	/* This is just for simplicity. */
2353 	if (m0->m_pkthdr.len != m0->m_len) {
2354 		if (m0->m_next) {
2355 			m_freem(m0->m_next);
2356 			m0->m_next = NULL;
2357 		}
2358 		m0->m_pkthdr.len = m0->m_len;
2359 	}
2360 
2361 	/*
2362 	 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2363 	 * about padding/truncate rule for the original IP packet.
2364 	 * From the discussion on IPv6imp in Feb 1999, the consensus was:
2365 	 * - "attach as much as possible" is the goal
2366 	 * - pad if not aligned (original size can be guessed by original
2367 	 *   ip6 header)
2368 	 * Following code adds the padding if it is simple enough,
2369 	 * and truncates if not.
2370 	 */
2371 	if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
2372 		panic("assumption failed in %s:%d\n", __FILE__, __LINE__);
2373 
2374 	if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2375 		/* not enough room, truncate */
2376 		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2377 	} else {
2378 		/* enough room, pad or truncate */
2379 		size_t extra;
2380 
2381 		extra = m0->m_pkthdr.len % 8;
2382 		if (extra) {
2383 			/* pad if easy enough, truncate if not */
2384 			if (8 - extra <= M_TRAILINGSPACE(m0)) {
2385 				/* pad */
2386 				m0->m_len += (8 - extra);
2387 				m0->m_pkthdr.len += (8 - extra);
2388 			} else {
2389 				/* truncate */
2390 				m0->m_pkthdr.len -= extra;
2391 				m0->m_len -= extra;
2392 			}
2393 		}
2394 		len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2395 		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2396 	}
2397 
2398 	nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2399 	bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2400 	nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2401 	nd_opt_rh->nd_opt_rh_len = len >> 3;
2402 	p += sizeof(*nd_opt_rh);
2403 	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2404 
2405 	/* connect m0 to m */
2406 	m->m_next = m0;
2407 	m->m_pkthdr.len = m->m_len + m0->m_len;
2408     }
2409 noredhdropt:;
2410 
2411 	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src))
2412 		sip6->ip6_src.s6_addr16[1] = 0;
2413 	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst))
2414 		sip6->ip6_dst.s6_addr16[1] = 0;
2415 #if 0
2416 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
2417 		ip6->ip6_src.s6_addr16[1] = 0;
2418 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
2419 		ip6->ip6_dst.s6_addr16[1] = 0;
2420 #endif
2421 	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target))
2422 		nd_rd->nd_rd_target.s6_addr16[1] = 0;
2423 	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst))
2424 		nd_rd->nd_rd_dst.s6_addr16[1] = 0;
2425 
2426 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2427 
2428 	nd_rd->nd_rd_cksum = 0;
2429 	nd_rd->nd_rd_cksum
2430 		= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2431 
2432 	/* send the packet to outside... */
2433 #ifdef IPSEC
2434 	/* Don't lookup socket */
2435 	ipsec_setsocket(m, NULL);
2436 #endif /*IPSEC*/
2437 	ip6_output(m, NULL, NULL, 0, NULL, &outif);
2438 	if (outif) {
2439 		icmp6_ifstat_inc(outif, ifs6_out_msg);
2440 		icmp6_ifstat_inc(outif, ifs6_out_redirect);
2441 	}
2442 	icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2443 
2444 	return;
2445 
2446 fail:
2447 	if (m)
2448 		m_freem(m);
2449 	if (m0)
2450 		m_freem(m0);
2451 }
2452 
2453 /*
2454  * ICMPv6 socket option processing.
2455  *
2456  * NOTE: for OSes that use NRL inpcb (bsdi4/openbsd), do not forget to modify
2457  * sys/netinet6/raw_ipv6.c:rip6_ctloutput().
2458  */
2459 int
2460 icmp6_ctloutput(so, sopt)
2461 	struct socket *so;
2462 	struct sockopt *sopt;
2463 {
2464 	int error = 0;
2465 	int optlen;
2466 	register struct inpcb *inp = sotoinpcb(so);
2467 	int level, op, optname;
2468 
2469 	if (sopt) {
2470 		level = sopt->sopt_level;
2471 		op = sopt->sopt_dir;
2472 		optname = sopt->sopt_name;
2473 		optlen = sopt->sopt_valsize;
2474 	} else
2475 		level = op = optname = optlen = 0;
2476 	if (level != IPPROTO_ICMPV6) {
2477 		return EINVAL;
2478 	}
2479 
2480 	switch(op) {
2481 	case PRCO_SETOPT:
2482 		switch (optname) {
2483 		case ICMP6_FILTER:
2484 		    {
2485 			struct icmp6_filter *p;
2486 
2487 			if (optlen != sizeof(*p)) {
2488 				error = EMSGSIZE;
2489 				break;
2490 			}
2491 			if (inp->in6p_icmp6filt == NULL) {
2492 				error = EINVAL;
2493 				break;
2494 			}
2495 			error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen,
2496 				optlen);
2497 			break;
2498 		    }
2499 
2500 		default:
2501 			error = ENOPROTOOPT;
2502 			break;
2503 		}
2504 		break;
2505 
2506 	case PRCO_GETOPT:
2507 		switch (optname) {
2508 		case ICMP6_FILTER:
2509 		    {
2510 			if (inp->in6p_icmp6filt == NULL) {
2511 				error = EINVAL;
2512 				break;
2513 			}
2514 			error = sooptcopyout(sopt, inp->in6p_icmp6filt,
2515 				sizeof(struct icmp6_filter));
2516 			break;
2517 		    }
2518 
2519 		default:
2520 			error = ENOPROTOOPT;
2521 			break;
2522 		}
2523 		break;
2524 	}
2525 
2526 	return(error);
2527 }
2528 
2529 #ifndef HAVE_RATECHECK
2530 /*
2531  * ratecheck() returns true if it is okay to send.  We return
2532  * true if it is not okay to send.
2533  */
2534 static int
2535 ratecheck(last, limit)
2536 	struct timeval *last;
2537 	struct timeval *limit;
2538 {
2539 	struct timeval tp;
2540 	struct timeval nextsend;
2541 
2542 	microtime(&tp);
2543 	tp.tv_sec = time_second;
2544 
2545 	/* rate limit */
2546 	if (last->tv_sec != 0 || last->tv_usec != 0) {
2547 		nextsend.tv_sec = last->tv_sec + limit->tv_sec;
2548 		nextsend.tv_usec = last->tv_usec + limit->tv_usec;
2549 		nextsend.tv_sec += (nextsend.tv_usec / 1000000);
2550 		nextsend.tv_usec %= 1000000;
2551 
2552 		if (nextsend.tv_sec == tp.tv_sec && nextsend.tv_usec <= tp.tv_usec)
2553 			;
2554 		else if (nextsend.tv_sec <= tp.tv_sec)
2555 			;
2556 		else {
2557 			/* The packet is subject to rate limit */
2558 			return 0;
2559 		}
2560 	}
2561 
2562 	*last = tp;
2563 	return 1;
2564 }
2565 #endif
2566 
2567 /*
2568  * Perform rate limit check.
2569  * Returns 0 if it is okay to send the icmp6 packet.
2570  * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2571  * limitation.
2572  *
2573  * There are two limitations defined:
2574  * - pps limit: ICMPv6 error packet cannot exceed defined packet-per-second.
2575  *   we measure it every 0.2 second, since fasttimo works every 0.2 second.
2576  * - rate limit: ICMPv6 error packet cannot appear more than once per
2577  *   defined interval.
2578  * In any case, if we perform rate limitation, we'll see jitter in the ICMPv6
2579  * error packets.
2580  *
2581  * XXX per-destination/type check necessary?
2582  */
2583 static int
2584 icmp6_ratelimit(dst, type, code)
2585 	const struct in6_addr *dst;	/* not used at this moment */
2586 	const int type;			/* not used at this moment */
2587 	const int code;			/* not used at this moment */
2588 {
2589 	int ret;
2590 
2591 	ret = 0;	/*okay to send*/
2592 
2593 	/* PPS limit */
2594 	icmp6errpps_count++;
2595 	if (icmp6errppslim && icmp6errpps_count > icmp6errppslim / 5) {
2596 		/* The packet is subject to pps limit */
2597 		ret++;
2598 	}
2599 
2600 	if (!ratecheck(&icmp6errratelim_last, &icmp6errratelim)) {
2601 		/* The packet is subject to rate limit */
2602 		ret++;
2603 	}
2604 
2605 	return ret;
2606 }
2607