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