ip6_input.c revision 195699
1139826Simp/*-
253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
353541Sshin * All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 3. Neither the name of the project nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
28174510Sobrien *
29174510Sobrien *	$KAME: ip6_input.c,v 1.259 2002/01/21 04:58:09 jinmei Exp $
3053541Sshin */
3153541Sshin
32139826Simp/*-
3353541Sshin * Copyright (c) 1982, 1986, 1988, 1993
3453541Sshin *	The Regents of the University of California.  All rights reserved.
3553541Sshin *
3653541Sshin * Redistribution and use in source and binary forms, with or without
3753541Sshin * modification, are permitted provided that the following conditions
3853541Sshin * are met:
3953541Sshin * 1. Redistributions of source code must retain the above copyright
4053541Sshin *    notice, this list of conditions and the following disclaimer.
4153541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4253541Sshin *    notice, this list of conditions and the following disclaimer in the
4353541Sshin *    documentation and/or other materials provided with the distribution.
4453541Sshin * 4. Neither the name of the University nor the names of its contributors
4553541Sshin *    may be used to endorse or promote products derived from this software
4653541Sshin *    without specific prior written permission.
4753541Sshin *
4853541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4953541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5053541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5153541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5253541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5353541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5453541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5553541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5653541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5753541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5853541Sshin * SUCH DAMAGE.
5953541Sshin *
6053541Sshin *	@(#)ip_input.c	8.2 (Berkeley) 1/4/94
6153541Sshin */
6253541Sshin
63174510Sobrien#include <sys/cdefs.h>
64174510Sobrien__FBSDID("$FreeBSD: head/sys/netinet6/ip6_input.c 195699 2009-07-14 22:48:30Z rwatson $");
65174510Sobrien
6662587Sitojun#include "opt_inet.h"
6762587Sitojun#include "opt_inet6.h"
6855009Sshin#include "opt_ipsec.h"
6955009Sshin
7053541Sshin#include <sys/param.h>
7153541Sshin#include <sys/systm.h>
7278064Sume#include <sys/malloc.h>
7353541Sshin#include <sys/mbuf.h>
7483366Sjulian#include <sys/proc.h>
7553541Sshin#include <sys/domain.h>
7653541Sshin#include <sys/protosw.h>
7753541Sshin#include <sys/socket.h>
7853541Sshin#include <sys/socketvar.h>
7953541Sshin#include <sys/errno.h>
8053541Sshin#include <sys/time.h>
8153541Sshin#include <sys/kernel.h>
8253541Sshin#include <sys/syslog.h>
83181803Sbz#include <sys/vimage.h>
8453541Sshin
8553541Sshin#include <net/if.h>
8653541Sshin#include <net/if_types.h>
8753541Sshin#include <net/if_dl.h>
8853541Sshin#include <net/route.h>
8953541Sshin#include <net/netisr.h>
9064060Sdarrenr#include <net/pfil.h>
91185571Sbz#include <net/vnet.h>
9253541Sshin
9353541Sshin#include <netinet/in.h>
9453541Sshin#include <netinet/in_systm.h>
95186119Sqingli#include <net/if_llatbl.h>
9662587Sitojun#ifdef INET
9753541Sshin#include <netinet/ip.h>
9853541Sshin#include <netinet/ip_icmp.h>
9995023Ssuz#endif /* INET */
10062587Sitojun#include <netinet/ip6.h>
10153541Sshin#include <netinet6/in6_var.h>
10253541Sshin#include <netinet6/ip6_var.h>
10362587Sitojun#include <netinet/in_pcb.h>
10462587Sitojun#include <netinet/icmp6.h>
105121161Sume#include <netinet6/scope6_var.h>
10653541Sshin#include <netinet6/in6_ifattach.h>
10753541Sshin#include <netinet6/nd6.h>
10853541Sshin
109171167Sgnn#ifdef IPSEC
110105199Ssam#include <netipsec/ipsec.h>
111171133Sgnn#include <netinet6/ip6_ipsec.h>
112105199Ssam#include <netipsec/ipsec6.h>
113171167Sgnn#endif /* IPSEC */
114105199Ssam
11553541Sshin#include <netinet6/ip6protosw.h>
11653541Sshin
11762587Sitojunextern struct domain inet6domain;
11853541Sshin
11962587Sitojunu_char ip6_protox[IPPROTO_MAX];
120185088Szec
121193219Srwatsonstatic struct netisr_handler ip6_nh = {
122193219Srwatson	.nh_name = "ip6",
123193219Srwatson	.nh_handler = ip6_input,
124193219Srwatson	.nh_proto = NETISR_IPV6,
125193219Srwatson	.nh_policy = NETISR_POLICY_FLOW,
126193219Srwatson};
127193219Srwatson
128195699SrwatsonVNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead);
129195699SrwatsonVNET_DEFINE(struct ip6stat, ip6stat);
130185895Szec
131195699SrwatsonVNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
132195699SrwatsonVNET_DECLARE(int, dad_init);
133195699SrwatsonVNET_DECLARE(int, pmtu_expire);
134195699SrwatsonVNET_DECLARE(int, pmtu_probe);
135195699SrwatsonVNET_DECLARE(u_long, rip6_sendspace);
136195699SrwatsonVNET_DECLARE(u_long, rip6_recvspace);
137195699SrwatsonVNET_DECLARE(int, icmp6errppslim);
138195699SrwatsonVNET_DECLARE(int, icmp6_nodeinfo);
139195699SrwatsonVNET_DECLARE(int, udp6_sendspace);
140195699SrwatsonVNET_DECLARE(int, udp6_recvspace);
14153541Sshin
142195699Srwatson#define	V_in6_tmpaddrtimer_ch		VNET_GET(in6_tmpaddrtimer_ch)
143195699Srwatson#define	V_dad_init			VNET_GET(dad_init)
144195699Srwatson#define	V_pmtu_expire			VNET_GET(pmtu_expire)
145195699Srwatson#define	V_pmtu_probe			VNET_GET(pmtu_probe)
146195699Srwatson#define	V_rip6_sendspace		VNET_GET(rip6_sendspace)
147195699Srwatson#define	V_rip6_recvspace		VNET_GET(rip6_recvspace)
148195699Srwatson#define	V_icmp6errppslim		VNET_GET(icmp6errppslim)
149195699Srwatson#define	V_icmp6_nodeinfo		VNET_GET(icmp6_nodeinfo)
150195699Srwatson#define	V_udp6_sendspace		VNET_GET(udp6_sendspace)
151195699Srwatson#define	V_udp6_recvspace		VNET_GET(udp6_recvspace)
15278064Sume
153194971Srwatsonstruct rwlock in6_ifaddr_lock;
154194971SrwatsonRW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
155194971Srwatson
156120386Ssamstruct pfil_head inet6_pfil_hook;
15778064Sume
158175162Sobrienstatic void ip6_init2(void *);
159175162Sobrienstatic struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
160175162Sobrienstatic int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
16162587Sitojun#ifdef PULLDOWN_TEST
162175162Sobrienstatic struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
16353541Sshin#endif
16453541Sshin
165195699Srwatson#ifdef VIMAGE
166195699Srwatson/* XXX only has to stay for .vmi_dependson elsewhere. */
167190909Szecstatic void vnet_inet6_register(void);
168190909Szec
169190909Szecstatic const vnet_modinfo_t vnet_inet6_modinfo = {
170190909Szec	.vmi_id		= VNET_MOD_INET6,
171190909Szec	.vmi_name	= "inet6",
172190909Szec	.vmi_dependson	= VNET_MOD_INET	/* XXX revisit - TCP/UDP needs this? */
173190909Szec};
174190909Szec
175190909Szecstatic void
176190909Szecvnet_inet6_register(void)
177190909Szec{
178190909Szec
179190909Szec	vnet_mod_register(&vnet_inet6_modinfo);
180190909Szec}
181190909Szec
182190909SzecSYSINIT(inet6, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, vnet_inet6_register, 0);
183190909Szec#endif
184190909Szec
18553541Sshin/*
18653541Sshin * IP6 initialization: fill in IP6 protocol switch table.
18753541Sshin * All protocols not implemented in kernel go to raw IP6 protocol handler.
18853541Sshin */
18953541Sshinvoid
190171259Sdelphijip6_init(void)
19153541Sshin{
19278064Sume	struct ip6protosw *pr;
19378064Sume	int i;
19453541Sshin
195185088Szec	V_in6_maxmtu = 0;
196185088Szec#ifdef IP6_AUTO_LINKLOCAL
197185088Szec	V_ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
198185088Szec#else
199185088Szec	V_ip6_auto_linklocal = 1;	/* enable by default */
200185088Szec#endif
201185895Szec	TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
202185895Szec	    &V_ip6_auto_linklocal);
203185088Szec
204185088Szec#ifndef IPV6FORWARDING
205185088Szec#ifdef GATEWAY6
206185088Szec#define IPV6FORWARDING	1	/* forward IP6 packets not for us */
207185088Szec#else
208185088Szec#define IPV6FORWARDING	0	/* don't forward IP6 packets not for us */
209185088Szec#endif /* GATEWAY6 */
210185088Szec#endif /* !IPV6FORWARDING */
211185088Szec
212185088Szec#ifndef IPV6_SENDREDIRECTS
213185088Szec#define IPV6_SENDREDIRECTS	1
214185088Szec#endif
215185088Szec
216185088Szec	V_ip6_forwarding = IPV6FORWARDING; /* act as router? */
217185088Szec	V_ip6_sendredirects = IPV6_SENDREDIRECTS;
218185088Szec	V_ip6_defhlim = IPV6_DEFHLIM;
219185088Szec	V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
220185088Szec	V_ip6_accept_rtadv = 0;	 /* "IPV6FORWARDING ? 0 : 1" is dangerous */
221185088Szec	V_ip6_log_interval = 5;
222185088Szec	V_ip6_hdrnestlimit = 15; /* How many header options will we process? */
223185088Szec	V_ip6_dad_count = 1;	 /* DupAddrDetectionTransmits */
224185088Szec	V_ip6_auto_flowlabel = 1;
225185088Szec	V_ip6_use_deprecated = 1;/* allow deprecated addr (RFC2462 5.5.4) */
226185088Szec	V_ip6_rr_prune = 5;	 /* router renumbering prefix
227185088Szec                                  * walk list every 5 sec. */
228185088Szec	V_ip6_mcast_pmtu = 0;	 /* enable pMTU discovery for multicast? */
229185088Szec	V_ip6_v6only = 1;
230185088Szec	V_ip6_keepfaith = 0;
231185088Szec	V_ip6_log_time = (time_t)0L;
232185088Szec#ifdef IPSTEALTH
233185088Szec	V_ip6stealth = 0;
234185088Szec#endif
235185088Szec	V_nd6_onlink_ns_rfc4861 = 0; /* allow 'on-link' nd6 NS (RFC 4861) */
236185088Szec
237185088Szec	V_pmtu_expire = 60*10;
238185088Szec	V_pmtu_probe = 60*2;
239185088Szec
240185088Szec	/* raw IP6 parameters */
241185088Szec	/*
242185088Szec	 * Nominal space allocated to a raw ip socket.
243185088Szec	 */
244185088Szec#define RIPV6SNDQ	8192
245185088Szec#define RIPV6RCVQ	8192
246185088Szec	V_rip6_sendspace = RIPV6SNDQ;
247185088Szec	V_rip6_recvspace = RIPV6RCVQ;
248185088Szec
249185088Szec	/* ICMPV6 parameters */
250185088Szec	V_icmp6_rediraccept = 1;	/* accept and process redirects */
251185088Szec	V_icmp6_redirtimeout = 10 * 60;	/* 10 minutes */
252185088Szec	V_icmp6errppslim = 100;		/* 100pps */
253185088Szec	/* control how to respond to NI queries */
254185088Szec	V_icmp6_nodeinfo = (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
255185088Szec
256185088Szec	/* UDP on IP6 parameters */
257185088Szec	V_udp6_sendspace = 9216;	/* really max datagram size */
258185088Szec	V_udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
259185088Szec					/* 40 1K datagrams */
260185088Szec	V_dad_init = 0;
261185088Szec
262194907Srwatson	TAILQ_INIT(&V_in6_ifaddrhead);
263194907Srwatson
264190787Szec	scope6_init();
265190787Szec	addrsel_policy_init();
266190787Szec	nd6_init();
267190787Szec	frag6_init();
268190787Szec
269190787Szec	V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
270190787Szec
271190787Szec	/* Skip global initialization stuff for non-default instances. */
272190787Szec	if (!IS_DEFAULT_VNET(curvnet))
273190787Szec		return;
274190787Szec
27578064Sume#ifdef DIAGNOSTIC
27678064Sume	if (sizeof(struct protosw) != sizeof(struct ip6protosw))
27778064Sume		panic("sizeof(protosw) != sizeof(ip6protosw)");
27878064Sume#endif
27953541Sshin	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
280191433Sbz	if (pr == NULL)
28153541Sshin		panic("ip6_init");
282136689Sandre
283186393Sbz	/* Initialize the entire ip6_protox[] array to IPPROTO_RAW. */
28453541Sshin	for (i = 0; i < IPPROTO_MAX; i++)
28553541Sshin		ip6_protox[i] = pr - inet6sw;
286136689Sandre	/*
287136689Sandre	 * Cycle through IP protocols and put them into the appropriate place
288136689Sandre	 * in ip6_protox[].
289136689Sandre	 */
29053541Sshin	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
29153541Sshin	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
29253541Sshin		if (pr->pr_domain->dom_family == PF_INET6 &&
293136689Sandre		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
294136689Sandre			/* Be careful to only index valid IP protocols. */
295143675Ssam			if (pr->pr_protocol < IPPROTO_MAX)
296136689Sandre				ip6_protox[pr->pr_protocol] = pr - inet6sw;
297136689Sandre		}
298134383Sandre
299134383Sandre	/* Initialize packet filter hooks. */
300120386Ssam	inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
301120386Ssam	inet6_pfil_hook.ph_af = AF_INET6;
302120386Ssam	if ((i = pfil_head_register(&inet6_pfil_hook)) != 0)
303120386Ssam		printf("%s: WARNING: unable to register pfil hook, "
304120386Ssam			"error %d\n", __func__, i);
305134383Sandre
306193219Srwatson	netisr_register(&ip6_nh);
30753541Sshin}
30853541Sshin
309193731Szec#ifdef VIMAGE
310193731Szecvoid
311193731Szecip6_destroy()
312193731Szec{
313193731Szec
314193731Szec	nd6_destroy();
315193731Szec	callout_drain(&V_in6_tmpaddrtimer_ch);
316193731Szec}
317193731Szec#endif
318193731Szec
319190787Szecstatic int
320190787Szecip6_init2_vnet(const void *unused __unused)
32153541Sshin{
32253541Sshin
32353541Sshin	/* nd6_timer_init */
324181803Sbz	callout_init(&V_nd6_timer_ch, 0);
325191688Szec	callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
32678064Sume
32778064Sume	/* timer for regeneranation of temporary addresses randomize ID */
328181803Sbz	callout_init(&V_in6_tmpaddrtimer_ch, 0);
329181803Sbz	callout_reset(&V_in6_tmpaddrtimer_ch,
330181803Sbz		      (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
331181803Sbz		       V_ip6_temp_regen_advance) * hz,
332191688Szec		      in6_tmpaddrtimer, curvnet);
333190787Szec
334190787Szec	return (0);
33553541Sshin}
33653541Sshin
337190787Szecstatic void
338190787Szecip6_init2(void *dummy)
339190787Szec{
340190787Szec
341190787Szec	ip6_init2_vnet(NULL);
342190787Szec}
343190787Szec
34453541Sshin/* cheat */
34555009Sshin/* This must be after route_init(), which is now SI_ORDER_THIRD */
34655009SshinSYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
34753541Sshin
34853541Sshinvoid
349171259Sdelphijip6_input(struct mbuf *m)
35053541Sshin{
35153541Sshin	struct ip6_hdr *ip6;
35253541Sshin	int off = sizeof(struct ip6_hdr), nest;
35353541Sshin	u_int32_t plen;
35453541Sshin	u_int32_t rtalert = ~0;
35553541Sshin	int nxt, ours = 0;
356186119Sqingli	struct ifnet *deliverifp = NULL, *ifp = NULL;
357121143Ssam	struct in6_addr odst;
358187989Sbz	struct route_in6 rin6;
359121143Ssam	int srcrt = 0;
360186119Sqingli	struct llentry *lle = NULL;
361187989Sbz	struct sockaddr_in6 dst6, *dst;
362121144Ssam
363187989Sbz	bzero(&rin6, sizeof(struct route_in6));
364171167Sgnn#ifdef IPSEC
36553541Sshin	/*
36653541Sshin	 * should the inner packet be considered authentic?
36753541Sshin	 * see comment in ah4_input().
368171133Sgnn	 * NB: m cannot be NULL when passed to the input routine
36953541Sshin	 */
37053541Sshin
371171133Sgnn	m->m_flags &= ~M_AUTHIPHDR;
372171133Sgnn	m->m_flags &= ~M_AUTHIPDGM;
373171133Sgnn
374171167Sgnn#endif /* IPSEC */
375171133Sgnn
37653541Sshin	/*
377121630Sume	 * make sure we don't have onion peering information into m_tag.
37878064Sume	 */
37978064Sume	ip6_delaux(m);
38078064Sume
38178064Sume	/*
38295023Ssuz	 * mbuf statistics
38353541Sshin	 */
38453541Sshin	if (m->m_flags & M_EXT) {
38553541Sshin		if (m->m_next)
386181803Sbz			V_ip6stat.ip6s_mext2m++;
38753541Sshin		else
388181803Sbz			V_ip6stat.ip6s_mext1++;
38953541Sshin	} else {
390181803Sbz#define M2MMAX	(sizeof(V_ip6stat.ip6s_m2m)/sizeof(V_ip6stat.ip6s_m2m[0]))
39153541Sshin		if (m->m_next) {
39253541Sshin			if (m->m_flags & M_LOOP) {
393193274Szec				V_ip6stat.ip6s_m2m[V_loif->if_index]++;
39478064Sume			} else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
395181803Sbz				V_ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
39653541Sshin			else
397181803Sbz				V_ip6stat.ip6s_m2m[0]++;
39853541Sshin		} else
399181803Sbz			V_ip6stat.ip6s_m1++;
40078064Sume#undef M2MMAX
40153541Sshin	}
40253541Sshin
403151474Ssuz	/* drop the packet if IPv6 operation is disabled on the IF */
404151474Ssuz	if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
405151474Ssuz		m_freem(m);
406151474Ssuz		return;
407151474Ssuz	}
408151474Ssuz
40953541Sshin	in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
410181803Sbz	V_ip6stat.ip6s_total++;
41153541Sshin
41262587Sitojun#ifndef PULLDOWN_TEST
41374336Skuriyama	/*
41474336Skuriyama	 * L2 bridge code and some other code can return mbuf chain
41574336Skuriyama	 * that does not conform to KAME requirement.  too bad.
41674336Skuriyama	 * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
41774336Skuriyama	 */
41874336Skuriyama	if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
41974336Skuriyama		struct mbuf *n;
42074336Skuriyama
421111119Simp		MGETHDR(n, M_DONTWAIT, MT_HEADER);
42277003Sume		if (n)
423108466Ssam			M_MOVE_PKTHDR(n, m);
424108825Ssam		if (n && n->m_pkthdr.len > MHLEN) {
425111119Simp			MCLGET(n, M_DONTWAIT);
42674336Skuriyama			if ((n->m_flags & M_EXT) == 0) {
42774336Skuriyama				m_freem(n);
42874336Skuriyama				n = NULL;
42974336Skuriyama			}
43074336Skuriyama		}
43195023Ssuz		if (n == NULL) {
43277003Sume			m_freem(m);
433120913Sume			return;	/* ENOBUFS */
43477003Sume		}
43574336Skuriyama
436108825Ssam		m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
437108825Ssam		n->m_len = n->m_pkthdr.len;
43874336Skuriyama		m_freem(m);
43974336Skuriyama		m = n;
44074336Skuriyama	}
441120913Sume	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */);
44262587Sitojun#endif
44353541Sshin
44453541Sshin	if (m->m_len < sizeof(struct ip6_hdr)) {
44553541Sshin		struct ifnet *inifp;
44653541Sshin		inifp = m->m_pkthdr.rcvif;
447120913Sume		if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
448181803Sbz			V_ip6stat.ip6s_toosmall++;
44953541Sshin			in6_ifstat_inc(inifp, ifs6_in_hdrerr);
45053541Sshin			return;
45153541Sshin		}
45253541Sshin	}
45353541Sshin
45453541Sshin	ip6 = mtod(m, struct ip6_hdr *);
45553541Sshin
45653541Sshin	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
457181803Sbz		V_ip6stat.ip6s_badvers++;
45853541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
45953541Sshin		goto bad;
46053541Sshin	}
46153541Sshin
462181803Sbz	V_ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
46353541Sshin
46453541Sshin	/*
46578064Sume	 * Check against address spoofing/corruption.
46653541Sshin	 */
46753541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
46853541Sshin	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
46978064Sume		/*
47078064Sume		 * XXX: "badscope" is not very suitable for a multicast source.
47178064Sume		 */
472181803Sbz		V_ip6stat.ip6s_badscope++;
47353541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
47453541Sshin		goto bad;
47553541Sshin	}
476126444Sume	if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
477126444Sume	    !(m->m_flags & M_LOOP)) {
478126444Sume		/*
479126444Sume		 * In this case, the packet should come from the loopback
480126444Sume		 * interface.  However, we cannot just check the if_flags,
481126444Sume		 * because ip6_mloopback() passes the "actual" interface
482126444Sume		 * as the outgoing/incoming interface.
483126444Sume		 */
484181803Sbz		V_ip6stat.ip6s_badscope++;
48578064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
48678064Sume		goto bad;
48778064Sume	}
48895023Ssuz
489130416Smlaier#ifdef ALTQ
490130416Smlaier	if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
491130416Smlaier		/* packet is dropped by traffic conditioner */
492130416Smlaier		return;
493130416Smlaier	}
494130416Smlaier#endif
49562587Sitojun	/*
49678064Sume	 * The following check is not documented in specs.  A malicious
49778064Sume	 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
49878064Sume	 * and bypass security checks (act as if it was from 127.0.0.1 by using
499120913Sume	 * IPv6 src ::ffff:127.0.0.1).  Be cautious.
50078064Sume	 *
50178064Sume	 * This check chokes if we are in an SIIT cloud.  As none of BSDs
50278064Sume	 * support IPv4-less kernel compilation, we cannot support SIIT
50378064Sume	 * environment at all.  So, it makes more sense for us to reject any
50478064Sume	 * malicious packets for non-SIIT environment, than try to do a
505120913Sume	 * partial support for SIIT environment.
50662587Sitojun	 */
50778064Sume	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
50878064Sume	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
509181803Sbz		V_ip6stat.ip6s_badscope++;
51078064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
51178064Sume		goto bad;
51278064Sume	}
51362587Sitojun#if 0
51462587Sitojun	/*
51562587Sitojun	 * Reject packets with IPv4 compatible addresses (auto tunnel).
51662587Sitojun	 *
51762587Sitojun	 * The code forbids auto tunnel relay case in RFC1933 (the check is
51862587Sitojun	 * stronger than RFC1933).  We may want to re-enable it if mech-xx
51962587Sitojun	 * is revised to forbid relaying case.
52062587Sitojun	 */
52162587Sitojun	if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
52262587Sitojun	    IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
523181803Sbz		V_ip6stat.ip6s_badscope++;
52462587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
52562587Sitojun		goto bad;
52662587Sitojun	}
52762587Sitojun#endif
52875246Sume
529126444Sume	/*
530126508Smlaier	 * Run through list of hooks for input packets.
531126508Smlaier	 *
532126508Smlaier	 * NB: Beware of the destination address changing
533126508Smlaier	 *     (e.g. by NAT rewriting).  When this happens,
534126508Smlaier	 *     tell ip6_forward to do the right thing.
535126508Smlaier	 */
536126508Smlaier	odst = ip6->ip6_dst;
537134383Sandre
538134383Sandre	/* Jump over all PFIL processing if hooks are not active. */
539155201Scsjp	if (!PFIL_HOOKED(&inet6_pfil_hook))
540134383Sandre		goto passin;
541134383Sandre
542135920Smlaier	if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL))
543126508Smlaier		return;
544126508Smlaier	if (m == NULL)			/* consumed by filter */
545126508Smlaier		return;
546126508Smlaier	ip6 = mtod(m, struct ip6_hdr *);
547126508Smlaier	srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
548126508Smlaier
549134383Sandrepassin:
550126508Smlaier	/*
551154804Sume	 * Disambiguate address scope zones (if there is ambiguity).
552154804Sume	 * We first make sure that the original source or destination address
553154804Sume	 * is not in our internal form for scoped addresses.  Such addresses
554154804Sume	 * are not necessarily invalid spec-wise, but we cannot accept them due
555154804Sume	 * to the usage conflict.
556154804Sume	 * in6_setscope() then also checks and rejects the cases where src or
557154804Sume	 * dst are the loopback address and the receiving interface
558154804Sume	 * is not loopback.
559154804Sume	 */
560154804Sume	if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) {
561181803Sbz		V_ip6stat.ip6s_badscope++; /* XXX */
562154804Sume		goto bad;
563154804Sume	}
564154804Sume	if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||
565154804Sume	    in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {
566181803Sbz		V_ip6stat.ip6s_badscope++;
567154804Sume		goto bad;
568154804Sume	}
569154804Sume
570154804Sume	/*
571191672Sbms	 * Multicast check. Assume packet is for us to avoid
572191672Sbms	 * prematurely taking locks.
57353541Sshin	 */
57453541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
575191672Sbms		ours = 1;
57653541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
57753541Sshin		deliverifp = m->m_pkthdr.rcvif;
57853541Sshin		goto hbhcheck;
57953541Sshin	}
58053541Sshin
58153541Sshin	/*
58253541Sshin	 *  Unicast check
58353541Sshin	 */
584186119Sqingli
585186119Sqingli	bzero(&dst6, sizeof(dst6));
586186119Sqingli	dst6.sin6_family = AF_INET6;
587186119Sqingli	dst6.sin6_len = sizeof(struct sockaddr_in6);
588186119Sqingli	dst6.sin6_addr = ip6->ip6_dst;
589186119Sqingli	ifp = m->m_pkthdr.rcvif;
590186119Sqingli	IF_AFDATA_LOCK(ifp);
591186119Sqingli	lle = lla_lookup(LLTABLE6(ifp), 0,
592186119Sqingli	     (struct sockaddr *)&dst6);
593186119Sqingli	IF_AFDATA_UNLOCK(ifp);
594186119Sqingli	if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
595186119Sqingli		ours = 1;
596186119Sqingli		deliverifp = ifp;
597186119Sqingli		LLE_RUNLOCK(lle);
598186119Sqingli		goto hbhcheck;
599186119Sqingli	}
600186293Sbz	if (lle != NULL)
601186293Sbz		LLE_RUNLOCK(lle);
602186119Sqingli
603187989Sbz	dst = &rin6.ro_dst;
604187989Sbz	dst->sin6_len = sizeof(struct sockaddr_in6);
605187989Sbz	dst->sin6_family = AF_INET6;
606187989Sbz	dst->sin6_addr = ip6->ip6_dst;
607187989Sbz	rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
608187989Sbz	if (rin6.ro_rt)
609187989Sbz		RT_UNLOCK(rin6.ro_rt);
61078064Sume
61153541Sshin#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
61253541Sshin
61353541Sshin	/*
61453541Sshin	 * Accept the packet if the forwarding interface to the destination
61553541Sshin	 * according to the routing table is the loopback interface,
61653541Sshin	 * unless the associated route has a gateway.
61753541Sshin	 * Note that this approach causes to accept a packet if there is a
61853541Sshin	 * route to the loopback interface for the destination of the packet.
61953541Sshin	 * But we think it's even useful in some situations, e.g. when using
62053541Sshin	 * a special daemon which wants to intercept the packet.
62178064Sume	 *
62278064Sume	 * XXX: some OSes automatically make a cloned route for the destination
62378064Sume	 * of an outgoing packet.  If the outgoing interface of the packet
62478064Sume	 * is a loopback one, the kernel would consider the packet to be
62578064Sume	 * accepted, even if we have no such address assinged on the interface.
62678064Sume	 * We check the cloned flag of the route entry to reject such cases,
62778064Sume	 * assuming that route entries for our own addresses are not made by
62878064Sume	 * cloning (it should be true because in6_addloop explicitly installs
62978064Sume	 * the host route).  However, we might have to do an explicit check
63078064Sume	 * while it would be less efficient.  Or, should we rather install a
63178064Sume	 * reject route for such a case?
63253541Sshin	 */
633187989Sbz	if (rin6.ro_rt &&
634187989Sbz	    (rin6.ro_rt->rt_flags &
63553541Sshin	     (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
63678064Sume#ifdef RTF_WASCLONED
637187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
63878064Sume#endif
63978064Sume#ifdef RTF_CLONED
640187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_CLONED) &&
64178064Sume#endif
64262587Sitojun#if 0
64353541Sshin	    /*
64462587Sitojun	     * The check below is redundant since the comparison of
64562587Sitojun	     * the destination and the key of the rtentry has
64662587Sitojun	     * already done through looking up the routing table.
64753541Sshin	     */
64862587Sitojun	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
649187989Sbz	    &rt6_key(rin6.ro_rt)->sin6_addr)
65062587Sitojun#endif
651187989Sbz	    rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
65253541Sshin		struct in6_ifaddr *ia6 =
653187989Sbz			(struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
65478064Sume
65562587Sitojun		/*
656121630Sume		 * record address information into m_tag.
65778064Sume		 */
65878064Sume		(void)ip6_setdstifaddr(m, ia6);
65978064Sume
66078064Sume		/*
66162587Sitojun		 * packets to a tentative, duplicated, or somehow invalid
66262587Sitojun		 * address must not be accepted.
66362587Sitojun		 */
66453541Sshin		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
66562587Sitojun			/* this address is ready */
66653541Sshin			ours = 1;
66753541Sshin			deliverifp = ia6->ia_ifp;	/* correct? */
66867334Sjoe			/* Count the packet in the ip address stats */
66967334Sjoe			ia6->ia_ifa.if_ipackets++;
67067334Sjoe			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
67153541Sshin			goto hbhcheck;
67253541Sshin		} else {
673165118Sbz			char ip6bufs[INET6_ADDRSTRLEN];
674165118Sbz			char ip6bufd[INET6_ADDRSTRLEN];
67562587Sitojun			/* address is not ready, so discard the packet. */
67678064Sume			nd6log((LOG_INFO,
67778064Sume			    "ip6_input: packet to an unready address %s->%s\n",
678165118Sbz			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
679165118Sbz			    ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
68062587Sitojun
68162587Sitojun			goto bad;
68253541Sshin		}
68353541Sshin	}
68453541Sshin
68553541Sshin	/*
686120913Sume	 * FAITH (Firewall Aided Internet Translator)
68753541Sshin	 */
688181803Sbz	if (V_ip6_keepfaith) {
689187989Sbz		if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
690187989Sbz		    rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
69153541Sshin			/* XXX do we need more sanity checks? */
69253541Sshin			ours = 1;
693187989Sbz			deliverifp = rin6.ro_rt->rt_ifp; /* faith */
69453541Sshin			goto hbhcheck;
69553541Sshin		}
69653541Sshin	}
69753541Sshin
69853541Sshin	/*
69953541Sshin	 * Now there is no reason to process the packet if it's not our own
70053541Sshin	 * and we're not a router.
70153541Sshin	 */
702181803Sbz	if (!V_ip6_forwarding) {
703181803Sbz		V_ip6stat.ip6s_cantforward++;
70453541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
70553541Sshin		goto bad;
70653541Sshin	}
70753541Sshin
70853541Sshin  hbhcheck:
70953541Sshin	/*
710121630Sume	 * record address information into m_tag, if we don't have one yet.
71178064Sume	 * note that we are unable to record it, if the address is not listed
71278064Sume	 * as our interface address (e.g. multicast addresses, addresses
71378064Sume	 * within FAITH prefixes and such).
71478064Sume	 */
71578064Sume	if (deliverifp && !ip6_getdstifaddr(m)) {
71678064Sume		struct in6_ifaddr *ia6;
71778064Sume
71878064Sume		ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
71978064Sume		if (ia6) {
72078064Sume			if (!ip6_setdstifaddr(m, ia6)) {
72178064Sume				/*
72278064Sume				 * XXX maybe we should drop the packet here,
72378064Sume				 * as we could not provide enough information
72478064Sume				 * to the upper layers.
72578064Sume				 */
72678064Sume			}
727194760Srwatson			ifa_free(&ia6->ia_ifa);
72878064Sume		}
72978064Sume	}
73078064Sume
73178064Sume	/*
73253541Sshin	 * Process Hop-by-Hop options header if it's contained.
73353541Sshin	 * m may be modified in ip6_hopopts_input().
73453541Sshin	 * If a JumboPayload option is included, plen will also be modified.
73553541Sshin	 */
73653541Sshin	plen = (u_int32_t)ntohs(ip6->ip6_plen);
73753541Sshin	if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
73862587Sitojun		struct ip6_hbh *hbh;
73962587Sitojun
74053541Sshin		if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
74162587Sitojun#if 0	/*touches NULL pointer*/
74253541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
74362587Sitojun#endif
744187989Sbz			goto out;	/* m have already been freed */
74553541Sshin		}
74662587Sitojun
74753541Sshin		/* adjust pointer */
74853541Sshin		ip6 = mtod(m, struct ip6_hdr *);
74953541Sshin
75053541Sshin		/*
75195023Ssuz		 * if the payload length field is 0 and the next header field
75262587Sitojun		 * indicates Hop-by-Hop Options header, then a Jumbo Payload
75362587Sitojun		 * option MUST be included.
75462587Sitojun		 */
75562587Sitojun		if (ip6->ip6_plen == 0 && plen == 0) {
75662587Sitojun			/*
75762587Sitojun			 * Note that if a valid jumbo payload option is
758120913Sume			 * contained, ip6_hopopts_input() must set a valid
759120913Sume			 * (non-zero) payload length to the variable plen.
76062587Sitojun			 */
761181803Sbz			V_ip6stat.ip6s_badoptions++;
76262587Sitojun			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
76362587Sitojun			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
76462587Sitojun			icmp6_error(m, ICMP6_PARAM_PROB,
76562587Sitojun				    ICMP6_PARAMPROB_HEADER,
76662587Sitojun				    (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
767187989Sbz			goto out;
76862587Sitojun		}
76962587Sitojun#ifndef PULLDOWN_TEST
77062587Sitojun		/* ip6_hopopts_input() ensures that mbuf is contiguous */
77162587Sitojun		hbh = (struct ip6_hbh *)(ip6 + 1);
77262587Sitojun#else
77362587Sitojun		IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
77462587Sitojun			sizeof(struct ip6_hbh));
77562587Sitojun		if (hbh == NULL) {
776181803Sbz			V_ip6stat.ip6s_tooshort++;
777187989Sbz			goto out;
77862587Sitojun		}
77962587Sitojun#endif
78062587Sitojun		nxt = hbh->ip6h_nxt;
78162587Sitojun
78262587Sitojun		/*
783169557Sjinmei		 * If we are acting as a router and the packet contains a
784169557Sjinmei		 * router alert option, see if we know the option value.
785169557Sjinmei		 * Currently, we only support the option value for MLD, in which
786169557Sjinmei		 * case we should pass the packet to the multicast routing
787169557Sjinmei		 * daemon.
78853541Sshin		 */
789192923Sbms		if (rtalert != ~0) {
790169557Sjinmei			switch (rtalert) {
791169557Sjinmei			case IP6OPT_RTALERT_MLD:
792192923Sbms				if (V_ip6_forwarding)
793192923Sbms					ours = 1;
794169557Sjinmei				break;
795169557Sjinmei			default:
796169557Sjinmei				/*
797169557Sjinmei				 * RFC2711 requires unrecognized values must be
798169557Sjinmei				 * silently ignored.
799169557Sjinmei				 */
800169557Sjinmei				break;
801169557Sjinmei			}
802169557Sjinmei		}
80353541Sshin	} else
80453541Sshin		nxt = ip6->ip6_nxt;
80553541Sshin
80653541Sshin	/*
80753541Sshin	 * Check that the amount of data in the buffers
80853541Sshin	 * is as at least much as the IPv6 header would have us expect.
80953541Sshin	 * Trim mbufs if longer than we expect.
81053541Sshin	 * Drop packet if shorter than we expect.
81153541Sshin	 */
81253541Sshin	if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
813181803Sbz		V_ip6stat.ip6s_tooshort++;
81453541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
81553541Sshin		goto bad;
81653541Sshin	}
81753541Sshin	if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
81853541Sshin		if (m->m_len == m->m_pkthdr.len) {
81953541Sshin			m->m_len = sizeof(struct ip6_hdr) + plen;
82053541Sshin			m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
82153541Sshin		} else
82253541Sshin			m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
82353541Sshin	}
82453541Sshin
82553541Sshin	/*
82653541Sshin	 * Forward if desirable.
82753541Sshin	 */
828191672Sbms	if (V_ip6_mrouter &&
829191672Sbms	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
83056723Sshin		/*
83156723Sshin		 * If we are acting as a multicast router, all
83256723Sshin		 * incoming multicast packets are passed to the
83356723Sshin		 * kernel-level multicast forwarding function.
83456723Sshin		 * The packet is returned (relatively) intact; if
83556723Sshin		 * ip6_mforward() returns a non-zero value, the packet
83656723Sshin		 * must be discarded, else it may be accepted below.
837192923Sbms		 *
838192923Sbms		 * XXX TODO: Check hlim and multicast scope here to avoid
839192923Sbms		 * unnecessarily calling into ip6_mforward().
84056723Sshin		 */
841191672Sbms		if (ip6_mforward &&
842166938Sbms		    ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
843191672Sbms			IP6STAT_INC(ip6s_cantforward);
844191672Sbms			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
845187989Sbz			goto bad;
84656723Sshin		}
84753541Sshin	} else if (!ours) {
848121143Ssam		ip6_forward(m, srcrt);
849187989Sbz		goto out;
850121673Sume	}
85153541Sshin
85262587Sitojun	ip6 = mtod(m, struct ip6_hdr *);
85362587Sitojun
85453541Sshin	/*
85562587Sitojun	 * Malicious party may be able to use IPv4 mapped addr to confuse
85662587Sitojun	 * tcp/udp stack and bypass security checks (act as if it was from
85762587Sitojun	 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
85862587Sitojun	 *
85962587Sitojun	 * For SIIT end node behavior, you may want to disable the check.
86062587Sitojun	 * However, you will  become vulnerable to attacks using IPv4 mapped
86162587Sitojun	 * source.
86262587Sitojun	 */
86362587Sitojun	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
86462587Sitojun	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
865181803Sbz		V_ip6stat.ip6s_badscope++;
86662587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
86762587Sitojun		goto bad;
86862587Sitojun	}
86962587Sitojun
87062587Sitojun	/*
87153541Sshin	 * Tell launch routine the next header
87253541Sshin	 */
873181803Sbz	V_ip6stat.ip6s_delivered++;
87453541Sshin	in6_ifstat_inc(deliverifp, ifs6_in_deliver);
87553541Sshin	nest = 0;
87678064Sume
87753541Sshin	while (nxt != IPPROTO_DONE) {
878181803Sbz		if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
879181803Sbz			V_ip6stat.ip6s_toomanyhdr++;
88053541Sshin			goto bad;
88153541Sshin		}
88253541Sshin
88353541Sshin		/*
88453541Sshin		 * protection against faulty packet - there should be
88553541Sshin		 * more sanity checks in header chain processing.
88653541Sshin		 */
88753541Sshin		if (m->m_pkthdr.len < off) {
888181803Sbz			V_ip6stat.ip6s_tooshort++;
88953541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
89053541Sshin			goto bad;
89153541Sshin		}
89253541Sshin
893171167Sgnn#ifdef IPSEC
89478064Sume		/*
89578064Sume		 * enforce IPsec policy checking if we are seeing last header.
89678064Sume		 * note that we do not visit this with protocols with pcb layer
89778064Sume		 * code - like udp/tcp/raw ip.
89878064Sume		 */
899171133Sgnn		if (ip6_ipsec_input(m, nxt))
90078064Sume			goto bad;
901171167Sgnn#endif /* IPSEC */
902192923Sbms
903192923Sbms		/*
904192923Sbms		 * Use mbuf flags to propagate Router Alert option to
905192923Sbms		 * ICMPv6 layer, as hop-by-hop options have been stripped.
906192923Sbms		 */
907192923Sbms		if (nxt == IPPROTO_ICMPV6 && rtalert != ~0)
908192923Sbms			m->m_flags |= M_RTALERT_MLD;
909192923Sbms
91053541Sshin		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
91153541Sshin	}
912187989Sbz	goto out;
913187989Sbzbad:
91453541Sshin	m_freem(m);
915187989Sbzout:
916187989Sbz	if (rin6.ro_rt)
917187989Sbz		RTFREE(rin6.ro_rt);
91853541Sshin}
91953541Sshin
92053541Sshin/*
92178064Sume * set/grab in6_ifaddr correspond to IPv6 destination address.
92278064Sume * XXX backward compatibility wrapper
923194760Srwatson *
924194760Srwatson * XXXRW: We should bump the refcount on ia6 before sticking it in the m_tag,
925194760Srwatson * and then bump it when the tag is copied, and release it when the tag is
926194760Srwatson * freed.  Unfortunately, m_tags don't support deep copies (yet), so instead
927194760Srwatson * we just bump the ia refcount when we receive it.  This should be fixed.
92878064Sume */
929121673Sumestatic struct ip6aux *
930171259Sdelphijip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
93178064Sume{
932121673Sume	struct ip6aux *ip6a;
93378064Sume
934121673Sume	ip6a = ip6_addaux(m);
935121673Sume	if (ip6a)
936121673Sume		ip6a->ip6a_dstia6 = ia6;
937121673Sume	return ip6a;	/* NULL if failed to set */
93878064Sume}
93978064Sume
94078064Sumestruct in6_ifaddr *
941171259Sdelphijip6_getdstifaddr(struct mbuf *m)
94278064Sume{
943121673Sume	struct ip6aux *ip6a;
944194760Srwatson	struct in6_ifaddr *ia;
94578064Sume
946121673Sume	ip6a = ip6_findaux(m);
947194760Srwatson	if (ip6a) {
948194760Srwatson		ia = ip6a->ip6a_dstia6;
949194760Srwatson		ifa_ref(&ia->ia_ifa);
950194760Srwatson		return ia;
951194760Srwatson	} else
95278064Sume		return NULL;
95378064Sume}
95478064Sume
95578064Sume/*
95653541Sshin * Hop-by-Hop options header processing. If a valid jumbo payload option is
95753541Sshin * included, the real payload length will be stored in plenp.
958171259Sdelphij *
959171259Sdelphij * rtalertp - XXX: should be stored more smart way
96053541Sshin */
96153541Sshinstatic int
962171259Sdelphijip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
963171259Sdelphij    struct mbuf **mp, int *offp)
96453541Sshin{
96578064Sume	struct mbuf *m = *mp;
96653541Sshin	int off = *offp, hbhlen;
96753541Sshin	struct ip6_hbh *hbh;
96853541Sshin	u_int8_t *opt;
96953541Sshin
97053541Sshin	/* validation of the length of the header */
97162587Sitojun#ifndef PULLDOWN_TEST
97253541Sshin	IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
97353541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
97453541Sshin	hbhlen = (hbh->ip6h_len + 1) << 3;
97553541Sshin
97653541Sshin	IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
97753541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
97862587Sitojun#else
97962587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
98062587Sitojun		sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
98162587Sitojun	if (hbh == NULL) {
982181803Sbz		V_ip6stat.ip6s_tooshort++;
98362587Sitojun		return -1;
98462587Sitojun	}
98562587Sitojun	hbhlen = (hbh->ip6h_len + 1) << 3;
98662587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
98762587Sitojun		hbhlen);
98862587Sitojun	if (hbh == NULL) {
989181803Sbz		V_ip6stat.ip6s_tooshort++;
99062587Sitojun		return -1;
99162587Sitojun	}
99262587Sitojun#endif
99353541Sshin	off += hbhlen;
99453541Sshin	hbhlen -= sizeof(struct ip6_hbh);
99553541Sshin	opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
99653541Sshin
99753541Sshin	if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
99853541Sshin				hbhlen, rtalertp, plenp) < 0)
999120856Sume		return (-1);
100053541Sshin
100153541Sshin	*offp = off;
100253541Sshin	*mp = m;
1003120856Sume	return (0);
100453541Sshin}
100553541Sshin
100653541Sshin/*
100753541Sshin * Search header for all Hop-by-hop options and process each option.
100853541Sshin * This function is separate from ip6_hopopts_input() in order to
100953541Sshin * handle a case where the sending node itself process its hop-by-hop
101053541Sshin * options header. In such a case, the function is called from ip6_output().
101178064Sume *
101278064Sume * The function assumes that hbh header is located right after the IPv6 header
101378064Sume * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
101478064Sume * opthead + hbhlen is located in continuous memory region.
101553541Sshin */
101653541Sshinint
1017171259Sdelphijip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
1018171259Sdelphij    u_int32_t *rtalertp, u_int32_t *plenp)
101953541Sshin{
102053541Sshin	struct ip6_hdr *ip6;
102153541Sshin	int optlen = 0;
102253541Sshin	u_int8_t *opt = opthead;
102353541Sshin	u_int16_t rtalert_val;
102462587Sitojun	u_int32_t jumboplen;
102578064Sume	const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
102653541Sshin
102753541Sshin	for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
102878064Sume		switch (*opt) {
102978064Sume		case IP6OPT_PAD1:
103078064Sume			optlen = 1;
103178064Sume			break;
103278064Sume		case IP6OPT_PADN:
103378064Sume			if (hbhlen < IP6OPT_MINLEN) {
1034181803Sbz				V_ip6stat.ip6s_toosmall++;
103578064Sume				goto bad;
103678064Sume			}
103778064Sume			optlen = *(opt + 1) + 2;
103878064Sume			break;
1039121472Sume		case IP6OPT_ROUTER_ALERT:
104062587Sitojun			/* XXX may need check for alignment */
104178064Sume			if (hbhlen < IP6OPT_RTALERT_LEN) {
1042181803Sbz				V_ip6stat.ip6s_toosmall++;
104378064Sume				goto bad;
104478064Sume			}
104578064Sume			if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
104678064Sume				/* XXX stat */
104778064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1048120913Sume				    ICMP6_PARAMPROB_HEADER,
1049120913Sume				    erroff + opt + 1 - opthead);
1050120856Sume				return (-1);
105178064Sume			}
105278064Sume			optlen = IP6OPT_RTALERT_LEN;
105378064Sume			bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
105478064Sume			*rtalertp = ntohs(rtalert_val);
105578064Sume			break;
105678064Sume		case IP6OPT_JUMBO:
105778064Sume			/* XXX may need check for alignment */
105862587Sitojun			if (hbhlen < IP6OPT_JUMBO_LEN) {
1059181803Sbz				V_ip6stat.ip6s_toosmall++;
106062587Sitojun				goto bad;
106162587Sitojun			}
106278064Sume			if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
106378064Sume				/* XXX stat */
106478064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1065120913Sume				    ICMP6_PARAMPROB_HEADER,
1066120913Sume				    erroff + opt + 1 - opthead);
1067120856Sume				return (-1);
106878064Sume			}
106962587Sitojun			optlen = IP6OPT_JUMBO_LEN;
107053541Sshin
107162587Sitojun			/*
107262587Sitojun			 * IPv6 packets that have non 0 payload length
107378064Sume			 * must not contain a jumbo payload option.
107462587Sitojun			 */
107562587Sitojun			ip6 = mtod(m, struct ip6_hdr *);
107662587Sitojun			if (ip6->ip6_plen) {
1077181803Sbz				V_ip6stat.ip6s_badoptions++;
107862587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1079120913Sume				    ICMP6_PARAMPROB_HEADER,
1080120913Sume				    erroff + opt - opthead);
1081120856Sume				return (-1);
108262587Sitojun			}
108353541Sshin
108462587Sitojun			/*
108562587Sitojun			 * We may see jumbolen in unaligned location, so
108662587Sitojun			 * we'd need to perform bcopy().
108762587Sitojun			 */
108862587Sitojun			bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
108962587Sitojun			jumboplen = (u_int32_t)htonl(jumboplen);
109062587Sitojun
109162587Sitojun#if 1
109262587Sitojun			/*
109362587Sitojun			 * if there are multiple jumbo payload options,
109462587Sitojun			 * *plenp will be non-zero and the packet will be
109562587Sitojun			 * rejected.
109662587Sitojun			 * the behavior may need some debate in ipngwg -
109762587Sitojun			 * multiple options does not make sense, however,
109862587Sitojun			 * there's no explicit mention in specification.
109962587Sitojun			 */
110062587Sitojun			if (*plenp != 0) {
1101181803Sbz				V_ip6stat.ip6s_badoptions++;
110262587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1103120913Sume				    ICMP6_PARAMPROB_HEADER,
1104120913Sume				    erroff + opt + 2 - opthead);
1105120856Sume				return (-1);
110662587Sitojun			}
110762587Sitojun#endif
110862587Sitojun
110962587Sitojun			/*
111062587Sitojun			 * jumbo payload length must be larger than 65535.
111162587Sitojun			 */
111262587Sitojun			if (jumboplen <= IPV6_MAXPACKET) {
1113181803Sbz				V_ip6stat.ip6s_badoptions++;
111462587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1115120913Sume				    ICMP6_PARAMPROB_HEADER,
1116120913Sume				    erroff + opt + 2 - opthead);
1117120856Sume				return (-1);
111862587Sitojun			}
111962587Sitojun			*plenp = jumboplen;
112062587Sitojun
112162587Sitojun			break;
112278064Sume		default:		/* unknown option */
112378064Sume			if (hbhlen < IP6OPT_MINLEN) {
1124181803Sbz				V_ip6stat.ip6s_toosmall++;
112578064Sume				goto bad;
112678064Sume			}
112778064Sume			optlen = ip6_unknown_opt(opt, m,
112878064Sume			    erroff + opt - opthead);
112978064Sume			if (optlen == -1)
1130120856Sume				return (-1);
113178064Sume			optlen += 2;
113278064Sume			break;
113353541Sshin		}
113453541Sshin	}
113553541Sshin
1136120856Sume	return (0);
113753541Sshin
113853541Sshin  bad:
113953541Sshin	m_freem(m);
1140120856Sume	return (-1);
114153541Sshin}
114253541Sshin
114353541Sshin/*
114453541Sshin * Unknown option processing.
114553541Sshin * The third argument `off' is the offset from the IPv6 header to the option,
114653541Sshin * which is necessary if the IPv6 header the and option header and IPv6 header
114753541Sshin * is not continuous in order to return an ICMPv6 error.
114853541Sshin */
114953541Sshinint
1150171259Sdelphijip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off)
115153541Sshin{
115253541Sshin	struct ip6_hdr *ip6;
115353541Sshin
115478064Sume	switch (IP6OPT_TYPE(*optp)) {
115578064Sume	case IP6OPT_TYPE_SKIP: /* ignore the option */
1156120856Sume		return ((int)*(optp + 1));
115778064Sume	case IP6OPT_TYPE_DISCARD:	/* silently discard */
115878064Sume		m_freem(m);
1159120856Sume		return (-1);
116078064Sume	case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1161181803Sbz		V_ip6stat.ip6s_badoptions++;
116278064Sume		icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1163120856Sume		return (-1);
116478064Sume	case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1165181803Sbz		V_ip6stat.ip6s_badoptions++;
116678064Sume		ip6 = mtod(m, struct ip6_hdr *);
116778064Sume		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
116878064Sume		    (m->m_flags & (M_BCAST|M_MCAST)))
116978064Sume			m_freem(m);
117078064Sume		else
117178064Sume			icmp6_error(m, ICMP6_PARAM_PROB,
117278064Sume				    ICMP6_PARAMPROB_OPTION, off);
1173120856Sume		return (-1);
117453541Sshin	}
117553541Sshin
117653541Sshin	m_freem(m);		/* XXX: NOTREACHED */
1177120856Sume	return (-1);
117853541Sshin}
117953541Sshin
118053541Sshin/*
118162587Sitojun * Create the "control" list for this pcb.
1182179289Sbz * These functions will not modify mbuf chain at all.
118362587Sitojun *
1184179289Sbz * With KAME mbuf chain restriction:
118562587Sitojun * The routine will be called from upper layer handlers like tcp6_input().
118662587Sitojun * Thus the routine assumes that the caller (tcp6_input) have already
118762587Sitojun * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
118862587Sitojun * very first mbuf on the mbuf chain.
1189179289Sbz *
1190179289Sbz * ip6_savecontrol_v4 will handle those options that are possible to be
1191179289Sbz * set on a v4-mapped socket.
1192179289Sbz * ip6_savecontrol will directly call ip6_savecontrol_v4 to handle those
1193179289Sbz * options and handle the v6-only ones itself.
119453541Sshin */
1195181782Sbzstruct mbuf **
1196181782Sbzip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
1197181782Sbz    int *v4only)
119853541Sshin{
1199121674Sume	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
120053541Sshin
120178064Sume#ifdef SO_TIMESTAMP
1202179289Sbz	if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
120353541Sshin		struct timeval tv;
120453541Sshin
120553541Sshin		microtime(&tv);
120653541Sshin		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1207120913Sume		    SCM_TIMESTAMP, SOL_SOCKET);
1208121472Sume		if (*mp)
120953541Sshin			mp = &(*mp)->m_next;
121097658Stanimura	}
121162587Sitojun#endif
121262587Sitojun
1213181782Sbz	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1214181782Sbz		if (v4only != NULL)
1215181782Sbz			*v4only = 1;
1216181782Sbz		return (mp);
1217181782Sbz	}
1218121631Sume
1219179289Sbz#define IS2292(inp, x, y)	(((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
122053541Sshin	/* RFC 2292 sec. 5 */
1221179289Sbz	if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
122253541Sshin		struct in6_pktinfo pi6;
1223120913Sume
122453541Sshin		bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1225121315Sume		in6_clearscope(&pi6.ipi6_addr);	/* XXX */
1226120913Sume		pi6.ipi6_ifindex =
1227120913Sume		    (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
1228120913Sume
122953541Sshin		*mp = sbcreatecontrol((caddr_t) &pi6,
1230120913Sume		    sizeof(struct in6_pktinfo),
1231179289Sbz		    IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
1232121472Sume		if (*mp)
123353541Sshin			mp = &(*mp)->m_next;
123453541Sshin	}
123578064Sume
1236179289Sbz	if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
123753541Sshin		int hlim = ip6->ip6_hlim & 0xff;
1238120913Sume
1239120913Sume		*mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1240179289Sbz		    IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
1241179289Sbz		    IPPROTO_IPV6);
1242121472Sume		if (*mp)
124353541Sshin			mp = &(*mp)->m_next;
124453541Sshin	}
124553541Sshin
1246181782Sbz	if (v4only != NULL)
1247181782Sbz		*v4only = 0;
1248181782Sbz	return (mp);
1249179289Sbz}
1250179289Sbz
1251179289Sbzvoid
1252179289Sbzip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
1253179289Sbz{
1254179289Sbz	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1255181782Sbz	int v4only = 0;
1256179289Sbz
1257181782Sbz	mp = ip6_savecontrol_v4(in6p, m, mp, &v4only);
1258181782Sbz	if (v4only)
1259179289Sbz		return;
1260179289Sbz
1261186141Sbz	if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
1262121472Sume		u_int32_t flowinfo;
1263121472Sume		int tclass;
1264121472Sume
1265121472Sume		flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1266121472Sume		flowinfo >>= 20;
1267121472Sume
1268121472Sume		tclass = flowinfo & 0xff;
1269121472Sume		*mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass),
1270121472Sume		    IPV6_TCLASS, IPPROTO_IPV6);
1271121472Sume		if (*mp)
1272121472Sume			mp = &(*mp)->m_next;
1273121472Sume	}
1274121472Sume
127553541Sshin	/*
1276130002Sume	 * IPV6_HOPOPTS socket option.  Recall that we required super-user
1277130002Sume	 * privilege for the option (see ip6_ctloutput), but it might be too
1278130002Sume	 * strict, since there might be some hop-by-hop options which can be
1279130002Sume	 * returned to normal user.
1280130002Sume	 * See also RFC 2292 section 6 (or RFC 3542 section 8).
128153541Sshin	 */
1282186141Sbz	if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
128353541Sshin		/*
128453541Sshin		 * Check if a hop-by-hop options header is contatined in the
128553541Sshin		 * received packet, and if so, store the options as ancillary
128653541Sshin		 * data. Note that a hop-by-hop options header must be
1287120913Sume		 * just after the IPv6 header, which is assured through the
1288120913Sume		 * IPv6 input processing.
128953541Sshin		 */
129053541Sshin		if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
129162587Sitojun			struct ip6_hbh *hbh;
129278064Sume			int hbhlen = 0;
129378064Sume#ifdef PULLDOWN_TEST
129478064Sume			struct mbuf *ext;
129578064Sume#endif
129653541Sshin
129762587Sitojun#ifndef PULLDOWN_TEST
129862587Sitojun			hbh = (struct ip6_hbh *)(ip6 + 1);
129962587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
130062587Sitojun#else
130178064Sume			ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
130278064Sume			    ip6->ip6_nxt);
130378064Sume			if (ext == NULL) {
1304181803Sbz				V_ip6stat.ip6s_tooshort++;
130562587Sitojun				return;
130662587Sitojun			}
130778064Sume			hbh = mtod(ext, struct ip6_hbh *);
130862587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
130978064Sume			if (hbhlen != ext->m_len) {
131078064Sume				m_freem(ext);
1311181803Sbz				V_ip6stat.ip6s_tooshort++;
131262587Sitojun				return;
131362587Sitojun			}
131462587Sitojun#endif
131562587Sitojun
131653541Sshin			/*
1317120913Sume			 * XXX: We copy the whole header even if a
1318120913Sume			 * jumbo payload option is included, the option which
1319120913Sume			 * is to be removed before returning according to
1320120913Sume			 * RFC2292.
1321148169Sume			 * Note: this constraint is removed in RFC3542
132253541Sshin			 */
132362587Sitojun			*mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1324179289Sbz			    IS2292(in6p, IPV6_2292HOPOPTS, IPV6_HOPOPTS),
1325121472Sume			    IPPROTO_IPV6);
1326121472Sume			if (*mp)
132753541Sshin				mp = &(*mp)->m_next;
132878064Sume#ifdef PULLDOWN_TEST
132978064Sume			m_freem(ext);
133078064Sume#endif
133153541Sshin		}
133253541Sshin	}
133353541Sshin
1334186141Sbz	if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
133578064Sume		int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
133653541Sshin
133753541Sshin		/*
133853541Sshin		 * Search for destination options headers or routing
133953541Sshin		 * header(s) through the header chain, and stores each
134053541Sshin		 * header as ancillary data.
134153541Sshin		 * Note that the order of the headers remains in
134253541Sshin		 * the chain of ancillary data.
134353541Sshin		 */
134478064Sume		while (1) {	/* is explicit loop prevention necessary? */
134578064Sume			struct ip6_ext *ip6e = NULL;
134662587Sitojun			int elen;
134778064Sume#ifdef PULLDOWN_TEST
134878064Sume			struct mbuf *ext = NULL;
134978064Sume#endif
135053541Sshin
135178064Sume			/*
135278064Sume			 * if it is not an extension header, don't try to
135378064Sume			 * pull it from the chain.
135478064Sume			 */
135578064Sume			switch (nxt) {
135678064Sume			case IPPROTO_DSTOPTS:
135778064Sume			case IPPROTO_ROUTING:
135878064Sume			case IPPROTO_HOPOPTS:
135978064Sume			case IPPROTO_AH: /* is it possible? */
136078064Sume				break;
136178064Sume			default:
136278064Sume				goto loopend;
136378064Sume			}
136478064Sume
136562587Sitojun#ifndef PULLDOWN_TEST
136678064Sume			if (off + sizeof(*ip6e) > m->m_len)
136778064Sume				goto loopend;
136862587Sitojun			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
136962587Sitojun			if (nxt == IPPROTO_AH)
137062587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
137162587Sitojun			else
137262587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
137378064Sume			if (off + elen > m->m_len)
137478064Sume				goto loopend;
137562587Sitojun#else
137678064Sume			ext = ip6_pullexthdr(m, off, nxt);
137778064Sume			if (ext == NULL) {
1378181803Sbz				V_ip6stat.ip6s_tooshort++;
137962587Sitojun				return;
138062587Sitojun			}
138178064Sume			ip6e = mtod(ext, struct ip6_ext *);
138262587Sitojun			if (nxt == IPPROTO_AH)
138362587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
138462587Sitojun			else
138562587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
138678064Sume			if (elen != ext->m_len) {
138778064Sume				m_freem(ext);
1388181803Sbz				V_ip6stat.ip6s_tooshort++;
138962587Sitojun				return;
139062587Sitojun			}
139162587Sitojun#endif
139262587Sitojun
139378064Sume			switch (nxt) {
139478064Sume			case IPPROTO_DSTOPTS:
1395186141Sbz				if (!(in6p->inp_flags & IN6P_DSTOPTS))
139678064Sume					break;
139753541Sshin
139878064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1399179289Sbz				    IS2292(in6p,
1400179289Sbz					IPV6_2292DSTOPTS, IPV6_DSTOPTS),
1401120913Sume				    IPPROTO_IPV6);
140278064Sume				if (*mp)
140378064Sume					mp = &(*mp)->m_next;
140478064Sume				break;
140578064Sume			case IPPROTO_ROUTING:
1406186141Sbz				if (!in6p->inp_flags & IN6P_RTHDR)
140778064Sume					break;
140853541Sshin
140978064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1410179289Sbz				    IS2292(in6p, IPV6_2292RTHDR, IPV6_RTHDR),
1411120913Sume				    IPPROTO_IPV6);
141278064Sume				if (*mp)
141378064Sume					mp = &(*mp)->m_next;
141478064Sume				break;
141578064Sume			case IPPROTO_HOPOPTS:
141678064Sume			case IPPROTO_AH: /* is it possible? */
141778064Sume				break;
141853541Sshin
141978064Sume			default:
142078064Sume				/*
1421171260Sdelphij				 * other cases have been filtered in the above.
142278064Sume				 * none will visit this case.  here we supply
142378064Sume				 * the code just in case (nxt overwritten or
142478064Sume				 * other cases).
142578064Sume				 */
142678064Sume#ifdef PULLDOWN_TEST
142778064Sume				m_freem(ext);
142878064Sume#endif
142978064Sume				goto loopend;
143053541Sshin
143153541Sshin			}
143253541Sshin
143353541Sshin			/* proceed with the next header. */
143462587Sitojun			off += elen;
143553541Sshin			nxt = ip6e->ip6e_nxt;
143678064Sume			ip6e = NULL;
143778064Sume#ifdef PULLDOWN_TEST
143878064Sume			m_freem(ext);
143978064Sume			ext = NULL;
144078064Sume#endif
144153541Sshin		}
144253541Sshin	  loopend:
144378064Sume		;
144453541Sshin	}
1445179289Sbz}
1446121472Sume#undef IS2292
144778064Sume
1448125776Sumevoid
1449171259Sdelphijip6_notify_pmtu(struct inpcb *in6p, struct sockaddr_in6 *dst, u_int32_t *mtu)
1450125776Sume{
1451125776Sume	struct socket *so;
1452125776Sume	struct mbuf *m_mtu;
1453125776Sume	struct ip6_mtuinfo mtuctl;
1454125776Sume
1455125776Sume	so =  in6p->inp_socket;
1456125776Sume
1457125776Sume	if (mtu == NULL)
1458125776Sume		return;
1459125776Sume
1460125776Sume#ifdef DIAGNOSTIC
1461125776Sume	if (so == NULL)		/* I believe this is impossible */
1462125776Sume		panic("ip6_notify_pmtu: socket is NULL");
1463125776Sume#endif
1464125776Sume
1465125776Sume	bzero(&mtuctl, sizeof(mtuctl));	/* zero-clear for safety */
1466125776Sume	mtuctl.ip6m_mtu = *mtu;
1467125776Sume	mtuctl.ip6m_addr = *dst;
1468148385Sume	if (sa6_recoverscope(&mtuctl.ip6m_addr))
1469148385Sume		return;
1470125776Sume
1471125776Sume	if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
1472125776Sume	    IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
1473125776Sume		return;
1474125776Sume
1475125776Sume	if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
1476125776Sume	    == 0) {
1477125776Sume		m_freem(m_mtu);
1478125776Sume		/* XXX: should count statistics */
1479125776Sume	} else
1480125776Sume		sorwakeup(so);
1481125776Sume
1482125776Sume	return;
1483125776Sume}
1484125776Sume
148578064Sume#ifdef PULLDOWN_TEST
148678064Sume/*
148778064Sume * pull single extension header from mbuf chain.  returns single mbuf that
148878064Sume * contains the result, or NULL on error.
148978064Sume */
149078064Sumestatic struct mbuf *
1491171259Sdelphijip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
149278064Sume{
149378064Sume	struct ip6_ext ip6e;
149478064Sume	size_t elen;
149578064Sume	struct mbuf *n;
149678064Sume
149778064Sume#ifdef DIAGNOSTIC
149878064Sume	switch (nxt) {
149978064Sume	case IPPROTO_DSTOPTS:
150078064Sume	case IPPROTO_ROUTING:
150178064Sume	case IPPROTO_HOPOPTS:
150278064Sume	case IPPROTO_AH: /* is it possible? */
150378064Sume		break;
150478064Sume	default:
150578064Sume		printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
150653541Sshin	}
150778064Sume#endif
150878064Sume
150978064Sume	m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
151078064Sume	if (nxt == IPPROTO_AH)
151178064Sume		elen = (ip6e.ip6e_len + 2) << 2;
151278064Sume	else
151378064Sume		elen = (ip6e.ip6e_len + 1) << 3;
151478064Sume
1515111119Simp	MGET(n, M_DONTWAIT, MT_DATA);
151678064Sume	if (n && elen >= MLEN) {
1517111119Simp		MCLGET(n, M_DONTWAIT);
151878064Sume		if ((n->m_flags & M_EXT) == 0) {
151978064Sume			m_free(n);
152078064Sume			n = NULL;
152178064Sume		}
152253541Sshin	}
152378064Sume	if (!n)
152478064Sume		return NULL;
152562587Sitojun
152678064Sume	n->m_len = 0;
152778064Sume	if (elen >= M_TRAILINGSPACE(n)) {
152878064Sume		m_free(n);
152978064Sume		return NULL;
153078064Sume	}
153178064Sume
153278064Sume	m_copydata(m, off, elen, mtod(n, caddr_t));
153378064Sume	n->m_len = elen;
153478064Sume	return n;
153553541Sshin}
153678064Sume#endif
153753541Sshin
153853541Sshin/*
153953541Sshin * Get pointer to the previous header followed by the header
154053541Sshin * currently processed.
154153541Sshin * XXX: This function supposes that
154253541Sshin *	M includes all headers,
154353541Sshin *	the next header field and the header length field of each header
154453541Sshin *	are valid, and
154553541Sshin *	the sum of each header length equals to OFF.
154653541Sshin * Because of these assumptions, this function must be called very
154753541Sshin * carefully. Moreover, it will not be used in the near future when
154853541Sshin * we develop `neater' mechanism to process extension headers.
154953541Sshin */
155053541Sshinchar *
1551171259Sdelphijip6_get_prevhdr(struct mbuf *m, int off)
155253541Sshin{
155353541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
155453541Sshin
155553541Sshin	if (off == sizeof(struct ip6_hdr))
1556120856Sume		return (&ip6->ip6_nxt);
155753541Sshin	else {
155853541Sshin		int len, nxt;
155953541Sshin		struct ip6_ext *ip6e = NULL;
156053541Sshin
156153541Sshin		nxt = ip6->ip6_nxt;
156253541Sshin		len = sizeof(struct ip6_hdr);
156353541Sshin		while (len < off) {
156453541Sshin			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
156553541Sshin
156678064Sume			switch (nxt) {
156753541Sshin			case IPPROTO_FRAGMENT:
156853541Sshin				len += sizeof(struct ip6_frag);
156953541Sshin				break;
157053541Sshin			case IPPROTO_AH:
157153541Sshin				len += (ip6e->ip6e_len + 2) << 2;
157253541Sshin				break;
157353541Sshin			default:
157453541Sshin				len += (ip6e->ip6e_len + 1) << 3;
157553541Sshin				break;
157653541Sshin			}
157753541Sshin			nxt = ip6e->ip6e_nxt;
157853541Sshin		}
157953541Sshin		if (ip6e)
1580120856Sume			return (&ip6e->ip6e_nxt);
158153541Sshin		else
158253541Sshin			return NULL;
158353541Sshin	}
158453541Sshin}
158553541Sshin
158653541Sshin/*
158762587Sitojun * get next header offset.  m will be retained.
158862587Sitojun */
158962587Sitojunint
1590171259Sdelphijip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
159162587Sitojun{
159262587Sitojun	struct ip6_hdr ip6;
159362587Sitojun	struct ip6_ext ip6e;
159462587Sitojun	struct ip6_frag fh;
159562587Sitojun
159662587Sitojun	/* just in case */
159762587Sitojun	if (m == NULL)
159862587Sitojun		panic("ip6_nexthdr: m == NULL");
159962587Sitojun	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
160062587Sitojun		return -1;
160162587Sitojun
160262587Sitojun	switch (proto) {
160362587Sitojun	case IPPROTO_IPV6:
160462587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6))
160562587Sitojun			return -1;
160662587Sitojun		m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
160762587Sitojun		if (nxtp)
160862587Sitojun			*nxtp = ip6.ip6_nxt;
160962587Sitojun		off += sizeof(ip6);
161062587Sitojun		return off;
161162587Sitojun
161262587Sitojun	case IPPROTO_FRAGMENT:
161362587Sitojun		/*
161462587Sitojun		 * terminate parsing if it is not the first fragment,
161562587Sitojun		 * it does not make sense to parse through it.
161662587Sitojun		 */
161762587Sitojun		if (m->m_pkthdr.len < off + sizeof(fh))
161862587Sitojun			return -1;
161962587Sitojun		m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1620120978Sume		/* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */
1621120978Sume		if (fh.ip6f_offlg & IP6F_OFF_MASK)
162262587Sitojun			return -1;
162362587Sitojun		if (nxtp)
162462587Sitojun			*nxtp = fh.ip6f_nxt;
162562587Sitojun		off += sizeof(struct ip6_frag);
162662587Sitojun		return off;
162762587Sitojun
162862587Sitojun	case IPPROTO_AH:
162962587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
163062587Sitojun			return -1;
163162587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
163262587Sitojun		if (nxtp)
163362587Sitojun			*nxtp = ip6e.ip6e_nxt;
163462587Sitojun		off += (ip6e.ip6e_len + 2) << 2;
163562587Sitojun		return off;
163662587Sitojun
163762587Sitojun	case IPPROTO_HOPOPTS:
163862587Sitojun	case IPPROTO_ROUTING:
163962587Sitojun	case IPPROTO_DSTOPTS:
164062587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
164162587Sitojun			return -1;
164262587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
164362587Sitojun		if (nxtp)
164462587Sitojun			*nxtp = ip6e.ip6e_nxt;
164562587Sitojun		off += (ip6e.ip6e_len + 1) << 3;
164662587Sitojun		return off;
164762587Sitojun
164862587Sitojun	case IPPROTO_NONE:
164962587Sitojun	case IPPROTO_ESP:
165062587Sitojun	case IPPROTO_IPCOMP:
165162587Sitojun		/* give up */
165262587Sitojun		return -1;
165362587Sitojun
165462587Sitojun	default:
165562587Sitojun		return -1;
165662587Sitojun	}
165762587Sitojun
165862587Sitojun	return -1;
165962587Sitojun}
166062587Sitojun
166162587Sitojun/*
166262587Sitojun * get offset for the last header in the chain.  m will be kept untainted.
166362587Sitojun */
166462587Sitojunint
1665171259Sdelphijip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
166662587Sitojun{
166762587Sitojun	int newoff;
166862587Sitojun	int nxt;
166962587Sitojun
167062587Sitojun	if (!nxtp) {
167162587Sitojun		nxt = -1;
167262587Sitojun		nxtp = &nxt;
167362587Sitojun	}
167462587Sitojun	while (1) {
167562587Sitojun		newoff = ip6_nexthdr(m, off, proto, nxtp);
167662587Sitojun		if (newoff < 0)
167762587Sitojun			return off;
167862587Sitojun		else if (newoff < off)
167962587Sitojun			return -1;	/* invalid */
168062587Sitojun		else if (newoff == off)
168162587Sitojun			return newoff;
168262587Sitojun
168362587Sitojun		off = newoff;
168462587Sitojun		proto = *nxtp;
168562587Sitojun	}
168662587Sitojun}
168762587Sitojun
1688121673Sumestruct ip6aux *
1689171259Sdelphijip6_addaux(struct mbuf *m)
169078064Sume{
1691120913Sume	struct m_tag *mtag;
1692120913Sume
1693120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1694120913Sume	if (!mtag) {
1695120913Sume		mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux),
1696120913Sume		    M_NOWAIT);
1697121630Sume		if (mtag) {
1698120913Sume			m_tag_prepend(m, mtag);
1699121630Sume			bzero(mtag + 1, sizeof(struct ip6aux));
1700121630Sume		}
170178064Sume	}
1702121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
170378064Sume}
170478064Sume
1705121673Sumestruct ip6aux *
1706171259Sdelphijip6_findaux(struct mbuf *m)
170778064Sume{
1708120913Sume	struct m_tag *mtag;
1709120913Sume
1710120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1711121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
171278064Sume}
171378064Sume
171478064Sumevoid
1715171259Sdelphijip6_delaux(struct mbuf *m)
171678064Sume{
1717120913Sume	struct m_tag *mtag;
1718120913Sume
1719120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1720120913Sume	if (mtag)
1721120913Sume		m_tag_delete(m, mtag);
172278064Sume}
172378064Sume
172462587Sitojun/*
172553541Sshin * System control for IP6
172653541Sshin */
172753541Sshin
172853541Sshinu_char	inet6ctlerrmap[PRC_NCMDS] = {
172953541Sshin	0,		0,		0,		0,
173053541Sshin	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
173153541Sshin	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
173253541Sshin	EMSGSIZE,	EHOSTUNREACH,	0,		0,
173353541Sshin	0,		0,		0,		0,
173453541Sshin	ENOPROTOOPT
173553541Sshin};
1736