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