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