icmp6.c revision 1.26
1/*	$NetBSD: icmp6.c,v 1.26 2000/03/01 12:49:44 itojun Exp $	*/
2/*	$KAME: icmp6.c,v 1.71 2000/02/28 09:25:42 jinmei 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_ipsec.h"
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.h>
75#include <sys/protosw.h>
76#include <sys/socket.h>
77#include <sys/socketvar.h>
78#include <sys/time.h>
79#include <sys/kernel.h>
80#include <sys/syslog.h>
81#include <sys/domain.h>
82
83#include <net/if.h>
84#include <net/route.h>
85#include <net/if_dl.h>
86#include <net/if_types.h>
87
88#include <netinet/in.h>
89#include <netinet/in_var.h>
90#include <netinet/ip6.h>
91#include <netinet6/ip6_var.h>
92#include <netinet/icmp6.h>
93#include <netinet6/mld6_var.h>
94#include <netinet6/in6_pcb.h>
95#include <netinet6/nd6.h>
96#include <netinet6/in6_ifattach.h>
97#include <netinet6/ip6protosw.h>
98
99
100#ifdef IPSEC
101#include <netinet6/ipsec.h>
102#include <netkey/key.h>
103#include <netkey/key_debug.h>
104#endif
105
106#include "faith.h"
107
108#include <net/net_osdep.h>
109
110extern struct domain inet6domain;
111
112struct icmp6stat icmp6stat;
113
114extern struct in6pcb rawin6pcb;
115extern struct timeval icmp6errratelim;
116extern int icmp6_nodeinfo;
117static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
118extern int pmtu_expire;
119
120static int icmp6_rip6_input __P((struct mbuf **, int));
121static void icmp6_mtudisc_update __P((struct in6_addr *, struct icmp6_hdr *,
122				      struct mbuf *));
123static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int));
124static const char *icmp6_redirect_diag __P((struct in6_addr *,
125	struct in6_addr *, struct in6_addr *));
126static struct mbuf * ni6_input __P((struct mbuf *, int));
127static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *,
128			  struct ifnet **));
129static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
130				struct ifnet *, int));
131static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *));
132static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
133
134#ifdef COMPAT_RFC1885
135static struct route_in6 icmp6_reflect_rt;
136#endif
137
138void
139icmp6_init()
140{
141	mld6_init();
142	icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire);
143}
144
145/*
146 * Generate an error packet of type error in response to bad IP6 packet.
147 */
148void
149icmp6_error(m, type, code, param)
150	struct mbuf *m;
151	int type, code, param;
152{
153	struct ip6_hdr *oip6, *nip6;
154	struct icmp6_hdr *icmp6;
155	u_int preplen;
156	int off;
157	u_char nxt;
158
159	icmp6stat.icp6s_error++;
160
161	if (m->m_flags & M_DECRYPTED) {
162		icmp6stat.icp6s_canterror++;
163		goto freeit;
164	}
165
166#ifndef PULLDOWN_TEST
167	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );
168#else
169	if (m->m_len < sizeof(struct ip6_hdr)) {
170		m = m_pullup(m, sizeof(struct ip6_hdr));
171		if (m == NULL)
172			return;
173	}
174#endif
175	oip6 = mtod(m, struct ip6_hdr *);
176
177	/*
178	 * Multicast destination check. For unrecognized option errors,
179	 * this check has already done in ip6_unknown_opt(), so we can
180	 * check only for other errors.
181	 */
182	if ((m->m_flags & (M_BCAST|M_MCAST) ||
183	     IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
184	    (type != ICMP6_PACKET_TOO_BIG &&
185	     (type != ICMP6_PARAM_PROB ||
186	      code != ICMP6_PARAMPROB_OPTION)))
187		goto freeit;
188
189	/* Source address check. XXX: the case of anycast source? */
190	if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
191	    IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
192		goto freeit;
193
194	/*
195	 * If the erroneous packet is also an ICMP error, discard it.
196	 */
197	off = sizeof(struct ip6_hdr);
198	nxt = oip6->ip6_nxt;
199	while (1) {		/* XXX: should avoid inf. loop explicitly? */
200		struct ip6_ext *ip6e;
201		struct icmp6_hdr *icp;
202
203		switch(nxt) {
204		case IPPROTO_IPV6:
205		case IPPROTO_IPV4:
206		case IPPROTO_UDP:
207		case IPPROTO_TCP:
208		case IPPROTO_ESP:
209		case IPPROTO_IPCOMP:
210		case IPPROTO_FRAGMENT:
211			/*
212			 * ICMPv6 error must not be fragmented.
213			 * XXX: but can we trust the sender?
214			 */
215		default:
216			/* What if unknown header followed by ICMP error? */
217			goto generate;
218		case IPPROTO_ICMPV6:
219#ifndef PULLDOWN_TEST
220			IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), );
221			icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
222#else
223			IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
224				sizeof(*icp));
225			if (icp == NULL) {
226				icmp6stat.icp6s_tooshort++;
227				return;
228			}
229#endif
230			if (icp->icmp6_type < ICMP6_ECHO_REQUEST
231			 || icp->icmp6_type == ND_REDIRECT) {
232				/*
233				 * ICMPv6 error
234				 * Special case: for redirect (which is
235				 * informational) we must not send icmp6 error.
236				 */
237				icmp6stat.icp6s_canterror++;
238				goto freeit;
239			} else {
240				/* ICMPv6 informational */
241				goto generate;
242			}
243		case IPPROTO_HOPOPTS:
244		case IPPROTO_DSTOPTS:
245		case IPPROTO_ROUTING:
246		case IPPROTO_AH:
247#ifndef PULLDOWN_TEST
248			IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct ip6_ext), );
249			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
250#else
251			IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
252				sizeof(*ip6e));
253			if (ip6e == NULL) {
254				/*XXX stat */
255				return;
256			}
257#endif
258			if (nxt == IPPROTO_AH)
259				off += (ip6e->ip6e_len + 2) << 2;
260			else
261				off += (ip6e->ip6e_len + 1) << 3;
262			nxt = ip6e->ip6e_nxt;
263			break;
264		}
265	}
266
267  freeit:
268	/*
269	 * If we can't tell wheter or not we can generate ICMP6, free it.
270	 */
271	m_freem(m);
272	return;
273
274  generate:
275	oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
276
277	/* Finally, do rate limitation check. */
278	if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
279		icmp6stat.icp6s_toofreq++;
280		goto freeit;
281	}
282
283	/*
284	 * OK, ICMP6 can be generated.
285	 */
286
287	if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
288		m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
289
290	preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
291	M_PREPEND(m, preplen, M_DONTWAIT);
292	if (m && m->m_len < preplen)
293		m = m_pullup(m, preplen);
294	if (m == NULL) {
295		printf("ENOBUFS in icmp6_error %d\n", __LINE__);
296		return;
297	}
298
299	nip6 = mtod(m, struct ip6_hdr *);
300	nip6->ip6_src  = oip6->ip6_src;
301	nip6->ip6_dst  = oip6->ip6_dst;
302
303	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
304		oip6->ip6_src.s6_addr16[1] = 0;
305	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
306		oip6->ip6_dst.s6_addr16[1] = 0;
307
308	icmp6 = (struct icmp6_hdr *)(nip6 + 1);
309	icmp6->icmp6_type = type;
310	icmp6->icmp6_code = code;
311	icmp6->icmp6_pptr = htonl((u_int32_t)param);
312
313	icmp6stat.icp6s_outhist[type]++;
314	icmp6_reflect(m, sizeof(struct ip6_hdr)); /*header order: IPv6 - ICMPv6*/
315}
316
317/*
318 * Process a received ICMP6 message.
319 */
320int
321icmp6_input(mp, offp, proto)
322	struct mbuf **mp;
323	int *offp, proto;
324{
325	struct mbuf *m = *mp, *n;
326	struct ip6_hdr *ip6, *nip6;
327	struct icmp6_hdr *icmp6, *nicmp6;
328	int off = *offp;
329	int icmp6len = m->m_pkthdr.len - *offp;
330	int code, sum, noff;
331	struct sockaddr_in6 icmp6src;
332
333#ifndef PULLDOWN_TEST
334	IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE);
335	/* m might change if M_LOOP. So, call mtod after this */
336#endif
337
338	/*
339	 * Locate icmp6 structure in mbuf, and check
340	 * that not corrupted and of at least minimum length
341	 */
342
343	ip6 = mtod(m, struct ip6_hdr *);
344	if (icmp6len < sizeof(struct icmp6_hdr)) {
345		icmp6stat.icp6s_tooshort++;
346		goto freeit;
347	}
348
349	/*
350	 * calculate the checksum
351	 */
352#ifndef PULLDOWN_TEST
353	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
354#else
355	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
356	if (icmp6 == NULL) {
357		icmp6stat.icp6s_tooshort++;
358		return IPPROTO_DONE;
359	}
360#endif
361	code = icmp6->icmp6_code;
362
363	if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
364		log(LOG_ERR,
365		    "ICMP6 checksum error(%d|%x) %s\n",
366		    icmp6->icmp6_type,
367		    sum,
368		    ip6_sprintf(&ip6->ip6_src));
369		icmp6stat.icp6s_checksum++;
370		goto freeit;
371	}
372
373#if defined(NFAITH) && 0 < NFAITH
374	if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
375		/*
376		 * Deliver very specific ICMP6 type only.
377		 * This is important to deilver TOOBIG.  Otherwise PMTUD
378		 * will not work.
379		 */
380		switch (icmp6->icmp6_type) {
381		case ICMP6_DST_UNREACH:
382		case ICMP6_PACKET_TOO_BIG:
383		case ICMP6_TIME_EXCEEDED:
384			break;
385		default:
386			goto freeit;
387		}
388	}
389#endif
390
391#ifdef IPSEC
392	/* drop it if it does not match the default policy */
393	if (ipsec6_in_reject(m, NULL)) {
394		ipsecstat.in_polvio++;
395		goto freeit;
396	}
397#endif
398
399	icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
400	icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
401	if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
402		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
403
404	switch (icmp6->icmp6_type) {
405
406	case ICMP6_DST_UNREACH:
407		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
408		switch (code) {
409		case ICMP6_DST_UNREACH_NOROUTE:
410			code = PRC_UNREACH_NET;
411			break;
412		case ICMP6_DST_UNREACH_ADMIN:
413			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib);
414			code = PRC_UNREACH_PROTOCOL; /* is this a good code? */
415			break;
416		case ICMP6_DST_UNREACH_ADDR:
417			code = PRC_HOSTDEAD;
418			break;
419#ifdef COMPAT_RFC1885
420		case ICMP6_DST_UNREACH_NOTNEIGHBOR:
421			code = PRC_UNREACH_SRCFAIL;
422			break;
423#else
424		case ICMP6_DST_UNREACH_BEYONDSCOPE:
425			/* I mean "source address was incorrect." */
426			code = PRC_PARAMPROB;
427			break;
428#endif
429		case ICMP6_DST_UNREACH_NOPORT:
430			code = PRC_UNREACH_PORT;
431			break;
432		default:
433			goto badcode;
434		}
435		goto deliver;
436		break;
437
438	case ICMP6_PACKET_TOO_BIG:
439		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
440		if (code != 0)
441			goto badcode;
442
443		code = PRC_MSGSIZE;
444
445		/*
446		 * Updating the path MTU will be done after examining
447		 * intermediate extension headers.
448		 */
449		goto deliver;
450		break;
451
452	case ICMP6_TIME_EXCEEDED:
453		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
454		switch (code) {
455		case ICMP6_TIME_EXCEED_TRANSIT:
456		case ICMP6_TIME_EXCEED_REASSEMBLY:
457			code += PRC_TIMXCEED_INTRANS;
458			break;
459		default:
460			goto badcode;
461		}
462		goto deliver;
463		break;
464
465	case ICMP6_PARAM_PROB:
466		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob);
467		switch (code) {
468		case ICMP6_PARAMPROB_NEXTHEADER:
469			code = PRC_UNREACH_PROTOCOL;
470			break;
471		case ICMP6_PARAMPROB_HEADER:
472		case ICMP6_PARAMPROB_OPTION:
473			code = PRC_PARAMPROB;
474			break;
475		default:
476			goto badcode;
477		}
478		goto deliver;
479		break;
480
481	case ICMP6_ECHO_REQUEST:
482		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo);
483		if (code != 0)
484			goto badcode;
485		if ((n = m_copy(m, 0, M_COPYALL)) == NULL) {
486			/* Give up remote */
487			break;
488		}
489		if ((n->m_flags & M_EXT) != 0
490		 || n->m_len < off + sizeof(struct icmp6_hdr)) {
491			struct mbuf *n0 = n;
492			const int maxlen = sizeof(*nip6) + sizeof(*nicmp6);
493
494			/*
495			 * Prepare an internal mbuf. m_pullup() doesn't
496			 * always copy the length we specified.
497			 */
498			if (maxlen >= MCLBYTES) {
499#ifdef DIAGNOSTIC
500				printf("MCLBYTES too small\n");
501#endif
502				/* Give up remote */
503				m_freem(n0);
504				break;
505			}
506			MGETHDR(n, M_DONTWAIT, n0->m_type);
507			if (n && maxlen >= MHLEN) {
508				MCLGET(n, M_DONTWAIT);
509				if ((n->m_flags & M_EXT) == 0) {
510					m_free(n);
511					n = NULL;
512				}
513			}
514			if (n == NULL) {
515				/* Give up remote */
516				m_freem(n0);
517				break;
518			}
519			M_COPY_PKTHDR(n, n0);
520			/*
521			 * Copy IPv6 and ICMPv6 only.
522			 */
523			nip6 = mtod(n, struct ip6_hdr *);
524			bcopy(ip6, nip6, sizeof(struct ip6_hdr));
525			nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
526			bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
527			noff = sizeof(struct ip6_hdr);
528			n->m_pkthdr.len = n->m_len =
529				noff + sizeof(struct icmp6_hdr);
530			/*
531			 * Adjust mbuf. ip6_plen will be adjusted in
532			 * ip6_output().
533			 */
534			m_adj(n0, off + sizeof(struct icmp6_hdr));
535			n->m_pkthdr.len += n0->m_pkthdr.len;
536			n->m_next = n0;
537			n0->m_flags &= ~M_PKTHDR;
538		} else {
539			nip6 = mtod(n, struct ip6_hdr *);
540			nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off);
541			noff = off;
542		}
543		nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
544		nicmp6->icmp6_code = 0;
545		if (n) {
546			icmp6stat.icp6s_reflect++;
547			icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
548			icmp6_reflect(n, noff);
549		}
550		break;
551
552	case ICMP6_ECHO_REPLY:
553		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
554		if (code != 0)
555			goto badcode;
556		break;
557
558	case MLD6_LISTENER_QUERY:
559	case MLD6_LISTENER_REPORT:
560		if (icmp6len < sizeof(struct mld6_hdr))
561			goto badlen;
562		if (icmp6->icmp6_type == MLD6_LISTENER_QUERY) /* XXX: ugly... */
563			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery);
564		else
565			icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport);
566		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
567			/* give up local */
568			mld6_input(m, off);
569			m = NULL;
570			goto freeit;
571		}
572		mld6_input(n, off);
573		/* m stays. */
574		break;
575
576	case MLD6_LISTENER_DONE:
577		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone);
578		if (icmp6len < sizeof(struct mld6_hdr))	/* necessary? */
579			goto badlen;
580		break;		/* nothing to be done in kernel */
581
582	case MLD6_MTRACE_RESP:
583	case MLD6_MTRACE:
584		/* XXX: these two are experimental. not officially defind. */
585		/* XXX: per-interface statistics? */
586		break;		/* just pass it to applications */
587
588	case ICMP6_WRUREQUEST:	/* ICMP6_FQDN_QUERY */
589	    {
590		enum { WRU, FQDN } mode;
591
592		if (code != 0)
593			goto badcode;
594		if (!icmp6_nodeinfo)
595			break;
596
597		if (icmp6len == sizeof(struct icmp6_hdr) + 4)
598			mode = WRU;
599		else if (icmp6len >= sizeof(struct icmp6_hdr) + 8) /* XXX */
600			mode = FQDN;
601		else
602			goto badlen;
603
604		if (mode == FQDN) {
605#ifndef PULLDOWN_TEST
606			IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo),
607					 IPPROTO_DONE);
608#endif
609			n = m_copy(m, 0, M_COPYALL);
610			if (n)
611				n = ni6_input(n, off);
612			if (n)
613				noff = sizeof(struct ip6_hdr);
614		} else {
615			u_char *p;
616			int maxlen, maxhlen;
617
618			maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4;
619			if (maxlen >= MCLBYTES) {
620#ifdef DIAGNOSTIC
621				printf("MCLBYTES too small\n");
622#endif
623				/* Give up remote */
624				break;
625			}
626			MGETHDR(n, M_DONTWAIT, m->m_type);
627			if (n && maxlen > MHLEN) {
628				MCLGET(n, M_DONTWAIT);
629				if ((n->m_flags & M_EXT) == 0) {
630					m_free(n);
631					n = NULL;
632				}
633			}
634			if (n == NULL) {
635				/* Give up remote */
636				break;
637			}
638			n->m_len = 0;
639			maxhlen = M_TRAILINGSPACE(n) - maxlen;
640			if (maxhlen > hostnamelen)
641				maxhlen = hostnamelen;
642			/*
643			 * Copy IPv6 and ICMPv6 only.
644			 */
645			nip6 = mtod(n, struct ip6_hdr *);
646			bcopy(ip6, nip6, sizeof(struct ip6_hdr));
647			nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
648			bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
649			p = (u_char *)(nicmp6 + 1);
650			bzero(p, 4);
651			bcopy(hostname, p + 4, maxhlen);
652			noff = sizeof(struct ip6_hdr);
653			M_COPY_PKTHDR(n, m); /* just for recvif */
654			n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
655				sizeof(struct icmp6_hdr) + 4 + maxhlen;
656			nicmp6->icmp6_type = ICMP6_WRUREPLY;
657			nicmp6->icmp6_code = 0;
658		}
659#undef hostnamelen
660		if (n) {
661			icmp6stat.icp6s_reflect++;
662			icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
663			icmp6_reflect(n, noff);
664		}
665		break;
666	    }
667
668	case ICMP6_WRUREPLY:
669		if (code != 0)
670			goto badcode;
671		break;
672
673	case ND_ROUTER_SOLICIT:
674		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit);
675		if (code != 0)
676			goto badcode;
677		if (icmp6len < sizeof(struct nd_router_solicit))
678			goto badlen;
679		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
680			/* give up local */
681			nd6_rs_input(m, off, icmp6len);
682			m = NULL;
683			goto freeit;
684		}
685		nd6_rs_input(n, off, icmp6len);
686		/* m stays. */
687		break;
688
689	case ND_ROUTER_ADVERT:
690		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert);
691		if (code != 0)
692			goto badcode;
693		if (icmp6len < sizeof(struct nd_router_advert))
694			goto badlen;
695		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
696			/* give up local */
697			nd6_ra_input(m, off, icmp6len);
698			m = NULL;
699			goto freeit;
700		}
701		nd6_ra_input(n, off, icmp6len);
702		/* m stays. */
703		break;
704
705	case ND_NEIGHBOR_SOLICIT:
706		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit);
707		if (code != 0)
708			goto badcode;
709		if (icmp6len < sizeof(struct nd_neighbor_solicit))
710			goto badlen;
711		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
712			/* give up local */
713			nd6_ns_input(m, off, icmp6len);
714			m = NULL;
715			goto freeit;
716		}
717		nd6_ns_input(n, off, icmp6len);
718		/* m stays. */
719		break;
720
721	case ND_NEIGHBOR_ADVERT:
722		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert);
723		if (code != 0)
724			goto badcode;
725		if (icmp6len < sizeof(struct nd_neighbor_advert))
726			goto badlen;
727		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
728			/* give up local */
729			nd6_na_input(m, off, icmp6len);
730			m = NULL;
731			goto freeit;
732		}
733		nd6_na_input(n, off, icmp6len);
734		/* m stays. */
735		break;
736
737	case ND_REDIRECT:
738		icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect);
739		if (code != 0)
740			goto badcode;
741		if (icmp6len < sizeof(struct nd_redirect))
742			goto badlen;
743		if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
744			/* give up local */
745			icmp6_redirect_input(m, off);
746			m = NULL;
747			goto freeit;
748		}
749		icmp6_redirect_input(n, off);
750		/* m stays. */
751		break;
752
753	case ICMP6_ROUTER_RENUMBERING:
754		if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
755		    code != ICMP6_ROUTER_RENUMBERING_RESULT)
756			goto badcode;
757		if (icmp6len < sizeof(struct icmp6_router_renum))
758			goto badlen;
759		break;
760
761	default:
762		printf("icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
763		       icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
764		       ip6_sprintf(&ip6->ip6_dst),
765		       m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0);
766		if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
767			/* ICMPv6 error: MUST deliver it by spec... */
768			code = PRC_NCMDS;
769			/* deliver */
770		} else {
771			/* ICMPv6 informational: MUST not deliver */
772			break;
773		}
774	deliver:
775		if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
776			icmp6stat.icp6s_tooshort++;
777			goto freeit;
778		}
779#ifndef PULLDOWN_TEST
780		IP6_EXTHDR_CHECK(m, off,
781			sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr),
782			IPPROTO_DONE);
783		icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
784#else
785		IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
786			sizeof(*icmp6) + sizeof(struct ip6_hdr));
787		if (icmp6 == NULL) {
788			icmp6stat.icp6s_tooshort++;
789			return IPPROTO_DONE;
790		}
791#endif
792		bzero(&icmp6src, sizeof(icmp6src));
793		icmp6src.sin6_len = sizeof(struct sockaddr_in6);
794		icmp6src.sin6_family = AF_INET6;
795		icmp6src.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
796
797		/* Detect the upper level protocol */
798	    {
799		void (*ctlfunc) __P((int, struct sockaddr *, void *));
800		struct ip6_hdr *eip6 = (struct ip6_hdr *)(icmp6 + 1);
801		u_int8_t nxt = eip6->ip6_nxt;
802		int eoff = off + sizeof(struct icmp6_hdr) +
803			sizeof(struct ip6_hdr);
804		struct ip6ctlparam ip6cp;
805		struct in6_addr *finaldst = NULL;
806		int icmp6type = icmp6->icmp6_type;
807		struct ip6_frag *fh;
808		struct ip6_rthdr *rth;
809		struct ip6_rthdr0 *rth0;
810		int rthlen;
811
812		while (1) { /* XXX: should avoid inf. loop explicitly? */
813			struct ip6_ext *eh;
814
815			switch(nxt) {
816			case IPPROTO_HOPOPTS:
817			case IPPROTO_DSTOPTS:
818			case IPPROTO_AH:
819#ifndef PULLDOWN_TEST
820				IP6_EXTHDR_CHECK(m, 0, eoff +
821						 sizeof(struct ip6_ext),
822						 IPPROTO_DONE);
823				eh = (struct ip6_ext *)(mtod(m, caddr_t)
824							+ eoff);
825#else
826				IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
827					eoff, sizeof(*eh));
828				if (eh == NULL) {
829					icmp6stat.icp6s_tooshort++;
830					return IPPROTO_DONE;
831				}
832#endif
833
834				if (nxt == IPPROTO_AH)
835					eoff += (eh->ip6e_len + 2) << 2;
836				else
837					eoff += (eh->ip6e_len + 1) << 3;
838				nxt = eh->ip6e_nxt;
839				break;
840			case IPPROTO_ROUTING:
841				/*
842				 * When the erroneous packet contains a
843				 * routing header, we should examine the
844				 * header to determine the final destination.
845				 * Otherwise, we can't properly update
846				 * information that depends on the final
847				 * destination (e.g. path MTU).
848				 */
849#ifndef PULLDOWN_TEST
850				IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth),
851						 IPPROTO_DONE);
852				rth = (struct ip6_rthdr *)(mtod(m, caddr_t)
853							   + eoff);
854#else
855				IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
856					eoff, sizeof(*rth));
857				if (rth == NULL) {
858					icmp6stat.icp6s_tooshort++;
859					return IPPROTO_DONE;
860				}
861#endif
862				rthlen = (rth->ip6r_len + 1) << 3;
863				/*
864				 * XXX: currently there is no
865				 * officially defined type other
866				 * than type-0.
867				 * Note that if the segment left field
868				 * is 0, all intermediate hops must
869				 * have been passed.
870				 */
871				if (rth->ip6r_segleft &&
872				    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
873					int hops;
874
875#ifndef PULLDOWN_TEST
876					IP6_EXTHDR_CHECK(m, 0, eoff + rthlen,
877							 IPPROTO_DONE);
878					rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff);
879#else
880					IP6_EXTHDR_GET(rth0,
881						       struct ip6_rthdr0 *, m,
882						       eoff, rthlen);
883					if (rth0 == NULL) {
884						icmp6stat.icp6s_tooshort++;
885						return IPPROTO_DONE;
886					}
887#endif
888					/* just ignore a bogus header */
889					if ((rth0->ip6r0_len % 2) == 0 &&
890					    (hops = rth0->ip6r0_len/2))
891						finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
892				}
893				eoff += rthlen;
894				nxt = rth->ip6r_nxt;
895				break;
896			case IPPROTO_FRAGMENT:
897#ifndef PULLDOWN_TEST
898				IP6_EXTHDR_CHECK(m, 0, eoff +
899						 sizeof(struct ip6_frag),
900						 IPPROTO_DONE);
901				fh = (struct ip6_frag *)(mtod(m, caddr_t)
902							 + eoff);
903#else
904				IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
905					eoff, sizeof(*fh));
906				if (fh == NULL) {
907					icmp6stat.icp6s_tooshort++;
908					return IPPROTO_DONE;
909				}
910#endif
911				/*
912				 * Data after a fragment header is meaningless
913				 * unless it is the first fragment, but
914				 * we'll go to the notify label for path MTU
915				 * discovery.
916				 */
917				if (fh->ip6f_offlg & IP6F_OFF_MASK)
918					goto notify;
919
920				eoff += sizeof(struct ip6_frag);
921				nxt = fh->ip6f_nxt;
922				break;
923			default:
924				/*
925				 * This case includes ESP and the No Next
926				 * Header. In such cases going to the notify
927				 * label does not have any meaning
928				 * (i.e. ctlfunc will be NULL), but we go
929				 * anyway since we might have to update
930				 * path MTU information.
931				 */
932				goto notify;
933			}
934		}
935	    notify:
936#ifndef PULLDOWN_TEST
937		icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
938#else
939		IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
940			sizeof(*icmp6) + sizeof(struct ip6_hdr));
941		if (icmp6 == NULL) {
942			icmp6stat.icp6s_tooshort++;
943			return IPPROTO_DONE;
944		}
945#endif
946		if (icmp6type == ICMP6_PACKET_TOO_BIG) {
947			if (finaldst == NULL)
948				finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
949			icmp6_mtudisc_update(finaldst, icmp6, m);
950		}
951
952		ctlfunc = (void (*) __P((int, struct sockaddr *, void *)))
953			(inet6sw[ip6_protox[nxt]].pr_ctlinput);
954		if (ctlfunc) {
955			ip6cp.ip6c_m = m;
956			ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
957			ip6cp.ip6c_off = eoff;
958			(*ctlfunc)(code, (struct sockaddr *)&icmp6src, &ip6cp);
959		}
960	    }
961		break;
962
963	badcode:
964		icmp6stat.icp6s_badcode++;
965		break;
966
967	badlen:
968		icmp6stat.icp6s_badlen++;
969		break;
970	}
971
972	icmp6_rip6_input(&m, *offp);
973	return IPPROTO_DONE;
974
975 freeit:
976	m_freem(m);
977	return IPPROTO_DONE;
978}
979
980static void
981icmp6_mtudisc_update(dst, icmp6, m)
982	struct in6_addr *dst;
983	struct icmp6_hdr *icmp6;/* we can assume the validity of the pointer */
984	struct mbuf *m;	/* currently unused but added for scoped addrs */
985{
986	u_int mtu = ntohl(icmp6->icmp6_mtu);
987	struct rtentry *rt = NULL;
988	struct sockaddr_in6 sin6;
989
990	bzero(&sin6, sizeof(sin6));
991	sin6.sin6_family = PF_INET6;
992	sin6.sin6_len = sizeof(struct sockaddr_in6);
993	sin6.sin6_addr = *dst;
994	/* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */
995	rt = rtalloc1((struct sockaddr *)&sin6, 1);	/*clone*/
996	if (!rt || (rt->rt_flags & RTF_HOST) == 0) {
997		if (rt)
998			RTFREE(rt);
999		rt = icmp6_mtudisc_clone((struct sockaddr *)&sin6);
1000	}
1001
1002	if (rt && (rt->rt_flags & RTF_HOST)
1003	    && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
1004		if (mtu < IPV6_MMTU) {
1005				/* xxx */
1006			rt->rt_rmx.rmx_locks |= RTV_MTU;
1007		} else if (mtu < rt->rt_ifp->if_mtu &&
1008			   rt->rt_rmx.rmx_mtu > mtu) {
1009			rt->rt_rmx.rmx_mtu = mtu;
1010		}
1011	}
1012	if (rt)
1013		RTFREE(rt);
1014}
1015
1016/*
1017 * Process a Node Information Query
1018 */
1019#ifndef offsetof		/* XXX */
1020#define	offsetof(type, member)	((size_t)(&((type *)0)->member))
1021#endif
1022
1023static struct mbuf *
1024ni6_input(m, off)
1025	struct mbuf *m;
1026	int off;
1027{
1028	struct icmp6_nodeinfo *ni6, *nni6;
1029	struct mbuf *n = NULL;
1030	u_int16_t qtype;
1031	int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1032	struct ni_reply_fqdn *fqdn;
1033	int addrs;		/* for NI_QTYPE_NODEADDR */
1034	struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1035
1036#ifndef PULLDOWN_TEST
1037	ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1038#else
1039	IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
1040	if (ni6 == NULL) {
1041		/* m is already reclaimed */
1042		return NULL;
1043	}
1044#endif
1045	qtype = ntohs(ni6->ni_qtype);
1046
1047	switch(qtype) {
1048	 case NI_QTYPE_NOOP:
1049		 break;		/* no reply data */
1050	 case NI_QTYPE_SUPTYPES:
1051		 goto bad;	/* xxx: to be implemented */
1052		 break;
1053	 case NI_QTYPE_FQDN:
1054		 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) +
1055			 hostnamelen;
1056		 break;
1057	 case NI_QTYPE_NODEADDR:
1058		 addrs = ni6_addrs(ni6, m, &ifp);
1059		 if ((replylen += addrs * sizeof(struct in6_addr)) > MCLBYTES)
1060			 replylen = MCLBYTES; /* XXX: we'll truncate later */
1061
1062		 break;
1063	 default:
1064		 /*
1065		  * XXX: We must return a reply with the ICMP6 code
1066		  * `unknown Qtype' in this case. However we regard the case
1067		  * as an FQDN query for backward compatibility.
1068		  * Older versions set a random value to this field,
1069		  * so it rarely varies in the defined qtypes.
1070		  * But the mechanism is not reliable...
1071		  * maybe we should obsolete older versions.
1072		  */
1073		 qtype = NI_QTYPE_FQDN;
1074		 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) +
1075			 hostnamelen;
1076		 break;
1077	}
1078
1079	/* allocate a mbuf to reply. */
1080	MGETHDR(n, M_DONTWAIT, m->m_type);
1081	if (n == NULL) {
1082		m_freem(m);
1083		return(NULL);
1084	}
1085	M_COPY_PKTHDR(n, m); /* just for recvif */
1086	if (replylen > MHLEN) {
1087		if (replylen > MCLBYTES)
1088			 /*
1089			  * XXX: should we try to allocate more? But MCLBYTES is
1090			  * probably much larger than IPV6_MMTU...
1091			  */
1092			goto bad;
1093		MCLGET(n, M_DONTWAIT);
1094		if ((n->m_flags & M_EXT) == 0) {
1095			goto bad;
1096		}
1097	}
1098	n->m_pkthdr.len = n->m_len = replylen;
1099
1100	/* copy mbuf header and IPv6 + Node Information base headers */
1101	bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1102	nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1103	bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1104
1105	/* qtype dependent procedure */
1106	switch (qtype) {
1107	 case NI_QTYPE_NOOP:
1108		 nni6->ni_flags = 0;
1109		 break;
1110	 case NI_QTYPE_SUPTYPES:
1111		 goto bad;	/* xxx: to be implemented */
1112		 break;
1113	 case NI_QTYPE_FQDN:
1114		 if (hostnamelen > 255) { /* XXX: rare case, but may happen */
1115			 printf("ni6_input: "
1116				"hostname length(%d) is too large for reply\n",
1117				hostnamelen);
1118			 goto bad;
1119		 }
1120		 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1121						 sizeof(struct ip6_hdr) +
1122						 sizeof(struct icmp6_nodeinfo));
1123		 nni6->ni_flags = 0; /* XXX: meaningless TTL */
1124		 fqdn->ni_fqdn_ttl = 0;	/* ditto. */
1125		 fqdn->ni_fqdn_namelen = hostnamelen;
1126		 bcopy(hostname, &fqdn->ni_fqdn_name[0], hostnamelen);
1127		 break;
1128	 case NI_QTYPE_NODEADDR:
1129	 {
1130		 int lenlim, copied;
1131
1132		 if (n->m_flags & M_EXT)
1133			 lenlim = MCLBYTES - sizeof(struct ip6_hdr) -
1134				 sizeof(struct icmp6_nodeinfo);
1135		 else
1136			 lenlim = MHLEN - sizeof(struct ip6_hdr) -
1137				 sizeof(struct icmp6_nodeinfo);
1138		 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1139		 /* XXX: reset mbuf length */
1140		 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1141			 sizeof(struct icmp6_nodeinfo) + copied;
1142		 break;
1143	 }
1144	 default:
1145		 break;		/* XXX impossible! */
1146	}
1147
1148	nni6->ni_type = ICMP6_NI_REPLY;
1149	nni6->ni_code = ICMP6_NI_SUCESS;
1150	m_freem(m);
1151	return(n);
1152
1153  bad:
1154	m_freem(m);
1155	if (n)
1156		m_freem(n);
1157	return(NULL);
1158}
1159#undef hostnamelen
1160
1161/*
1162 * calculate the number of addresses to be returned in the node info reply.
1163 */
1164static int
1165ni6_addrs(ni6, m, ifpp)
1166	struct icmp6_nodeinfo *ni6;
1167	struct mbuf *m;
1168	struct ifnet **ifpp;
1169{
1170	register struct ifnet *ifp;
1171	register struct in6_ifaddr *ifa6;
1172	register struct ifaddr *ifa;
1173	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1174	int addrs = 0, addrsofif, iffound = 0;
1175
1176	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1177	{
1178		addrsofif = 0;
1179		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1180		     ifa = ifa->ifa_list.tqe_next)
1181		{
1182			if (ifa->ifa_addr->sa_family != AF_INET6)
1183				continue;
1184			ifa6 = (struct in6_ifaddr *)ifa;
1185
1186			if (!(ni6->ni_flags & NI_NODEADDR_FLAG_ALL) &&
1187			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1188					       &ifa6->ia_addr.sin6_addr))
1189				iffound = 1;
1190
1191			/*
1192			 * IPv4-mapped addresses can only be returned by a
1193			 * Node Information proxy, since they represent
1194			 * addresses of IPv4-only nodes, which perforce do
1195			 * not implement this protocol.
1196			 * [icmp-name-lookups-05]
1197			 * So we don't support NI_NODEADDR_FLAG_COMPAT in
1198			 * this function at this moment.
1199			 */
1200
1201			if (ifa6->ia6_flags & IN6_IFF_ANYCAST)
1202				continue; /* we need only unicast addresses */
1203
1204			if ((ni6->ni_flags & (NI_NODEADDR_FLAG_LINKLOCAL |
1205					      NI_NODEADDR_FLAG_SITELOCAL |
1206					      NI_NODEADDR_FLAG_GLOBAL)) == 0)
1207				continue;
1208
1209			/* What do we have to do about ::1? */
1210			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1211			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1212				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1213					addrsofif++;
1214				break;
1215			 case IPV6_ADDR_SCOPE_SITELOCAL:
1216				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1217					addrsofif++;
1218				break;
1219			 case IPV6_ADDR_SCOPE_GLOBAL:
1220				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1221					 addrsofif++;
1222				 break;
1223			 default:
1224				 continue;
1225			}
1226		}
1227		if (iffound) {
1228			*ifpp = ifp;
1229			return(addrsofif);
1230		}
1231
1232		addrs += addrsofif;
1233	}
1234
1235	return(addrs);
1236}
1237
1238static int
1239ni6_store_addrs(ni6, nni6, ifp0, resid)
1240	struct icmp6_nodeinfo *ni6, *nni6;
1241	struct ifnet *ifp0;
1242	int resid;
1243{
1244	register struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
1245	register struct in6_ifaddr *ifa6;
1246	register struct ifaddr *ifa;
1247	int docopy, copied = 0;
1248	u_char *cp = (u_char *)(nni6 + 1);
1249
1250	if (ifp0 == NULL && !(ni6->ni_flags & NI_NODEADDR_FLAG_ALL))
1251		return(0);	/* needless to copy */
1252
1253	for (; ifp; ifp = TAILQ_NEXT(ifp, if_list))
1254	{
1255		for (ifa = ifp->if_addrlist.tqh_first; ifa;
1256		     ifa = ifa->ifa_list.tqe_next)
1257		{
1258			docopy = 0;
1259
1260			if (ifa->ifa_addr->sa_family != AF_INET6)
1261				continue;
1262			ifa6 = (struct in6_ifaddr *)ifa;
1263
1264			if (ifa6->ia6_flags & IN6_IFF_ANYCAST) {
1265				/* just experimental. not in the spec. */
1266				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1267					docopy = 1;
1268				else
1269					continue;
1270			}
1271			else {	/* unicast address */
1272				if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST)
1273					continue;
1274				else
1275					docopy = 1;
1276			}
1277
1278			/* What do we have to do about ::1? */
1279			switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1280			 case IPV6_ADDR_SCOPE_LINKLOCAL:
1281				if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL)
1282					docopy = 1;
1283				break;
1284			 case IPV6_ADDR_SCOPE_SITELOCAL:
1285				if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL)
1286					docopy = 1;
1287				break;
1288			 case IPV6_ADDR_SCOPE_GLOBAL:
1289				 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL)
1290					 docopy = 1;
1291				 break;
1292			 default:
1293				 continue;
1294			}
1295
1296			if (docopy) {
1297				if (resid < sizeof(struct in6_addr)) {
1298					/*
1299					 * We give up much more copy.
1300					 * Set the truncate flag and return.
1301					 */
1302					nni6->ni_flags |=
1303						NI_NODEADDR_FLAG_TRUNCATE;
1304					return(copied);
1305				}
1306				bcopy(&ifa6->ia_addr.sin6_addr, cp,
1307				      sizeof(struct in6_addr));
1308				/* XXX: KAME link-local hack; remove ifindex */
1309				if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))
1310					((struct in6_addr *)cp)->s6_addr16[1] = 0;
1311				cp += sizeof(struct in6_addr);
1312				resid -= sizeof(struct in6_addr);
1313				copied += sizeof(struct in6_addr);
1314			}
1315		}
1316		if (ifp0)	/* we need search only on the specified IF */
1317			break;
1318	}
1319
1320	return(copied);
1321}
1322
1323/*
1324 * XXX almost dup'ed code with rip6_input.
1325 */
1326static int
1327icmp6_rip6_input(mp, off)
1328	struct	mbuf **mp;
1329	int	off;
1330{
1331	struct mbuf *m = *mp;
1332	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1333	register struct in6pcb *in6p;
1334	struct in6pcb *last = NULL;
1335	struct sockaddr_in6 rip6src;
1336	struct icmp6_hdr *icmp6;
1337	struct mbuf *opts = NULL;
1338
1339#ifndef PULLDOWN_TEST
1340	/* this is assumed to be safe. */
1341	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
1342#else
1343	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
1344	if (icmp6 == NULL) {
1345		/* m is already reclaimed */
1346		return IPPROTO_DONE;
1347	}
1348#endif
1349
1350	bzero(&rip6src, sizeof(rip6src));
1351	rip6src.sin6_len = sizeof(struct sockaddr_in6);
1352	rip6src.sin6_family = AF_INET6;
1353	rip6src.sin6_addr = ip6->ip6_src;
1354	if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr))
1355		rip6src.sin6_addr.s6_addr16[1] = 0;
1356	if (m->m_pkthdr.rcvif) {
1357		if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr))
1358			rip6src.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
1359		else
1360			rip6src.sin6_scope_id = 0;
1361	} else
1362		rip6src.sin6_scope_id = 0;
1363
1364	for (in6p = rawin6pcb.in6p_next;
1365	     in6p != &rawin6pcb; in6p = in6p->in6p_next)
1366	{
1367		if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
1368			continue;
1369		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1370		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1371			continue;
1372		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1373		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
1374			continue;
1375		if (in6p->in6p_icmp6filt
1376		    && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1377				 in6p->in6p_icmp6filt))
1378			continue;
1379		if (last) {
1380			struct	mbuf *n;
1381			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1382				if (last->in6p_flags & IN6P_CONTROLOPTS)
1383					ip6_savecontrol(last, &opts, ip6, n);
1384				/* strip intermediate headers */
1385				m_adj(n, off);
1386				if (sbappendaddr(&last->in6p_socket->so_rcv,
1387						 (struct sockaddr *)&rip6src,
1388						 n, opts) == 0) {
1389					/* should notify about lost packet */
1390					m_freem(n);
1391					if (opts)
1392						m_freem(opts);
1393				} else
1394					sorwakeup(last->in6p_socket);
1395				opts = NULL;
1396			}
1397		}
1398		last = in6p;
1399	}
1400	if (last) {
1401		if (last->in6p_flags & IN6P_CONTROLOPTS)
1402			ip6_savecontrol(last, &opts, ip6, m);
1403		/* strip intermediate headers */
1404		m_adj(m, off);
1405		if (sbappendaddr(&last->in6p_socket->so_rcv,
1406				(struct sockaddr *)&rip6src, m, opts) == 0) {
1407			m_freem(m);
1408			if (opts)
1409				m_freem(opts);
1410		} else
1411			sorwakeup(last->in6p_socket);
1412	} else {
1413		m_freem(m);
1414		ip6stat.ip6s_delivered--;
1415	}
1416	return IPPROTO_DONE;
1417}
1418
1419/*
1420 * Reflect the ip6 packet back to the source.
1421 * OFF points to the icmp6 header, counted from the top of the mbuf.
1422 */
1423void
1424icmp6_reflect(m, off)
1425	struct	mbuf *m;
1426	size_t off;
1427{
1428	struct ip6_hdr *ip6;
1429	struct icmp6_hdr *icmp6;
1430	struct in6_ifaddr *ia;
1431	struct in6_addr t, *src = 0;
1432	int plen;
1433	int type, code;
1434	struct ifnet *outif = NULL;
1435#ifdef COMPAT_RFC1885
1436	int mtu = IPV6_MMTU;
1437	struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst;
1438#endif
1439
1440	/* too short to reflect */
1441	if (off < sizeof(struct ip6_hdr)) {
1442		printf("sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
1443		       (u_long)off, (u_long)sizeof(struct ip6_hdr),
1444		       __FILE__, __LINE__);
1445		goto bad;
1446	}
1447
1448	/*
1449	 * If there are extra headers between IPv6 and ICMPv6, strip
1450	 * off that header first.
1451	 */
1452	if (off > sizeof(struct ip6_hdr)) {
1453		size_t l;
1454		struct ip6_hdr nip6;
1455
1456		l = off - sizeof(struct ip6_hdr);
1457		m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
1458		m_adj(m, l);
1459		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1460		if (m->m_len < l) {
1461			if ((m = m_pullup(m, l)) == NULL)
1462				return;
1463		}
1464		bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
1465	} else /* off == sizeof(struct ip6_hdr) */ {
1466		size_t l;
1467		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1468		if (m->m_len < l) {
1469			if ((m = m_pullup(m, l)) == NULL)
1470				return;
1471		}
1472	}
1473	plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
1474	ip6 = mtod(m, struct ip6_hdr *);
1475	ip6->ip6_nxt = IPPROTO_ICMPV6;
1476	icmp6 = (struct icmp6_hdr *)(ip6 + 1);
1477	type = icmp6->icmp6_type; /* keep type for statistics */
1478	code = icmp6->icmp6_code; /* ditto. */
1479
1480	t = ip6->ip6_dst;
1481	/*
1482	 * ip6_input() drops a packet if its src is multicast.
1483	 * So, the src is never multicast.
1484	 */
1485	ip6->ip6_dst = ip6->ip6_src;
1486
1487	/* XXX hack for link-local addresses */
1488	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
1489		ip6->ip6_dst.s6_addr16[1] =
1490			htons(m->m_pkthdr.rcvif->if_index);
1491	if (IN6_IS_ADDR_LINKLOCAL(&t))
1492		t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
1493
1494#ifdef COMPAT_RFC1885
1495	/*
1496	 * xxx guess MTU
1497	 * RFC 1885 requires that echo reply should be truncated if it
1498	 * does not fit in with (return) path MTU, but the description was
1499	 * removed in the new spec.
1500	 */
1501	if (icmp6_reflect_rt.ro_rt == 0 ||
1502	    ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) {
1503		if (icmp6_reflect_rt.ro_rt) {
1504			icmp6_reflect_rt.ro_rt = 0;
1505		}
1506		bzero(sin6, sizeof(*sin6));
1507		sin6->sin6_family = PF_INET6;
1508		sin6->sin6_len = sizeof(struct sockaddr_in6);
1509		sin6->sin6_addr = ip6->ip6_dst;
1510
1511		rtalloc((struct route *)&icmp6_reflect_rt.ro_rt);
1512	}
1513
1514	if (icmp6_reflect_rt.ro_rt == 0)
1515		goto bad;
1516
1517	if ((icmp6_reflect_rt.ro_rt->rt_flags & RTF_HOST)
1518	    && mtu < icmp6_reflect_rt.ro_rt->rt_ifp->if_mtu)
1519		mtu = icmp6_reflect_rt.ro_rt->rt_rmx.rmx_mtu;
1520
1521	if (mtu < m->m_pkthdr.len) {
1522		plen -= (m->m_pkthdr.len - mtu);
1523		m_adj(m, mtu - m->m_pkthdr.len);
1524	}
1525#endif
1526	/*
1527	 * If the incoming packet was addressed directly to us(i.e. unicast),
1528	 * use dst as the src for the reply.
1529	 * The IN6_IFF_NOTREADY case would be VERY rare, but is possible when
1530	 * (for example) when we encounter an error while forwarding procedure
1531	 * destined to a duplicated address of ours.
1532	 */
1533	for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1534		if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
1535		    (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) {
1536			src = &t;
1537			break;
1538		}
1539	if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) {
1540		/*
1541		 * This is the case if the dst is our link-local address
1542		 * and the sender is also ourseleves.
1543		 */
1544		src = &t;
1545	}
1546
1547	if (src == 0)
1548		/*
1549		 * This case matches to multicasts, our anycast, or unicasts
1550		 * that we do not own. Select a source address which has the
1551		 * same scope.
1552		 * XXX: for (non link-local) multicast addresses, this might
1553		 * not be a good choice.
1554		 */
1555		if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0)
1556			src = &IA6_SIN6(ia)->sin6_addr;
1557
1558	if (src == 0)
1559		goto bad;
1560
1561	ip6->ip6_src = *src;
1562
1563	ip6->ip6_flow = 0;
1564	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1565	ip6->ip6_vfc |= IPV6_VERSION;
1566	ip6->ip6_nxt = IPPROTO_ICMPV6;
1567	if (m->m_pkthdr.rcvif) {
1568		/* XXX: This may not be the outgoing interface */
1569		ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim;
1570	}
1571
1572	icmp6->icmp6_cksum = 0;
1573	icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
1574					sizeof(struct ip6_hdr), plen);
1575
1576	/*
1577	 * xxx option handling
1578	 */
1579
1580	m->m_flags &= ~(M_BCAST|M_MCAST);
1581#ifdef IPSEC
1582	/* Don't lookup socket */
1583	ipsec_setsocket(m, NULL);
1584#endif /*IPSEC*/
1585
1586#ifdef COMPAT_RFC1885
1587	ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL, &outif);
1588#else
1589	ip6_output(m, NULL, NULL, 0, NULL, &outif);
1590#endif
1591	if (outif)
1592		icmp6_ifoutstat_inc(outif, type, code);
1593
1594	return;
1595
1596 bad:
1597	m_freem(m);
1598	return;
1599}
1600
1601void
1602icmp6_fasttimo()
1603{
1604	mld6_fasttimeo();
1605}
1606
1607static const char *
1608icmp6_redirect_diag(src6, dst6, tgt6)
1609	struct in6_addr *src6;
1610	struct in6_addr *dst6;
1611	struct in6_addr *tgt6;
1612{
1613	static char buf[1024];
1614	snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
1615		ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
1616	return buf;
1617}
1618
1619void
1620icmp6_redirect_input(m, off)
1621	register struct mbuf *m;
1622	int off;
1623{
1624	struct ifnet *ifp = m->m_pkthdr.rcvif;
1625	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1626	struct nd_redirect *nd_rd;
1627	int icmp6len = ntohs(ip6->ip6_plen);
1628	char *lladdr = NULL;
1629	int lladdrlen = 0;
1630	u_char *redirhdr = NULL;
1631	int redirhdrlen = 0;
1632	struct rtentry *rt = NULL;
1633	int is_router;
1634	int is_onlink;
1635	struct in6_addr src6 = ip6->ip6_src;
1636	struct in6_addr redtgt6;
1637	struct in6_addr reddst6;
1638	union nd_opts ndopts;
1639
1640	if (!m || !ifp)
1641		return;
1642
1643	/* XXX if we are router, we don't update route by icmp6 redirect */
1644	if (ip6_forwarding)
1645		goto freeit;
1646	if (!icmp6_rediraccept)
1647		goto freeit;
1648
1649#ifndef PULLDOWN_TEST
1650	IP6_EXTHDR_CHECK(m, off, icmp6len,);
1651	nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
1652#else
1653	IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
1654	if (nd_rd == NULL) {
1655		icmp6stat.icp6s_tooshort++;
1656		return;
1657	}
1658#endif
1659	redtgt6 = nd_rd->nd_rd_target;
1660	reddst6 = nd_rd->nd_rd_dst;
1661
1662	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
1663		redtgt6.s6_addr16[1] = htons(ifp->if_index);
1664	if (IN6_IS_ADDR_LINKLOCAL(&reddst6))
1665		reddst6.s6_addr16[1] = htons(ifp->if_index);
1666
1667	/* validation */
1668	if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
1669		log(LOG_ERR,
1670			"ICMP6 redirect sent from %s rejected; "
1671			"must be from linklocal\n", ip6_sprintf(&src6));
1672		goto freeit;
1673	}
1674	if (ip6->ip6_hlim != 255) {
1675		log(LOG_ERR,
1676			"ICMP6 redirect sent from %s rejected; "
1677			"hlim=%d (must be 255)\n",
1678			ip6_sprintf(&src6), ip6->ip6_hlim);
1679		goto freeit;
1680	}
1681    {
1682	/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
1683	struct sockaddr_in6 sin6;
1684	struct in6_addr *gw6;
1685
1686	bzero(&sin6, sizeof(sin6));
1687	sin6.sin6_family = AF_INET6;
1688	sin6.sin6_len = sizeof(struct sockaddr_in6);
1689	bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
1690	rt = rtalloc1((struct sockaddr *)&sin6, 0);
1691	if (rt) {
1692		gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
1693		if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
1694			log(LOG_ERR,
1695				"ICMP6 redirect rejected; "
1696				"not equal to gw-for-src=%s (must be same): "
1697				"%s\n",
1698				ip6_sprintf(gw6),
1699				icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1700			RTFREE(rt);
1701			goto freeit;
1702		}
1703	} else {
1704		log(LOG_ERR,
1705			"ICMP6 redirect rejected; "
1706			"no route found for redirect dst: %s\n",
1707			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1708		goto freeit;
1709	}
1710	RTFREE(rt);
1711	rt = NULL;
1712    }
1713	if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
1714		log(LOG_ERR,
1715			"ICMP6 redirect rejected; "
1716			"redirect dst must be unicast: %s\n",
1717			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1718		goto freeit;
1719	}
1720
1721	is_router = is_onlink = 0;
1722	if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
1723		is_router = 1;	/* router case */
1724	if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
1725		is_onlink = 1;	/* on-link destination case */
1726	if (!is_router && !is_onlink) {
1727		log(LOG_ERR,
1728			"ICMP6 redirect rejected; "
1729			"neither router case nor onlink case: %s\n",
1730			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1731		goto freeit;
1732	}
1733	/* validation passed */
1734
1735	icmp6len -= sizeof(*nd_rd);
1736	nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
1737	if (nd6_options(&ndopts) < 0) {
1738		log(LOG_INFO, "icmp6_redirect_input: "
1739			"invalid ND option, rejected: %s\n",
1740			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1741		goto freeit;
1742	}
1743
1744	if (ndopts.nd_opts_tgt_lladdr) {
1745		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
1746		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
1747	}
1748
1749	if (ndopts.nd_opts_rh) {
1750		redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
1751		redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
1752	}
1753
1754	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1755		log(LOG_INFO,
1756			"icmp6_redirect_input: lladdrlen mismatch for %s "
1757			"(if %d, icmp6 packet %d): %s\n",
1758			ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
1759			icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
1760	}
1761
1762	/* RFC 2461 8.3 */
1763	nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
1764			 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
1765
1766	if (!is_onlink) {	/* better router case. perform rtredirect. */
1767		/* perform rtredirect */
1768		struct sockaddr_in6 sdst;
1769		struct sockaddr_in6 sgw;
1770		struct sockaddr_in6 ssrc;
1771
1772		bzero(&sdst, sizeof(sdst));
1773		bzero(&sgw, sizeof(sgw));
1774		bzero(&ssrc, sizeof(ssrc));
1775		sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
1776		sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
1777			sizeof(struct sockaddr_in6);
1778		bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
1779		bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
1780		bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
1781		rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
1782			   (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
1783			   (struct sockaddr *)&ssrc,
1784			   (struct rtentry **)NULL
1785			   );
1786	}
1787	/* finally update cached route in each socket via pfctlinput */
1788    {
1789	struct sockaddr_in6 sdst;
1790#if 1
1791#else
1792	struct ip6protosw *pr;
1793#endif
1794
1795	bzero(&sdst, sizeof(sdst));
1796	sdst.sin6_family = AF_INET6;
1797	sdst.sin6_len = sizeof(struct sockaddr_in6);
1798	bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
1799#if 1
1800	pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
1801#else
1802	/*
1803	 * do not use pfctlinput() here, we have different prototype for
1804	 * xx_ctlinput() in ip6proto.
1805	 */
1806	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
1807	     pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW;
1808	     pr++) {
1809		if (pr->pr_ctlinput) {
1810			(*pr->pr_ctlinput)(PRC_REDIRECT_HOST,
1811				(struct sockaddr *)&sdst, NULL, NULL, 0);
1812		}
1813	}
1814#endif
1815#ifdef IPSEC
1816	key_sa_routechange((struct sockaddr *)&sdst);
1817#endif
1818    }
1819
1820 freeit:
1821	m_freem(m);
1822}
1823
1824void
1825icmp6_redirect_output(m0, rt)
1826	struct mbuf *m0;
1827	struct rtentry *rt;
1828{
1829	struct ifnet *ifp;	/* my outgoing interface */
1830	struct in6_addr *ifp_ll6;
1831	struct in6_addr *router_ll6;
1832	struct ip6_hdr *sip6;	/* m0 as struct ip6_hdr */
1833	struct mbuf *m = NULL;	/* newly allocated one */
1834	struct ip6_hdr *ip6;	/* m as struct ip6_hdr */
1835	struct nd_redirect *nd_rd;
1836	size_t maxlen;
1837	u_char *p;
1838	struct ifnet *outif = NULL;
1839
1840	/* if we are not router, we don't send icmp6 redirect */
1841	if (!ip6_forwarding || ip6_accept_rtadv)
1842		goto fail;
1843
1844	/* sanity check */
1845	if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
1846		goto fail;
1847
1848	/*
1849	 * Address check:
1850	 *  the source address must identify a neighbor, and
1851	 *  the destination address must not be a multicast address
1852	 *  [RFC 2461, sec 8.2]
1853	 */
1854	sip6 = mtod(m0, struct ip6_hdr *);
1855	if (nd6_is_addr_neighbor(&sip6->ip6_src, ifp) == 0)
1856		goto fail;
1857	if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
1858		goto fail;	/* what should we do here? */
1859
1860	/* rate limit */
1861	if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
1862		goto fail;
1863
1864	/*
1865	 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
1866	 * we almost always ask for an mbuf cluster for simplicity.
1867	 * (MHLEN < IPV6_MMTU is almost always true)
1868	 */
1869#if IPV6_MMTU >= MCLBYTES
1870# error assumption failed about IPV6_MMTU and MCLBYTES
1871#endif
1872	MGETHDR(m, M_DONTWAIT, MT_HEADER);
1873	if (m && IPV6_MMTU >= MHLEN)
1874		MCLGET(m, M_DONTWAIT);
1875	if (!m)
1876		goto fail;
1877	maxlen = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
1878	maxlen = min(IPV6_MMTU, maxlen);
1879	/* just for safety */
1880	if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
1881	    ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
1882		goto fail;
1883	}
1884
1885	{
1886		/* get ip6 linklocal address for ifp(my outgoing interface). */
1887		struct in6_ifaddr *ia;
1888		if ((ia = in6ifa_ifpforlinklocal(ifp,
1889						 IN6_IFF_NOTREADY|
1890						 IN6_IFF_ANYCAST)) == NULL)
1891			goto fail;
1892		ifp_ll6 = &ia->ia_addr.sin6_addr;
1893	}
1894
1895	/* get ip6 linklocal address for the router. */
1896	if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
1897		struct sockaddr_in6 *sin6;
1898		sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
1899		router_ll6 = &sin6->sin6_addr;
1900		if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
1901			router_ll6 = (struct in6_addr *)NULL;
1902	} else
1903		router_ll6 = (struct in6_addr *)NULL;
1904
1905	/* ip6 */
1906	ip6 = mtod(m, struct ip6_hdr *);
1907	ip6->ip6_flow = 0;
1908	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1909	ip6->ip6_vfc |= IPV6_VERSION;
1910	/* ip6->ip6_plen will be set later */
1911	ip6->ip6_nxt = IPPROTO_ICMPV6;
1912	ip6->ip6_hlim = 255;
1913	/* ip6->ip6_src must be linklocal addr for my outgoing if. */
1914	bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
1915	bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
1916
1917	/* ND Redirect */
1918	nd_rd = (struct nd_redirect *)(ip6 + 1);
1919	nd_rd->nd_rd_type = ND_REDIRECT;
1920	nd_rd->nd_rd_code = 0;
1921	nd_rd->nd_rd_reserved = 0;
1922	if (rt->rt_flags & RTF_GATEWAY) {
1923		/*
1924		 * nd_rd->nd_rd_target must be a link-local address in
1925		 * better router cases.
1926		 */
1927		if (!router_ll6)
1928			goto fail;
1929		bcopy(router_ll6, &nd_rd->nd_rd_target,
1930		      sizeof(nd_rd->nd_rd_target));
1931		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
1932		      sizeof(nd_rd->nd_rd_dst));
1933	} else {
1934		/* make sure redtgt == reddst */
1935		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
1936		      sizeof(nd_rd->nd_rd_target));
1937		bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
1938		      sizeof(nd_rd->nd_rd_dst));
1939	}
1940
1941	p = (u_char *)(nd_rd + 1);
1942
1943	if (!router_ll6)
1944		goto nolladdropt;
1945
1946    {
1947	/* target lladdr option */
1948	struct rtentry *rt_router = NULL;
1949	int len;
1950	struct sockaddr_dl *sdl;
1951	struct nd_opt_hdr *nd_opt;
1952	char *lladdr;
1953
1954	rt_router = nd6_lookup(router_ll6, 0, ifp);
1955	if (!rt_router)
1956		goto nolladdropt;
1957	len = sizeof(*nd_opt) + ifp->if_addrlen;
1958	len = (len + 7) & ~7;	/*round by 8*/
1959	/* safety check */
1960	if (len + (p - (u_char *)ip6) > maxlen)
1961		goto nolladdropt;
1962	if (!(rt_router->rt_flags & RTF_GATEWAY) &&
1963	    (rt_router->rt_flags & RTF_LLINFO) &&
1964	    (rt_router->rt_gateway->sa_family == AF_LINK) &&
1965	    (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) &&
1966	    sdl->sdl_alen) {
1967		nd_opt = (struct nd_opt_hdr *)p;
1968		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
1969		nd_opt->nd_opt_len = len >> 3;
1970		lladdr = (char *)(nd_opt + 1);
1971		bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
1972		p += len;
1973	}
1974    }
1975nolladdropt:;
1976
1977	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
1978
1979	/* just to be safe */
1980	if (m0->m_flags & M_DECRYPTED)
1981		goto noredhdropt;
1982	if (p - (u_char *)ip6 > maxlen)
1983		goto noredhdropt;
1984
1985    {
1986	/* redirected header option */
1987	int len;
1988	struct nd_opt_rd_hdr *nd_opt_rh;
1989
1990	/*
1991	 * compute the maximum size for icmp6 redirect header option.
1992	 * XXX room for auth header?
1993	 */
1994	len = maxlen - (p - (u_char *)ip6);
1995	len &= ~7;
1996
1997	/* This is just for simplicity. */
1998	if (m0->m_pkthdr.len != m0->m_len) {
1999		if (m0->m_next) {
2000			m_freem(m0->m_next);
2001			m0->m_next = NULL;
2002		}
2003		m0->m_pkthdr.len = m0->m_len;
2004	}
2005
2006	/*
2007	 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2008	 * about padding/truncate rule for the original IP packet.
2009	 * From the discussion on IPv6imp in Feb 1999, the consensus was:
2010	 * - "attach as much as possible" is the goal
2011	 * - pad if not aligned (original size can be guessed by original
2012	 *   ip6 header)
2013	 * Following code adds the padding if it is simple enough,
2014	 * and truncates if not.
2015	 */
2016	if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
2017		panic("assumption failed in %s:%d\n", __FILE__, __LINE__);
2018
2019	if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2020		/* not enough room, truncate */
2021		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2022	} else {
2023		/* enough room, pad or truncate */
2024		size_t extra;
2025
2026		extra = m0->m_pkthdr.len % 8;
2027		if (extra) {
2028			/* pad if easy enough, truncate if not */
2029			if (8 - extra <= M_TRAILINGSPACE(m0)) {
2030				/* pad */
2031				m0->m_len += (8 - extra);
2032				m0->m_pkthdr.len += (8 - extra);
2033			} else {
2034				/* truncate */
2035				m0->m_pkthdr.len -= extra;
2036				m0->m_len -= extra;
2037			}
2038		}
2039		len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2040		m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
2041	}
2042
2043	nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2044	bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2045	nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2046	nd_opt_rh->nd_opt_rh_len = len >> 3;
2047	p += sizeof(*nd_opt_rh);
2048	m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2049
2050	/* connect m0 to m */
2051	m->m_next = m0;
2052	m->m_pkthdr.len = m->m_len + m0->m_len;
2053    }
2054noredhdropt:;
2055
2056	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src))
2057		sip6->ip6_src.s6_addr16[1] = 0;
2058	if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst))
2059		sip6->ip6_dst.s6_addr16[1] = 0;
2060#if 0
2061	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
2062		ip6->ip6_src.s6_addr16[1] = 0;
2063	if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
2064		ip6->ip6_dst.s6_addr16[1] = 0;
2065#endif
2066	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target))
2067		nd_rd->nd_rd_target.s6_addr16[1] = 0;
2068	if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst))
2069		nd_rd->nd_rd_dst.s6_addr16[1] = 0;
2070
2071	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2072
2073	nd_rd->nd_rd_cksum = 0;
2074	nd_rd->nd_rd_cksum
2075		= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2076
2077	/* send the packet to outside... */
2078#ifdef IPSEC
2079	/* Don't lookup socket */
2080	ipsec_setsocket(m, NULL);
2081#endif /*IPSEC*/
2082	ip6_output(m, NULL, NULL, 0, NULL, &outif);
2083	if (outif) {
2084		icmp6_ifstat_inc(outif, ifs6_out_msg);
2085		icmp6_ifstat_inc(outif, ifs6_out_redirect);
2086	}
2087	icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2088
2089	return;
2090
2091fail:
2092	if (m)
2093		m_freem(m);
2094	if (m0)
2095		m_freem(m0);
2096}
2097
2098/*
2099 * ICMPv6 socket option processing.
2100 */
2101int
2102icmp6_ctloutput(op, so, level, optname, mp)
2103	int op;
2104	struct socket *so;
2105	int level, optname;
2106	struct mbuf **mp;
2107{
2108	register struct in6pcb *in6p = sotoin6pcb(so);
2109	register struct mbuf *m = *mp;
2110	int error = 0;
2111
2112	if (level != IPPROTO_ICMPV6) {
2113		error = EINVAL;
2114		if (op == PRCO_SETOPT && m)
2115			(void)m_free(m);
2116	} else switch(op) {
2117	 case PRCO_SETOPT:
2118		 switch (optname) {
2119		  case ICMP6_FILTER:
2120		  {
2121			  struct icmp6_filter *p;
2122
2123			  p = mtod(m, struct icmp6_filter *);
2124			  if (!p || !in6p->in6p_icmp6filt) {
2125				  error = EINVAL;
2126				  break;
2127			  }
2128			  bcopy(p, in6p->in6p_icmp6filt,
2129				sizeof(struct icmp6_filter));
2130			  error = 0;
2131			  break;
2132		  }
2133
2134		  default:
2135			  error = ENOPROTOOPT;
2136			  break;
2137		 }
2138		 if (m)
2139			 (void)m_free(m);
2140		 break;
2141
2142	 case PRCO_GETOPT:
2143		 switch (optname) {
2144		  case ICMP6_FILTER:
2145		  {
2146			  struct icmp6_filter *p;
2147
2148			  if (!in6p->in6p_icmp6filt) {
2149				  error = EINVAL;
2150				  break;
2151			  }
2152			  *mp = m = m_get(M_WAIT, MT_SOOPTS);
2153			  m->m_len = sizeof(struct icmp6_filter);
2154			  p = mtod(m, struct icmp6_filter *);
2155			  bcopy(in6p->in6p_icmp6filt, p,
2156				sizeof(struct icmp6_filter));
2157			  error = 0;
2158			  break;
2159		  }
2160
2161		  default:
2162			  error = ENOPROTOOPT;
2163			  break;
2164		 }
2165		 break;
2166	}
2167
2168	return(error);
2169}
2170
2171/*
2172 * Perform rate limit check.
2173 * Returns 0 if it is okay to send the icmp6 packet.
2174 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2175 * limitation.
2176 *
2177 * XXX per-destination/type check necessary?
2178 */
2179static int
2180icmp6_ratelimit(dst, type, code)
2181	const struct in6_addr *dst;	/* not used at this moment */
2182	const int type;			/* not used at this moment */
2183	const int code;			/* not used at this moment */
2184{
2185	static struct timeval icmp6errratelim_last;
2186
2187	/*
2188	 * ratecheck() returns true if it is okay to send.  We return
2189	 * true if it is not okay to send.
2190	 */
2191	return (ratecheck(&icmp6errratelim_last, &icmp6errratelim) == 0);
2192}
2193
2194static struct rtentry *
2195icmp6_mtudisc_clone(dst)
2196	struct sockaddr *dst;
2197{
2198	struct rtentry *rt;
2199	int    error;
2200
2201	rt = rtalloc1(dst, 1);
2202	if (rt == 0)
2203		return NULL;
2204
2205	/* If we didn't get a host route, allocate one */
2206	if ((rt->rt_flags & RTF_HOST) == 0) {
2207		struct rtentry *nrt;
2208
2209		error = rtrequest((int) RTM_ADD, dst,
2210		    (struct sockaddr *) rt->rt_gateway,
2211		    (struct sockaddr *) 0,
2212		    RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt);
2213		if (error) {
2214			rtfree(rt);
2215			rtfree(nrt);
2216			return NULL;
2217		}
2218		nrt->rt_rmx = rt->rt_rmx;
2219		rtfree(rt);
2220		rt = nrt;
2221	}
2222	error = rt_timer_add(rt, icmp6_mtudisc_timeout,
2223			icmp6_mtudisc_timeout_q);
2224	if (error) {
2225		rtfree(rt);
2226		return NULL;
2227	}
2228
2229	return rt;	/* caller need to call rtfree() */
2230}
2231
2232static void
2233icmp6_mtudisc_timeout(rt, r)
2234	struct rtentry *rt;
2235	struct rttimer *r;
2236{
2237	if (rt == NULL)
2238		panic("icmp6_mtudisc_timeout: bad route to timeout");
2239	if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
2240	    (RTF_DYNAMIC | RTF_HOST)) {
2241		rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
2242		    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
2243	} else {
2244		if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
2245			rt->rt_rmx.rmx_mtu = 0;
2246		}
2247	}
2248}
2249
2250#include <vm/vm.h>
2251#include <sys/sysctl.h>
2252int
2253icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
2254	int *name;
2255	u_int namelen;
2256	void *oldp;
2257	size_t *oldlenp;
2258	void *newp;
2259	size_t newlen;
2260{
2261
2262	/* All sysctl names at this level are terminal. */
2263	if (namelen != 1)
2264		return ENOTDIR;
2265
2266	switch (name[0]) {
2267
2268	case ICMPV6CTL_REDIRACCEPT:
2269		return sysctl_int(oldp, oldlenp, newp, newlen,
2270				&icmp6_rediraccept);
2271	case ICMPV6CTL_REDIRTIMEOUT:
2272		return sysctl_int(oldp, oldlenp, newp, newlen,
2273				&icmp6_redirtimeout);
2274	case ICMPV6CTL_STATS:
2275		return sysctl_rdstruct(oldp, oldlenp, newp,
2276				&icmp6stat, sizeof(icmp6stat));
2277	case ICMPV6CTL_ERRRATELIMIT:
2278	    {
2279		int rate_usec, error, s;
2280
2281		/*
2282		 * The sysctl specifies the rate in usec-between-icmp,
2283		 * so we must convert from/to a timeval.
2284		 */
2285		rate_usec = (icmp6errratelim.tv_sec * 1000000) +
2286		    icmp6errratelim.tv_usec;
2287		error = sysctl_int(oldp, oldlenp, newp, newlen, &rate_usec);
2288		if (error)
2289			return (error);
2290		s = splsoftnet();
2291		icmp6errratelim.tv_sec = rate_usec / 1000000;
2292		icmp6errratelim.tv_usec = rate_usec % 1000000;
2293		splx(s);
2294
2295		return (0);
2296	    }
2297	case ICMPV6CTL_ND6_PRUNE:
2298		return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_prune);
2299	case ICMPV6CTL_ND6_DELAY:
2300		return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_delay);
2301	case ICMPV6CTL_ND6_UMAXTRIES:
2302		return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_umaxtries);
2303	case ICMPV6CTL_ND6_MMAXTRIES:
2304		return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_mmaxtries);
2305	case ICMPV6CTL_ND6_USELOOPBACK:
2306		return sysctl_int(oldp, oldlenp, newp, newlen,
2307				&nd6_useloopback);
2308	case ICMPV6CTL_NODEINFO:
2309		return sysctl_int(oldp, oldlenp, newp, newlen, &icmp6_nodeinfo);
2310	default:
2311		return ENOPROTOOPT;
2312	}
2313	/* NOTREACHED */
2314}
2315