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