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: stable/10/sys/netinet6/ip6_input.c 329158 2018-02-12 13:52:58Z ae $");
65174510Sobrien
6662587Sitojun#include "opt_inet.h"
6762587Sitojun#include "opt_inet6.h"
68225044Sbz#include "opt_ipfw.h"
6955009Sshin#include "opt_ipsec.h"
70254889Smarkj#include "opt_kdtrace.h"
71207828Skmacy#include "opt_route.h"
7255009Sshin
7353541Sshin#include <sys/param.h>
7453541Sshin#include <sys/systm.h>
7578064Sume#include <sys/malloc.h>
7653541Sshin#include <sys/mbuf.h>
7783366Sjulian#include <sys/proc.h>
7853541Sshin#include <sys/domain.h>
7953541Sshin#include <sys/protosw.h>
80254889Smarkj#include <sys/sdt.h>
8153541Sshin#include <sys/socket.h>
8253541Sshin#include <sys/socketvar.h>
8353541Sshin#include <sys/errno.h>
8453541Sshin#include <sys/time.h>
8553541Sshin#include <sys/kernel.h>
8653541Sshin#include <sys/syslog.h>
8753541Sshin
8853541Sshin#include <net/if.h>
8953541Sshin#include <net/if_types.h>
9053541Sshin#include <net/if_dl.h>
9153541Sshin#include <net/route.h>
9253541Sshin#include <net/netisr.h>
9364060Sdarrenr#include <net/pfil.h>
94185571Sbz#include <net/vnet.h>
9553541Sshin
9653541Sshin#include <netinet/in.h>
97254889Smarkj#include <netinet/in_kdtrace.h>
98225044Sbz#include <netinet/ip_var.h>
9953541Sshin#include <netinet/in_systm.h>
100186119Sqingli#include <net/if_llatbl.h>
10162587Sitojun#ifdef INET
10253541Sshin#include <netinet/ip.h>
10353541Sshin#include <netinet/ip_icmp.h>
10495023Ssuz#endif /* INET */
10562587Sitojun#include <netinet/ip6.h>
10653541Sshin#include <netinet6/in6_var.h>
10753541Sshin#include <netinet6/ip6_var.h>
10862587Sitojun#include <netinet/in_pcb.h>
10962587Sitojun#include <netinet/icmp6.h>
110121161Sume#include <netinet6/scope6_var.h>
11153541Sshin#include <netinet6/in6_ifattach.h>
11253541Sshin#include <netinet6/nd6.h>
11353541Sshin
114171167Sgnn#ifdef IPSEC
115105199Ssam#include <netipsec/ipsec.h>
116171133Sgnn#include <netinet6/ip6_ipsec.h>
117105199Ssam#include <netipsec/ipsec6.h>
118171167Sgnn#endif /* IPSEC */
119105199Ssam
12053541Sshin#include <netinet6/ip6protosw.h>
12153541Sshin
12262587Sitojunextern struct domain inet6domain;
12353541Sshin
12462587Sitojunu_char ip6_protox[IPPROTO_MAX];
125207369SbzVNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead);
126244272SaeVNET_DEFINE(struct in6_ifaddrlisthead *, in6_ifaddrhashtbl);
127244272SaeVNET_DEFINE(u_long, in6_ifaddrhmask);
128185088Szec
129193219Srwatsonstatic struct netisr_handler ip6_nh = {
130193219Srwatson	.nh_name = "ip6",
131193219Srwatson	.nh_handler = ip6_input,
132193219Srwatson	.nh_proto = NETISR_IPV6,
133193219Srwatson	.nh_policy = NETISR_POLICY_FLOW,
134193219Srwatson};
135193219Srwatson
136195699SrwatsonVNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
137195727Srwatson#define	V_in6_tmpaddrtimer_ch		VNET(in6_tmpaddrtimer_ch)
13878064Sume
139207369SbzVNET_DEFINE(struct pfil_head, inet6_pfil_hook);
140207369Sbz
141253085SaeVNET_PCPUSTAT_DEFINE(struct ip6stat, ip6stat);
142253085SaeVNET_PCPUSTAT_SYSINIT(ip6stat);
143253085Sae#ifdef VIMAGE
144253085SaeVNET_PCPUSTAT_SYSUNINIT(ip6stat);
145253085Sae#endif /* VIMAGE */
146207369Sbz
147194971Srwatsonstruct rwlock in6_ifaddr_lock;
148194971SrwatsonRW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
149194971Srwatson
150175162Sobrienstatic void ip6_init2(void *);
151175162Sobrienstatic struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
152235956Sbzstatic struct ip6aux *ip6_addaux(struct mbuf *);
153235956Sbzstatic struct ip6aux *ip6_findaux(struct mbuf *m);
154235956Sbzstatic void ip6_delaux (struct mbuf *);
155175162Sobrienstatic int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
15662587Sitojun#ifdef PULLDOWN_TEST
157175162Sobrienstatic struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
15853541Sshin#endif
15953541Sshin
16053541Sshin/*
16153541Sshin * IP6 initialization: fill in IP6 protocol switch table.
16253541Sshin * All protocols not implemented in kernel go to raw IP6 protocol handler.
16353541Sshin */
16453541Sshinvoid
165171259Sdelphijip6_init(void)
16653541Sshin{
16778064Sume	struct ip6protosw *pr;
16878064Sume	int i;
16953541Sshin
170185895Szec	TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
171185895Szec	    &V_ip6_auto_linklocal);
172232379Shrs	TUNABLE_INT_FETCH("net.inet6.ip6.accept_rtadv", &V_ip6_accept_rtadv);
173232379Shrs	TUNABLE_INT_FETCH("net.inet6.ip6.no_radr", &V_ip6_no_radr);
174185088Szec
175207369Sbz	TAILQ_INIT(&V_in6_ifaddrhead);
176244272Sae	V_in6_ifaddrhashtbl = hashinit(IN6ADDR_NHASH, M_IFADDR,
177244272Sae	    &V_in6_ifaddrhmask);
178185088Szec
179207369Sbz	/* Initialize packet filter hooks. */
180207369Sbz	V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
181207369Sbz	V_inet6_pfil_hook.ph_af = AF_INET6;
182207369Sbz	if ((i = pfil_head_register(&V_inet6_pfil_hook)) != 0)
183207369Sbz		printf("%s: WARNING: unable to register pfil hook, "
184207369Sbz			"error %d\n", __func__, i);
185185088Szec
186190787Szec	scope6_init();
187190787Szec	addrsel_policy_init();
188190787Szec	nd6_init();
189190787Szec	frag6_init();
190190787Szec
191190787Szec	V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
192190787Szec
193190787Szec	/* Skip global initialization stuff for non-default instances. */
194190787Szec	if (!IS_DEFAULT_VNET(curvnet))
195190787Szec		return;
196190787Szec
19778064Sume#ifdef DIAGNOSTIC
19878064Sume	if (sizeof(struct protosw) != sizeof(struct ip6protosw))
19978064Sume		panic("sizeof(protosw) != sizeof(ip6protosw)");
20078064Sume#endif
20153541Sshin	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
202191433Sbz	if (pr == NULL)
20353541Sshin		panic("ip6_init");
204136689Sandre
205186393Sbz	/* Initialize the entire ip6_protox[] array to IPPROTO_RAW. */
20653541Sshin	for (i = 0; i < IPPROTO_MAX; i++)
20753541Sshin		ip6_protox[i] = pr - inet6sw;
208136689Sandre	/*
209136689Sandre	 * Cycle through IP protocols and put them into the appropriate place
210136689Sandre	 * in ip6_protox[].
211136689Sandre	 */
21253541Sshin	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
21353541Sshin	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
21453541Sshin		if (pr->pr_domain->dom_family == PF_INET6 &&
215136689Sandre		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
216136689Sandre			/* Be careful to only index valid IP protocols. */
217143675Ssam			if (pr->pr_protocol < IPPROTO_MAX)
218136689Sandre				ip6_protox[pr->pr_protocol] = pr - inet6sw;
219136689Sandre		}
220134383Sandre
221193219Srwatson	netisr_register(&ip6_nh);
22253541Sshin}
22353541Sshin
224212155Sbz/*
225212155Sbz * The protocol to be inserted into ip6_protox[] must be already registered
226212155Sbz * in inet6sw[], either statically or through pf_proto_register().
227212155Sbz */
228212155Sbzint
229212155Sbzip6proto_register(short ip6proto)
230212155Sbz{
231212155Sbz	struct ip6protosw *pr;
232212155Sbz
233212155Sbz	/* Sanity checks. */
234212155Sbz	if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
235212155Sbz		return (EPROTONOSUPPORT);
236212155Sbz
237212155Sbz	/*
238212155Sbz	 * The protocol slot must not be occupied by another protocol
239212155Sbz	 * already.  An index pointing to IPPROTO_RAW is unused.
240212155Sbz	 */
241212155Sbz	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
242212155Sbz	if (pr == NULL)
243212155Sbz		return (EPFNOSUPPORT);
244212155Sbz	if (ip6_protox[ip6proto] != pr - inet6sw)	/* IPPROTO_RAW */
245212155Sbz		return (EEXIST);
246212155Sbz
247212155Sbz	/*
248212155Sbz	 * Find the protocol position in inet6sw[] and set the index.
249212155Sbz	 */
250212155Sbz	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
251212155Sbz	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) {
252212155Sbz		if (pr->pr_domain->dom_family == PF_INET6 &&
253212155Sbz		    pr->pr_protocol && pr->pr_protocol == ip6proto) {
254212155Sbz			ip6_protox[pr->pr_protocol] = pr - inet6sw;
255212155Sbz			return (0);
256212155Sbz		}
257212155Sbz	}
258212155Sbz	return (EPROTONOSUPPORT);
259212155Sbz}
260212155Sbz
261212155Sbzint
262212155Sbzip6proto_unregister(short ip6proto)
263212155Sbz{
264212155Sbz	struct ip6protosw *pr;
265212155Sbz
266212155Sbz	/* Sanity checks. */
267212155Sbz	if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
268212155Sbz		return (EPROTONOSUPPORT);
269212155Sbz
270212155Sbz	/* Check if the protocol was indeed registered. */
271212155Sbz	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
272212155Sbz	if (pr == NULL)
273212155Sbz		return (EPFNOSUPPORT);
274212155Sbz	if (ip6_protox[ip6proto] == pr - inet6sw)	/* IPPROTO_RAW */
275212155Sbz		return (ENOENT);
276212155Sbz
277212155Sbz	/* Reset the protocol slot to IPPROTO_RAW. */
278212155Sbz	ip6_protox[ip6proto] = pr - inet6sw;
279212155Sbz	return (0);
280212155Sbz}
281212155Sbz
282193731Szec#ifdef VIMAGE
283193731Szecvoid
284193731Szecip6_destroy()
285193731Szec{
286255523Strociny	int i;
287193731Szec
288255523Strociny	if ((i = pfil_head_unregister(&V_inet6_pfil_hook)) != 0)
289255523Strociny		printf("%s: WARNING: unable to unregister pfil hook, "
290255523Strociny		    "error %d\n", __func__, i);
291244272Sae	hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask);
292193731Szec	nd6_destroy();
293193731Szec	callout_drain(&V_in6_tmpaddrtimer_ch);
294193731Szec}
295193731Szec#endif
296193731Szec
297190787Szecstatic int
298190787Szecip6_init2_vnet(const void *unused __unused)
29953541Sshin{
30053541Sshin
30153541Sshin	/* nd6_timer_init */
302181803Sbz	callout_init(&V_nd6_timer_ch, 0);
303191688Szec	callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
30478064Sume
30578064Sume	/* timer for regeneranation of temporary addresses randomize ID */
306181803Sbz	callout_init(&V_in6_tmpaddrtimer_ch, 0);
307181803Sbz	callout_reset(&V_in6_tmpaddrtimer_ch,
308181803Sbz		      (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
309181803Sbz		       V_ip6_temp_regen_advance) * hz,
310191688Szec		      in6_tmpaddrtimer, curvnet);
311190787Szec
312190787Szec	return (0);
31353541Sshin}
31453541Sshin
315190787Szecstatic void
316190787Szecip6_init2(void *dummy)
317190787Szec{
318190787Szec
319190787Szec	ip6_init2_vnet(NULL);
320190787Szec}
321190787Szec
32253541Sshin/* cheat */
32355009Sshin/* This must be after route_init(), which is now SI_ORDER_THIRD */
32455009SshinSYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
32553541Sshin
326235962Sbzstatic int
327235962Sbzip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
328235962Sbz    int *nxt, int *ours)
329235962Sbz{
330235962Sbz	struct ip6_hdr *ip6;
331235962Sbz	struct ip6_hbh *hbh;
332235962Sbz
333235962Sbz	if (ip6_hopopts_input(plen, rtalert, &m, off)) {
334235962Sbz#if 0	/*touches NULL pointer*/
335235962Sbz		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
336235962Sbz#endif
337235962Sbz		goto out;	/* m have already been freed */
338235962Sbz	}
339235962Sbz
340235962Sbz	/* adjust pointer */
341235962Sbz	ip6 = mtod(m, struct ip6_hdr *);
342235962Sbz
343235962Sbz	/*
344235962Sbz	 * if the payload length field is 0 and the next header field
345235962Sbz	 * indicates Hop-by-Hop Options header, then a Jumbo Payload
346235962Sbz	 * option MUST be included.
347235962Sbz	 */
348235962Sbz	if (ip6->ip6_plen == 0 && *plen == 0) {
349235962Sbz		/*
350235962Sbz		 * Note that if a valid jumbo payload option is
351235962Sbz		 * contained, ip6_hopopts_input() must set a valid
352235962Sbz		 * (non-zero) payload length to the variable plen.
353235962Sbz		 */
354249294Sae		IP6STAT_INC(ip6s_badoptions);
355235962Sbz		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
356235962Sbz		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
357235962Sbz		icmp6_error(m, ICMP6_PARAM_PROB,
358235962Sbz			    ICMP6_PARAMPROB_HEADER,
359235962Sbz			    (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
360235962Sbz		goto out;
361235962Sbz	}
362235962Sbz#ifndef PULLDOWN_TEST
363235962Sbz	/* ip6_hopopts_input() ensures that mbuf is contiguous */
364235962Sbz	hbh = (struct ip6_hbh *)(ip6 + 1);
365235962Sbz#else
366235962Sbz	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
367235962Sbz		sizeof(struct ip6_hbh));
368235962Sbz	if (hbh == NULL) {
369249294Sae		IP6STAT_INC(ip6s_tooshort);
370235962Sbz		goto out;
371235962Sbz	}
372235962Sbz#endif
373235962Sbz	*nxt = hbh->ip6h_nxt;
374235962Sbz
375235962Sbz	/*
376235962Sbz	 * If we are acting as a router and the packet contains a
377235962Sbz	 * router alert option, see if we know the option value.
378235962Sbz	 * Currently, we only support the option value for MLD, in which
379235962Sbz	 * case we should pass the packet to the multicast routing
380235962Sbz	 * daemon.
381235962Sbz	 */
382235962Sbz	if (*rtalert != ~0) {
383235962Sbz		switch (*rtalert) {
384235962Sbz		case IP6OPT_RTALERT_MLD:
385235962Sbz			if (V_ip6_forwarding)
386235962Sbz				*ours = 1;
387235962Sbz			break;
388235962Sbz		default:
389235962Sbz			/*
390235962Sbz			 * RFC2711 requires unrecognized values must be
391235962Sbz			 * silently ignored.
392235962Sbz			 */
393235962Sbz			break;
394235962Sbz		}
395235962Sbz	}
396235962Sbz
397235962Sbz	return (0);
398235962Sbz
399235962Sbzout:
400235962Sbz	return (1);
401235962Sbz}
402235962Sbz
40353541Sshinvoid
404171259Sdelphijip6_input(struct mbuf *m)
40553541Sshin{
40653541Sshin	struct ip6_hdr *ip6;
40753541Sshin	int off = sizeof(struct ip6_hdr), nest;
40853541Sshin	u_int32_t plen;
40953541Sshin	u_int32_t rtalert = ~0;
41053541Sshin	int nxt, ours = 0;
411186119Sqingli	struct ifnet *deliverifp = NULL, *ifp = NULL;
412121143Ssam	struct in6_addr odst;
413187989Sbz	struct route_in6 rin6;
414121143Ssam	int srcrt = 0;
415186119Sqingli	struct llentry *lle = NULL;
416187989Sbz	struct sockaddr_in6 dst6, *dst;
417121144Ssam
418187989Sbz	bzero(&rin6, sizeof(struct route_in6));
419171167Sgnn#ifdef IPSEC
42053541Sshin	/*
42153541Sshin	 * should the inner packet be considered authentic?
42253541Sshin	 * see comment in ah4_input().
423171133Sgnn	 * NB: m cannot be NULL when passed to the input routine
42453541Sshin	 */
42553541Sshin
426171133Sgnn	m->m_flags &= ~M_AUTHIPHDR;
427171133Sgnn	m->m_flags &= ~M_AUTHIPDGM;
428171133Sgnn
429171167Sgnn#endif /* IPSEC */
430171133Sgnn
43153541Sshin	/*
432121630Sume	 * make sure we don't have onion peering information into m_tag.
43378064Sume	 */
43478064Sume	ip6_delaux(m);
43578064Sume
436225044Sbz	if (m->m_flags & M_FASTFWD_OURS) {
437225044Sbz		/*
438225044Sbz		 * Firewall changed destination to local.
439225044Sbz		 */
440225044Sbz		m->m_flags &= ~M_FASTFWD_OURS;
441225044Sbz		ours = 1;
442225044Sbz		deliverifp = m->m_pkthdr.rcvif;
443225044Sbz		ip6 = mtod(m, struct ip6_hdr *);
444225044Sbz		goto hbhcheck;
445225044Sbz	}
446225044Sbz
44778064Sume	/*
44895023Ssuz	 * mbuf statistics
44953541Sshin	 */
45053541Sshin	if (m->m_flags & M_EXT) {
45153541Sshin		if (m->m_next)
452249294Sae			IP6STAT_INC(ip6s_mext2m);
45353541Sshin		else
454249294Sae			IP6STAT_INC(ip6s_mext1);
45553541Sshin	} else {
45653541Sshin		if (m->m_next) {
45753541Sshin			if (m->m_flags & M_LOOP) {
458249294Sae				IP6STAT_INC(ip6s_m2m[V_loif->if_index]);
459249544Sae			} else if (m->m_pkthdr.rcvif->if_index < IP6S_M2MMAX)
460249294Sae				IP6STAT_INC(
461249294Sae				    ip6s_m2m[m->m_pkthdr.rcvif->if_index]);
46253541Sshin			else
463249294Sae				IP6STAT_INC(ip6s_m2m[0]);
46453541Sshin		} else
465249294Sae			IP6STAT_INC(ip6s_m1);
46653541Sshin	}
46753541Sshin
468151474Ssuz	/* drop the packet if IPv6 operation is disabled on the IF */
469151474Ssuz	if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
470151474Ssuz		m_freem(m);
471151474Ssuz		return;
472151474Ssuz	}
473151474Ssuz
47453541Sshin	in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
475249294Sae	IP6STAT_INC(ip6s_total);
47653541Sshin
47762587Sitojun#ifndef PULLDOWN_TEST
47874336Skuriyama	/*
47974336Skuriyama	 * L2 bridge code and some other code can return mbuf chain
48074336Skuriyama	 * that does not conform to KAME requirement.  too bad.
48174336Skuriyama	 * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
48274336Skuriyama	 */
48374336Skuriyama	if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
48474336Skuriyama		struct mbuf *n;
48574336Skuriyama
486248320Sglebius		if (m->m_pkthdr.len > MHLEN)
487248320Sglebius			n = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
488248320Sglebius		else
489248320Sglebius			n = m_gethdr(M_NOWAIT, MT_DATA);
49095023Ssuz		if (n == NULL) {
49177003Sume			m_freem(m);
492120913Sume			return;	/* ENOBUFS */
49377003Sume		}
49474336Skuriyama
495248328Sglebius		m_move_pkthdr(n, m);
496108825Ssam		m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
497108825Ssam		n->m_len = n->m_pkthdr.len;
49874336Skuriyama		m_freem(m);
49974336Skuriyama		m = n;
50074336Skuriyama	}
501120913Sume	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */);
50262587Sitojun#endif
50353541Sshin
50453541Sshin	if (m->m_len < sizeof(struct ip6_hdr)) {
50553541Sshin		struct ifnet *inifp;
50653541Sshin		inifp = m->m_pkthdr.rcvif;
507120913Sume		if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
508249294Sae			IP6STAT_INC(ip6s_toosmall);
50953541Sshin			in6_ifstat_inc(inifp, ifs6_in_hdrerr);
51053541Sshin			return;
51153541Sshin		}
51253541Sshin	}
51353541Sshin
51453541Sshin	ip6 = mtod(m, struct ip6_hdr *);
51553541Sshin
51653541Sshin	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
517249294Sae		IP6STAT_INC(ip6s_badvers);
51853541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
51953541Sshin		goto bad;
52053541Sshin	}
52153541Sshin
522249294Sae	IP6STAT_INC(ip6s_nxthist[ip6->ip6_nxt]);
52353541Sshin
524254889Smarkj	IP_PROBE(receive, NULL, NULL, ip6, m->m_pkthdr.rcvif, NULL, ip6);
525254889Smarkj
52653541Sshin	/*
52778064Sume	 * Check against address spoofing/corruption.
52853541Sshin	 */
52953541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
53053541Sshin	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
53178064Sume		/*
53278064Sume		 * XXX: "badscope" is not very suitable for a multicast source.
53378064Sume		 */
534249294Sae		IP6STAT_INC(ip6s_badscope);
53553541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
53653541Sshin		goto bad;
53753541Sshin	}
538126444Sume	if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
539126444Sume	    !(m->m_flags & M_LOOP)) {
540126444Sume		/*
541126444Sume		 * In this case, the packet should come from the loopback
542126444Sume		 * interface.  However, we cannot just check the if_flags,
543126444Sume		 * because ip6_mloopback() passes the "actual" interface
544126444Sume		 * as the outgoing/incoming interface.
545126444Sume		 */
546249294Sae		IP6STAT_INC(ip6s_badscope);
54778064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
54878064Sume		goto bad;
54978064Sume	}
550262256Sae	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
551262256Sae	    IPV6_ADDR_MC_SCOPE(&ip6->ip6_dst) == 0) {
552262256Sae		/*
553262256Sae		 * RFC4291 2.7:
554262256Sae		 * Nodes must not originate a packet to a multicast address
555262256Sae		 * whose scop field contains the reserved value 0; if such
556262256Sae		 * a packet is received, it must be silently dropped.
557262256Sae		 */
558262256Sae		IP6STAT_INC(ip6s_badscope);
559262256Sae		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
560262256Sae		goto bad;
561262256Sae	}
562130416Smlaier#ifdef ALTQ
563130416Smlaier	if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
564130416Smlaier		/* packet is dropped by traffic conditioner */
565130416Smlaier		return;
566130416Smlaier	}
567130416Smlaier#endif
56862587Sitojun	/*
56978064Sume	 * The following check is not documented in specs.  A malicious
57078064Sume	 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
57178064Sume	 * and bypass security checks (act as if it was from 127.0.0.1 by using
572120913Sume	 * IPv6 src ::ffff:127.0.0.1).  Be cautious.
57378064Sume	 *
57478064Sume	 * This check chokes if we are in an SIIT cloud.  As none of BSDs
57578064Sume	 * support IPv4-less kernel compilation, we cannot support SIIT
57678064Sume	 * environment at all.  So, it makes more sense for us to reject any
57778064Sume	 * malicious packets for non-SIIT environment, than try to do a
578120913Sume	 * partial support for SIIT environment.
57962587Sitojun	 */
58078064Sume	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
58178064Sume	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
582249294Sae		IP6STAT_INC(ip6s_badscope);
58378064Sume		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
58478064Sume		goto bad;
58578064Sume	}
58662587Sitojun#if 0
58762587Sitojun	/*
58862587Sitojun	 * Reject packets with IPv4 compatible addresses (auto tunnel).
58962587Sitojun	 *
59062587Sitojun	 * The code forbids auto tunnel relay case in RFC1933 (the check is
59162587Sitojun	 * stronger than RFC1933).  We may want to re-enable it if mech-xx
59262587Sitojun	 * is revised to forbid relaying case.
59362587Sitojun	 */
59462587Sitojun	if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
59562587Sitojun	    IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
596249294Sae		IP6STAT_INC(ip6s_badscope);
59762587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
59862587Sitojun		goto bad;
59962587Sitojun	}
60062587Sitojun#endif
601222856Sbz#ifdef IPSEC
602222856Sbz	/*
603222856Sbz	 * Bypass packet filtering for packets previously handled by IPsec.
604222856Sbz	 */
605222856Sbz	if (ip6_ipsec_filtertunnel(m))
606222856Sbz		goto passin;
607222856Sbz#endif /* IPSEC */
60875246Sume
609126444Sume	/*
610126508Smlaier	 * Run through list of hooks for input packets.
611126508Smlaier	 *
612126508Smlaier	 * NB: Beware of the destination address changing
613126508Smlaier	 *     (e.g. by NAT rewriting).  When this happens,
614126508Smlaier	 *     tell ip6_forward to do the right thing.
615126508Smlaier	 */
616126508Smlaier	odst = ip6->ip6_dst;
617134383Sandre
618134383Sandre	/* Jump over all PFIL processing if hooks are not active. */
619197952Sjulian	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
620134383Sandre		goto passin;
621134383Sandre
622197952Sjulian	if (pfil_run_hooks(&V_inet6_pfil_hook, &m,
623197952Sjulian	    m->m_pkthdr.rcvif, PFIL_IN, NULL))
624126508Smlaier		return;
625126508Smlaier	if (m == NULL)			/* consumed by filter */
626126508Smlaier		return;
627126508Smlaier	ip6 = mtod(m, struct ip6_hdr *);
628126508Smlaier	srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
629126508Smlaier
630225044Sbz	if (m->m_flags & M_FASTFWD_OURS) {
631225044Sbz		m->m_flags &= ~M_FASTFWD_OURS;
632225044Sbz		ours = 1;
633225044Sbz		deliverifp = m->m_pkthdr.rcvif;
634225044Sbz		goto hbhcheck;
635225044Sbz	}
636242463Sae	if ((m->m_flags & M_IP6_NEXTHOP) &&
637242463Sae	    m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) {
638225044Sbz		/*
639225044Sbz		 * Directly ship the packet on.  This allows forwarding
640225044Sbz		 * packets originally destined to us to some other directly
641225044Sbz		 * connected host.
642225044Sbz		 */
643225044Sbz		ip6_forward(m, 1);
644225044Sbz		goto out;
645225044Sbz	}
646225044Sbz
647134383Sandrepassin:
648126508Smlaier	/*
649154804Sume	 * Disambiguate address scope zones (if there is ambiguity).
650154804Sume	 * We first make sure that the original source or destination address
651154804Sume	 * is not in our internal form for scoped addresses.  Such addresses
652154804Sume	 * are not necessarily invalid spec-wise, but we cannot accept them due
653154804Sume	 * to the usage conflict.
654154804Sume	 * in6_setscope() then also checks and rejects the cases where src or
655154804Sume	 * dst are the loopback address and the receiving interface
656154804Sume	 * is not loopback.
657154804Sume	 */
658154804Sume	if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) {
659249294Sae		IP6STAT_INC(ip6s_badscope); /* XXX */
660154804Sume		goto bad;
661154804Sume	}
662154804Sume	if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||
663154804Sume	    in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {
664249294Sae		IP6STAT_INC(ip6s_badscope);
665154804Sume		goto bad;
666154804Sume	}
667154804Sume
668154804Sume	/*
669191672Sbms	 * Multicast check. Assume packet is for us to avoid
670191672Sbms	 * prematurely taking locks.
67153541Sshin	 */
67253541Sshin	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
673191672Sbms		ours = 1;
67453541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
67553541Sshin		deliverifp = m->m_pkthdr.rcvif;
67653541Sshin		goto hbhcheck;
67753541Sshin	}
67853541Sshin
67953541Sshin	/*
68053541Sshin	 *  Unicast check
68153541Sshin	 */
682186119Sqingli
683186119Sqingli	bzero(&dst6, sizeof(dst6));
684186119Sqingli	dst6.sin6_family = AF_INET6;
685186119Sqingli	dst6.sin6_len = sizeof(struct sockaddr_in6);
686186119Sqingli	dst6.sin6_addr = ip6->ip6_dst;
687186119Sqingli	ifp = m->m_pkthdr.rcvif;
688243148Sae	IF_AFDATA_RLOCK(ifp);
689186119Sqingli	lle = lla_lookup(LLTABLE6(ifp), 0,
690186119Sqingli	     (struct sockaddr *)&dst6);
691243148Sae	IF_AFDATA_RUNLOCK(ifp);
692186119Sqingli	if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
693210350Sbz		struct ifaddr *ifa;
694210350Sbz		struct in6_ifaddr *ia6;
695210350Sbz		int bad;
696210350Sbz
697210350Sbz		bad = 1;
698210350Sbz#define	sa_equal(a1, a2)						\
699210350Sbz	(bcmp((a1), (a2), ((a1))->sin6_len) == 0)
700229621Sjhb		IF_ADDR_RLOCK(ifp);
701210350Sbz		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
702210350Sbz			if (ifa->ifa_addr->sa_family != dst6.sin6_family)
703210350Sbz				continue;
704210350Sbz			if (sa_equal(&dst6, ifa->ifa_addr))
705210350Sbz				break;
706210350Sbz		}
707210350Sbz		KASSERT(ifa != NULL, ("%s: ifa not found for lle %p",
708210350Sbz		    __func__, lle));
709210350Sbz#undef sa_equal
710210350Sbz
711210350Sbz		ia6 = (struct in6_ifaddr *)ifa;
712210350Sbz		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
713210350Sbz			/* Count the packet in the ip address stats */
714210350Sbz			ia6->ia_ifa.if_ipackets++;
715210350Sbz			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
716210350Sbz
717210350Sbz			/*
718210350Sbz			 * record address information into m_tag.
719210350Sbz			 */
720210350Sbz			(void)ip6_setdstifaddr(m, ia6);
721210350Sbz
722210350Sbz			bad = 0;
723210350Sbz		} else {
724210350Sbz			char ip6bufs[INET6_ADDRSTRLEN];
725210350Sbz			char ip6bufd[INET6_ADDRSTRLEN];
726210350Sbz			/* address is not ready, so discard the packet. */
727210350Sbz			nd6log((LOG_INFO,
728210350Sbz			    "ip6_input: packet to an unready address %s->%s\n",
729210350Sbz			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
730210350Sbz			    ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
731210350Sbz		}
732229621Sjhb		IF_ADDR_RUNLOCK(ifp);
733186119Sqingli		LLE_RUNLOCK(lle);
734210350Sbz		if (bad)
735210350Sbz			goto bad;
736210350Sbz		else {
737210350Sbz			ours = 1;
738210350Sbz			deliverifp = ifp;
739210350Sbz			goto hbhcheck;
740210350Sbz		}
741186119Sqingli	}
742186293Sbz	if (lle != NULL)
743186293Sbz		LLE_RUNLOCK(lle);
744186119Sqingli
745187989Sbz	dst = &rin6.ro_dst;
746187989Sbz	dst->sin6_len = sizeof(struct sockaddr_in6);
747187989Sbz	dst->sin6_family = AF_INET6;
748187989Sbz	dst->sin6_addr = ip6->ip6_dst;
749231852Sbz	rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
750187989Sbz	if (rin6.ro_rt)
751187989Sbz		RT_UNLOCK(rin6.ro_rt);
75278064Sume
75353541Sshin#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
75453541Sshin
75553541Sshin	/*
75653541Sshin	 * Accept the packet if the forwarding interface to the destination
75753541Sshin	 * according to the routing table is the loopback interface,
75853541Sshin	 * unless the associated route has a gateway.
75953541Sshin	 * Note that this approach causes to accept a packet if there is a
76053541Sshin	 * route to the loopback interface for the destination of the packet.
76153541Sshin	 * But we think it's even useful in some situations, e.g. when using
76253541Sshin	 * a special daemon which wants to intercept the packet.
76378064Sume	 *
76478064Sume	 * XXX: some OSes automatically make a cloned route for the destination
76578064Sume	 * of an outgoing packet.  If the outgoing interface of the packet
76678064Sume	 * is a loopback one, the kernel would consider the packet to be
76778064Sume	 * accepted, even if we have no such address assinged on the interface.
76878064Sume	 * We check the cloned flag of the route entry to reject such cases,
76978064Sume	 * assuming that route entries for our own addresses are not made by
77078064Sume	 * cloning (it should be true because in6_addloop explicitly installs
77178064Sume	 * the host route).  However, we might have to do an explicit check
77278064Sume	 * while it would be less efficient.  Or, should we rather install a
77378064Sume	 * reject route for such a case?
77453541Sshin	 */
775187989Sbz	if (rin6.ro_rt &&
776187989Sbz	    (rin6.ro_rt->rt_flags &
77753541Sshin	     (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
77878064Sume#ifdef RTF_WASCLONED
779187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
78078064Sume#endif
78178064Sume#ifdef RTF_CLONED
782187989Sbz	    !(rin6.ro_rt->rt_flags & RTF_CLONED) &&
78378064Sume#endif
78462587Sitojun#if 0
78553541Sshin	    /*
78662587Sitojun	     * The check below is redundant since the comparison of
78762587Sitojun	     * the destination and the key of the rtentry has
78862587Sitojun	     * already done through looking up the routing table.
78953541Sshin	     */
79062587Sitojun	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
791187989Sbz	    &rt6_key(rin6.ro_rt)->sin6_addr)
79262587Sitojun#endif
793187989Sbz	    rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
794196569Sqingli		int free_ia6 = 0;
795196569Sqingli		struct in6_ifaddr *ia6;
79678064Sume
79762587Sitojun		/*
798196569Sqingli		 * found the loopback route to the interface address
799196569Sqingli		 */
800196569Sqingli		if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) {
801196569Sqingli			struct sockaddr_in6 dest6;
802196569Sqingli
803196569Sqingli			bzero(&dest6, sizeof(dest6));
804196569Sqingli			dest6.sin6_family = AF_INET6;
805196569Sqingli			dest6.sin6_len = sizeof(dest6);
806196569Sqingli			dest6.sin6_addr = ip6->ip6_dst;
807196569Sqingli			ia6 = (struct in6_ifaddr *)
808196569Sqingli			    ifa_ifwithaddr((struct sockaddr *)&dest6);
809196569Sqingli			if (ia6 == NULL)
810196569Sqingli				goto bad;
811196569Sqingli			free_ia6 = 1;
812196569Sqingli		}
813196569Sqingli		else
814196569Sqingli			ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
815196569Sqingli
816196569Sqingli		/*
817121630Sume		 * record address information into m_tag.
81878064Sume		 */
81978064Sume		(void)ip6_setdstifaddr(m, ia6);
82078064Sume
82178064Sume		/*
82262587Sitojun		 * packets to a tentative, duplicated, or somehow invalid
82362587Sitojun		 * address must not be accepted.
82462587Sitojun		 */
82553541Sshin		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
82662587Sitojun			/* this address is ready */
82753541Sshin			ours = 1;
82853541Sshin			deliverifp = ia6->ia_ifp;	/* correct? */
82967334Sjoe			/* Count the packet in the ip address stats */
83067334Sjoe			ia6->ia_ifa.if_ipackets++;
83167334Sjoe			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
832196569Sqingli			if (ia6 != NULL && free_ia6 != 0)
833196569Sqingli				ifa_free(&ia6->ia_ifa);
83453541Sshin			goto hbhcheck;
83553541Sshin		} else {
836165118Sbz			char ip6bufs[INET6_ADDRSTRLEN];
837165118Sbz			char ip6bufd[INET6_ADDRSTRLEN];
83862587Sitojun			/* address is not ready, so discard the packet. */
83978064Sume			nd6log((LOG_INFO,
84078064Sume			    "ip6_input: packet to an unready address %s->%s\n",
841165118Sbz			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
842165118Sbz			    ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
84362587Sitojun
844196569Sqingli			if (ia6 != NULL && free_ia6 != 0)
845196569Sqingli				ifa_free(&ia6->ia_ifa);
84662587Sitojun			goto bad;
84753541Sshin		}
84853541Sshin	}
84953541Sshin
85053541Sshin	/*
851120913Sume	 * FAITH (Firewall Aided Internet Translator)
85253541Sshin	 */
853181803Sbz	if (V_ip6_keepfaith) {
854187989Sbz		if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
855187989Sbz		    rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
85653541Sshin			/* XXX do we need more sanity checks? */
85753541Sshin			ours = 1;
858187989Sbz			deliverifp = rin6.ro_rt->rt_ifp; /* faith */
85953541Sshin			goto hbhcheck;
86053541Sshin		}
86153541Sshin	}
86253541Sshin
86353541Sshin	/*
86453541Sshin	 * Now there is no reason to process the packet if it's not our own
86553541Sshin	 * and we're not a router.
86653541Sshin	 */
867181803Sbz	if (!V_ip6_forwarding) {
868249294Sae		IP6STAT_INC(ip6s_cantforward);
86953541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
87053541Sshin		goto bad;
87153541Sshin	}
87253541Sshin
87353541Sshin  hbhcheck:
87453541Sshin	/*
875121630Sume	 * record address information into m_tag, if we don't have one yet.
87678064Sume	 * note that we are unable to record it, if the address is not listed
87778064Sume	 * as our interface address (e.g. multicast addresses, addresses
87878064Sume	 * within FAITH prefixes and such).
87978064Sume	 */
880236501Semax	if (deliverifp) {
88178064Sume		struct in6_ifaddr *ia6;
88278064Sume
883236501Semax 		if ((ia6 = ip6_getdstifaddr(m)) != NULL) {
884236501Semax			ifa_free(&ia6->ia_ifa);
885236501Semax		} else {
886236501Semax			ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
887236501Semax			if (ia6) {
888236501Semax				if (!ip6_setdstifaddr(m, ia6)) {
889236501Semax					/*
890236501Semax					 * XXX maybe we should drop the packet here,
891236501Semax					 * as we could not provide enough information
892236501Semax					 * to the upper layers.
893236501Semax					 */
894236501Semax				}
895236501Semax				ifa_free(&ia6->ia_ifa);
89678064Sume			}
89778064Sume		}
89878064Sume	}
89978064Sume
90078064Sume	/*
90153541Sshin	 * Process Hop-by-Hop options header if it's contained.
90253541Sshin	 * m may be modified in ip6_hopopts_input().
90353541Sshin	 * If a JumboPayload option is included, plen will also be modified.
90453541Sshin	 */
90553541Sshin	plen = (u_int32_t)ntohs(ip6->ip6_plen);
90653541Sshin	if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
907235962Sbz		int error;
90862587Sitojun
909235962Sbz		error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours);
910235962Sbz		if (error != 0)
911187989Sbz			goto out;
91253541Sshin	} else
91353541Sshin		nxt = ip6->ip6_nxt;
91453541Sshin
91553541Sshin	/*
91653541Sshin	 * Check that the amount of data in the buffers
91753541Sshin	 * is as at least much as the IPv6 header would have us expect.
91853541Sshin	 * Trim mbufs if longer than we expect.
91953541Sshin	 * Drop packet if shorter than we expect.
92053541Sshin	 */
92153541Sshin	if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
922249294Sae		IP6STAT_INC(ip6s_tooshort);
92353541Sshin		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
92453541Sshin		goto bad;
92553541Sshin	}
92653541Sshin	if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
92753541Sshin		if (m->m_len == m->m_pkthdr.len) {
92853541Sshin			m->m_len = sizeof(struct ip6_hdr) + plen;
92953541Sshin			m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
93053541Sshin		} else
93153541Sshin			m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
93253541Sshin	}
93353541Sshin
93453541Sshin	/*
93553541Sshin	 * Forward if desirable.
93653541Sshin	 */
937191672Sbms	if (V_ip6_mrouter &&
938191672Sbms	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
93956723Sshin		/*
94056723Sshin		 * If we are acting as a multicast router, all
94156723Sshin		 * incoming multicast packets are passed to the
94256723Sshin		 * kernel-level multicast forwarding function.
94356723Sshin		 * The packet is returned (relatively) intact; if
94456723Sshin		 * ip6_mforward() returns a non-zero value, the packet
94556723Sshin		 * must be discarded, else it may be accepted below.
946192923Sbms		 *
947192923Sbms		 * XXX TODO: Check hlim and multicast scope here to avoid
948192923Sbms		 * unnecessarily calling into ip6_mforward().
94956723Sshin		 */
950191672Sbms		if (ip6_mforward &&
951166938Sbms		    ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
952191672Sbms			IP6STAT_INC(ip6s_cantforward);
953191672Sbms			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
954187989Sbz			goto bad;
95556723Sshin		}
95653541Sshin	} else if (!ours) {
957121143Ssam		ip6_forward(m, srcrt);
958187989Sbz		goto out;
959121673Sume	}
96053541Sshin
96162587Sitojun	ip6 = mtod(m, struct ip6_hdr *);
96262587Sitojun
96353541Sshin	/*
96462587Sitojun	 * Malicious party may be able to use IPv4 mapped addr to confuse
96562587Sitojun	 * tcp/udp stack and bypass security checks (act as if it was from
96662587Sitojun	 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
96762587Sitojun	 *
96862587Sitojun	 * For SIIT end node behavior, you may want to disable the check.
96962587Sitojun	 * However, you will  become vulnerable to attacks using IPv4 mapped
97062587Sitojun	 * source.
97162587Sitojun	 */
97262587Sitojun	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
97362587Sitojun	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
974249294Sae		IP6STAT_INC(ip6s_badscope);
97562587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
97662587Sitojun		goto bad;
97762587Sitojun	}
97862587Sitojun
97962587Sitojun	/*
98053541Sshin	 * Tell launch routine the next header
98153541Sshin	 */
982249294Sae	IP6STAT_INC(ip6s_delivered);
98353541Sshin	in6_ifstat_inc(deliverifp, ifs6_in_deliver);
98453541Sshin	nest = 0;
98578064Sume
98653541Sshin	while (nxt != IPPROTO_DONE) {
987181803Sbz		if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
988249294Sae			IP6STAT_INC(ip6s_toomanyhdr);
98953541Sshin			goto bad;
99053541Sshin		}
99153541Sshin
99253541Sshin		/*
99353541Sshin		 * protection against faulty packet - there should be
99453541Sshin		 * more sanity checks in header chain processing.
99553541Sshin		 */
99653541Sshin		if (m->m_pkthdr.len < off) {
997249294Sae			IP6STAT_INC(ip6s_tooshort);
99853541Sshin			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
99953541Sshin			goto bad;
100053541Sshin		}
100153541Sshin
1002171167Sgnn#ifdef IPSEC
100378064Sume		/*
100478064Sume		 * enforce IPsec policy checking if we are seeing last header.
100578064Sume		 * note that we do not visit this with protocols with pcb layer
100678064Sume		 * code - like udp/tcp/raw ip.
100778064Sume		 */
1008171133Sgnn		if (ip6_ipsec_input(m, nxt))
100978064Sume			goto bad;
1010171167Sgnn#endif /* IPSEC */
1011192923Sbms
1012192923Sbms		/*
1013192923Sbms		 * Use mbuf flags to propagate Router Alert option to
1014192923Sbms		 * ICMPv6 layer, as hop-by-hop options have been stripped.
1015192923Sbms		 */
1016192923Sbms		if (nxt == IPPROTO_ICMPV6 && rtalert != ~0)
1017192923Sbms			m->m_flags |= M_RTALERT_MLD;
1018192923Sbms
101953541Sshin		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
102053541Sshin	}
1021187989Sbz	goto out;
1022187989Sbzbad:
102353541Sshin	m_freem(m);
1024187989Sbzout:
1025187989Sbz	if (rin6.ro_rt)
1026187989Sbz		RTFREE(rin6.ro_rt);
102753541Sshin}
102853541Sshin
102953541Sshin/*
103078064Sume * set/grab in6_ifaddr correspond to IPv6 destination address.
103178064Sume * XXX backward compatibility wrapper
1032194760Srwatson *
1033194760Srwatson * XXXRW: We should bump the refcount on ia6 before sticking it in the m_tag,
1034194760Srwatson * and then bump it when the tag is copied, and release it when the tag is
1035194760Srwatson * freed.  Unfortunately, m_tags don't support deep copies (yet), so instead
1036194760Srwatson * we just bump the ia refcount when we receive it.  This should be fixed.
103778064Sume */
1038121673Sumestatic struct ip6aux *
1039171259Sdelphijip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
104078064Sume{
1041121673Sume	struct ip6aux *ip6a;
104278064Sume
1043121673Sume	ip6a = ip6_addaux(m);
1044121673Sume	if (ip6a)
1045121673Sume		ip6a->ip6a_dstia6 = ia6;
1046121673Sume	return ip6a;	/* NULL if failed to set */
104778064Sume}
104878064Sume
104978064Sumestruct in6_ifaddr *
1050171259Sdelphijip6_getdstifaddr(struct mbuf *m)
105178064Sume{
1052121673Sume	struct ip6aux *ip6a;
1053194760Srwatson	struct in6_ifaddr *ia;
105478064Sume
1055121673Sume	ip6a = ip6_findaux(m);
1056194760Srwatson	if (ip6a) {
1057194760Srwatson		ia = ip6a->ip6a_dstia6;
1058194760Srwatson		ifa_ref(&ia->ia_ifa);
1059194760Srwatson		return ia;
1060194760Srwatson	} else
106178064Sume		return NULL;
106278064Sume}
106378064Sume
106478064Sume/*
106553541Sshin * Hop-by-Hop options header processing. If a valid jumbo payload option is
106653541Sshin * included, the real payload length will be stored in plenp.
1067171259Sdelphij *
1068171259Sdelphij * rtalertp - XXX: should be stored more smart way
106953541Sshin */
107053541Sshinstatic int
1071171259Sdelphijip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
1072171259Sdelphij    struct mbuf **mp, int *offp)
107353541Sshin{
107478064Sume	struct mbuf *m = *mp;
107553541Sshin	int off = *offp, hbhlen;
107653541Sshin	struct ip6_hbh *hbh;
107753541Sshin
107853541Sshin	/* validation of the length of the header */
107962587Sitojun#ifndef PULLDOWN_TEST
108053541Sshin	IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
108153541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
108253541Sshin	hbhlen = (hbh->ip6h_len + 1) << 3;
108353541Sshin
108453541Sshin	IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
108553541Sshin	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
108662587Sitojun#else
108762587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
108862587Sitojun		sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
108962587Sitojun	if (hbh == NULL) {
1090249294Sae		IP6STAT_INC(ip6s_tooshort);
109162587Sitojun		return -1;
109262587Sitojun	}
109362587Sitojun	hbhlen = (hbh->ip6h_len + 1) << 3;
109462587Sitojun	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
109562587Sitojun		hbhlen);
109662587Sitojun	if (hbh == NULL) {
1097249294Sae		IP6STAT_INC(ip6s_tooshort);
109862587Sitojun		return -1;
109962587Sitojun	}
110062587Sitojun#endif
110153541Sshin	off += hbhlen;
110253541Sshin	hbhlen -= sizeof(struct ip6_hbh);
110353541Sshin	if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
110453541Sshin				hbhlen, rtalertp, plenp) < 0)
1105120856Sume		return (-1);
110653541Sshin
110753541Sshin	*offp = off;
110853541Sshin	*mp = m;
1109120856Sume	return (0);
111053541Sshin}
111153541Sshin
111253541Sshin/*
111353541Sshin * Search header for all Hop-by-hop options and process each option.
111453541Sshin * This function is separate from ip6_hopopts_input() in order to
111553541Sshin * handle a case where the sending node itself process its hop-by-hop
111653541Sshin * options header. In such a case, the function is called from ip6_output().
111778064Sume *
111878064Sume * The function assumes that hbh header is located right after the IPv6 header
111978064Sume * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
1120215956Sbrucec * opthead + hbhlen is located in contiguous memory region.
112153541Sshin */
112253541Sshinint
1123171259Sdelphijip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
1124171259Sdelphij    u_int32_t *rtalertp, u_int32_t *plenp)
112553541Sshin{
112653541Sshin	struct ip6_hdr *ip6;
112753541Sshin	int optlen = 0;
112853541Sshin	u_int8_t *opt = opthead;
112953541Sshin	u_int16_t rtalert_val;
113062587Sitojun	u_int32_t jumboplen;
113178064Sume	const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
113253541Sshin
113353541Sshin	for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
113478064Sume		switch (*opt) {
113578064Sume		case IP6OPT_PAD1:
113678064Sume			optlen = 1;
113778064Sume			break;
113878064Sume		case IP6OPT_PADN:
113978064Sume			if (hbhlen < IP6OPT_MINLEN) {
1140249294Sae				IP6STAT_INC(ip6s_toosmall);
114178064Sume				goto bad;
114278064Sume			}
114378064Sume			optlen = *(opt + 1) + 2;
114478064Sume			break;
1145121472Sume		case IP6OPT_ROUTER_ALERT:
114662587Sitojun			/* XXX may need check for alignment */
114778064Sume			if (hbhlen < IP6OPT_RTALERT_LEN) {
1148249294Sae				IP6STAT_INC(ip6s_toosmall);
114978064Sume				goto bad;
115078064Sume			}
115178064Sume			if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
115278064Sume				/* XXX stat */
115378064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1154120913Sume				    ICMP6_PARAMPROB_HEADER,
1155120913Sume				    erroff + opt + 1 - opthead);
1156120856Sume				return (-1);
115778064Sume			}
115878064Sume			optlen = IP6OPT_RTALERT_LEN;
115978064Sume			bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
116078064Sume			*rtalertp = ntohs(rtalert_val);
116178064Sume			break;
116278064Sume		case IP6OPT_JUMBO:
116378064Sume			/* XXX may need check for alignment */
116462587Sitojun			if (hbhlen < IP6OPT_JUMBO_LEN) {
1165249294Sae				IP6STAT_INC(ip6s_toosmall);
116662587Sitojun				goto bad;
116762587Sitojun			}
116878064Sume			if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
116978064Sume				/* XXX stat */
117078064Sume				icmp6_error(m, ICMP6_PARAM_PROB,
1171120913Sume				    ICMP6_PARAMPROB_HEADER,
1172120913Sume				    erroff + opt + 1 - opthead);
1173120856Sume				return (-1);
117478064Sume			}
117562587Sitojun			optlen = IP6OPT_JUMBO_LEN;
117653541Sshin
117762587Sitojun			/*
117862587Sitojun			 * IPv6 packets that have non 0 payload length
117978064Sume			 * must not contain a jumbo payload option.
118062587Sitojun			 */
118162587Sitojun			ip6 = mtod(m, struct ip6_hdr *);
118262587Sitojun			if (ip6->ip6_plen) {
1183249294Sae				IP6STAT_INC(ip6s_badoptions);
118462587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1185120913Sume				    ICMP6_PARAMPROB_HEADER,
1186120913Sume				    erroff + opt - opthead);
1187120856Sume				return (-1);
118862587Sitojun			}
118953541Sshin
119062587Sitojun			/*
119162587Sitojun			 * We may see jumbolen in unaligned location, so
119262587Sitojun			 * we'd need to perform bcopy().
119362587Sitojun			 */
119462587Sitojun			bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
119562587Sitojun			jumboplen = (u_int32_t)htonl(jumboplen);
119662587Sitojun
119762587Sitojun#if 1
119862587Sitojun			/*
119962587Sitojun			 * if there are multiple jumbo payload options,
120062587Sitojun			 * *plenp will be non-zero and the packet will be
120162587Sitojun			 * rejected.
120262587Sitojun			 * the behavior may need some debate in ipngwg -
120362587Sitojun			 * multiple options does not make sense, however,
120462587Sitojun			 * there's no explicit mention in specification.
120562587Sitojun			 */
120662587Sitojun			if (*plenp != 0) {
1207249294Sae				IP6STAT_INC(ip6s_badoptions);
120862587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1209120913Sume				    ICMP6_PARAMPROB_HEADER,
1210120913Sume				    erroff + opt + 2 - opthead);
1211120856Sume				return (-1);
121262587Sitojun			}
121362587Sitojun#endif
121462587Sitojun
121562587Sitojun			/*
121662587Sitojun			 * jumbo payload length must be larger than 65535.
121762587Sitojun			 */
121862587Sitojun			if (jumboplen <= IPV6_MAXPACKET) {
1219249294Sae				IP6STAT_INC(ip6s_badoptions);
122062587Sitojun				icmp6_error(m, ICMP6_PARAM_PROB,
1221120913Sume				    ICMP6_PARAMPROB_HEADER,
1222120913Sume				    erroff + opt + 2 - opthead);
1223120856Sume				return (-1);
122462587Sitojun			}
122562587Sitojun			*plenp = jumboplen;
122662587Sitojun
122762587Sitojun			break;
122878064Sume		default:		/* unknown option */
122978064Sume			if (hbhlen < IP6OPT_MINLEN) {
1230249294Sae				IP6STAT_INC(ip6s_toosmall);
123178064Sume				goto bad;
123278064Sume			}
123378064Sume			optlen = ip6_unknown_opt(opt, m,
123478064Sume			    erroff + opt - opthead);
123578064Sume			if (optlen == -1)
1236120856Sume				return (-1);
123778064Sume			optlen += 2;
123878064Sume			break;
123953541Sshin		}
124053541Sshin	}
124153541Sshin
1242120856Sume	return (0);
124353541Sshin
124453541Sshin  bad:
124553541Sshin	m_freem(m);
1246120856Sume	return (-1);
124753541Sshin}
124853541Sshin
124953541Sshin/*
125053541Sshin * Unknown option processing.
125153541Sshin * The third argument `off' is the offset from the IPv6 header to the option,
125253541Sshin * which is necessary if the IPv6 header the and option header and IPv6 header
1253215956Sbrucec * is not contiguous in order to return an ICMPv6 error.
125453541Sshin */
125553541Sshinint
1256171259Sdelphijip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off)
125753541Sshin{
125853541Sshin	struct ip6_hdr *ip6;
125953541Sshin
126078064Sume	switch (IP6OPT_TYPE(*optp)) {
126178064Sume	case IP6OPT_TYPE_SKIP: /* ignore the option */
1262120856Sume		return ((int)*(optp + 1));
126378064Sume	case IP6OPT_TYPE_DISCARD:	/* silently discard */
126478064Sume		m_freem(m);
1265120856Sume		return (-1);
126678064Sume	case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1267249294Sae		IP6STAT_INC(ip6s_badoptions);
126878064Sume		icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1269120856Sume		return (-1);
127078064Sume	case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1271249294Sae		IP6STAT_INC(ip6s_badoptions);
127278064Sume		ip6 = mtod(m, struct ip6_hdr *);
127378064Sume		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
127478064Sume		    (m->m_flags & (M_BCAST|M_MCAST)))
127578064Sume			m_freem(m);
127678064Sume		else
127778064Sume			icmp6_error(m, ICMP6_PARAM_PROB,
127878064Sume				    ICMP6_PARAMPROB_OPTION, off);
1279120856Sume		return (-1);
128053541Sshin	}
128153541Sshin
128253541Sshin	m_freem(m);		/* XXX: NOTREACHED */
1283120856Sume	return (-1);
128453541Sshin}
128553541Sshin
128653541Sshin/*
128762587Sitojun * Create the "control" list for this pcb.
1288179289Sbz * These functions will not modify mbuf chain at all.
128962587Sitojun *
1290179289Sbz * With KAME mbuf chain restriction:
129162587Sitojun * The routine will be called from upper layer handlers like tcp6_input().
129262587Sitojun * Thus the routine assumes that the caller (tcp6_input) have already
129362587Sitojun * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
129462587Sitojun * very first mbuf on the mbuf chain.
1295179289Sbz *
1296179289Sbz * ip6_savecontrol_v4 will handle those options that are possible to be
1297179289Sbz * set on a v4-mapped socket.
1298179289Sbz * ip6_savecontrol will directly call ip6_savecontrol_v4 to handle those
1299179289Sbz * options and handle the v6-only ones itself.
130053541Sshin */
1301181782Sbzstruct mbuf **
1302181782Sbzip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
1303181782Sbz    int *v4only)
130453541Sshin{
1305121674Sume	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
130653541Sshin
130778064Sume#ifdef SO_TIMESTAMP
1308179289Sbz	if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
130953541Sshin		struct timeval tv;
131053541Sshin
131153541Sshin		microtime(&tv);
131253541Sshin		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1313120913Sume		    SCM_TIMESTAMP, SOL_SOCKET);
1314121472Sume		if (*mp)
131553541Sshin			mp = &(*mp)->m_next;
131697658Stanimura	}
131762587Sitojun#endif
131862587Sitojun
1319179289Sbz#define IS2292(inp, x, y)	(((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
132053541Sshin	/* RFC 2292 sec. 5 */
1321179289Sbz	if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
132253541Sshin		struct in6_pktinfo pi6;
1323120913Sume
1324236958Stuexen		if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1325236958Stuexen#ifdef INET
1326236958Stuexen			struct ip *ip;
1327236958Stuexen
1328236958Stuexen			ip = mtod(m, struct ip *);
1329236958Stuexen			pi6.ipi6_addr.s6_addr32[0] = 0;
1330236958Stuexen			pi6.ipi6_addr.s6_addr32[1] = 0;
1331236958Stuexen			pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
1332236958Stuexen			pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr;
1333236958Stuexen#else
1334236958Stuexen			/* We won't hit this code */
1335236958Stuexen			bzero(&pi6.ipi6_addr, sizeof(struct in6_addr));
1336236958Stuexen#endif
1337236958Stuexen		} else {
1338236958Stuexen			bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1339236958Stuexen			in6_clearscope(&pi6.ipi6_addr);	/* XXX */
1340236958Stuexen		}
1341120913Sume		pi6.ipi6_ifindex =
1342120913Sume		    (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
1343120913Sume
134453541Sshin		*mp = sbcreatecontrol((caddr_t) &pi6,
1345120913Sume		    sizeof(struct in6_pktinfo),
1346179289Sbz		    IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
1347121472Sume		if (*mp)
134853541Sshin			mp = &(*mp)->m_next;
134953541Sshin	}
135078064Sume
1351179289Sbz	if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
1352236958Stuexen		int hlim;
1353120913Sume
1354236958Stuexen		if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1355236958Stuexen#ifdef INET
1356236958Stuexen			struct ip *ip;
1357236958Stuexen
1358236958Stuexen			ip = mtod(m, struct ip *);
1359236958Stuexen			hlim = ip->ip_ttl;
1360236958Stuexen#else
1361236958Stuexen			/* We won't hit this code */
1362236958Stuexen			hlim = 0;
1363236958Stuexen#endif
1364236958Stuexen		} else {
1365236958Stuexen			hlim = ip6->ip6_hlim & 0xff;
1366236958Stuexen		}
1367120913Sume		*mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1368179289Sbz		    IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
1369179289Sbz		    IPPROTO_IPV6);
1370121472Sume		if (*mp)
137153541Sshin			mp = &(*mp)->m_next;
137253541Sshin	}
137353541Sshin
1374236958Stuexen	if ((inp->inp_flags & IN6P_TCLASS) != 0) {
1375236958Stuexen		int tclass;
1376236958Stuexen
1377236958Stuexen		if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1378236958Stuexen#ifdef INET
1379236958Stuexen			struct ip *ip;
1380236958Stuexen
1381236958Stuexen			ip = mtod(m, struct ip *);
1382236958Stuexen			tclass = ip->ip_tos;
1383236958Stuexen#else
1384236958Stuexen			/* We won't hit this code */
1385236958Stuexen			tclass = 0;
1386236958Stuexen#endif
1387236958Stuexen		} else {
1388236958Stuexen			u_int32_t flowinfo;
1389236958Stuexen
1390236958Stuexen			flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1391236958Stuexen			flowinfo >>= 20;
1392236958Stuexen			tclass = flowinfo & 0xff;
1393236958Stuexen		}
1394236958Stuexen		*mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int),
1395236958Stuexen		    IPV6_TCLASS, IPPROTO_IPV6);
1396236958Stuexen		if (*mp)
1397236958Stuexen			mp = &(*mp)->m_next;
1398236958Stuexen	}
1399236958Stuexen
1400236958Stuexen	if (v4only != NULL) {
1401236958Stuexen		if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1402236958Stuexen			*v4only = 1;
1403236958Stuexen		} else {
1404236958Stuexen			*v4only = 0;
1405236958Stuexen		}
1406236958Stuexen	}
1407236958Stuexen
1408181782Sbz	return (mp);
1409179289Sbz}
1410179289Sbz
1411179289Sbzvoid
1412179289Sbzip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
1413179289Sbz{
1414179289Sbz	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1415181782Sbz	int v4only = 0;
1416179289Sbz
1417181782Sbz	mp = ip6_savecontrol_v4(in6p, m, mp, &v4only);
1418181782Sbz	if (v4only)
1419179289Sbz		return;
1420179289Sbz
142153541Sshin	/*
1422130002Sume	 * IPV6_HOPOPTS socket option.  Recall that we required super-user
1423130002Sume	 * privilege for the option (see ip6_ctloutput), but it might be too
1424130002Sume	 * strict, since there might be some hop-by-hop options which can be
1425130002Sume	 * returned to normal user.
1426130002Sume	 * See also RFC 2292 section 6 (or RFC 3542 section 8).
142753541Sshin	 */
1428186141Sbz	if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
142953541Sshin		/*
143053541Sshin		 * Check if a hop-by-hop options header is contatined in the
143153541Sshin		 * received packet, and if so, store the options as ancillary
143253541Sshin		 * data. Note that a hop-by-hop options header must be
1433120913Sume		 * just after the IPv6 header, which is assured through the
1434120913Sume		 * IPv6 input processing.
143553541Sshin		 */
143653541Sshin		if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
143762587Sitojun			struct ip6_hbh *hbh;
143878064Sume			int hbhlen = 0;
143978064Sume#ifdef PULLDOWN_TEST
144078064Sume			struct mbuf *ext;
144178064Sume#endif
144253541Sshin
144362587Sitojun#ifndef PULLDOWN_TEST
144462587Sitojun			hbh = (struct ip6_hbh *)(ip6 + 1);
144562587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
144662587Sitojun#else
144778064Sume			ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
144878064Sume			    ip6->ip6_nxt);
144978064Sume			if (ext == NULL) {
1450249294Sae				IP6STAT_INC(ip6s_tooshort);
145162587Sitojun				return;
145262587Sitojun			}
145378064Sume			hbh = mtod(ext, struct ip6_hbh *);
145462587Sitojun			hbhlen = (hbh->ip6h_len + 1) << 3;
145578064Sume			if (hbhlen != ext->m_len) {
145678064Sume				m_freem(ext);
1457249294Sae				IP6STAT_INC(ip6s_tooshort);
145862587Sitojun				return;
145962587Sitojun			}
146062587Sitojun#endif
146162587Sitojun
146253541Sshin			/*
1463120913Sume			 * XXX: We copy the whole header even if a
1464120913Sume			 * jumbo payload option is included, the option which
1465120913Sume			 * is to be removed before returning according to
1466120913Sume			 * RFC2292.
1467148169Sume			 * Note: this constraint is removed in RFC3542
146853541Sshin			 */
146962587Sitojun			*mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1470179289Sbz			    IS2292(in6p, IPV6_2292HOPOPTS, IPV6_HOPOPTS),
1471121472Sume			    IPPROTO_IPV6);
1472121472Sume			if (*mp)
147353541Sshin				mp = &(*mp)->m_next;
147478064Sume#ifdef PULLDOWN_TEST
147578064Sume			m_freem(ext);
147678064Sume#endif
147753541Sshin		}
147853541Sshin	}
147953541Sshin
1480186141Sbz	if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
148178064Sume		int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
148253541Sshin
148353541Sshin		/*
148453541Sshin		 * Search for destination options headers or routing
148553541Sshin		 * header(s) through the header chain, and stores each
148653541Sshin		 * header as ancillary data.
148753541Sshin		 * Note that the order of the headers remains in
148853541Sshin		 * the chain of ancillary data.
148953541Sshin		 */
149078064Sume		while (1) {	/* is explicit loop prevention necessary? */
149178064Sume			struct ip6_ext *ip6e = NULL;
149262587Sitojun			int elen;
149378064Sume#ifdef PULLDOWN_TEST
149478064Sume			struct mbuf *ext = NULL;
149578064Sume#endif
149653541Sshin
149778064Sume			/*
149878064Sume			 * if it is not an extension header, don't try to
149978064Sume			 * pull it from the chain.
150078064Sume			 */
150178064Sume			switch (nxt) {
150278064Sume			case IPPROTO_DSTOPTS:
150378064Sume			case IPPROTO_ROUTING:
150478064Sume			case IPPROTO_HOPOPTS:
150578064Sume			case IPPROTO_AH: /* is it possible? */
150678064Sume				break;
150778064Sume			default:
150878064Sume				goto loopend;
150978064Sume			}
151078064Sume
151162587Sitojun#ifndef PULLDOWN_TEST
151278064Sume			if (off + sizeof(*ip6e) > m->m_len)
151378064Sume				goto loopend;
151462587Sitojun			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
151562587Sitojun			if (nxt == IPPROTO_AH)
151662587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
151762587Sitojun			else
151862587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
151978064Sume			if (off + elen > m->m_len)
152078064Sume				goto loopend;
152162587Sitojun#else
152278064Sume			ext = ip6_pullexthdr(m, off, nxt);
152378064Sume			if (ext == NULL) {
1524249294Sae				IP6STAT_INC(ip6s_tooshort);
152562587Sitojun				return;
152662587Sitojun			}
152778064Sume			ip6e = mtod(ext, struct ip6_ext *);
152862587Sitojun			if (nxt == IPPROTO_AH)
152962587Sitojun				elen = (ip6e->ip6e_len + 2) << 2;
153062587Sitojun			else
153162587Sitojun				elen = (ip6e->ip6e_len + 1) << 3;
153278064Sume			if (elen != ext->m_len) {
153378064Sume				m_freem(ext);
1534249294Sae				IP6STAT_INC(ip6s_tooshort);
153562587Sitojun				return;
153662587Sitojun			}
153762587Sitojun#endif
153862587Sitojun
153978064Sume			switch (nxt) {
154078064Sume			case IPPROTO_DSTOPTS:
1541186141Sbz				if (!(in6p->inp_flags & IN6P_DSTOPTS))
154278064Sume					break;
154353541Sshin
154478064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1545179289Sbz				    IS2292(in6p,
1546179289Sbz					IPV6_2292DSTOPTS, IPV6_DSTOPTS),
1547120913Sume				    IPPROTO_IPV6);
154878064Sume				if (*mp)
154978064Sume					mp = &(*mp)->m_next;
155078064Sume				break;
155178064Sume			case IPPROTO_ROUTING:
1552201794Strasz				if (!(in6p->inp_flags & IN6P_RTHDR))
155378064Sume					break;
155453541Sshin
155578064Sume				*mp = sbcreatecontrol((caddr_t)ip6e, elen,
1556179289Sbz				    IS2292(in6p, IPV6_2292RTHDR, IPV6_RTHDR),
1557120913Sume				    IPPROTO_IPV6);
155878064Sume				if (*mp)
155978064Sume					mp = &(*mp)->m_next;
156078064Sume				break;
156178064Sume			case IPPROTO_HOPOPTS:
156278064Sume			case IPPROTO_AH: /* is it possible? */
156378064Sume				break;
156453541Sshin
156578064Sume			default:
156678064Sume				/*
1567171260Sdelphij				 * other cases have been filtered in the above.
156878064Sume				 * none will visit this case.  here we supply
156978064Sume				 * the code just in case (nxt overwritten or
157078064Sume				 * other cases).
157178064Sume				 */
157278064Sume#ifdef PULLDOWN_TEST
157378064Sume				m_freem(ext);
157478064Sume#endif
157578064Sume				goto loopend;
157653541Sshin
157753541Sshin			}
157853541Sshin
157953541Sshin			/* proceed with the next header. */
158062587Sitojun			off += elen;
158153541Sshin			nxt = ip6e->ip6e_nxt;
158278064Sume			ip6e = NULL;
158378064Sume#ifdef PULLDOWN_TEST
158478064Sume			m_freem(ext);
158578064Sume			ext = NULL;
158678064Sume#endif
158753541Sshin		}
158853541Sshin	  loopend:
158978064Sume		;
159053541Sshin	}
1591179289Sbz}
1592121472Sume#undef IS2292
159378064Sume
1594125776Sumevoid
1595279911Saeip6_notify_pmtu(struct inpcb *inp, struct sockaddr_in6 *dst, u_int32_t mtu)
1596125776Sume{
1597125776Sume	struct socket *so;
1598125776Sume	struct mbuf *m_mtu;
1599125776Sume	struct ip6_mtuinfo mtuctl;
1600125776Sume
1601279911Sae	KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
1602279911Sae	/*
1603279911Sae	 * Notify the error by sending IPV6_PATHMTU ancillary data if
1604279911Sae	 * application wanted to know the MTU value.
1605279911Sae	 * NOTE: we notify disconnected sockets, because some udp
1606279911Sae	 * applications keep sending sockets disconnected.
1607279911Sae	 * NOTE: our implementation doesn't notify connected sockets that has
1608279911Sae	 * foreign address that is different than given destination addresses
1609279911Sae	 * (this is permitted by RFC 3542).
1610279911Sae	 */
1611279911Sae	if ((inp->inp_flags & IN6P_MTU) == 0 || (
1612279911Sae	    !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1613279911Sae	    !IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &dst->sin6_addr)))
1614125776Sume		return;
1615125776Sume
1616279911Sae	mtuctl.ip6m_mtu = mtu;
1617125776Sume	mtuctl.ip6m_addr = *dst;
1618148385Sume	if (sa6_recoverscope(&mtuctl.ip6m_addr))
1619148385Sume		return;
1620125776Sume
1621125776Sume	if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
1622125776Sume	    IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
1623125776Sume		return;
1624125776Sume
1625279911Sae	so =  inp->inp_socket;
1626125776Sume	if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
1627125776Sume	    == 0) {
1628125776Sume		m_freem(m_mtu);
1629125776Sume		/* XXX: should count statistics */
1630125776Sume	} else
1631125776Sume		sorwakeup(so);
1632125776Sume}
1633125776Sume
163478064Sume#ifdef PULLDOWN_TEST
163578064Sume/*
163678064Sume * pull single extension header from mbuf chain.  returns single mbuf that
163778064Sume * contains the result, or NULL on error.
163878064Sume */
163978064Sumestatic struct mbuf *
1640171259Sdelphijip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
164178064Sume{
164278064Sume	struct ip6_ext ip6e;
164378064Sume	size_t elen;
164478064Sume	struct mbuf *n;
164578064Sume
164678064Sume#ifdef DIAGNOSTIC
164778064Sume	switch (nxt) {
164878064Sume	case IPPROTO_DSTOPTS:
164978064Sume	case IPPROTO_ROUTING:
165078064Sume	case IPPROTO_HOPOPTS:
165178064Sume	case IPPROTO_AH: /* is it possible? */
165278064Sume		break;
165378064Sume	default:
165478064Sume		printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
165553541Sshin	}
165678064Sume#endif
165778064Sume
165878064Sume	m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
165978064Sume	if (nxt == IPPROTO_AH)
166078064Sume		elen = (ip6e.ip6e_len + 2) << 2;
166178064Sume	else
166278064Sume		elen = (ip6e.ip6e_len + 1) << 3;
166378064Sume
1664248328Sglebius	if (elen > MLEN)
1665248328Sglebius		n = m_getcl(M_NOWAIT, MT_DATA, 0);
1666248328Sglebius	else
1667248328Sglebius		n = m_get(M_NOWAIT, MT_DATA);
1668248328Sglebius	if (n == NULL)
166978064Sume		return NULL;
167062587Sitojun
167178064Sume	m_copydata(m, off, elen, mtod(n, caddr_t));
167278064Sume	n->m_len = elen;
167378064Sume	return n;
167453541Sshin}
167578064Sume#endif
167653541Sshin
167753541Sshin/*
167853541Sshin * Get pointer to the previous header followed by the header
167953541Sshin * currently processed.
168053541Sshin */
1681329158Saeint
1682171259Sdelphijip6_get_prevhdr(struct mbuf *m, int off)
168353541Sshin{
1684329158Sae	struct ip6_ext ip6e;
1685329158Sae	struct ip6_hdr *ip6;
1686329158Sae	int len, nlen, nxt;
168753541Sshin
168853541Sshin	if (off == sizeof(struct ip6_hdr))
1689329158Sae		return (offsetof(struct ip6_hdr, ip6_nxt));
1690329158Sae	if (off < sizeof(struct ip6_hdr))
1691329158Sae		panic("%s: off < sizeof(struct ip6_hdr)", __func__);
169253541Sshin
1693329158Sae	ip6 = mtod(m, struct ip6_hdr *);
1694329158Sae	nxt = ip6->ip6_nxt;
1695329158Sae	len = sizeof(struct ip6_hdr);
1696329158Sae	nlen = 0;
1697329158Sae	while (len < off) {
1698329158Sae		m_copydata(m, len, sizeof(ip6e), (caddr_t)&ip6e);
1699329158Sae		switch (nxt) {
1700329158Sae		case IPPROTO_FRAGMENT:
1701329158Sae			nlen = sizeof(struct ip6_frag);
1702329158Sae			break;
1703329158Sae		case IPPROTO_AH:
1704329158Sae			nlen = (ip6e.ip6e_len + 2) << 2;
1705329158Sae			break;
1706329158Sae		default:
1707329158Sae			nlen = (ip6e.ip6e_len + 1) << 3;
170853541Sshin		}
1709329158Sae		len += nlen;
1710329158Sae		nxt = ip6e.ip6e_nxt;
171153541Sshin	}
1712329158Sae	return (len - nlen);
171353541Sshin}
171453541Sshin
171553541Sshin/*
171662587Sitojun * get next header offset.  m will be retained.
171762587Sitojun */
171862587Sitojunint
1719171259Sdelphijip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
172062587Sitojun{
172162587Sitojun	struct ip6_hdr ip6;
172262587Sitojun	struct ip6_ext ip6e;
172362587Sitojun	struct ip6_frag fh;
172462587Sitojun
172562587Sitojun	/* just in case */
172662587Sitojun	if (m == NULL)
172762587Sitojun		panic("ip6_nexthdr: m == NULL");
172862587Sitojun	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
172962587Sitojun		return -1;
173062587Sitojun
173162587Sitojun	switch (proto) {
173262587Sitojun	case IPPROTO_IPV6:
173362587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6))
173462587Sitojun			return -1;
173562587Sitojun		m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
173662587Sitojun		if (nxtp)
173762587Sitojun			*nxtp = ip6.ip6_nxt;
173862587Sitojun		off += sizeof(ip6);
173962587Sitojun		return off;
174062587Sitojun
174162587Sitojun	case IPPROTO_FRAGMENT:
174262587Sitojun		/*
174362587Sitojun		 * terminate parsing if it is not the first fragment,
174462587Sitojun		 * it does not make sense to parse through it.
174562587Sitojun		 */
174662587Sitojun		if (m->m_pkthdr.len < off + sizeof(fh))
174762587Sitojun			return -1;
174862587Sitojun		m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1749120978Sume		/* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */
1750120978Sume		if (fh.ip6f_offlg & IP6F_OFF_MASK)
175162587Sitojun			return -1;
175262587Sitojun		if (nxtp)
175362587Sitojun			*nxtp = fh.ip6f_nxt;
175462587Sitojun		off += sizeof(struct ip6_frag);
175562587Sitojun		return off;
175662587Sitojun
175762587Sitojun	case IPPROTO_AH:
175862587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
175962587Sitojun			return -1;
176062587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
176162587Sitojun		if (nxtp)
176262587Sitojun			*nxtp = ip6e.ip6e_nxt;
176362587Sitojun		off += (ip6e.ip6e_len + 2) << 2;
176462587Sitojun		return off;
176562587Sitojun
176662587Sitojun	case IPPROTO_HOPOPTS:
176762587Sitojun	case IPPROTO_ROUTING:
176862587Sitojun	case IPPROTO_DSTOPTS:
176962587Sitojun		if (m->m_pkthdr.len < off + sizeof(ip6e))
177062587Sitojun			return -1;
177162587Sitojun		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
177262587Sitojun		if (nxtp)
177362587Sitojun			*nxtp = ip6e.ip6e_nxt;
177462587Sitojun		off += (ip6e.ip6e_len + 1) << 3;
177562587Sitojun		return off;
177662587Sitojun
177762587Sitojun	case IPPROTO_NONE:
177862587Sitojun	case IPPROTO_ESP:
177962587Sitojun	case IPPROTO_IPCOMP:
178062587Sitojun		/* give up */
178162587Sitojun		return -1;
178262587Sitojun
178362587Sitojun	default:
178462587Sitojun		return -1;
178562587Sitojun	}
178662587Sitojun
178762587Sitojun	return -1;
178862587Sitojun}
178962587Sitojun
179062587Sitojun/*
179162587Sitojun * get offset for the last header in the chain.  m will be kept untainted.
179262587Sitojun */
179362587Sitojunint
1794171259Sdelphijip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
179562587Sitojun{
179662587Sitojun	int newoff;
179762587Sitojun	int nxt;
179862587Sitojun
179962587Sitojun	if (!nxtp) {
180062587Sitojun		nxt = -1;
180162587Sitojun		nxtp = &nxt;
180262587Sitojun	}
180362587Sitojun	while (1) {
180462587Sitojun		newoff = ip6_nexthdr(m, off, proto, nxtp);
180562587Sitojun		if (newoff < 0)
180662587Sitojun			return off;
180762587Sitojun		else if (newoff < off)
180862587Sitojun			return -1;	/* invalid */
180962587Sitojun		else if (newoff == off)
181062587Sitojun			return newoff;
181162587Sitojun
181262587Sitojun		off = newoff;
181362587Sitojun		proto = *nxtp;
181462587Sitojun	}
181562587Sitojun}
181662587Sitojun
1817235956Sbzstatic struct ip6aux *
1818171259Sdelphijip6_addaux(struct mbuf *m)
181978064Sume{
1820120913Sume	struct m_tag *mtag;
1821120913Sume
1822120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1823120913Sume	if (!mtag) {
1824120913Sume		mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux),
1825120913Sume		    M_NOWAIT);
1826121630Sume		if (mtag) {
1827120913Sume			m_tag_prepend(m, mtag);
1828121630Sume			bzero(mtag + 1, sizeof(struct ip6aux));
1829121630Sume		}
183078064Sume	}
1831121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
183278064Sume}
183378064Sume
1834235956Sbzstatic struct ip6aux *
1835171259Sdelphijip6_findaux(struct mbuf *m)
183678064Sume{
1837120913Sume	struct m_tag *mtag;
1838120913Sume
1839120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1840121673Sume	return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
184178064Sume}
184278064Sume
1843235956Sbzstatic void
1844171259Sdelphijip6_delaux(struct mbuf *m)
184578064Sume{
1846120913Sume	struct m_tag *mtag;
1847120913Sume
1848120913Sume	mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1849120913Sume	if (mtag)
1850120913Sume		m_tag_delete(m, mtag);
185178064Sume}
185278064Sume
185362587Sitojun/*
185453541Sshin * System control for IP6
185553541Sshin */
185653541Sshin
185753541Sshinu_char	inet6ctlerrmap[PRC_NCMDS] = {
185853541Sshin	0,		0,		0,		0,
185953541Sshin	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
186053541Sshin	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
186153541Sshin	EMSGSIZE,	EHOSTUNREACH,	0,		0,
186253541Sshin	0,		0,		0,		0,
186353541Sshin	ENOPROTOOPT
186453541Sshin};
1865