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