xref: /freebsd/sys/netinet6/icmp6.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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 
1065 static struct mbuf *
1066 ni6_input(m, off)
1067 	struct mbuf *m;
1068 	int off;
1069 {
1070 	struct icmp6_nodeinfo *ni6, *nni6;
1071 	struct mbuf *n = NULL;
1072 	u_int16_t qtype;
1073 	int subjlen;
1074 	int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1075 	struct ni_reply_fqdn *fqdn;
1076 	int addrs;		/* for NI_QTYPE_NODEADDR */
1077 	struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1078 	struct sockaddr_in6 sin6;
1079 	struct ip6_hdr *ip6;
1080 	int oldfqdn = 0;	/* if 1, return pascal string (03 draft) */
1081 	char *subj;
1082 
1083 	ip6 = mtod(m, struct ip6_hdr *);
1084 #ifndef PULLDOWN_TEST
1085 	ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1086 #else
1087 	IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
1088 	if (ni6 == NULL) {
1089 		/* m is already reclaimed */
1090 		return NULL;
1091 	}
1092 #endif
1093 
1094 	/*
1095 	 * Validate IPv6 destination address.
1096 	 *
1097 	 * We accept packets with the following IPv6 destination address:
1098 	 * - Responder's unicast/anycast address,
1099 	 * - link-local multicast address
1100 	 * This is a violation to last paragraph in icmp-name-lookups-05
1101 	 * page 4, which restricts IPv6 destination address of a query to:
1102 	 * - Responder's unicast/anycast address,
1103 	 * - NI group address for a name belongs to the Responder, or
1104 	 * - NI group address for a name for which the Responder is providing
1105 	 *   proxy service.
1106 	 * (note: NI group address is a link-local multicast address)
1107 	 *
1108 	 * We allow any link-local multicast address, since "ping6 -w ff02::1"
1109 	 * has been really useful for us debugging our network.  Also this is
1110 	 * still questionable if the restriction in spec buy us security at all,
1111 	 * since RFC2463 permits echo packet to multicast destination.
1112 	 * Even if we forbid NI query to ff02::1, we can effectively get the
1113 	 * same result as "ping6 -w ff02::1" by the following steps:
1114 	 * - run "ping6 ff02::1", then
1115 	 * - run "ping6 -w" for all addresses replied.
1116 	 */
1117 	bzero(&sin6, sizeof(sin6));
1118 	sin6.sin6_family = AF_INET6;
1119 	sin6.sin6_len = sizeof(struct sockaddr_in6);
1120 	bcopy(&ip6->ip6_dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
1121 	/* XXX scopeid */
1122 	if (ifa_ifwithaddr((struct sockaddr *)&sin6))
1123 		; /*unicast/anycast, fine*/
1124 	else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr))
1125 		; /*violates spec slightly, see above*/
1126 	else
1127 		goto bad;
1128 
1129 	/* guess reply length */
1130 	qtype = ntohs(ni6->ni_qtype);
1131 	switch (qtype) {
1132 	case NI_QTYPE_NOOP:
1133 		break;		/* no reply data */
1134 	case NI_QTYPE_SUPTYPES:
1135 		goto bad;	/* xxx: to be implemented */
1136 		break;
1137 	case NI_QTYPE_FQDN:
1138 		/* XXX will append a mbuf */
1139 		replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1140 		break;
1141 	case NI_QTYPE_NODEADDR:
1142 		addrs = ni6_addrs(ni6, m, &ifp);
1143 		if ((replylen += addrs * sizeof(struct in6_addr)) > MCLBYTES)
1144 			replylen = MCLBYTES; /* XXX: we'll truncate later */
1145 		break;
1146 	default:
1147 		/*
1148 		 * XXX: We must return a reply with the ICMP6 code
1149 		 * `unknown Qtype' in this case. However we regard the case
1150 		 * as an FQDN query for backward compatibility.
1151 		 * Older versions set a random value to this field,
1152 		 * so it rarely varies in the defined qtypes.
1153 		 * But the mechanism is not reliable...
1154 		 * maybe we should obsolete older versions.
1155 		 */
1156 		qtype = NI_QTYPE_FQDN;
1157 		/* XXX will append a mbuf */
1158 		replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1159 		oldfqdn++;
1160 		break;
1161 	}
1162 
1163 	/* validate query Subject field. */
1164 	subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1165 	switch (qtype) {
1166 	case NI_QTYPE_NOOP:
1167 	case NI_QTYPE_SUPTYPES:
1168 		if (subjlen != 0)
1169 			goto bad;
1170 		break;
1171 
1172 	case NI_QTYPE_FQDN:
1173 	case NI_QTYPE_NODEADDR:
1174 		switch (ni6->ni_code) {
1175 		case ICMP6_NI_SUBJ_IPV6:
1176 #if ICMP6_NI_SUBJ_IPV6 != 0
1177 		case 0:
1178 #endif
1179 			/*
1180 			 * backward compatibility - try to accept 03 draft
1181 			 * format, where no Subject is present.
1182 			 */
1183 			if (subjlen == 0) {
1184 				oldfqdn++;
1185 				break;
1186 			}
1187 
1188 			if (subjlen != sizeof(sin6.sin6_addr))
1189 				goto bad;
1190 
1191 			/*
1192 			 * Validate Subject address.
1193 			 *
1194 			 * Not sure what exactly does "address belongs to the
1195 			 * node" mean in the spec, is it just unicast, or what?
1196 			 *
1197 			 * At this moment we consider Subject address as
1198 			 * "belong to the node" if the Subject address equals
1199 			 * to the IPv6 destination address; validation for
1200 			 * IPv6 destination address should have done enough
1201 			 * check for us.
1202 			 *
1203 			 * We do not do proxy at this moment.
1204 			 */
1205 			/* m_pulldown instead of copy? */
1206 			m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1207 			    subjlen, (caddr_t)&sin6.sin6_addr);
1208 			/* XXX kame scope hack */
1209 			if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
1210 #ifdef FAKE_LOOPBACK_IF
1211 				if ((m->m_flags & M_PKTHDR) != 0 &&
1212 				    m->m_pkthdr.rcvif) {
1213 					sin6.sin6_addr.s6_addr16[1] =
1214 					    htons(m->m_pkthdr.rcvif->if_index);
1215 				}
1216 #else
1217 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
1218 					sin6.sin6_addr.s6_addr16[1] =
1219 					    ip6->ip6_dst.s6_addr16[1];
1220 				}
1221 #endif
1222 			}
1223 			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &sin6.sin6_addr))
1224 				break;
1225 			/*
1226 			 * XXX if we are to allow other cases, we should really
1227 			 * be careful about scope here.
1228 			 * basically, we should disallow queries toward IPv6
1229 			 * destination X with subject Y, if scope(X) > scope(Y).
1230 			 * if we allow scope(X) > scope(Y), it will result in
1231 			 * information leakage across scope boundary.
1232 			 */
1233 			goto bad;
1234 
1235 		case ICMP6_NI_SUBJ_FQDN:
1236 			/*
1237 			 * Validate Subject name with gethostname(3).
1238 			 *
1239 			 * The behavior may need some debate, since:
1240 			 * - we are not sure if the node has FQDN as
1241 			 *   hostname (returned by gethostname(3)).
1242 			 * - the code does wildcard match for truncated names.
1243 			 *   however, we are not sure if we want to perform
1244 			 *   wildcard match, if gethostname(3) side has
1245 			 *   truncated hostname.
1246 			 */
1247 			n = ni6_nametodns(hostname, hostnamelen, 0);
1248 			if (!n || n->m_next || n->m_len == 0)
1249 				goto bad;
1250 			IP6_EXTHDR_GET(subj, char *, m,
1251 			    off + sizeof(struct icmp6_nodeinfo), subjlen);
1252 			if (subj == NULL)
1253 				goto bad;
1254 			if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1255 					n->m_len)) {
1256 				goto bad;
1257 			}
1258 			m_freem(n);
1259 			n = NULL;
1260 			break;
1261 
1262 		case ICMP6_NI_SUBJ_IPV4:	/* xxx: to be implemented? */
1263 		default:
1264 			goto bad;
1265 		}
1266 		break;
1267 
1268 	default:
1269 		/* should never be here due to "switch (qtype)" above */
1270 		goto bad;
1271 	}
1272 
1273 	/* allocate a mbuf to reply. */
1274 	MGETHDR(n, M_DONTWAIT, m->m_type);
1275 	if (n == NULL) {
1276 		m_freem(m);
1277 		return(NULL);
1278 	}
1279 	M_COPY_PKTHDR(n, m); /* just for recvif */
1280 	if (replylen > MHLEN) {
1281 		if (replylen > MCLBYTES) {
1282 			 /*
1283 			  * XXX: should we try to allocate more? But MCLBYTES is
1284 			  * probably much larger than IPV6_MMTU...
1285 			  */
1286 			goto bad;
1287 		}
1288 		MCLGET(n, M_DONTWAIT);
1289 		if ((n->m_flags & M_EXT) == 0) {
1290 			goto bad;
1291 		}
1292 	}
1293 	n->m_pkthdr.len = n->m_len = replylen;
1294 
1295 	/* copy mbuf header and IPv6 + Node Information base headers */
1296 	bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1297 	nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1298 	bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1299 
1300 	/* qtype dependent procedure */
1301 	switch (qtype) {
1302 	case NI_QTYPE_NOOP:
1303 		nni6->ni_flags = 0;
1304 		break;
1305 	case NI_QTYPE_SUPTYPES:
1306 		goto bad;	/* xxx: to be implemented */
1307 		break;
1308 	case NI_QTYPE_FQDN:
1309 		fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1310 						sizeof(struct ip6_hdr) +
1311 						sizeof(struct icmp6_nodeinfo));
1312 		nni6->ni_flags = 0; /* XXX: meaningless TTL */
1313 		fqdn->ni_fqdn_ttl = 0;	/* ditto. */
1314 		/*
1315 		 * XXX do we really have FQDN in variable "hostname"?
1316 		 */
1317 		n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
1318 		if (n->m_next == NULL)
1319 			goto bad;
1320 		/* XXX we assume that n->m_next is not a chain */
1321 		if (n->m_next->m_next != NULL)
1322 			goto bad;
1323 		n->m_pkthdr.len += n->m_next->m_len;
1324 		break;
1325 	case NI_QTYPE_NODEADDR:
1326 	{
1327 		int lenlim, copied;
1328 
1329 		if (n->m_flags & M_EXT)
1330 			lenlim = MCLBYTES - sizeof(struct ip6_hdr) -
1331 				sizeof(struct icmp6_nodeinfo);
1332 		else
1333 			lenlim = MHLEN - sizeof(struct ip6_hdr) -
1334 				sizeof(struct icmp6_nodeinfo);
1335 		copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1336 		/* XXX: reset mbuf length */
1337 		n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1338 			sizeof(struct icmp6_nodeinfo) + copied;
1339 		break;
1340 	}
1341 	default:
1342 		break;		/* XXX impossible! */
1343 	}
1344 
1345 	nni6->ni_type = ICMP6_NI_REPLY;
1346 	nni6->ni_code = ICMP6_NI_SUCESS;
1347 	m_freem(m);
1348 	return(n);
1349 
1350   bad:
1351 	m_freem(m);
1352 	if (n)
1353 		m_freem(n);
1354 	return(NULL);
1355 }
1356 #undef hostnamelen
1357 
1358 /*
1359  * make a mbuf with DNS-encoded string.  no compression support.
1360  *
1361  * XXX names with less than 2 dots (like "foo" or "foo.section") will be
1362  * treated as truncated name (two \0 at the end).  this is a wild guess.
1363  */
1364 static struct mbuf *
1365 ni6_nametodns(name, namelen, old)
1366 	const char *name;
1367 	int namelen;
1368 	int old;	/* return pascal string if non-zero */
1369 {
1370 	struct mbuf *m;
1371 	char *cp, *ep;
1372 	const char *p, *q;
1373 	int i, len, nterm;
1374 
1375 	if (old)
1376 		len = namelen + 1;
1377 	else
1378 		len = MCLBYTES;
1379 
1380 	/* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
1381 	MGET(m, M_DONTWAIT, MT_DATA);
1382 	if (m && len > MLEN) {
1383 		MCLGET(m, M_DONTWAIT);
1384 		if ((m->m_flags & M_EXT) == 0)
1385 			goto fail;
1386 	}
1387 	if (!m)
1388 		goto fail;
1389 	m->m_next = NULL;
1390 
1391 	if (old) {
1392 		m->m_len = len;
1393 		*mtod(m, char *) = namelen;
1394 		bcopy(name, mtod(m, char *) + 1, namelen);
1395 		return m;
1396 	} else {
1397 		m->m_len = 0;
1398 		cp = mtod(m, char *);
1399 		ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1400 
1401 		/* if not certain about my name, return empty buffer */
1402 		if (namelen == 0)
1403 			return m;
1404 
1405 		/*
1406 		 * guess if it looks like shortened hostname, or FQDN.
1407 		 * shortened hostname needs two trailing "\0".
1408 		 */
1409 		i = 0;
1410 		for (p = name; p < name + namelen; p++) {
1411 			if (*p && *p == '.')
1412 				i++;
1413 		}
1414 		if (i < 2)
1415 			nterm = 2;
1416 		else
1417 			nterm = 1;
1418 
1419 		p = name;
1420 		while (cp < ep && p < name + namelen) {
1421 			i = 0;
1422 			for (q = p; q < name + namelen && *q && *q != '.'; q++)
1423 				i++;
1424 			/* result does not fit into mbuf */
1425 			if (cp + i + 1 >= ep)
1426 				goto fail;
1427 			/* DNS label length restriction, RFC1035 page 8 */
1428 			if (i >= 64)
1429 				goto fail;
1430 			*cp++ = i;
1431 			bcopy(p, cp, i);
1432 			cp += i;
1433 			p = q;
1434 			if (p < name + namelen && *p == '.')
1435 				p++;
1436 		}
1437 		/* termination */
1438 		if (cp + nterm >= ep)
1439 			goto fail;
1440 		while (nterm-- > 0)
1441 			*cp++ = '\0';
1442 		m->m_len = cp - mtod(m, char *);
1443 		return m;
1444 	}
1445 
1446 	panic("should not reach here");
1447 	/*NOTREACHED*/
1448 
1449  fail:
1450 	if (m)
1451 		m_freem(m);
1452 	return NULL;
1453 }
1454 
1455 /*
1456  * check if two DNS-encoded string matches.  takes care of truncated
1457  * form (with \0\0 at the end).  no compression support.
1458  */
1459 static int
1460 ni6_dnsmatch(a, alen, b, blen)
1461 	const char *a;
1462 	int alen;
1463 	const char *b;
1464 	int blen;
1465 {
1466 	const char *a0, *b0;
1467 	int l;
1468 
1469 	/* simplest case - need validation? */
1470 	if (alen == blen && bcmp(a, b, alen) == 0)
1471 		return 1;
1472 
1473 	a0 = a;
1474 	b0 = b;
1475 
1476 	/* termination is mandatory */
1477 	if (alen < 2 || blen < 2)
1478 		return 0;
1479 	if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
1480 		return 0;
1481 	alen--;
1482 	blen--;
1483 
1484 	while (a - a0 < alen && b - b0 < blen) {
1485 		if (a - a0 + 1 > alen || b - b0 + 1 > blen)
1486 			return 0;
1487 
1488 		if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
1489 			return 0;
1490 		/* we don't support compression yet */
1491 		if (a[0] >= 64 || b[0] >= 64)
1492 			return 0;
1493 
1494 		/* truncated case */
1495 		if (a[0] == 0 && a - a0 == alen - 1)
1496 			return 1;
1497 		if (b[0] == 0 && b - b0 == blen - 1)
1498 			return 1;
1499 		if (a[0] == 0 || b[0] == 0)
1500 			return 0;
1501 
1502 		if (a[0] != b[0])
1503 			return 0;
1504 		l = a[0];
1505 		if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
1506 			return 0;
1507 		if (bcmp(a + 1, b + 1, l) != 0)
1508 			return 0;
1509 
1510 		a += 1 + l;
1511 		b += 1 + l;
1512 	}
1513 
1514 	if (a - a0 == alen && b - b0 == blen)
1515 		return 1;
1516 	else
1517 		return 0;
1518 }
1519 
1520 /*
1521  * calculate the number of addresses to be returned in the node info reply.
1522  */
1523 static int
1524 ni6_addrs(ni6, m, ifpp)
1525 	struct icmp6_nodeinfo *ni6;
1526 	struct mbuf *m;
1527 	struct ifnet **ifpp;
1528 {
1529 	register struct ifnet *ifp;
1530 	register struct in6_ifaddr *ifa6;
1531 	register struct ifaddr *ifa;
1532 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1533 	int addrs = 0, addrsofif, iffound = 0;
1534 
1535 	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1536 	{
1537 		addrsofif = 0;
1538 		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1539 		     ifa = ifa->ifa_list.tqe_next)
1540 		{
1541 			if (ifa->ifa_addr->sa_family != AF_INET6)
1542 				continue;
1543 			ifa6 = (struct in6_ifaddr *)ifa;
1544 
1545 			if (!(ni6->ni_flags & NI_NODEADDR_FLAG_ALL) &&
1546 			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1547 					       &ifa6->ia_addr.sin6_addr))
1548 				iffound = 1;
1549 
1550 			/*
1551 			 * IPv4-mapped addresses can only be returned by a
1552 			 * Node Information proxy, since they represent
1553 			 * addresses of IPv4-only nodes, which perforce do
1554 			 * not implement this protocol.
1555 			 * [icmp-name-lookups-05]
1556 			 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1557 			 * this function at this moment.
1558 			 */
1559 
1560 			if (ifa6->ia6_flags & IN6_IFF_ANYCAST)
1561 				continue; /* we need only unicast addresses */
1562 
1563 			if ((ni6->ni_flags & (NI_NODEADDR_FLAG_LINKLOCAL |
1564 					      NI_NODEADDR_FLAG_SITELOCAL |
1565 					      NI_NODEADDR_FLAG_GLOBAL)) == 0)
1566 				continue;
1567 
1568 			/* What do we have to do about ::1? */
1569 			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1570 			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1571 				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1572 					addrsofif++;
1573 				break;
1574 			 case IPV6_ADDR_SCOPE_SITELOCAL:
1575 				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1576 					addrsofif++;
1577 				break;
1578 			 case IPV6_ADDR_SCOPE_GLOBAL:
1579 				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1580 					 addrsofif++;
1581 				 break;
1582 			 default:
1583 				 continue;
1584 			}
1585 		}
1586 		if (iffound) {
1587 			*ifpp = ifp;
1588 			return(addrsofif);
1589 		}
1590 
1591 		addrs += addrsofif;
1592 	}
1593 
1594 	return(addrs);
1595 }
1596 
1597 static int
1598 ni6_store_addrs(ni6, nni6, ifp0, resid)
1599 	struct icmp6_nodeinfo *ni6, *nni6;
1600 	struct ifnet *ifp0;
1601 	int resid;
1602 {
1603 	register struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
1604 	register struct in6_ifaddr *ifa6;
1605 	register struct ifaddr *ifa;
1606 	int docopy, copied = 0;
1607 	u_char *cp = (u_char *)(nni6 + 1);
1608 
1609 	if (ifp0 == NULL && !(ni6->ni_flags & NI_NODEADDR_FLAG_ALL))
1610 		return(0);	/* needless to copy */
1611 
1612 	for (; ifp; ifp = TAILQ_NEXT(ifp, if_list))
1613 	{
1614 		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1615 		     ifa = ifa->ifa_list.tqe_next)
1616 		{
1617 			docopy = 0;
1618 
1619 			if (ifa->ifa_addr->sa_family != AF_INET6)
1620 				continue;
1621 			ifa6 = (struct in6_ifaddr *)ifa;
1622 
1623 			if (ifa6->ia6_flags & IN6_IFF_ANYCAST) {
1624 				/* just experimental. not in the spec. */
1625 				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1626 					docopy = 1;
1627 				else
1628 					continue;
1629 			}
1630 			else {	/* unicast address */
1631 				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1632 					continue;
1633 				else
1634 					docopy = 1;
1635 			}
1636 
1637 			/* What do we have to do about ::1? */
1638 			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1639 			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1640 				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1641 					docopy = 1;
1642 				break;
1643 			 case IPV6_ADDR_SCOPE_SITELOCAL:
1644 				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1645 					docopy = 1;
1646 				break;
1647 			 case IPV6_ADDR_SCOPE_GLOBAL:
1648 				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1649 					 docopy = 1;
1650 				 break;
1651 			 default:
1652 				 continue;
1653 			}
1654 
1655 			if (docopy) {
1656 				if (resid < sizeof(struct in6_addr)) {
1657 					/*
1658 					 * We give up much more copy.
1659 					 * Set the truncate flag and return.
1660 					 */
1661 					nni6->ni_flags |=
1662 						NI_NODEADDR_FLAG_TRUNCATE;
1663 					return(copied);
1664 				}
1665 				bcopy(&ifa6->ia_addr.sin6_addr, cp,
1666 				      sizeof(struct in6_addr));
1667 				/* XXX: KAME link-local hack; remove ifindex */
1668 				if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))
1669 					((struct in6_addr *)cp)->s6_addr16[1] = 0;
1670 				cp += sizeof(struct in6_addr);
1671 				resid -= sizeof(struct in6_addr);
1672 				copied += sizeof(struct in6_addr);
1673 			}
1674 		}
1675 		if (ifp0)	/* we need search only on the specified IF */
1676 			break;
1677 	}
1678 
1679 	return(copied);
1680 }
1681 
1682 /*
1683  * XXX almost dup'ed code with rip6_input.
1684  */
1685 static int
1686 icmp6_rip6_input(mp, off)
1687 	struct	mbuf **mp;
1688 	int	off;
1689 {
1690 	struct mbuf *m = *mp;
1691 	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1692 	register struct in6pcb *in6p;
1693 	struct in6pcb *last = NULL;
1694 	struct sockaddr_in6 rip6src;
1695 	struct icmp6_hdr *icmp6;
1696 	struct mbuf *opts = NULL;
1697 
1698 #ifndef PULLDOWN_TEST
1699 	/* this is assumed to be safe. */
1700 	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
1701 #else
1702 	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
1703 	if (icmp6 == NULL) {
1704 		/* m is already reclaimed */
1705 		return IPPROTO_DONE;
1706 	}
1707 #endif
1708 
1709 	bzero(&rip6src, sizeof(rip6src));
1710 	rip6src.sin6_len = sizeof(struct sockaddr_in6);
1711 	rip6src.sin6_family = AF_INET6;
1712 	/* KAME hack: recover scopeid */
1713 	(void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);
1714 
1715 	LIST_FOREACH(in6p, &ripcb, inp_list)
1716 	{
1717 		if ((in6p->inp_vflag & INP_IPV6) == NULL)
1718 			continue;
1719 		if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
1720 			continue;
1721 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1722 		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1723 			continue;
1724 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1725 		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
1726 			continue;
1727 		if (in6p->in6p_icmp6filt
1728 		    && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1729 				 in6p->in6p_icmp6filt))
1730 			continue;
1731 		if (last) {
1732 			struct	mbuf *n;
1733 			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1734 				if (last->in6p_flags & IN6P_CONTROLOPTS)
1735 					ip6_savecontrol(last, &opts, ip6, n);
1736 				/* strip intermediate headers */
1737 				m_adj(n, off);
1738 				if (sbappendaddr(&last->in6p_socket->so_rcv,
1739 						 (struct sockaddr *)&rip6src,
1740 						 n, opts) == 0) {
1741 					/* should notify about lost packet */
1742 					m_freem(n);
1743 					if (opts)
1744 						m_freem(opts);
1745 				} else
1746 					sorwakeup(last->in6p_socket);
1747 				opts = NULL;
1748 			}
1749 		}
1750 		last = in6p;
1751 	}
1752 	if (last) {
1753 		if (last->in6p_flags & IN6P_CONTROLOPTS)
1754 			ip6_savecontrol(last, &opts, ip6, m);
1755 		/* strip intermediate headers */
1756 		m_adj(m, off);
1757 		if (sbappendaddr(&last->in6p_socket->so_rcv,
1758 				(struct sockaddr *)&rip6src, m, opts) == 0) {
1759 			m_freem(m);
1760 			if (opts)
1761 				m_freem(opts);
1762 		} else
1763 			sorwakeup(last->in6p_socket);
1764 	} else {
1765 		m_freem(m);
1766 		ip6stat.ip6s_delivered--;
1767 	}
1768 	return IPPROTO_DONE;
1769 }
1770 
1771 /*
1772  * Reflect the ip6 packet back to the source.
1773  * OFF points to the icmp6 header, counted from the top of the mbuf.
1774  */
1775 void
1776 icmp6_reflect(m, off)
1777 	struct	mbuf *m;
1778 	size_t off;
1779 {
1780 	struct ip6_hdr *ip6;
1781 	struct icmp6_hdr *icmp6;
1782 	struct in6_ifaddr *ia;
1783 	struct in6_addr t, *src = 0;
1784 	int plen;
1785 	int type, code;
1786 	struct ifnet *outif = NULL;
1787 #ifdef COMPAT_RFC1885
1788 	int mtu = IPV6_MMTU;
1789 	struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst;
1790 #endif
1791 
1792 	/* too short to reflect */
1793 	if (off < sizeof(struct ip6_hdr)) {
1794 		printf("sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
1795 		       (u_long)off, (u_long)sizeof(struct ip6_hdr),
1796 		       __FILE__, __LINE__);
1797 		goto bad;
1798 	}
1799 
1800 	/*
1801 	 * If there are extra headers between IPv6 and ICMPv6, strip
1802 	 * off that header first.
1803 	 */
1804 #ifdef DIAGNOSTIC
1805 	if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
1806 		panic("assumption failed in icmp6_reflect");
1807 #endif
1808 	if (off > sizeof(struct ip6_hdr)) {
1809 		size_t l;
1810 		struct ip6_hdr nip6;
1811 
1812 		l = off - sizeof(struct ip6_hdr);
1813 		m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
1814 		m_adj(m, l);
1815 		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1816 		if (m->m_len < l) {
1817 			if ((m = m_pullup(m, l)) == NULL)
1818 				return;
1819 		}
1820 		bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
1821 	} else /* off == sizeof(struct ip6_hdr) */ {
1822 		size_t l;
1823 		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1824 		if (m->m_len < l) {
1825 			if ((m = m_pullup(m, l)) == NULL)
1826 				return;
1827 		}
1828 	}
1829 	plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
1830 	ip6 = mtod(m, struct ip6_hdr *);
1831 	ip6->ip6_nxt = IPPROTO_ICMPV6;
1832 	icmp6 = (struct icmp6_hdr *)(ip6 + 1);
1833 	type = icmp6->icmp6_type; /* keep type for statistics */
1834 	code = icmp6->icmp6_code; /* ditto. */
1835 
1836 	t = ip6->ip6_dst;
1837 	/*
1838 	 * ip6_input() drops a packet if its src is multicast.
1839 	 * So, the src is never multicast.
1840 	 */
1841 	ip6->ip6_dst = ip6->ip6_src;
1842 
1843 	/* XXX hack for link-local addresses */
1844 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
1845 		ip6->ip6_dst.s6_addr16[1] =
1846 			htons(m->m_pkthdr.rcvif->if_index);
1847 	if (IN6_IS_ADDR_LINKLOCAL(&t))
1848 		t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
1849 
1850 #ifdef COMPAT_RFC1885
1851 	/*
1852 	 * xxx guess MTU
1853 	 * RFC 1885 requires that echo reply should be truncated if it
1854 	 * does not fit in with (return) path MTU, but the description was
1855 	 * removed in the new spec.
1856 	 */
1857 	if (icmp6_reflect_rt.ro_rt == 0 ||
1858 	    ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) {
1859 		if (icmp6_reflect_rt.ro_rt) {
1860 			RTFREE(icmp6_reflect_rt.ro_rt);
1861 			icmp6_reflect_rt.ro_rt = 0;
1862 		}
1863 		bzero(sin6, sizeof(*sin6));
1864 		sin6->sin6_family = PF_INET6;
1865 		sin6->sin6_len = sizeof(struct sockaddr_in6);
1866 		sin6->sin6_addr = ip6->ip6_dst;
1867 
1868 		rtalloc_ign((struct route *)&icmp6_reflect_rt.ro_rt,
1869 			    RTF_PRCLONING);
1870 	}
1871 
1872 	if (icmp6_reflect_rt.ro_rt == 0)
1873 		goto bad;
1874 
1875 	if ((icmp6_reflect_rt.ro_rt->rt_flags & RTF_HOST)
1876 	    && mtu < icmp6_reflect_rt.ro_rt->rt_ifp->if_mtu)
1877 		mtu = icmp6_reflect_rt.ro_rt->rt_rmx.rmx_mtu;
1878 
1879 	if (mtu < m->m_pkthdr.len) {
1880 		plen -= (m->m_pkthdr.len - mtu);
1881 		m_adj(m, mtu - m->m_pkthdr.len);
1882 	}
1883 #endif
1884 	/*
1885 	 * If the incoming packet was addressed directly to us(i.e. unicast),
1886 	 * use dst as the src for the reply.
1887 	 * The IN6_IFF_NOTREADY case would be VERY rare, but is possible
1888 	 * (for example) when we encounter an error while forwarding procedure
1889 	 * destined to a duplicated address of ours.
1890 	 */
1891 	for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1892 		if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
1893 		    (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) {
1894 			src = &t;
1895 			break;
1896 		}
1897 	if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) {
1898 		/*
1899 		 * This is the case if the dst is our link-local address
1900 		 * and the sender is also ourseleves.
1901 		 */
1902 		src = &t;
1903 	}
1904 
1905 	if (src == 0)
1906 		/*
1907 		 * This case matches to multicasts, our anycast, or unicasts
1908 		 * that we do not own. Select a source address which has the
1909 		 * same scope.
1910 		 * XXX: for (non link-local) multicast addresses, this might
1911 		 * not be a good choice.
1912 		 */
1913 		if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0)
1914 			src = &IA6_SIN6(ia)->sin6_addr;
1915 
1916 	if (src == 0)
1917 		goto bad;
1918 
1919 	ip6->ip6_src = *src;
1920 
1921 	ip6->ip6_flow = 0;
1922 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1923 	ip6->ip6_vfc |= IPV6_VERSION;
1924 	ip6->ip6_nxt = IPPROTO_ICMPV6;
1925 	if (m->m_pkthdr.rcvif) {
1926 		/* XXX: This may not be the outgoing interface */
1927 		ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim;
1928 	}
1929 
1930 	icmp6->icmp6_cksum = 0;
1931 	icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
1932 					sizeof(struct ip6_hdr), plen);
1933 
1934 	/*
1935 	 * xxx option handling
1936 	 */
1937 
1938 	m->m_flags &= ~(M_BCAST|M_MCAST);
1939 #ifdef IPSEC
1940 	/* Don't lookup socket */
1941 	ipsec_setsocket(m, NULL);
1942 #endif /*IPSEC*/
1943 
1944 #ifdef COMPAT_RFC1885
1945 	ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL, &outif);
1946 #else
1947 	ip6_output(m, NULL, NULL, 0, NULL, &outif);
1948 #endif
1949 	if (outif)
1950 		icmp6_ifoutstat_inc(outif, type, code);
1951 
1952 	return;
1953 
1954  bad:
1955 	m_freem(m);
1956 	return;
1957 }
1958 
1959 void
1960 icmp6_fasttimo()
1961 {
1962 
1963 	mld6_fasttimeo();
1964 
1965 	/* reset ICMPv6 pps limit */
1966 	icmp6errpps_count = 0;
1967 }
1968 
1969 static const char *
1970 icmp6_redirect_diag(src6, dst6, tgt6)
1971 	struct in6_addr *src6;
1972 	struct in6_addr *dst6;
1973 	struct in6_addr *tgt6;
1974 {
1975 	static char buf[1024];
1976 	snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
1977 		ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
1978 	return buf;
1979 }
1980 
1981 void
1982 icmp6_redirect_input(m, off)
1983 	register struct mbuf *m;
1984 	int off;
1985 {
1986 	struct ifnet *ifp = m->m_pkthdr.rcvif;
1987 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1988 	struct nd_redirect *nd_rd;
1989 	int icmp6len = ntohs(ip6->ip6_plen);
1990 	char *lladdr = NULL;
1991 	int lladdrlen = 0;
1992 	u_char *redirhdr = NULL;
1993 	int redirhdrlen = 0;
1994 	struct rtentry *rt = NULL;
1995 	int is_router;
1996 	int is_onlink;
1997 	struct in6_addr src6 = ip6->ip6_src;
1998 	struct in6_addr redtgt6;
1999 	struct in6_addr reddst6;
2000 	union nd_opts ndopts;
2001 
2002 	if (!m || !ifp)
2003 		return;
2004 
2005 	/* XXX if we are router, we don't update route by icmp6 redirect */
2006 	if (ip6_forwarding)
2007 		goto freeit;
2008 	if (!icmp6_rediraccept)
2009 		goto freeit;
2010 
2011 #ifndef PULLDOWN_TEST
2012 	IP6_EXTHDR_CHECK(m, off, icmp6len,);
2013 	nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2014 #else
2015 	IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2016 	if (nd_rd == NULL) {
2017 		icmp6stat.icp6s_tooshort++;
2018 		return;
2019 	}
2020 #endif
2021 	redtgt6 = nd_rd->nd_rd_target;
2022 	reddst6 = nd_rd->nd_rd_dst;
2023 
2024 	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2025 		redtgt6.s6_addr16[1] = htons(ifp->if_index);
2026 	if (IN6_IS_ADDR_LINKLOCAL(&reddst6))
2027 		reddst6.s6_addr16[1] = htons(ifp->if_index);
2028 
2029 	/* validation */
2030 	if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2031 		log(LOG_ERR,
2032 			"ICMP6 redirect sent from %s rejected; "
2033 			"must be from linklocal\n", ip6_sprintf(&src6));
2034 		goto freeit;
2035 	}
2036 	if (ip6->ip6_hlim != 255) {
2037 		log(LOG_ERR,
2038 			"ICMP6 redirect sent from %s rejected; "
2039 			"hlim=%d (must be 255)\n",
2040 			ip6_sprintf(&src6), ip6->ip6_hlim);
2041 		goto freeit;
2042 	}
2043     {
2044 	/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2045 	struct sockaddr_in6 sin6;
2046 	struct in6_addr *gw6;
2047 
2048 	bzero(&sin6, sizeof(sin6));
2049 	sin6.sin6_family = AF_INET6;
2050 	sin6.sin6_len = sizeof(struct sockaddr_in6);
2051 	bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
2052 	rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
2053 	if (rt) {
2054 		if (rt->rt_gateway == NULL ||
2055 		    rt->rt_gateway->sa_family != AF_INET6) {
2056 			log(LOG_ERR,
2057 			    "ICMP6 redirect rejected; no route "
2058 			    "with inet6 gateway found for redirect dst: %s\n",
2059 			    icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2060 			RTFREE(rt);
2061 			goto freeit;
2062 		}
2063 
2064 		gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
2065 		if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
2066 			log(LOG_ERR,
2067 				"ICMP6 redirect rejected; "
2068 				"not equal to gw-for-src=%s (must be same): "
2069 				"%s\n",
2070 				ip6_sprintf(gw6),
2071 				icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2072 			RTFREE(rt);
2073 			goto freeit;
2074 		}
2075 	} else {
2076 		log(LOG_ERR,
2077 			"ICMP6 redirect rejected; "
2078 			"no route found for redirect dst: %s\n",
2079 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2080 		goto freeit;
2081 	}
2082 	RTFREE(rt);
2083 	rt = NULL;
2084     }
2085 	if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2086 		log(LOG_ERR,
2087 			"ICMP6 redirect rejected; "
2088 			"redirect dst must be unicast: %s\n",
2089 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2090 		goto freeit;
2091 	}
2092 
2093 	is_router = is_onlink = 0;
2094 	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2095 		is_router = 1;	/* router case */
2096 	if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
2097 		is_onlink = 1;	/* on-link destination case */
2098 	if (!is_router && !is_onlink) {
2099 		log(LOG_ERR,
2100 			"ICMP6 redirect rejected; "
2101 			"neither router case nor onlink case: %s\n",
2102 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2103 		goto freeit;
2104 	}
2105 	/* validation passed */
2106 
2107 	icmp6len -= sizeof(*nd_rd);
2108 	nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2109 	if (nd6_options(&ndopts) < 0) {
2110 		log(LOG_INFO, "icmp6_redirect_input: "
2111 			"invalid ND option, rejected: %s\n",
2112 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2113 		goto freeit;
2114 	}
2115 
2116 	if (ndopts.nd_opts_tgt_lladdr) {
2117 		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2118 		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2119 	}
2120 
2121 	if (ndopts.nd_opts_rh) {
2122 		redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
2123 		redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
2124 	}
2125 
2126 	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2127 		log(LOG_INFO,
2128 			"icmp6_redirect_input: lladdrlen mismatch for %s "
2129 			"(if %d, icmp6 packet %d): %s\n",
2130 			ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
2131 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
2132 	}
2133 
2134 	/* RFC 2461 8.3 */
2135 	nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2136 			 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2137 
2138 	if (!is_onlink) {	/* better router case. perform rtredirect. */
2139 		/* perform rtredirect */
2140 		struct sockaddr_in6 sdst;
2141 		struct sockaddr_in6 sgw;
2142 		struct sockaddr_in6 ssrc;
2143 
2144 		bzero(&sdst, sizeof(sdst));
2145 		bzero(&sgw, sizeof(sgw));
2146 		bzero(&ssrc, sizeof(ssrc));
2147 		sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
2148 		sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
2149 			sizeof(struct sockaddr_in6);
2150 		bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
2151 		bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2152 		bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2153 		rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
2154 			   (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
2155 			   (struct sockaddr *)&ssrc,
2156 			   (struct rtentry **)NULL);
2157 	}
2158 	/* finally update cached route in each socket via pfctlinput */
2159     {
2160 	struct sockaddr_in6 sdst;
2161 
2162 	bzero(&sdst, sizeof(sdst));
2163 	sdst.sin6_family = AF_INET6;
2164 	sdst.sin6_len = sizeof(struct sockaddr_in6);
2165 	bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2166 	pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
2167 #ifdef IPSEC
2168 	key_sa_routechange((struct sockaddr *)&sdst);
2169 #endif
2170     }
2171 
2172  freeit:
2173 	m_freem(m);
2174 }
2175 
2176 void
2177 icmp6_redirect_output(m0, rt)
2178 	struct mbuf *m0;
2179 	struct rtentry *rt;
2180 {
2181 	struct ifnet *ifp;	/* my outgoing interface */
2182 	struct in6_addr *ifp_ll6;
2183 	struct in6_addr *router_ll6;
2184 	struct ip6_hdr *sip6;	/* m0 as struct ip6_hdr */
2185 	struct mbuf *m = NULL;	/* newly allocated one */
2186 	struct ip6_hdr *ip6;	/* m as struct ip6_hdr */
2187 	struct nd_redirect *nd_rd;
2188 	size_t maxlen;
2189 	u_char *p;
2190 	struct ifnet *outif = NULL;
2191 	struct sockaddr_in6 src_sa;
2192 
2193 	icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2194 
2195 	/* if we are not router, we don't send icmp6 redirect */
2196 	if (!ip6_forwarding || ip6_accept_rtadv)
2197 		goto fail;
2198 
2199 	/* sanity check */
2200 	if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
2201 		goto fail;
2202 
2203 	/*
2204 	 * Address check:
2205 	 *  the source address must identify a neighbor, and
2206 	 *  the destination address must not be a multicast address
2207 	 *  [RFC 2461, sec 8.2]
2208 	 */
2209 	sip6 = mtod(m0, struct ip6_hdr *);
2210 	bzero(&src_sa, sizeof(src_sa));
2211 	src_sa.sin6_family = AF_INET6;
2212 	src_sa.sin6_len = sizeof(src_sa);
2213 	src_sa.sin6_addr = sip6->ip6_src;
2214 	/* we don't currently use sin6_scope_id, but eventually use it */
2215 	src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
2216 	if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
2217 		goto fail;
2218 	if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
2219 		goto fail;	/* what should we do here? */
2220 
2221 	/* rate limit */
2222 	if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
2223 		goto fail;
2224 
2225 	/*
2226 	 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2227 	 * we almost always ask for an mbuf cluster for simplicity.
2228 	 * (MHLEN < IPV6_MMTU is almost always true)
2229 	 */
2230 #if IPV6_MMTU >= MCLBYTES
2231 # error assumption failed about IPV6_MMTU and MCLBYTES
2232 #endif
2233 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
2234 	if (m && IPV6_MMTU >= MHLEN)
2235 		MCLGET(m, M_DONTWAIT);
2236 	if (!m)
2237 		goto fail;
2238 	maxlen = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
2239 	maxlen = min(IPV6_MMTU, maxlen);
2240 	/* just for safety */
2241 	if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2242 	    ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2243 		goto fail;
2244 	}
2245 
2246 	{
2247 		/* get ip6 linklocal address for ifp(my outgoing interface). */
2248 		struct in6_ifaddr *ia;
2249 		if ((ia = in6ifa_ifpforlinklocal(ifp,
2250 						 IN6_IFF_NOTREADY|
2251 						 IN6_IFF_ANYCAST)) == NULL)
2252 			goto fail;
2253 		ifp_ll6 = &ia->ia_addr.sin6_addr;
2254 	}
2255 
2256 	/* get ip6 linklocal address for the router. */
2257 	if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
2258 		struct sockaddr_in6 *sin6;
2259 		sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
2260 		router_ll6 = &sin6->sin6_addr;
2261 		if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
2262 			router_ll6 = (struct in6_addr *)NULL;
2263 	} else
2264 		router_ll6 = (struct in6_addr *)NULL;
2265 
2266 	/* ip6 */
2267 	ip6 = mtod(m, struct ip6_hdr *);
2268 	ip6->ip6_flow = 0;
2269 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2270 	ip6->ip6_vfc |= IPV6_VERSION;
2271 	/* ip6->ip6_plen will be set later */
2272 	ip6->ip6_nxt = IPPROTO_ICMPV6;
2273 	ip6->ip6_hlim = 255;
2274 	/* ip6->ip6_src must be linklocal addr for my outgoing if. */
2275 	bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2276 	bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2277 
2278 	/* ND Redirect */
2279 	nd_rd = (struct nd_redirect *)(ip6 + 1);
2280 	nd_rd->nd_rd_type = ND_REDIRECT;
2281 	nd_rd->nd_rd_code = 0;
2282 	nd_rd->nd_rd_reserved = 0;
2283 	if (rt->rt_flags & RTF_GATEWAY) {
2284 		/*
2285 		 * nd_rd->nd_rd_target must be a link-local address in
2286 		 * better router cases.
2287 		 */
2288 		if (!router_ll6)
2289 			goto fail;
2290 		bcopy(router_ll6, &nd_rd->nd_rd_target,
2291 		      sizeof(nd_rd->nd_rd_target));
2292 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2293 		      sizeof(nd_rd->nd_rd_dst));
2294 	} else {
2295 		/* make sure redtgt == reddst */
2296 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2297 		      sizeof(nd_rd->nd_rd_target));
2298 		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2299 		      sizeof(nd_rd->nd_rd_dst));
2300 	}
2301 
2302 	p = (u_char *)(nd_rd + 1);
2303 
2304 	if (!router_ll6)
2305 		goto nolladdropt;
2306 
2307     {
2308 	/* target lladdr option */
2309 	struct rtentry *rt_router = NULL;
2310 	int len;
2311 	struct sockaddr_dl *sdl;
2312 	struct nd_opt_hdr *nd_opt;
2313 	char *lladdr;
2314 
2315 	rt_router = nd6_lookup(router_ll6, 0, ifp);
2316 	if (!rt_router)
2317 		goto nolladdropt;
2318 	len = sizeof(*nd_opt) + ifp->if_addrlen;
2319 	len = (len + 7) & ~7;	/*round by 8*/
2320 	/* safety check */
2321 	if (len + (p - (u_char *)ip6) > maxlen)
2322 		goto nolladdropt;
2323 	if (!(rt_router->rt_flags & RTF_GATEWAY) &&
2324 	    (rt_router->rt_flags & RTF_LLINFO) &&
2325 	    (rt_router->rt_gateway->sa_family == AF_LINK) &&
2326 	    (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) &&
2327 	    sdl->sdl_alen) {
2328 		nd_opt = (struct nd_opt_hdr *)p;
2329 		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2330 		nd_opt->nd_opt_len = len >> 3;
2331 		lladdr = (char *)(nd_opt + 1);
2332 		bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
2333 		p += len;
2334 	}
2335     }
2336 nolladdropt:;
2337 
2338 	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2339 
2340 	/* just to be safe */
2341 #ifdef M_DECRYPTED	/*not openbsd*/
2342 	if (m0->m_flags & M_DECRYPTED)
2343 		goto noredhdropt;
2344 #endif
2345 	if (p - (u_char *)ip6 > maxlen)
2346 		goto noredhdropt;
2347 
2348     {
2349 	/* redirected header option */
2350 	int len;
2351 	struct nd_opt_rd_hdr *nd_opt_rh;
2352 
2353 	/*
2354 	 * compute the maximum size for icmp6 redirect header option.
2355 	 * XXX room for auth header?
2356 	 */
2357 	len = maxlen - (p - (u_char *)ip6);
2358 	len &= ~7;
2359 
2360 	/* This is just for simplicity. */
2361 	if (m0->m_pkthdr.len != m0->m_len) {
2362 		if (m0->m_next) {
2363 			m_freem(m0->m_next);
2364 			m0->m_next = NULL;
2365 		}
2366 		m0->m_pkthdr.len = m0->m_len;
2367 	}
2368 
2369 	/*
2370 	 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2371 	 * about padding/truncate rule for the original IP packet.
2372 	 * From the discussion on IPv6imp in Feb 1999, the consensus was:
2373 	 * - "attach as much as possible" is the goal
2374 	 * - pad if not aligned (original size can be guessed by original
2375 	 *   ip6 header)
2376 	 * Following code adds the padding if it is simple enough,
2377 	 * and truncates if not.
2378 	 */
2379 	if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
2380 		panic("assumption failed in %s:%d\n", __FILE__, __LINE__);
2381 
2382 	if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2383 		/* not enough room, truncate */
2384 		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2385 	} else {
2386 		/* enough room, pad or truncate */
2387 		size_t extra;
2388 
2389 		extra = m0->m_pkthdr.len % 8;
2390 		if (extra) {
2391 			/* pad if easy enough, truncate if not */
2392 			if (8 - extra <= M_TRAILINGSPACE(m0)) {
2393 				/* pad */
2394 				m0->m_len += (8 - extra);
2395 				m0->m_pkthdr.len += (8 - extra);
2396 			} else {
2397 				/* truncate */
2398 				m0->m_pkthdr.len -= extra;
2399 				m0->m_len -= extra;
2400 			}
2401 		}
2402 		len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2403 		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2404 	}
2405 
2406 	nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2407 	bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2408 	nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2409 	nd_opt_rh->nd_opt_rh_len = len >> 3;
2410 	p += sizeof(*nd_opt_rh);
2411 	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2412 
2413 	/* connect m0 to m */
2414 	m->m_next = m0;
2415 	m->m_pkthdr.len = m->m_len + m0->m_len;
2416     }
2417 noredhdropt:;
2418 
2419 	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src))
2420 		sip6->ip6_src.s6_addr16[1] = 0;
2421 	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst))
2422 		sip6->ip6_dst.s6_addr16[1] = 0;
2423 #if 0
2424 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
2425 		ip6->ip6_src.s6_addr16[1] = 0;
2426 	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
2427 		ip6->ip6_dst.s6_addr16[1] = 0;
2428 #endif
2429 	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target))
2430 		nd_rd->nd_rd_target.s6_addr16[1] = 0;
2431 	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst))
2432 		nd_rd->nd_rd_dst.s6_addr16[1] = 0;
2433 
2434 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2435 
2436 	nd_rd->nd_rd_cksum = 0;
2437 	nd_rd->nd_rd_cksum
2438 		= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2439 
2440 	/* send the packet to outside... */
2441 #ifdef IPSEC
2442 	/* Don't lookup socket */
2443 	ipsec_setsocket(m, NULL);
2444 #endif /*IPSEC*/
2445 	ip6_output(m, NULL, NULL, 0, NULL, &outif);
2446 	if (outif) {
2447 		icmp6_ifstat_inc(outif, ifs6_out_msg);
2448 		icmp6_ifstat_inc(outif, ifs6_out_redirect);
2449 	}
2450 	icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2451 
2452 	return;
2453 
2454 fail:
2455 	if (m)
2456 		m_freem(m);
2457 	if (m0)
2458 		m_freem(m0);
2459 }
2460 
2461 /*
2462  * ICMPv6 socket option processing.
2463  *
2464  * NOTE: for OSes that use NRL inpcb (bsdi4/openbsd), do not forget to modify
2465  * sys/netinet6/raw_ipv6.c:rip6_ctloutput().
2466  */
2467 int
2468 icmp6_ctloutput(so, sopt)
2469 	struct socket *so;
2470 	struct sockopt *sopt;
2471 {
2472 	int error = 0;
2473 	int optlen;
2474 	register struct inpcb *inp = sotoinpcb(so);
2475 	int level, op, optname;
2476 
2477 	if (sopt) {
2478 		level = sopt->sopt_level;
2479 		op = sopt->sopt_dir;
2480 		optname = sopt->sopt_name;
2481 		optlen = sopt->sopt_valsize;
2482 	} else
2483 		level = op = optname = optlen = 0;
2484 	if (level != IPPROTO_ICMPV6) {
2485 		return EINVAL;
2486 	}
2487 
2488 	switch(op) {
2489 	case PRCO_SETOPT:
2490 		switch (optname) {
2491 		case ICMP6_FILTER:
2492 		    {
2493 			struct icmp6_filter *p;
2494 
2495 			if (optlen != sizeof(*p)) {
2496 				error = EMSGSIZE;
2497 				break;
2498 			}
2499 			if (inp->in6p_icmp6filt == NULL) {
2500 				error = EINVAL;
2501 				break;
2502 			}
2503 			error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen,
2504 				optlen);
2505 			break;
2506 		    }
2507 
2508 		default:
2509 			error = ENOPROTOOPT;
2510 			break;
2511 		}
2512 		break;
2513 
2514 	case PRCO_GETOPT:
2515 		switch (optname) {
2516 		case ICMP6_FILTER:
2517 		    {
2518 			if (inp->in6p_icmp6filt == NULL) {
2519 				error = EINVAL;
2520 				break;
2521 			}
2522 			error = sooptcopyout(sopt, inp->in6p_icmp6filt,
2523 				sizeof(struct icmp6_filter));
2524 			break;
2525 		    }
2526 
2527 		default:
2528 			error = ENOPROTOOPT;
2529 			break;
2530 		}
2531 		break;
2532 	}
2533 
2534 	return(error);
2535 }
2536 
2537 #ifndef HAVE_RATECHECK
2538 /*
2539  * ratecheck() returns true if it is okay to send.  We return
2540  * true if it is not okay to send.
2541  */
2542 static int
2543 ratecheck(last, limit)
2544 	struct timeval *last;
2545 	struct timeval *limit;
2546 {
2547 	struct timeval tp;
2548 	struct timeval nextsend;
2549 
2550 	microtime(&tp);
2551 	tp.tv_sec = time_second;
2552 
2553 	/* rate limit */
2554 	if (last->tv_sec != 0 || last->tv_usec != 0) {
2555 		nextsend.tv_sec = last->tv_sec + limit->tv_sec;
2556 		nextsend.tv_usec = last->tv_usec + limit->tv_usec;
2557 		nextsend.tv_sec += (nextsend.tv_usec / 1000000);
2558 		nextsend.tv_usec %= 1000000;
2559 
2560 		if (nextsend.tv_sec == tp.tv_sec && nextsend.tv_usec <= tp.tv_usec)
2561 			;
2562 		else if (nextsend.tv_sec <= tp.tv_sec)
2563 			;
2564 		else {
2565 			/* The packet is subject to rate limit */
2566 			return 0;
2567 		}
2568 	}
2569 
2570 	*last = tp;
2571 	return 1;
2572 }
2573 #endif
2574 
2575 /*
2576  * Perform rate limit check.
2577  * Returns 0 if it is okay to send the icmp6 packet.
2578  * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2579  * limitation.
2580  *
2581  * There are two limitations defined:
2582  * - pps limit: ICMPv6 error packet cannot exceed defined packet-per-second.
2583  *   we measure it every 0.2 second, since fasttimo works every 0.2 second.
2584  * - rate limit: ICMPv6 error packet cannot appear more than once per
2585  *   defined interval.
2586  * In any case, if we perform rate limitation, we'll see jitter in the ICMPv6
2587  * error packets.
2588  *
2589  * XXX per-destination/type check necessary?
2590  */
2591 static int
2592 icmp6_ratelimit(dst, type, code)
2593 	const struct in6_addr *dst;	/* not used at this moment */
2594 	const int type;			/* not used at this moment */
2595 	const int code;			/* not used at this moment */
2596 {
2597 	int ret;
2598 
2599 	ret = 0;	/*okay to send*/
2600 
2601 	/* PPS limit */
2602 	icmp6errpps_count++;
2603 	if (icmp6errppslim && icmp6errpps_count > icmp6errppslim / 5) {
2604 		/* The packet is subject to pps limit */
2605 		ret++;
2606 	}
2607 
2608 	if (!ratecheck(&icmp6errratelim_last, &icmp6errratelim)) {
2609 		/* The packet is subject to rate limit */
2610 		ret++;
2611 	}
2612 
2613 	return ret;
2614 }
2615