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