ip6_input.c revision 190787
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 190787 2009-04-06 22:29:41Z zec $");
65174510Sobrien
6662587Sitojun#include "opt_inet.h"
6762587Sitojun#include "opt_inet6.h"
6855009Sshin#include "opt_ipsec.h"
69189106Sbz#include "opt_route.h"
7055009Sshin
7153541Sshin#include <sys/param.h>
7253541Sshin#include <sys/systm.h>
7378064Sume#include <sys/malloc.h>
7453541Sshin#include <sys/mbuf.h>
7583366Sjulian#include <sys/proc.h>
7653541Sshin#include <sys/domain.h>
7753541Sshin#include <sys/protosw.h>
7853541Sshin#include <sys/socket.h>
7953541Sshin#include <sys/socketvar.h>
8053541Sshin#include <sys/errno.h>
8153541Sshin#include <sys/time.h>
8253541Sshin#include <sys/kernel.h>
8353541Sshin#include <sys/syslog.h>
84181803Sbz#include <sys/vimage.h>
8553541Sshin
8653541Sshin#include <net/if.h>
8753541Sshin#include <net/if_types.h>
8853541Sshin#include <net/if_dl.h>
8953541Sshin#include <net/route.h>
9053541Sshin#include <net/netisr.h>
9164060Sdarrenr#include <net/pfil.h>
92185571Sbz#include <net/vnet.h>
9353541Sshin
9453541Sshin#include <netinet/in.h>
9553541Sshin#include <netinet/in_systm.h>
96186119Sqingli#include <net/if_llatbl.h>
9762587Sitojun#ifdef INET
9853541Sshin#include <netinet/ip.h>
9953541Sshin#include <netinet/ip_icmp.h>
100185571Sbz#include <netinet/vinet.h>
10195023Ssuz#endif /* INET */
10262587Sitojun#include <netinet/ip6.h>
10353541Sshin#include <netinet6/in6_var.h>
10453541Sshin#include <netinet6/ip6_var.h>
10562587Sitojun#include <netinet/in_pcb.h>
10662587Sitojun#include <netinet/icmp6.h>
107121161Sume#include <netinet6/scope6_var.h>
10853541Sshin#include <netinet6/in6_ifattach.h>
10953541Sshin#include <netinet6/nd6.h>
110185571Sbz#include <netinet6/vinet6.h>
11153541Sshin
112171167Sgnn#ifdef IPSEC
113105199Ssam#include <netipsec/ipsec.h>
114171133Sgnn#include <netinet6/ip6_ipsec.h>
115105199Ssam#include <netipsec/ipsec6.h>
116171167Sgnn#endif /* IPSEC */
117105199Ssam
11853541Sshin#include <netinet6/ip6protosw.h>
11953541Sshin
12062587Sitojunextern struct domain inet6domain;
12153541Sshin
12262587Sitojunu_char ip6_protox[IPPROTO_MAX];
123111888Sjlemonstatic struct ifqueue ip6intrq;
124185088Szec
125185895Szec#ifndef VIMAGE
126185895Szec#ifndef VIMAGE_GLOBALS
127185895Szecstruct vnet_inet6 vnet_inet6_0;
128185895Szec#endif
129185895Szec#endif
130185895Szec
131185088Szec#ifdef VIMAGE_GLOBALS
132185088Szecstatic int ip6qmaxlen;
13362587Sitojunstruct in6_ifaddr *in6_ifaddr;
134185088Szecstruct ip6stat ip6stat;
13553541Sshin
13678064Sumeextern struct callout in6_tmpaddrtimer_ch;
13778064Sume
138185088Szecextern int dad_init;
139185088Szecextern int pmtu_expire;
140185088Szecextern int pmtu_probe;
141185088Szecextern u_long rip6_sendspace;
142185088Szecextern u_long rip6_recvspace;
143185088Szecextern int icmp6errppslim;
144185088Szecextern int icmp6_nodeinfo;
145185088Szecextern int udp6_sendspace;
146185088Szecextern int udp6_recvspace;
147185088Szec#endif
14878064Sume
149120386Ssamstruct pfil_head inet6_pfil_hook;
15078064Sume
151175162Sobrienstatic void ip6_init2(void *);
152175162Sobrienstatic struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
153175162Sobrienstatic int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
15462587Sitojun#ifdef PULLDOWN_TEST
155175162Sobrienstatic struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
15653541Sshin#endif
15753541Sshin
15853541Sshin/*
15953541Sshin * IP6 initialization: fill in IP6 protocol switch table.
16053541Sshin * All protocols not implemented in kernel go to raw IP6 protocol handler.
16153541Sshin */
16253541Sshinvoid
163171259Sdelphijip6_init(void)
16453541Sshin{
165183550Szec	INIT_VNET_INET6(curvnet);
16678064Sume	struct ip6protosw *pr;
16778064Sume	int i;
16853541Sshin
169185088Szec	V_ip6qmaxlen = IFQ_MAXLEN;
170185088Szec	V_in6_maxmtu = 0;
171185088Szec#ifdef IP6_AUTO_LINKLOCAL
172185088Szec	V_ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
173185088Szec#else
174185088Szec	V_ip6_auto_linklocal = 1;	/* enable by default */
175185088Szec#endif
176185895Szec	TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
177185895Szec	    &V_ip6_auto_linklocal);
178185088Szec
179185088Szec#ifndef IPV6FORWARDING
180185088Szec#ifdef GATEWAY6
181185088Szec#define IPV6FORWARDING	1	/* forward IP6 packets not for us */
182185088Szec#else
183185088Szec#define IPV6FORWARDING	0	/* don't forward IP6 packets not for us */
184185088Szec#endif /* GATEWAY6 */
185185088Szec#endif /* !IPV6FORWARDING */
186185088Szec
187185088Szec#ifndef IPV6_SENDREDIRECTS
188185088Szec#define IPV6_SENDREDIRECTS	1
189185088Szec#endif
190185088Szec
191185088Szec	V_ip6_forwarding = IPV6FORWARDING; /* act as router? */
192185088Szec	V_ip6_sendredirects = IPV6_SENDREDIRECTS;
193185088Szec	V_ip6_defhlim = IPV6_DEFHLIM;
194185088Szec	V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
195185088Szec	V_ip6_accept_rtadv = 0;	 /* "IPV6FORWARDING ? 0 : 1" is dangerous */
196185088Szec	V_ip6_log_interval = 5;
197185088Szec	V_ip6_hdrnestlimit = 15; /* How many header options will we process? */
198185088Szec	V_ip6_dad_count = 1;	 /* DupAddrDetectionTransmits */
199185088Szec	V_ip6_auto_flowlabel = 1;
200185088Szec	V_ip6_use_deprecated = 1;/* allow deprecated addr (RFC2462 5.5.4) */
201185088Szec	V_ip6_rr_prune = 5;	 /* router renumbering prefix
202185088Szec                                  * walk list every 5 sec. */
203185088Szec	V_ip6_mcast_pmtu = 0;	 /* enable pMTU discovery for multicast? */
204185088Szec	V_ip6_v6only = 1;
205185088Szec	V_ip6_keepfaith = 0;
206185088Szec	V_ip6_log_time = (time_t)0L;
207185088Szec#ifdef IPSTEALTH
208185088Szec	V_ip6stealth = 0;
209185088Szec#endif
210185088Szec	V_nd6_onlink_ns_rfc4861 = 0; /* allow 'on-link' nd6 NS (RFC 4861) */
211185088Szec
212185088Szec	V_pmtu_expire = 60*10;
213185088Szec	V_pmtu_probe = 60*2;
214185088Szec
215185088Szec	/* raw IP6 parameters */
216185088Szec	/*
217185088Szec	 * Nominal space allocated to a raw ip socket.
218185088Szec	 */
219185088Szec#define RIPV6SNDQ	8192
220185088Szec#define RIPV6RCVQ	8192
221185088Szec	V_rip6_sendspace = RIPV6SNDQ;
222185088Szec	V_rip6_recvspace = RIPV6RCVQ;
223185088Szec
224185088Szec	/* ICMPV6 parameters */
225185088Szec	V_icmp6_rediraccept = 1;	/* accept and process redirects */
226185088Szec	V_icmp6_redirtimeout = 10 * 60;	/* 10 minutes */
227185088Szec	V_icmp6errppslim = 100;		/* 100pps */
228185088Szec	/* control how to respond to NI queries */
229185088Szec	V_icmp6_nodeinfo = (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
230185088Szec
231185088Szec	/* UDP on IP6 parameters */
232185088Szec	V_udp6_sendspace = 9216;	/* really max datagram size */
233185088Szec	V_udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
234185088Szec					/* 40 1K datagrams */
235185088Szec	V_dad_init = 0;
236185088Szec
237190787Szec	scope6_init();
238190787Szec	addrsel_policy_init();
239190787Szec	nd6_init();
240190787Szec	frag6_init();
241190787Szec
242190787Szec	V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
243190787Szec
244190787Szec	/* Skip global initialization stuff for non-default instances. */
245190787Szec	if (!IS_DEFAULT_VNET(curvnet))
246190787Szec		return;
247190787Szec
24878064Sume#ifdef DIAGNOSTIC
24978064Sume	if (sizeof(struct protosw) != sizeof(struct ip6protosw))
25078064Sume		panic("sizeof(protosw) != sizeof(ip6protosw)");
25178064Sume#endif
25253541Sshin	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
25353541Sshin	if (pr == 0)
25453541Sshin		panic("ip6_init");
255136689Sandre
256186393Sbz	/* Initialize the entire ip6_protox[] array to IPPROTO_RAW. */
25753541Sshin	for (i = 0; i < IPPROTO_MAX; i++)
25853541Sshin		ip6_protox[i] = pr - inet6sw;
259136689Sandre	/*
260136689Sandre	 * Cycle through IP protocols and put them into the appropriate place
261136689Sandre	 * in ip6_protox[].
262136689Sandre	 */
26353541Sshin	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
26453541Sshin	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
26553541Sshin		if (pr->pr_domain->dom_family == PF_INET6 &&
266136689Sandre		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
267136689Sandre			/* Be careful to only index valid IP protocols. */
268143675Ssam			if (pr->pr_protocol < IPPROTO_MAX)
269136689Sandre				ip6_protox[pr->pr_protocol] = pr - inet6sw;
270136689Sandre		}
271134383Sandre
272134383Sandre	/* Initialize packet filter hooks. */
273120386Ssam	inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
274120386Ssam	inet6_pfil_hook.ph_af = AF_INET6;
275120386Ssam	if ((i = pfil_head_register(&inet6_pfil_hook)) != 0)
276120386Ssam		printf("%s: WARNING: unable to register pfil hook, "
277120386Ssam			"error %d\n", __func__, i);
278134383Sandre
279190787Szec	ip6intrq.ifq_maxlen = V_ip6qmaxlen; /* XXX */
28093818Sjhb	mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF);
281180239Srwatson	netisr_register(NETISR_IPV6, ip6_input, &ip6intrq, 0);
28253541Sshin}
28353541Sshin
284190787Szecstatic int
285190787Szecip6_init2_vnet(const void *unused __unused)
28653541Sshin{
287183550Szec	INIT_VNET_INET6(curvnet);
28853541Sshin
28953541Sshin	/* nd6_timer_init */
290181803Sbz	callout_init(&V_nd6_timer_ch, 0);
291181803Sbz	callout_reset(&V_nd6_timer_ch, hz, nd6_timer, NULL);
29278064Sume
29378064Sume	/* timer for regeneranation of temporary addresses randomize ID */
294181803Sbz	callout_init(&V_in6_tmpaddrtimer_ch, 0);
295181803Sbz	callout_reset(&V_in6_tmpaddrtimer_ch,
296181803Sbz		      (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
297181803Sbz		       V_ip6_temp_regen_advance) * hz,
29878064Sume		      in6_tmpaddrtimer, NULL);
299190787Szec
300190787Szec	return (0);
30153541Sshin}
30253541Sshin
303190787Szecstatic void
304190787Szecip6_init2(void *dummy)
305190787Szec{
306190787Szec
307190787Szec	ip6_init2_vnet(NULL);
308190787Szec}
309190787Szec
31053541Sshin/* cheat */
31155009Sshin/* This must be after route_init(), which is now SI_ORDER_THIRD */
31255009SshinSYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
31353541Sshin
31453541Sshinvoid
315171259Sdelphijip6_input(struct mbuf *m)
31653541Sshin{
317183550Szec	INIT_VNET_NET(curvnet);
318183550Szec	INIT_VNET_INET6(curvnet);
31953541Sshin	struct ip6_hdr *ip6;
32053541Sshin	int off = sizeof(struct ip6_hdr), nest;
32153541Sshin	u_int32_t plen;
32253541Sshin	u_int32_t rtalert = ~0;
32353541Sshin	int nxt, ours = 0;
324186119Sqingli	struct ifnet *deliverifp = NULL, *ifp = NULL;
325121143Ssam	struct in6_addr odst;
326187989Sbz	struct route_in6 rin6;
327121143Ssam	int srcrt = 0;
328186119Sqingli	struct llentry *lle = NULL;
329187989Sbz	struct sockaddr_in6 dst6, *dst;
330121144Ssam
331187989Sbz	bzero(&rin6, sizeof(struct route_in6));
332171167Sgnn#ifdef IPSEC
33353541Sshin	/*
33453541Sshin	 * should the inner packet be considered authentic?
33553541Sshin	 * see comment in ah4_input().
336171133Sgnn	 * NB: m cannot be NULL when passed to the input routine
33753541Sshin	 */
33853541Sshin
339171133Sgnn	m->m_flags &= ~M_AUTHIPHDR;
340171133Sgnn	m->m_flags &= ~M_AUTHIPDGM;
341171133Sgnn
342171167Sgnn#endif /* IPSEC */
343171133Sgnn
34453541Sshin	/*
345121630Sume	 * make sure we don't have onion peering information into m_tag.
34678064Sume	 */
34778064Sume	ip6_delaux(m);
34878064Sume
34978064Sume	/*
35095023Ssuz	 * mbuf statistics
35153541Sshin	 */
35253541Sshin	if (m->m_flags & M_EXT) {
35353541Sshin		if (m->m_next)
354181803Sbz			V_ip6stat.ip6s_mext2m++;
35553541Sshin		else
356181803Sbz			V_ip6stat.ip6s_mext1++;
35753541Sshin	} else {
358181803Sbz#define M2MMAX	(sizeof(V_ip6stat.ip6s_m2m)/sizeof(V_ip6stat.ip6s_m2m[0]))
35953541Sshin		if (m->m_next) {
36053541Sshin			if (m->m_flags & M_LOOP) {
361181803Sbz				V_ip6stat.ip6s_m2m[V_loif[0].if_index]++; /* XXX */
36278064Sume			} else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
363181803Sbz				V_ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
36453541Sshin			else
365181803Sbz				V_ip6stat.ip6s_m2m[0]++;
36653541Sshin		} else
367181803Sbz			V_ip6stat.ip6s_m1++;
36878064Sume#undef M2MMAX
36953541Sshin	}
37053541Sshin
371151474Ssuz	/* drop the packet if IPv6 operation is disabled on the IF */
372151474Ssuz	if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
373151474Ssuz		m_freem(m);
374151474Ssuz		return;
375151474Ssuz	}
376151474Ssuz
37753541Sshin	in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
378181803Sbz	V_ip6stat.ip6s_total++;
37953541Sshin
38062587Sitojun#ifndef PULLDOWN_TEST
38174336Skuriyama	/*
38274336Skuriyama	 * L2 bridge code and some other code can return mbuf chain
38374336Skuriyama	 * that does not conform to KAME requirement.  too bad.
38474336Skuriyama	 * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
38574336Skuriyama	 */
38674336Skuriyama	if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
38774336Skuriyama		struct mbuf *n;
38874336Skuriyama
389111119Simp		MGETHDR(n, M_DONTWAIT, MT_HEADER);
39077003Sume		if (n)
391108466Ssam			M_MOVE_PKTHDR(n, m);
392108825Ssam		if (n && n->m_pkthdr.len > MHLEN) {
393111119Simp			MCLGET(n, M_DONTWAIT);
39474336Skuriyama			if ((n->m_flags & M_EXT) == 0) {
39574336Skuriyama				m_freem(n);
39674336Skuriyama				n = NULL;
39774336Skuriyama			}
39874336Skuriyama		}
39995023Ssuz		if (n == NULL) {
40077003Sume			m_freem(m);
401120913Sume			return;	/* ENOBUFS */
40277003Sume		}
40374336Skuriyama
404108825Ssam		m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
405108825Ssam		n->m_len = n->m_pkthdr.len;
40674336Skuriyama		m_freem(m);
40774336Skuriyama		m = n;
40874336Skuriyama	}
409120913Sume	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */);
41062587Sitojun#endif
41153541Sshin
41253541Sshin	if (m->m_len < sizeof(struct ip6_hdr)) {
41353541Sshin		struct ifnet *inifp;
41453541Sshin		inifp = m->m_pkthdr.rcvif;
415120913Sume		if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
416181803Sbz			V_ip6stat.ip6s_toosmall++;
41753541Sshin			in6_ifstat_inc(inifp, ifs6_in_hdrerr);
41853541Sshin			return;
41953541Sshin		}
42053541Sshin	}
42153541Sshin
42253541Sshin	ip6 = mtod(m, struct ip6_hdr *);
42353541Sshin
42453541Sshin	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
425181803Sbz		V_ip6stat.ip6s_badvers++;
42653541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
42753541Sshin		goto bad;
42853541Sshin	}
42953541Sshin
430181803Sbz	V_ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
43153541Sshin
43253541Sshin	/*
43378064Sume	 * Check against address spoofing/corruption.
43453541Sshin	 */
43553541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
43653541Sshin	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
43778064Sume		/*
43878064Sume		 * XXX: "badscope" is not very suitable for a multicast source.
43978064Sume		 */
440181803Sbz		V_ip6stat.ip6s_badscope++;
44153541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
44253541Sshin		goto bad;
44353541Sshin	}
444126444Sume	if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
445126444Sume	    !(m->m_flags & M_LOOP)) {
446126444Sume		/*
447126444Sume		 * In this case, the packet should come from the loopback
448126444Sume		 * interface.  However, we cannot just check the if_flags,
449126444Sume		 * because ip6_mloopback() passes the "actual" interface
450126444Sume		 * as the outgoing/incoming interface.
451126444Sume		 */
452181803Sbz		V_ip6stat.ip6s_badscope++;
45378064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
45478064Sume		goto bad;
45578064Sume	}
45695023Ssuz
457130416Smlaier#ifdef ALTQ
458130416Smlaier	if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
459130416Smlaier		/* packet is dropped by traffic conditioner */
460130416Smlaier		return;
461130416Smlaier	}
462130416Smlaier#endif
46362587Sitojun	/*
46478064Sume	 * The following check is not documented in specs.  A malicious
46578064Sume	 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
46678064Sume	 * and bypass security checks (act as if it was from 127.0.0.1 by using
467120913Sume	 * IPv6 src ::ffff:127.0.0.1).  Be cautious.
46878064Sume	 *
46978064Sume	 * This check chokes if we are in an SIIT cloud.  As none of BSDs
47078064Sume	 * support IPv4-less kernel compilation, we cannot support SIIT
47178064Sume	 * environment at all.  So, it makes more sense for us to reject any
47278064Sume	 * malicious packets for non-SIIT environment, than try to do a
473120913Sume	 * partial support for SIIT environment.
47462587Sitojun	 */
47578064Sume	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
47678064Sume	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
477181803Sbz		V_ip6stat.ip6s_badscope++;
47878064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
47978064Sume		goto bad;
48078064Sume	}
48162587Sitojun#if 0
48262587Sitojun	/*
48362587Sitojun	 * Reject packets with IPv4 compatible addresses (auto tunnel).
48462587Sitojun	 *
48562587Sitojun	 * The code forbids auto tunnel relay case in RFC1933 (the check is
48662587Sitojun	 * stronger than RFC1933).  We may want to re-enable it if mech-xx
48762587Sitojun	 * is revised to forbid relaying case.
48862587Sitojun	 */
48962587Sitojun	if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
49062587Sitojun	    IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
491181803Sbz		V_ip6stat.ip6s_badscope++;
49262587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
49362587Sitojun		goto bad;
49462587Sitojun	}
49562587Sitojun#endif
49675246Sume
497126444Sume	/*
498126508Smlaier	 * Run through list of hooks for input packets.
499126508Smlaier	 *
500126508Smlaier	 * NB: Beware of the destination address changing
501126508Smlaier	 *     (e.g. by NAT rewriting).  When this happens,
502126508Smlaier	 *     tell ip6_forward to do the right thing.
503126508Smlaier	 */
504126508Smlaier	odst = ip6->ip6_dst;
505134383Sandre
506134383Sandre	/* Jump over all PFIL processing if hooks are not active. */
507155201Scsjp	if (!PFIL_HOOKED(&inet6_pfil_hook))
508134383Sandre		goto passin;
509134383Sandre
510135920Smlaier	if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL))
511126508Smlaier		return;
512126508Smlaier	if (m == NULL)			/* consumed by filter */
513126508Smlaier		return;
514126508Smlaier	ip6 = mtod(m, struct ip6_hdr *);
515126508Smlaier	srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
516126508Smlaier
517134383Sandrepassin:
518126508Smlaier	/*
519154804Sume	 * Disambiguate address scope zones (if there is ambiguity).
520154804Sume	 * We first make sure that the original source or destination address
521154804Sume	 * is not in our internal form for scoped addresses.  Such addresses
522154804Sume	 * are not necessarily invalid spec-wise, but we cannot accept them due
523154804Sume	 * to the usage conflict.
524154804Sume	 * in6_setscope() then also checks and rejects the cases where src or
525154804Sume	 * dst are the loopback address and the receiving interface
526154804Sume	 * is not loopback.
527154804Sume	 */
528154804Sume	if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) {
529181803Sbz		V_ip6stat.ip6s_badscope++; /* XXX */
530154804Sume		goto bad;
531154804Sume	}
532154804Sume	if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||
533154804Sume	    in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {
534181803Sbz		V_ip6stat.ip6s_badscope++;
535154804Sume		goto bad;
536154804Sume	}
537154804Sume
538154804Sume	/*
53953541Sshin	 * Multicast check
54053541Sshin	 */
54153541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
542171260Sdelphij		struct in6_multi *in6m = 0;
54353541Sshin
54453541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
54553541Sshin		/*
54653541Sshin		 * See if we belong to the destination multicast group on the
54753541Sshin		 * arrival interface.
54853541Sshin		 */
54953541Sshin		IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
55053541Sshin		if (in6m)
55153541Sshin			ours = 1;
55256723Sshin		else if (!ip6_mrouter) {
553181803Sbz			V_ip6stat.ip6s_notmember++;
554181803Sbz			V_ip6stat.ip6s_cantforward++;
55553541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
55653541Sshin			goto bad;
55753541Sshin		}
55853541Sshin		deliverifp = m->m_pkthdr.rcvif;
55953541Sshin		goto hbhcheck;
56053541Sshin	}
56153541Sshin
56253541Sshin	/*
56353541Sshin	 *  Unicast check
56453541Sshin	 */
565186119Sqingli
566186119Sqingli	bzero(&dst6, sizeof(dst6));
567186119Sqingli	dst6.sin6_family = AF_INET6;
568186119Sqingli	dst6.sin6_len = sizeof(struct sockaddr_in6);
569186119Sqingli	dst6.sin6_addr = ip6->ip6_dst;
570186119Sqingli	ifp = m->m_pkthdr.rcvif;
571186119Sqingli	IF_AFDATA_LOCK(ifp);
572186119Sqingli	lle = lla_lookup(LLTABLE6(ifp), 0,
573186119Sqingli	     (struct sockaddr *)&dst6);
574186119Sqingli	IF_AFDATA_UNLOCK(ifp);
575186119Sqingli	if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
576186119Sqingli		ours = 1;
577186119Sqingli		deliverifp = ifp;
578186119Sqingli		LLE_RUNLOCK(lle);
579186119Sqingli		goto hbhcheck;
580186119Sqingli	}
581186293Sbz	if (lle != NULL)
582186293Sbz		LLE_RUNLOCK(lle);
583186119Sqingli
584187989Sbz	dst = &rin6.ro_dst;
585187989Sbz	dst->sin6_len = sizeof(struct sockaddr_in6);
586187989Sbz	dst->sin6_family = AF_INET6;
587187989Sbz	dst->sin6_addr = ip6->ip6_dst;
588187989Sbz	rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
589187989Sbz	if (rin6.ro_rt)
590187989Sbz		RT_UNLOCK(rin6.ro_rt);
59178064Sume
59253541Sshin#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
59353541Sshin
59453541Sshin	/*
59553541Sshin	 * Accept the packet if the forwarding interface to the destination
59653541Sshin	 * according to the routing table is the loopback interface,
59753541Sshin	 * unless the associated route has a gateway.
59853541Sshin	 * Note that this approach causes to accept a packet if there is a
59953541Sshin	 * route to the loopback interface for the destination of the packet.
60053541Sshin	 * But we think it's even useful in some situations, e.g. when using
60153541Sshin	 * a special daemon which wants to intercept the packet.
60278064Sume	 *
60378064Sume	 * XXX: some OSes automatically make a cloned route for the destination
60478064Sume	 * of an outgoing packet.  If the outgoing interface of the packet
60578064Sume	 * is a loopback one, the kernel would consider the packet to be
60678064Sume	 * accepted, even if we have no such address assinged on the interface.
60778064Sume	 * We check the cloned flag of the route entry to reject such cases,
60878064Sume	 * assuming that route entries for our own addresses are not made by
60978064Sume	 * cloning (it should be true because in6_addloop explicitly installs
61078064Sume	 * the host route).  However, we might have to do an explicit check
61178064Sume	 * while it would be less efficient.  Or, should we rather install a
61278064Sume	 * reject route for such a case?
61353541Sshin	 */
614187989Sbz	if (rin6.ro_rt &&
615187989Sbz	    (rin6.ro_rt->rt_flags &
61653541Sshin	     (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
61778064Sume#ifdef RTF_WASCLONED
618187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
61978064Sume#endif
62078064Sume#ifdef RTF_CLONED
621187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_CLONED) &&
62278064Sume#endif
62362587Sitojun#if 0
62453541Sshin	    /*
62562587Sitojun	     * The check below is redundant since the comparison of
62662587Sitojun	     * the destination and the key of the rtentry has
62762587Sitojun	     * already done through looking up the routing table.
62853541Sshin	     */
62962587Sitojun	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
630187989Sbz	    &rt6_key(rin6.ro_rt)->sin6_addr)
63162587Sitojun#endif
632187989Sbz	    rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
63353541Sshin		struct in6_ifaddr *ia6 =
634187989Sbz			(struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
63578064Sume
63662587Sitojun		/*
637121630Sume		 * record address information into m_tag.
63878064Sume		 */
63978064Sume		(void)ip6_setdstifaddr(m, ia6);
64078064Sume
64178064Sume		/*
64262587Sitojun		 * packets to a tentative, duplicated, or somehow invalid
64362587Sitojun		 * address must not be accepted.
64462587Sitojun		 */
64553541Sshin		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
64662587Sitojun			/* this address is ready */
64753541Sshin			ours = 1;
64853541Sshin			deliverifp = ia6->ia_ifp;	/* correct? */
64967334Sjoe			/* Count the packet in the ip address stats */
65067334Sjoe			ia6->ia_ifa.if_ipackets++;
65167334Sjoe			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
65253541Sshin			goto hbhcheck;
65353541Sshin		} else {
654165118Sbz			char ip6bufs[INET6_ADDRSTRLEN];
655165118Sbz			char ip6bufd[INET6_ADDRSTRLEN];
65662587Sitojun			/* address is not ready, so discard the packet. */
65778064Sume			nd6log((LOG_INFO,
65878064Sume			    "ip6_input: packet to an unready address %s->%s\n",
659165118Sbz			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
660165118Sbz			    ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
66162587Sitojun
66262587Sitojun			goto bad;
66353541Sshin		}
66453541Sshin	}
66553541Sshin
66653541Sshin	/*
667120913Sume	 * FAITH (Firewall Aided Internet Translator)
66853541Sshin	 */
669181803Sbz	if (V_ip6_keepfaith) {
670187989Sbz		if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
671187989Sbz		    rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
67253541Sshin			/* XXX do we need more sanity checks? */
67353541Sshin			ours = 1;
674187989Sbz			deliverifp = rin6.ro_rt->rt_ifp; /* faith */
67553541Sshin			goto hbhcheck;
67653541Sshin		}
67753541Sshin	}
67853541Sshin
67953541Sshin	/*
68053541Sshin	 * Now there is no reason to process the packet if it's not our own
68153541Sshin	 * and we're not a router.
68253541Sshin	 */
683181803Sbz	if (!V_ip6_forwarding) {
684181803Sbz		V_ip6stat.ip6s_cantforward++;
68553541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
68653541Sshin		goto bad;
68753541Sshin	}
68853541Sshin
68953541Sshin  hbhcheck:
69053541Sshin	/*
691121630Sume	 * record address information into m_tag, if we don't have one yet.
69278064Sume	 * note that we are unable to record it, if the address is not listed
69378064Sume	 * as our interface address (e.g. multicast addresses, addresses
69478064Sume	 * within FAITH prefixes and such).
69578064Sume	 */
69678064Sume	if (deliverifp && !ip6_getdstifaddr(m)) {
69778064Sume		struct in6_ifaddr *ia6;
69878064Sume
69978064Sume		ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
70078064Sume		if (ia6) {
70178064Sume			if (!ip6_setdstifaddr(m, ia6)) {
70278064Sume				/*
70378064Sume				 * XXX maybe we should drop the packet here,
70478064Sume				 * as we could not provide enough information
70578064Sume				 * to the upper layers.
70678064Sume				 */
70778064Sume			}
70878064Sume		}
70978064Sume	}
71078064Sume
71178064Sume	/*
71253541Sshin	 * Process Hop-by-Hop options header if it's contained.
71353541Sshin	 * m may be modified in ip6_hopopts_input().
71453541Sshin	 * If a JumboPayload option is included, plen will also be modified.
71553541Sshin	 */
71653541Sshin	plen = (u_int32_t)ntohs(ip6->ip6_plen);
71753541Sshin	if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
71862587Sitojun		struct ip6_hbh *hbh;
71962587Sitojun
72053541Sshin		if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
72162587Sitojun#if 0	/*touches NULL pointer*/
72253541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
72362587Sitojun#endif
724187989Sbz			goto out;	/* m have already been freed */
72553541Sshin		}
72662587Sitojun
72753541Sshin		/* adjust pointer */
72853541Sshin		ip6 = mtod(m, struct ip6_hdr *);
72953541Sshin
73053541Sshin		/*
73195023Ssuz		 * if the payload length field is 0 and the next header field
73262587Sitojun		 * indicates Hop-by-Hop Options header, then a Jumbo Payload
73362587Sitojun		 * option MUST be included.
73462587Sitojun		 */
73562587Sitojun		if (ip6->ip6_plen == 0 && plen == 0) {
73662587Sitojun			/*
73762587Sitojun			 * Note that if a valid jumbo payload option is
738120913Sume			 * contained, ip6_hopopts_input() must set a valid
739120913Sume			 * (non-zero) payload length to the variable plen.
74062587Sitojun			 */
741181803Sbz			V_ip6stat.ip6s_badoptions++;
74262587Sitojun			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
74362587Sitojun			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
74462587Sitojun			icmp6_error(m, ICMP6_PARAM_PROB,
74562587Sitojun				    ICMP6_PARAMPROB_HEADER,
74662587Sitojun				    (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
747187989Sbz			goto out;
74862587Sitojun		}
74962587Sitojun#ifndef PULLDOWN_TEST
75062587Sitojun		/* ip6_hopopts_input() ensures that mbuf is contiguous */
75162587Sitojun		hbh = (struct ip6_hbh *)(ip6 + 1);
75262587Sitojun#else
75362587Sitojun		IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
75462587Sitojun			sizeof(struct ip6_hbh));
75562587Sitojun		if (hbh == NULL) {
756181803Sbz			V_ip6stat.ip6s_tooshort++;
757187989Sbz			goto out;
75862587Sitojun		}
75962587Sitojun#endif
76062587Sitojun		nxt = hbh->ip6h_nxt;
76162587Sitojun
76262587Sitojun		/*
763169557Sjinmei		 * If we are acting as a router and the packet contains a
764169557Sjinmei		 * router alert option, see if we know the option value.
765169557Sjinmei		 * Currently, we only support the option value for MLD, in which
766169557Sjinmei		 * case we should pass the packet to the multicast routing
767169557Sjinmei		 * daemon.
76853541Sshin		 */
769181803Sbz		if (rtalert != ~0 && V_ip6_forwarding) {
770169557Sjinmei			switch (rtalert) {
771169557Sjinmei			case IP6OPT_RTALERT_MLD:
772169557Sjinmei				ours = 1;
773169557Sjinmei				break;
774169557Sjinmei			default:
775169557Sjinmei				/*
776169557Sjinmei				 * RFC2711 requires unrecognized values must be
777169557Sjinmei				 * silently ignored.
778169557Sjinmei				 */
779169557Sjinmei				break;
780169557Sjinmei			}
781169557Sjinmei		}
78253541Sshin	} else
78353541Sshin		nxt = ip6->ip6_nxt;
78453541Sshin
78553541Sshin	/*
78653541Sshin	 * Check that the amount of data in the buffers
78753541Sshin	 * is as at least much as the IPv6 header would have us expect.
78853541Sshin	 * Trim mbufs if longer than we expect.
78953541Sshin	 * Drop packet if shorter than we expect.
79053541Sshin	 */
79153541Sshin	if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
792181803Sbz		V_ip6stat.ip6s_tooshort++;
79353541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
79453541Sshin		goto bad;
79553541Sshin	}
79653541Sshin	if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
79753541Sshin		if (m->m_len == m->m_pkthdr.len) {
79853541Sshin			m->m_len = sizeof(struct ip6_hdr) + plen;
79953541Sshin			m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
80053541Sshin		} else
80153541Sshin			m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
80253541Sshin	}
80353541Sshin
80453541Sshin	/*
80553541Sshin	 * Forward if desirable.
80653541Sshin	 */
80753541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
80856723Sshin		/*
80956723Sshin		 * If we are acting as a multicast router, all
81056723Sshin		 * incoming multicast packets are passed to the
81156723Sshin		 * kernel-level multicast forwarding function.
81256723Sshin		 * The packet is returned (relatively) intact; if
81356723Sshin		 * ip6_mforward() returns a non-zero value, the packet
81456723Sshin		 * must be discarded, else it may be accepted below.
81556723Sshin		 */
816166938Sbms		if (ip6_mrouter && ip6_mforward &&
817166938Sbms		    ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
818181803Sbz			V_ip6stat.ip6s_cantforward++;
819187989Sbz			goto bad;
82056723Sshin		}
821187989Sbz		if (!ours)
822187989Sbz			goto bad;
82353541Sshin	} else if (!ours) {
824121143Ssam		ip6_forward(m, srcrt);
825187989Sbz		goto out;
826121673Sume	}
82753541Sshin
82862587Sitojun	ip6 = mtod(m, struct ip6_hdr *);
82962587Sitojun
83053541Sshin	/*
83162587Sitojun	 * Malicious party may be able to use IPv4 mapped addr to confuse
83262587Sitojun	 * tcp/udp stack and bypass security checks (act as if it was from
83362587Sitojun	 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
83462587Sitojun	 *
83562587Sitojun	 * For SIIT end node behavior, you may want to disable the check.
83662587Sitojun	 * However, you will  become vulnerable to attacks using IPv4 mapped
83762587Sitojun	 * source.
83862587Sitojun	 */
83962587Sitojun	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
84062587Sitojun	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
841181803Sbz		V_ip6stat.ip6s_badscope++;
84262587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
84362587Sitojun		goto bad;
84462587Sitojun	}
84562587Sitojun
84662587Sitojun	/*
84753541Sshin	 * Tell launch routine the next header
84853541Sshin	 */
849181803Sbz	V_ip6stat.ip6s_delivered++;
85053541Sshin	in6_ifstat_inc(deliverifp, ifs6_in_deliver);
85153541Sshin	nest = 0;
85278064Sume
85353541Sshin	while (nxt != IPPROTO_DONE) {
854181803Sbz		if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
855181803Sbz			V_ip6stat.ip6s_toomanyhdr++;
85653541Sshin			goto bad;
85753541Sshin		}
85853541Sshin
85953541Sshin		/*
86053541Sshin		 * protection against faulty packet - there should be
86153541Sshin		 * more sanity checks in header chain processing.
86253541Sshin		 */
86353541Sshin		if (m->m_pkthdr.len < off) {
864181803Sbz			V_ip6stat.ip6s_tooshort++;
86553541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
86653541Sshin			goto bad;
86753541Sshin		}
86853541Sshin
869171167Sgnn#ifdef IPSEC
87078064Sume		/*
87178064Sume		 * enforce IPsec policy checking if we are seeing last header.
87278064Sume		 * note that we do not visit this with protocols with pcb layer
87378064Sume		 * code - like udp/tcp/raw ip.
87478064Sume		 */
875171133Sgnn		if (ip6_ipsec_input(m, nxt))
87678064Sume			goto bad;
877171167Sgnn#endif /* IPSEC */
87853541Sshin		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
87953541Sshin	}
880187989Sbz	goto out;
881187989Sbzbad:
88253541Sshin	m_freem(m);
883187989Sbzout:
884187989Sbz	if (rin6.ro_rt)
885187989Sbz		RTFREE(rin6.ro_rt);
88653541Sshin}
88753541Sshin
88853541Sshin/*
88978064Sume * set/grab in6_ifaddr correspond to IPv6 destination address.
89078064Sume * XXX backward compatibility wrapper
89178064Sume */
892121673Sumestatic struct ip6aux *
893171259Sdelphijip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
89478064Sume{
895121673Sume	struct ip6aux *ip6a;
89678064Sume
897121673Sume	ip6a = ip6_addaux(m);
898121673Sume	if (ip6a)
899121673Sume		ip6a->ip6a_dstia6 = ia6;
900121673Sume	return ip6a;	/* NULL if failed to set */
90178064Sume}
90278064Sume
90378064Sumestruct in6_ifaddr *
904171259Sdelphijip6_getdstifaddr(struct mbuf *m)
90578064Sume{
906121673Sume	struct ip6aux *ip6a;
90778064Sume
908121673Sume	ip6a = ip6_findaux(m);
909121673Sume	if (ip6a)
910121673Sume		return ip6a->ip6a_dstia6;
91178064Sume	else
91278064Sume		return NULL;
91378064Sume}
91478064Sume
91578064Sume/*
91653541Sshin * Hop-by-Hop options header processing. If a valid jumbo payload option is
91753541Sshin * included, the real payload length will be stored in plenp.
918171259Sdelphij *
919171259Sdelphij * rtalertp - XXX: should be stored more smart way
92053541Sshin */
92153541Sshinstatic int
922171259Sdelphijip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
923171259Sdelphij    struct mbuf **mp, int *offp)
92453541Sshin{
925183550Szec	INIT_VNET_INET6(curvnet);
92678064Sume	struct mbuf *m = *mp;
92753541Sshin	int off = *offp, hbhlen;
92853541Sshin	struct ip6_hbh *hbh;
92953541Sshin	u_int8_t *opt;
93053541Sshin
93153541Sshin	/* validation of the length of the header */
93262587Sitojun#ifndef PULLDOWN_TEST
93353541Sshin	IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
93453541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
93553541Sshin	hbhlen = (hbh->ip6h_len + 1) << 3;
93653541Sshin
93753541Sshin	IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
93853541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
93962587Sitojun#else
94062587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
94162587Sitojun		sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
94262587Sitojun	if (hbh == NULL) {
943181803Sbz		V_ip6stat.ip6s_tooshort++;
94462587Sitojun		return -1;
94562587Sitojun	}
94662587Sitojun	hbhlen = (hbh->ip6h_len + 1) << 3;
94762587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
94862587Sitojun		hbhlen);
94962587Sitojun	if (hbh == NULL) {
950181803Sbz		V_ip6stat.ip6s_tooshort++;
95162587Sitojun		return -1;
95262587Sitojun	}
95362587Sitojun#endif
95453541Sshin	off += hbhlen;
95553541Sshin	hbhlen -= sizeof(struct ip6_hbh);
95653541Sshin	opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
95753541Sshin
95853541Sshin	if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
95953541Sshin				hbhlen, rtalertp, plenp) < 0)
960120856Sume		return (-1);
96153541Sshin
96253541Sshin	*offp = off;
96353541Sshin	*mp = m;
964120856Sume	return (0);
96553541Sshin}
96653541Sshin
96753541Sshin/*
96853541Sshin * Search header for all Hop-by-hop options and process each option.
96953541Sshin * This function is separate from ip6_hopopts_input() in order to
97053541Sshin * handle a case where the sending node itself process its hop-by-hop
97153541Sshin * options header. In such a case, the function is called from ip6_output().
97278064Sume *
97378064Sume * The function assumes that hbh header is located right after the IPv6 header
97478064Sume * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
97578064Sume * opthead + hbhlen is located in continuous memory region.
97653541Sshin */
97753541Sshinint
978171259Sdelphijip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
979171259Sdelphij    u_int32_t *rtalertp, u_int32_t *plenp)
98053541Sshin{
981183550Szec	INIT_VNET_INET6(curvnet);
98253541Sshin	struct ip6_hdr *ip6;
98353541Sshin	int optlen = 0;
98453541Sshin	u_int8_t *opt = opthead;
98553541Sshin	u_int16_t rtalert_val;
98662587Sitojun	u_int32_t jumboplen;
98778064Sume	const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
98853541Sshin
98953541Sshin	for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
99078064Sume		switch (*opt) {
99178064Sume		case IP6OPT_PAD1:
99278064Sume			optlen = 1;
99378064Sume			break;
99478064Sume		case IP6OPT_PADN:
99578064Sume			if (hbhlen < IP6OPT_MINLEN) {
996181803Sbz				V_ip6stat.ip6s_toosmall++;
99778064Sume				goto bad;
99878064Sume			}
99978064Sume			optlen = *(opt + 1) + 2;
100078064Sume			break;
1001121472Sume		case IP6OPT_ROUTER_ALERT:
100262587Sitojun			/* XXX may need check for alignment */
100378064Sume			if (hbhlen < IP6OPT_RTALERT_LEN) {
1004181803Sbz				V_ip6stat.ip6s_toosmall++;
100578064Sume				goto bad;
100678064Sume			}
100778064Sume			if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
100878064Sume				/* XXX stat */
100978064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1010120913Sume				    ICMP6_PARAMPROB_HEADER,
1011120913Sume				    erroff + opt + 1 - opthead);
1012120856Sume				return (-1);
101378064Sume			}
101478064Sume			optlen = IP6OPT_RTALERT_LEN;
101578064Sume			bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
101678064Sume			*rtalertp = ntohs(rtalert_val);
101778064Sume			break;
101878064Sume		case IP6OPT_JUMBO:
101978064Sume			/* XXX may need check for alignment */
102062587Sitojun			if (hbhlen < IP6OPT_JUMBO_LEN) {
1021181803Sbz				V_ip6stat.ip6s_toosmall++;
102262587Sitojun				goto bad;
102362587Sitojun			}
102478064Sume			if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
102578064Sume				/* XXX stat */
102678064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1027120913Sume				    ICMP6_PARAMPROB_HEADER,
1028120913Sume				    erroff + opt + 1 - opthead);
1029120856Sume				return (-1);
103078064Sume			}
103162587Sitojun			optlen = IP6OPT_JUMBO_LEN;
103253541Sshin
103362587Sitojun			/*
103462587Sitojun			 * IPv6 packets that have non 0 payload length
103578064Sume			 * must not contain a jumbo payload option.
103662587Sitojun			 */
103762587Sitojun			ip6 = mtod(m, struct ip6_hdr *);
103862587Sitojun			if (ip6->ip6_plen) {
1039181803Sbz				V_ip6stat.ip6s_badoptions++;
104062587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1041120913Sume				    ICMP6_PARAMPROB_HEADER,
1042120913Sume				    erroff + opt - opthead);
1043120856Sume				return (-1);
104462587Sitojun			}
104553541Sshin
104662587Sitojun			/*
104762587Sitojun			 * We may see jumbolen in unaligned location, so
104862587Sitojun			 * we'd need to perform bcopy().
104962587Sitojun			 */
105062587Sitojun			bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
105162587Sitojun			jumboplen = (u_int32_t)htonl(jumboplen);
105262587Sitojun
105362587Sitojun#if 1
105462587Sitojun			/*
105562587Sitojun			 * if there are multiple jumbo payload options,
105662587Sitojun			 * *plenp will be non-zero and the packet will be
105762587Sitojun			 * rejected.
105862587Sitojun			 * the behavior may need some debate in ipngwg -
105962587Sitojun			 * multiple options does not make sense, however,
106062587Sitojun			 * there's no explicit mention in specification.
106162587Sitojun			 */
106262587Sitojun			if (*plenp != 0) {
1063181803Sbz				V_ip6stat.ip6s_badoptions++;
106462587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1065120913Sume				    ICMP6_PARAMPROB_HEADER,
1066120913Sume				    erroff + opt + 2 - opthead);
1067120856Sume				return (-1);
106862587Sitojun			}
106962587Sitojun#endif
107062587Sitojun
107162587Sitojun			/*
107262587Sitojun			 * jumbo payload length must be larger than 65535.
107362587Sitojun			 */
107462587Sitojun			if (jumboplen <= IPV6_MAXPACKET) {
1075181803Sbz				V_ip6stat.ip6s_badoptions++;
107662587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1077120913Sume				    ICMP6_PARAMPROB_HEADER,
1078120913Sume				    erroff + opt + 2 - opthead);
1079120856Sume				return (-1);
108062587Sitojun			}
108162587Sitojun			*plenp = jumboplen;
108262587Sitojun
108362587Sitojun			break;
108478064Sume		default:		/* unknown option */
108578064Sume			if (hbhlen < IP6OPT_MINLEN) {
1086181803Sbz				V_ip6stat.ip6s_toosmall++;
108778064Sume				goto bad;
108878064Sume			}
108978064Sume			optlen = ip6_unknown_opt(opt, m,
109078064Sume			    erroff + opt - opthead);
109178064Sume			if (optlen == -1)
1092120856Sume				return (-1);
109378064Sume			optlen += 2;
109478064Sume			break;
109553541Sshin		}
109653541Sshin	}
109753541Sshin
1098120856Sume	return (0);
109953541Sshin
110053541Sshin  bad:
110153541Sshin	m_freem(m);
1102120856Sume	return (-1);
110353541Sshin}
110453541Sshin
110553541Sshin/*
110653541Sshin * Unknown option processing.
110753541Sshin * The third argument `off' is the offset from the IPv6 header to the option,
110853541Sshin * which is necessary if the IPv6 header the and option header and IPv6 header
110953541Sshin * is not continuous in order to return an ICMPv6 error.
111053541Sshin */
111153541Sshinint
1112171259Sdelphijip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off)
111353541Sshin{
1114183550Szec	INIT_VNET_INET6(curvnet);
111553541Sshin	struct ip6_hdr *ip6;
111653541Sshin
111778064Sume	switch (IP6OPT_TYPE(*optp)) {
111878064Sume	case IP6OPT_TYPE_SKIP: /* ignore the option */
1119120856Sume		return ((int)*(optp + 1));
112078064Sume	case IP6OPT_TYPE_DISCARD:	/* silently discard */
112178064Sume		m_freem(m);
1122120856Sume		return (-1);
112378064Sume	case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1124181803Sbz		V_ip6stat.ip6s_badoptions++;
112578064Sume		icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1126120856Sume		return (-1);
112778064Sume	case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1128181803Sbz		V_ip6stat.ip6s_badoptions++;
112978064Sume		ip6 = mtod(m, struct ip6_hdr *);
113078064Sume		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
113178064Sume		    (m->m_flags & (M_BCAST|M_MCAST)))
113278064Sume			m_freem(m);
113378064Sume		else
113478064Sume			icmp6_error(m, ICMP6_PARAM_PROB,
113578064Sume				    ICMP6_PARAMPROB_OPTION, off);
1136120856Sume		return (-1);
113753541Sshin	}
113853541Sshin
113953541Sshin	m_freem(m);		/* XXX: NOTREACHED */
1140120856Sume	return (-1);
114153541Sshin}
114253541Sshin
114353541Sshin/*
114462587Sitojun * Create the "control" list for this pcb.
1145179289Sbz * These functions will not modify mbuf chain at all.
114662587Sitojun *
1147179289Sbz * With KAME mbuf chain restriction:
114862587Sitojun * The routine will be called from upper layer handlers like tcp6_input().
114962587Sitojun * Thus the routine assumes that the caller (tcp6_input) have already
115062587Sitojun * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
115162587Sitojun * very first mbuf on the mbuf chain.
1152179289Sbz *
1153179289Sbz * ip6_savecontrol_v4 will handle those options that are possible to be
1154179289Sbz * set on a v4-mapped socket.
1155179289Sbz * ip6_savecontrol will directly call ip6_savecontrol_v4 to handle those
1156179289Sbz * options and handle the v6-only ones itself.
115753541Sshin */
1158181782Sbzstruct mbuf **
1159181782Sbzip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
1160181782Sbz    int *v4only)
116153541Sshin{
1162121674Sume	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
116353541Sshin
116478064Sume#ifdef SO_TIMESTAMP
1165179289Sbz	if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
116653541Sshin		struct timeval tv;
116753541Sshin
116853541Sshin		microtime(&tv);
116953541Sshin		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1170120913Sume		    SCM_TIMESTAMP, SOL_SOCKET);
1171121472Sume		if (*mp)
117253541Sshin			mp = &(*mp)->m_next;
117397658Stanimura	}
117462587Sitojun#endif
117562587Sitojun
1176181782Sbz	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1177181782Sbz		if (v4only != NULL)
1178181782Sbz			*v4only = 1;
1179181782Sbz		return (mp);
1180181782Sbz	}
1181121631Sume
1182179289Sbz#define IS2292(inp, x, y)	(((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
118353541Sshin	/* RFC 2292 sec. 5 */
1184179289Sbz	if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
118553541Sshin		struct in6_pktinfo pi6;
1186120913Sume
118753541Sshin		bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1188121315Sume		in6_clearscope(&pi6.ipi6_addr);	/* XXX */
1189120913Sume		pi6.ipi6_ifindex =
1190120913Sume		    (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
1191120913Sume
119253541Sshin		*mp = sbcreatecontrol((caddr_t) &pi6,
1193120913Sume		    sizeof(struct in6_pktinfo),
1194179289Sbz		    IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
1195121472Sume		if (*mp)
119653541Sshin			mp = &(*mp)->m_next;
119753541Sshin	}
119878064Sume
1199179289Sbz	if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
120053541Sshin		int hlim = ip6->ip6_hlim & 0xff;
1201120913Sume
1202120913Sume		*mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1203179289Sbz		    IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
1204179289Sbz		    IPPROTO_IPV6);
1205121472Sume		if (*mp)
120653541Sshin			mp = &(*mp)->m_next;
120753541Sshin	}
120853541Sshin
1209181782Sbz	if (v4only != NULL)
1210181782Sbz		*v4only = 0;
1211181782Sbz	return (mp);
1212179289Sbz}
1213179289Sbz
1214179289Sbzvoid
1215179289Sbzip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
1216179289Sbz{
1217179289Sbz	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1218181782Sbz	int v4only = 0;
1219179289Sbz
1220181782Sbz	mp = ip6_savecontrol_v4(in6p, m, mp, &v4only);
1221181782Sbz	if (v4only)
1222179289Sbz		return;
1223179289Sbz
1224186141Sbz	if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
1225121472Sume		u_int32_t flowinfo;
1226121472Sume		int tclass;
1227121472Sume
1228121472Sume		flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1229121472Sume		flowinfo >>= 20;
1230121472Sume
1231121472Sume		tclass = flowinfo & 0xff;
1232121472Sume		*mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass),
1233121472Sume		    IPV6_TCLASS, IPPROTO_IPV6);
1234121472Sume		if (*mp)
1235121472Sume			mp = &(*mp)->m_next;
1236121472Sume	}
1237121472Sume
123853541Sshin	/*
1239130002Sume	 * IPV6_HOPOPTS socket option.  Recall that we required super-user
1240130002Sume	 * privilege for the option (see ip6_ctloutput), but it might be too
1241130002Sume	 * strict, since there might be some hop-by-hop options which can be
1242130002Sume	 * returned to normal user.
1243130002Sume	 * See also RFC 2292 section 6 (or RFC 3542 section 8).
124453541Sshin	 */
1245186141Sbz	if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
124653541Sshin		/*
124753541Sshin		 * Check if a hop-by-hop options header is contatined in the
124853541Sshin		 * received packet, and if so, store the options as ancillary
124953541Sshin		 * data. Note that a hop-by-hop options header must be
1250120913Sume		 * just after the IPv6 header, which is assured through the
1251120913Sume		 * IPv6 input processing.
125253541Sshin		 */
125353541Sshin		if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
125462587Sitojun			struct ip6_hbh *hbh;
125578064Sume			int hbhlen = 0;
125678064Sume#ifdef PULLDOWN_TEST
125778064Sume			struct mbuf *ext;
125878064Sume#endif
125953541Sshin
126062587Sitojun#ifndef PULLDOWN_TEST
126162587Sitojun			hbh = (struct ip6_hbh *)(ip6 + 1);
126262587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
126362587Sitojun#else
126478064Sume			ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
126578064Sume			    ip6->ip6_nxt);
126678064Sume			if (ext == NULL) {
1267181803Sbz				V_ip6stat.ip6s_tooshort++;
126862587Sitojun				return;
126962587Sitojun			}
127078064Sume			hbh = mtod(ext, struct ip6_hbh *);
127162587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
127278064Sume			if (hbhlen != ext->m_len) {
127378064Sume				m_freem(ext);
1274181803Sbz				V_ip6stat.ip6s_tooshort++;
127562587Sitojun				return;
127662587Sitojun			}
127762587Sitojun#endif
127862587Sitojun
127953541Sshin			/*
1280120913Sume			 * XXX: We copy the whole header even if a
1281120913Sume			 * jumbo payload option is included, the option which
1282120913Sume			 * is to be removed before returning according to
1283120913Sume			 * RFC2292.
1284148169Sume			 * Note: this constraint is removed in RFC3542
128553541Sshin			 */
128662587Sitojun			*mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1287179289Sbz			    IS2292(in6p, IPV6_2292HOPOPTS, IPV6_HOPOPTS),
1288121472Sume			    IPPROTO_IPV6);
1289121472Sume			if (*mp)
129053541Sshin				mp = &(*mp)->m_next;
129178064Sume#ifdef PULLDOWN_TEST
129278064Sume			m_freem(ext);
129378064Sume#endif
129453541Sshin		}
129553541Sshin	}
129653541Sshin
1297186141Sbz	if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
129878064Sume		int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
129953541Sshin
130053541Sshin		/*
130153541Sshin		 * Search for destination options headers or routing
130253541Sshin		 * header(s) through the header chain, and stores each
130353541Sshin		 * header as ancillary data.
130453541Sshin		 * Note that the order of the headers remains in
130553541Sshin		 * the chain of ancillary data.
130653541Sshin		 */
130778064Sume		while (1) {	/* is explicit loop prevention necessary? */
130878064Sume			struct ip6_ext *ip6e = NULL;
130962587Sitojun			int elen;
131078064Sume#ifdef PULLDOWN_TEST
131178064Sume			struct mbuf *ext = NULL;
131278064Sume#endif
131353541Sshin
131478064Sume			/*
131578064Sume			 * if it is not an extension header, don't try to
131678064Sume			 * pull it from the chain.
131778064Sume			 */
131878064Sume			switch (nxt) {
131978064Sume			case IPPROTO_DSTOPTS:
132078064Sume			case IPPROTO_ROUTING:
132178064Sume			case IPPROTO_HOPOPTS:
132278064Sume			case IPPROTO_AH: /* is it possible? */
132378064Sume				break;
132478064Sume			default:
132578064Sume				goto loopend;
132678064Sume			}
132778064Sume
132862587Sitojun#ifndef PULLDOWN_TEST
132978064Sume			if (off + sizeof(*ip6e) > m->m_len)
133078064Sume				goto loopend;
133162587Sitojun			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
133262587Sitojun			if (nxt == IPPROTO_AH)
133362587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
133462587Sitojun			else
133562587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
133678064Sume			if (off + elen > m->m_len)
133778064Sume				goto loopend;
133862587Sitojun#else
133978064Sume			ext = ip6_pullexthdr(m, off, nxt);
134078064Sume			if (ext == NULL) {
1341181803Sbz				V_ip6stat.ip6s_tooshort++;
134262587Sitojun				return;
134362587Sitojun			}
134478064Sume			ip6e = mtod(ext, struct ip6_ext *);
134562587Sitojun			if (nxt == IPPROTO_AH)
134662587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
134762587Sitojun			else
134862587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
134978064Sume			if (elen != ext->m_len) {
135078064Sume				m_freem(ext);
1351181803Sbz				V_ip6stat.ip6s_tooshort++;
135262587Sitojun				return;
135362587Sitojun			}
135462587Sitojun#endif
135562587Sitojun
135678064Sume			switch (nxt) {
135778064Sume			case IPPROTO_DSTOPTS:
1358186141Sbz				if (!(in6p->inp_flags & IN6P_DSTOPTS))
135978064Sume					break;
136053541Sshin
136178064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1362179289Sbz				    IS2292(in6p,
1363179289Sbz					IPV6_2292DSTOPTS, IPV6_DSTOPTS),
1364120913Sume				    IPPROTO_IPV6);
136578064Sume				if (*mp)
136678064Sume					mp = &(*mp)->m_next;
136778064Sume				break;
136878064Sume			case IPPROTO_ROUTING:
1369186141Sbz				if (!in6p->inp_flags & IN6P_RTHDR)
137078064Sume					break;
137153541Sshin
137278064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1373179289Sbz				    IS2292(in6p, IPV6_2292RTHDR, IPV6_RTHDR),
1374120913Sume				    IPPROTO_IPV6);
137578064Sume				if (*mp)
137678064Sume					mp = &(*mp)->m_next;
137778064Sume				break;
137878064Sume			case IPPROTO_HOPOPTS:
137978064Sume			case IPPROTO_AH: /* is it possible? */
138078064Sume				break;
138153541Sshin
138278064Sume			default:
138378064Sume				/*
1384171260Sdelphij				 * other cases have been filtered in the above.
138578064Sume				 * none will visit this case.  here we supply
138678064Sume				 * the code just in case (nxt overwritten or
138778064Sume				 * other cases).
138878064Sume				 */
138978064Sume#ifdef PULLDOWN_TEST
139078064Sume				m_freem(ext);
139178064Sume#endif
139278064Sume				goto loopend;
139353541Sshin
139453541Sshin			}
139553541Sshin
139653541Sshin			/* proceed with the next header. */
139762587Sitojun			off += elen;
139853541Sshin			nxt = ip6e->ip6e_nxt;
139978064Sume			ip6e = NULL;
140078064Sume#ifdef PULLDOWN_TEST
140178064Sume			m_freem(ext);
140278064Sume			ext = NULL;
140378064Sume#endif
140453541Sshin		}
140553541Sshin	  loopend:
140678064Sume		;
140753541Sshin	}
1408179289Sbz}
1409121472Sume#undef IS2292
141078064Sume
1411125776Sumevoid
1412171259Sdelphijip6_notify_pmtu(struct inpcb *in6p, struct sockaddr_in6 *dst, u_int32_t *mtu)
1413125776Sume{
1414125776Sume	struct socket *so;
1415125776Sume	struct mbuf *m_mtu;
1416125776Sume	struct ip6_mtuinfo mtuctl;
1417125776Sume
1418125776Sume	so =  in6p->inp_socket;
1419125776Sume
1420125776Sume	if (mtu == NULL)
1421125776Sume		return;
1422125776Sume
1423125776Sume#ifdef DIAGNOSTIC
1424125776Sume	if (so == NULL)		/* I believe this is impossible */
1425125776Sume		panic("ip6_notify_pmtu: socket is NULL");
1426125776Sume#endif
1427125776Sume
1428125776Sume	bzero(&mtuctl, sizeof(mtuctl));	/* zero-clear for safety */
1429125776Sume	mtuctl.ip6m_mtu = *mtu;
1430125776Sume	mtuctl.ip6m_addr = *dst;
1431148385Sume	if (sa6_recoverscope(&mtuctl.ip6m_addr))
1432148385Sume		return;
1433125776Sume
1434125776Sume	if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
1435125776Sume	    IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
1436125776Sume		return;
1437125776Sume
1438125776Sume	if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
1439125776Sume	    == 0) {
1440125776Sume		m_freem(m_mtu);
1441125776Sume		/* XXX: should count statistics */
1442125776Sume	} else
1443125776Sume		sorwakeup(so);
1444125776Sume
1445125776Sume	return;
1446125776Sume}
1447125776Sume
144878064Sume#ifdef PULLDOWN_TEST
144978064Sume/*
145078064Sume * pull single extension header from mbuf chain.  returns single mbuf that
145178064Sume * contains the result, or NULL on error.
145278064Sume */
145378064Sumestatic struct mbuf *
1454171259Sdelphijip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
145578064Sume{
145678064Sume	struct ip6_ext ip6e;
145778064Sume	size_t elen;
145878064Sume	struct mbuf *n;
145978064Sume
146078064Sume#ifdef DIAGNOSTIC
146178064Sume	switch (nxt) {
146278064Sume	case IPPROTO_DSTOPTS:
146378064Sume	case IPPROTO_ROUTING:
146478064Sume	case IPPROTO_HOPOPTS:
146578064Sume	case IPPROTO_AH: /* is it possible? */
146678064Sume		break;
146778064Sume	default:
146878064Sume		printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
146953541Sshin	}
147078064Sume#endif
147178064Sume
147278064Sume	m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
147378064Sume	if (nxt == IPPROTO_AH)
147478064Sume		elen = (ip6e.ip6e_len + 2) << 2;
147578064Sume	else
147678064Sume		elen = (ip6e.ip6e_len + 1) << 3;
147778064Sume
1478111119Simp	MGET(n, M_DONTWAIT, MT_DATA);
147978064Sume	if (n && elen >= MLEN) {
1480111119Simp		MCLGET(n, M_DONTWAIT);
148178064Sume		if ((n->m_flags & M_EXT) == 0) {
148278064Sume			m_free(n);
148378064Sume			n = NULL;
148478064Sume		}
148553541Sshin	}
148678064Sume	if (!n)
148778064Sume		return NULL;
148862587Sitojun
148978064Sume	n->m_len = 0;
149078064Sume	if (elen >= M_TRAILINGSPACE(n)) {
149178064Sume		m_free(n);
149278064Sume		return NULL;
149378064Sume	}
149478064Sume
149578064Sume	m_copydata(m, off, elen, mtod(n, caddr_t));
149678064Sume	n->m_len = elen;
149778064Sume	return n;
149853541Sshin}
149978064Sume#endif
150053541Sshin
150153541Sshin/*
150253541Sshin * Get pointer to the previous header followed by the header
150353541Sshin * currently processed.
150453541Sshin * XXX: This function supposes that
150553541Sshin *	M includes all headers,
150653541Sshin *	the next header field and the header length field of each header
150753541Sshin *	are valid, and
150853541Sshin *	the sum of each header length equals to OFF.
150953541Sshin * Because of these assumptions, this function must be called very
151053541Sshin * carefully. Moreover, it will not be used in the near future when
151153541Sshin * we develop `neater' mechanism to process extension headers.
151253541Sshin */
151353541Sshinchar *
1514171259Sdelphijip6_get_prevhdr(struct mbuf *m, int off)
151553541Sshin{
151653541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
151753541Sshin
151853541Sshin	if (off == sizeof(struct ip6_hdr))
1519120856Sume		return (&ip6->ip6_nxt);
152053541Sshin	else {
152153541Sshin		int len, nxt;
152253541Sshin		struct ip6_ext *ip6e = NULL;
152353541Sshin
152453541Sshin		nxt = ip6->ip6_nxt;
152553541Sshin		len = sizeof(struct ip6_hdr);
152653541Sshin		while (len < off) {
152753541Sshin			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
152853541Sshin
152978064Sume			switch (nxt) {
153053541Sshin			case IPPROTO_FRAGMENT:
153153541Sshin				len += sizeof(struct ip6_frag);
153253541Sshin				break;
153353541Sshin			case IPPROTO_AH:
153453541Sshin				len += (ip6e->ip6e_len + 2) << 2;
153553541Sshin				break;
153653541Sshin			default:
153753541Sshin				len += (ip6e->ip6e_len + 1) << 3;
153853541Sshin				break;
153953541Sshin			}
154053541Sshin			nxt = ip6e->ip6e_nxt;
154153541Sshin		}
154253541Sshin		if (ip6e)
1543120856Sume			return (&ip6e->ip6e_nxt);
154453541Sshin		else
154553541Sshin			return NULL;
154653541Sshin	}
154753541Sshin}
154853541Sshin
154953541Sshin/*
155062587Sitojun * get next header offset.  m will be retained.
155162587Sitojun */
155262587Sitojunint
1553171259Sdelphijip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
155462587Sitojun{
155562587Sitojun	struct ip6_hdr ip6;
155662587Sitojun	struct ip6_ext ip6e;
155762587Sitojun	struct ip6_frag fh;
155862587Sitojun
155962587Sitojun	/* just in case */
156062587Sitojun	if (m == NULL)
156162587Sitojun		panic("ip6_nexthdr: m == NULL");
156262587Sitojun	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
156362587Sitojun		return -1;
156462587Sitojun
156562587Sitojun	switch (proto) {
156662587Sitojun	case IPPROTO_IPV6:
156762587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6))
156862587Sitojun			return -1;
156962587Sitojun		m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
157062587Sitojun		if (nxtp)
157162587Sitojun			*nxtp = ip6.ip6_nxt;
157262587Sitojun		off += sizeof(ip6);
157362587Sitojun		return off;
157462587Sitojun
157562587Sitojun	case IPPROTO_FRAGMENT:
157662587Sitojun		/*
157762587Sitojun		 * terminate parsing if it is not the first fragment,
157862587Sitojun		 * it does not make sense to parse through it.
157962587Sitojun		 */
158062587Sitojun		if (m->m_pkthdr.len < off + sizeof(fh))
158162587Sitojun			return -1;
158262587Sitojun		m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1583120978Sume		/* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */
1584120978Sume		if (fh.ip6f_offlg & IP6F_OFF_MASK)
158562587Sitojun			return -1;
158662587Sitojun		if (nxtp)
158762587Sitojun			*nxtp = fh.ip6f_nxt;
158862587Sitojun		off += sizeof(struct ip6_frag);
158962587Sitojun		return off;
159062587Sitojun
159162587Sitojun	case IPPROTO_AH:
159262587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
159362587Sitojun			return -1;
159462587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
159562587Sitojun		if (nxtp)
159662587Sitojun			*nxtp = ip6e.ip6e_nxt;
159762587Sitojun		off += (ip6e.ip6e_len + 2) << 2;
159862587Sitojun		return off;
159962587Sitojun
160062587Sitojun	case IPPROTO_HOPOPTS:
160162587Sitojun	case IPPROTO_ROUTING:
160262587Sitojun	case IPPROTO_DSTOPTS:
160362587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
160462587Sitojun			return -1;
160562587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
160662587Sitojun		if (nxtp)
160762587Sitojun			*nxtp = ip6e.ip6e_nxt;
160862587Sitojun		off += (ip6e.ip6e_len + 1) << 3;
160962587Sitojun		return off;
161062587Sitojun
161162587Sitojun	case IPPROTO_NONE:
161262587Sitojun	case IPPROTO_ESP:
161362587Sitojun	case IPPROTO_IPCOMP:
161462587Sitojun		/* give up */
161562587Sitojun		return -1;
161662587Sitojun
161762587Sitojun	default:
161862587Sitojun		return -1;
161962587Sitojun	}
162062587Sitojun
162162587Sitojun	return -1;
162262587Sitojun}
162362587Sitojun
162462587Sitojun/*
162562587Sitojun * get offset for the last header in the chain.  m will be kept untainted.
162662587Sitojun */
162762587Sitojunint
1628171259Sdelphijip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
162962587Sitojun{
163062587Sitojun	int newoff;
163162587Sitojun	int nxt;
163262587Sitojun
163362587Sitojun	if (!nxtp) {
163462587Sitojun		nxt = -1;
163562587Sitojun		nxtp = &nxt;
163662587Sitojun	}
163762587Sitojun	while (1) {
163862587Sitojun		newoff = ip6_nexthdr(m, off, proto, nxtp);
163962587Sitojun		if (newoff < 0)
164062587Sitojun			return off;
164162587Sitojun		else if (newoff < off)
164262587Sitojun			return -1;	/* invalid */
164362587Sitojun		else if (newoff == off)
164462587Sitojun			return newoff;
164562587Sitojun
164662587Sitojun		off = newoff;
164762587Sitojun		proto = *nxtp;
164862587Sitojun	}
164962587Sitojun}
165062587Sitojun
1651121673Sumestruct ip6aux *
1652171259Sdelphijip6_addaux(struct mbuf *m)
165378064Sume{
1654120913Sume	struct m_tag *mtag;
1655120913Sume
1656120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1657120913Sume	if (!mtag) {
1658120913Sume		mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux),
1659120913Sume		    M_NOWAIT);
1660121630Sume		if (mtag) {
1661120913Sume			m_tag_prepend(m, mtag);
1662121630Sume			bzero(mtag + 1, sizeof(struct ip6aux));
1663121630Sume		}
166478064Sume	}
1665121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
166678064Sume}
166778064Sume
1668121673Sumestruct ip6aux *
1669171259Sdelphijip6_findaux(struct mbuf *m)
167078064Sume{
1671120913Sume	struct m_tag *mtag;
1672120913Sume
1673120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1674121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
167578064Sume}
167678064Sume
167778064Sumevoid
1678171259Sdelphijip6_delaux(struct mbuf *m)
167978064Sume{
1680120913Sume	struct m_tag *mtag;
1681120913Sume
1682120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1683120913Sume	if (mtag)
1684120913Sume		m_tag_delete(m, mtag);
168578064Sume}
168678064Sume
168762587Sitojun/*
168853541Sshin * System control for IP6
168953541Sshin */
169053541Sshin
169153541Sshinu_char	inet6ctlerrmap[PRC_NCMDS] = {
169253541Sshin	0,		0,		0,		0,
169353541Sshin	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
169453541Sshin	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
169553541Sshin	EMSGSIZE,	EHOSTUNREACH,	0,		0,
169653541Sshin	0,		0,		0,		0,
169753541Sshin	ENOPROTOOPT
169853541Sshin};
1699