ip6_input.c revision 71794
1/*	$FreeBSD: head/sys/netinet6/ip6_input.c 71794 2001-01-29 11:28:20Z peter $	*/
2/*	$KAME: ip6_input.c,v 1.95 2000/07/02 07:49:37 jinmei Exp $	*/
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1982, 1986, 1988, 1993
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 *    must display the following acknowledgement:
47 *	This product includes software developed by the University of
48 *	California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 *    may be used to endorse or promote products derived from this software
51 *    without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 *	@(#)ip_input.c	8.2 (Berkeley) 1/4/94
66 */
67
68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
72#include "opt_pfil_hooks.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/mbuf.h>
77#include <sys/domain.h>
78#include <sys/protosw.h>
79#include <sys/socket.h>
80#include <sys/socketvar.h>
81#include <sys/errno.h>
82#include <sys/time.h>
83#include <sys/kernel.h>
84#include <sys/syslog.h>
85
86#include <net/if.h>
87#include <net/if_types.h>
88#include <net/if_dl.h>
89#include <net/route.h>
90#include <net/netisr.h>
91#include <net/intrq.h>
92#ifdef PFIL_HOOKS
93#include <net/pfil.h>
94#endif
95
96#include <netinet/in.h>
97#include <netinet/in_systm.h>
98#ifdef INET
99#include <netinet/ip.h>
100#include <netinet/ip_icmp.h>
101#endif /*INET*/
102#include <netinet/ip6.h>
103#include <netinet6/in6_var.h>
104#include <netinet6/ip6_var.h>
105#include <netinet/in_pcb.h>
106#include <netinet/icmp6.h>
107#include <netinet6/in6_ifattach.h>
108#include <netinet6/nd6.h>
109#include <netinet6/in6_prefix.h>
110
111#include <netinet6/ip6_fw.h>
112
113#include <netinet6/ip6protosw.h>
114
115#include "faith.h"
116#include "gif.h"
117
118#include <net/net_osdep.h>
119
120extern struct domain inet6domain;
121extern struct ip6protosw inet6sw[];
122
123u_char ip6_protox[IPPROTO_MAX];
124static int ip6qmaxlen = IFQ_MAXLEN;
125struct in6_ifaddr *in6_ifaddr;
126
127int ip6_forward_srcrt;			/* XXX */
128int ip6_sourcecheck;			/* XXX */
129int ip6_sourcecheck_interval;		/* XXX */
130const int int6intrq_present = 1;
131
132/* firewall hooks */
133ip6_fw_chk_t *ip6_fw_chk_ptr;
134ip6_fw_ctl_t *ip6_fw_ctl_ptr;
135int ip6_fw_enable = 1;
136
137struct ip6stat ip6stat;
138
139static void ip6_init2 __P((void *));
140
141static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
142#ifdef PULLDOWN_TEST
143static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
144#endif
145
146/*
147 * IP6 initialization: fill in IP6 protocol switch table.
148 * All protocols not implemented in kernel go to raw IP6 protocol handler.
149 */
150void
151ip6_init()
152{
153	register struct ip6protosw *pr;
154	register int i;
155	struct timeval tv;
156
157	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
158	if (pr == 0)
159		panic("ip6_init");
160	for (i = 0; i < IPPROTO_MAX; i++)
161		ip6_protox[i] = pr - inet6sw;
162	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
163	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
164		if (pr->pr_domain->dom_family == PF_INET6 &&
165		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
166			ip6_protox[pr->pr_protocol] = pr - inet6sw;
167	ip6intrq.ifq_maxlen = ip6qmaxlen;
168	mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", MTX_DEF);
169	register_netisr(NETISR_IPV6, ip6intr);
170	nd6_init();
171	frag6_init();
172	/*
173	 * in many cases, random() here does NOT return random number
174	 * as initialization during bootstrap time occur in fixed order.
175	 */
176	microtime(&tv);
177	ip6_flow_seq = random() ^ tv.tv_usec;
178}
179
180static void
181ip6_init2(dummy)
182	void *dummy;
183{
184
185	/*
186	 * to route local address of p2p link to loopback,
187	 * assign loopback address first.
188	 */
189	in6_ifattach(&loif[0], NULL);
190
191	/* nd6_timer_init */
192	timeout(nd6_timer, (caddr_t)0, hz);
193	/* router renumbering prefix list maintenance */
194	timeout(in6_rr_timer, (caddr_t)0, hz);
195}
196
197/* cheat */
198/* This must be after route_init(), which is now SI_ORDER_THIRD */
199SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
200
201/*
202 * IP6 input interrupt handling. Just pass the packet to ip6_input.
203 */
204void
205ip6intr()
206{
207	int s;
208	struct mbuf *m;
209
210	for (;;) {
211		s = splimp();
212		IF_DEQUEUE(&ip6intrq, m);
213		splx(s);
214		if (m == 0)
215			return;
216		ip6_input(m);
217	}
218}
219
220extern struct	route_in6 ip6_forward_rt;
221
222void
223ip6_input(m)
224	struct mbuf *m;
225{
226	struct ip6_hdr *ip6;
227	int off = sizeof(struct ip6_hdr), nest;
228	u_int32_t plen;
229	u_int32_t rtalert = ~0;
230	int nxt, ours = 0;
231	struct ifnet *deliverifp = NULL;
232#ifdef  PFIL_HOOKS
233	struct packet_filter_hook *pfh;
234	struct mbuf *m0;
235	int rv;
236#endif  /* PFIL_HOOKS */
237
238#ifdef IPSEC
239	/*
240	 * should the inner packet be considered authentic?
241	 * see comment in ah4_input().
242	 */
243	if (m) {
244		m->m_flags &= ~M_AUTHIPHDR;
245		m->m_flags &= ~M_AUTHIPDGM;
246	}
247#endif
248
249	/*
250	 * mbuf statistics by kazu
251	 */
252	if (m->m_flags & M_EXT) {
253		if (m->m_next)
254			ip6stat.ip6s_mext2m++;
255		else
256			ip6stat.ip6s_mext1++;
257	} else {
258		if (m->m_next) {
259			if (m->m_flags & M_LOOP) {
260				ip6stat.ip6s_m2m[loif[0].if_index]++;	/*XXX*/
261			} else if (m->m_pkthdr.rcvif->if_index <= 31)
262				ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
263			else
264				ip6stat.ip6s_m2m[0]++;
265		} else
266			ip6stat.ip6s_m1++;
267	}
268
269	in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
270	ip6stat.ip6s_total++;
271
272#ifndef PULLDOWN_TEST
273	/* XXX is the line really necessary? */
274	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
275#endif
276
277	if (m->m_len < sizeof(struct ip6_hdr)) {
278		struct ifnet *inifp;
279		inifp = m->m_pkthdr.rcvif;
280		if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
281			ip6stat.ip6s_toosmall++;
282			in6_ifstat_inc(inifp, ifs6_in_hdrerr);
283			return;
284		}
285	}
286
287	ip6 = mtod(m, struct ip6_hdr *);
288
289	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
290		ip6stat.ip6s_badvers++;
291		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
292		goto bad;
293	}
294
295#ifdef PFIL_HOOKS
296	/*
297	 * Run through list of hooks for input packets.  If there are any
298	 * filters which require that additional packets in the flow are
299	 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
300	 * Note that filters must _never_ set this flag, as another filter
301	 * in the list may have previously cleared it.
302	 */
303	m0 = m;
304	pfh = pfil_hook_get(PFIL_IN, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
305	for (; pfh; pfh = pfh->pfil_link.tqe_next)
306		if (pfh->pfil_func) {
307			rv = pfh->pfil_func(ip6, sizeof(*ip6),
308					    m->m_pkthdr.rcvif, 0, &m0);
309			if (rv)
310				return;
311			m = m0;
312			if (m == NULL)
313				return;
314			ip6 = mtod(m, struct ip6_hdr *);
315		}
316#endif /* PFIL_HOOKS */
317
318	ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
319
320	/*
321	 * Check with the firewall...
322	 */
323	if (ip6_fw_enable && ip6_fw_chk_ptr) {
324		u_short port = 0;
325		/* If ipfw says divert, we have to just drop packet */
326		/* use port as a dummy argument */
327		if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
328			m_freem(m);
329			m = NULL;
330		}
331		if (!m)
332			return;
333	}
334
335	/*
336	 * Scope check
337	 */
338	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
339	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
340		ip6stat.ip6s_badscope++;
341		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
342		goto bad;
343	}
344
345	/*
346	 * Don't check IPv4 mapped address here.  SIIT assumes that
347	 * routers would forward IPv6 native packets with IPv4 mapped
348	 * address normally.
349	 */
350#if 0
351	/*
352	 * Reject packets with IPv4 compatible addresses (auto tunnel).
353	 *
354	 * The code forbids auto tunnel relay case in RFC1933 (the check is
355	 * stronger than RFC1933).  We may want to re-enable it if mech-xx
356	 * is revised to forbid relaying case.
357	 */
358	if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
359	    IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
360		ip6stat.ip6s_badscope++;
361		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
362		goto bad;
363	}
364#endif
365	if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
366	    IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
367		if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
368			ours = 1;
369			deliverifp = m->m_pkthdr.rcvif;
370			goto hbhcheck;
371		} else {
372			ip6stat.ip6s_badscope++;
373			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
374			goto bad;
375		}
376	}
377
378#ifndef FAKE_LOOPBACK_IF
379	if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
380#else
381	if (1)
382#endif
383	{
384		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
385			ip6->ip6_src.s6_addr16[1]
386				= htons(m->m_pkthdr.rcvif->if_index);
387		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
388			ip6->ip6_dst.s6_addr16[1]
389				= htons(m->m_pkthdr.rcvif->if_index);
390	}
391
392	/*
393	 * XXX we need this since we do not have "goto ours" hack route
394	 * for some of our ifaddrs on loopback interface.
395	 * we should correct it by changing in6_ifattach to install
396	 * "goto ours" hack route.
397	 */
398	if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0) {
399		if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
400			ours = 1;
401			deliverifp = m->m_pkthdr.rcvif;
402			goto hbhcheck;
403		}
404	}
405
406	/*
407	 * Multicast check
408	 */
409	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
410	  	struct	in6_multi *in6m = 0;
411
412		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
413		/*
414		 * See if we belong to the destination multicast group on the
415		 * arrival interface.
416		 */
417		IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
418		if (in6m)
419			ours = 1;
420		else if (!ip6_mrouter) {
421			ip6stat.ip6s_notmember++;
422			ip6stat.ip6s_cantforward++;
423			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
424			goto bad;
425		}
426		deliverifp = m->m_pkthdr.rcvif;
427		goto hbhcheck;
428	}
429
430	/*
431	 *  Unicast check
432	 */
433	if (ip6_forward_rt.ro_rt != NULL &&
434	    (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
435	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
436			       &ip6_forward_rt.ro_dst.sin6_addr))
437		ip6stat.ip6s_forward_cachehit++;
438	else {
439		if (ip6_forward_rt.ro_rt) {
440			/* route is down or destination is different */
441			ip6stat.ip6s_forward_cachemiss++;
442			RTFREE(ip6_forward_rt.ro_rt);
443			ip6_forward_rt.ro_rt = 0;
444		}
445
446		bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
447		ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
448		ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
449		ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
450#ifdef SCOPEDROUTING
451		ip6_forward_rt.ro_dst.sin6_scope_id =
452			in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
453#endif
454
455		rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
456	}
457
458#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
459
460	/*
461	 * Accept the packet if the forwarding interface to the destination
462	 * according to the routing table is the loopback interface,
463	 * unless the associated route has a gateway.
464	 * Note that this approach causes to accept a packet if there is a
465	 * route to the loopback interface for the destination of the packet.
466	 * But we think it's even useful in some situations, e.g. when using
467	 * a special daemon which wants to intercept the packet.
468	 */
469	if (ip6_forward_rt.ro_rt &&
470	    (ip6_forward_rt.ro_rt->rt_flags &
471	     (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
472#if 0
473	    /*
474	     * The check below is redundant since the comparison of
475	     * the destination and the key of the rtentry has
476	     * already done through looking up the routing table.
477	     */
478	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
479			       &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
480#endif
481	    ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
482		struct in6_ifaddr *ia6 =
483			(struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
484		if (ia6->ia6_flags & IN6_IFF_ANYCAST)
485			m->m_flags |= M_ANYCAST6;
486		/*
487		 * packets to a tentative, duplicated, or somehow invalid
488		 * address must not be accepted.
489		 */
490		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
491			/* this address is ready */
492			ours = 1;
493			deliverifp = ia6->ia_ifp;	/* correct? */
494
495			/* Count the packet in the ip address stats */
496			ia6->ia_ifa.if_ipackets++;
497			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
498
499			goto hbhcheck;
500		} else {
501			/* address is not ready, so discard the packet. */
502			log(LOG_INFO,
503			    "ip6_input: packet to an unready address %s->%s",
504			    ip6_sprintf(&ip6->ip6_src),
505			    ip6_sprintf(&ip6->ip6_dst));
506
507			goto bad;
508		}
509	}
510
511	/*
512	 * FAITH(Firewall Aided Internet Translator)
513	 */
514#if defined(NFAITH) && 0 < NFAITH
515	if (ip6_keepfaith) {
516		if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
517		 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
518			/* XXX do we need more sanity checks? */
519			ours = 1;
520			deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
521			goto hbhcheck;
522		}
523	}
524#endif
525
526	/*
527	 * Now there is no reason to process the packet if it's not our own
528	 * and we're not a router.
529	 */
530	if (!ip6_forwarding) {
531		ip6stat.ip6s_cantforward++;
532		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
533		goto bad;
534	}
535
536  hbhcheck:
537	/*
538	 * Process Hop-by-Hop options header if it's contained.
539	 * m may be modified in ip6_hopopts_input().
540	 * If a JumboPayload option is included, plen will also be modified.
541	 */
542	plen = (u_int32_t)ntohs(ip6->ip6_plen);
543	if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
544		struct ip6_hbh *hbh;
545
546		if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
547#if 0	/*touches NULL pointer*/
548			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
549#endif
550			return;	/* m have already been freed */
551		}
552
553		/* adjust pointer */
554		ip6 = mtod(m, struct ip6_hdr *);
555
556		/*
557		 * if the payload length field is 0 and the next header field
558		 * indicates Hop-by-Hop Options header, then a Jumbo Payload
559		 * option MUST be included.
560		 */
561		if (ip6->ip6_plen == 0 && plen == 0) {
562			/*
563			 * Note that if a valid jumbo payload option is
564			 * contained, ip6_hoptops_input() must set a valid
565			 * (non-zero) payload length to the variable plen.
566			 */
567			ip6stat.ip6s_badoptions++;
568			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
569			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
570			icmp6_error(m, ICMP6_PARAM_PROB,
571				    ICMP6_PARAMPROB_HEADER,
572				    (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
573			return;
574		}
575#ifndef PULLDOWN_TEST
576		/* ip6_hopopts_input() ensures that mbuf is contiguous */
577		hbh = (struct ip6_hbh *)(ip6 + 1);
578#else
579		IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
580			sizeof(struct ip6_hbh));
581		if (hbh == NULL) {
582			ip6stat.ip6s_tooshort++;
583			return;
584		}
585#endif
586		nxt = hbh->ip6h_nxt;
587
588		/*
589		 * accept the packet if a router alert option is included
590		 * and we act as an IPv6 router.
591		 */
592		if (rtalert != ~0 && ip6_forwarding)
593			ours = 1;
594	} else
595		nxt = ip6->ip6_nxt;
596
597	/*
598	 * Check that the amount of data in the buffers
599	 * is as at least much as the IPv6 header would have us expect.
600	 * Trim mbufs if longer than we expect.
601	 * Drop packet if shorter than we expect.
602	 */
603	if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
604		ip6stat.ip6s_tooshort++;
605		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
606		goto bad;
607	}
608	if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
609		if (m->m_len == m->m_pkthdr.len) {
610			m->m_len = sizeof(struct ip6_hdr) + plen;
611			m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
612		} else
613			m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
614	}
615
616	/*
617	 * Forward if desirable.
618	 */
619	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
620		/*
621		 * If we are acting as a multicast router, all
622		 * incoming multicast packets are passed to the
623		 * kernel-level multicast forwarding function.
624		 * The packet is returned (relatively) intact; if
625		 * ip6_mforward() returns a non-zero value, the packet
626		 * must be discarded, else it may be accepted below.
627		 */
628		if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
629			ip6stat.ip6s_cantforward++;
630			m_freem(m);
631			return;
632		}
633		if (!ours) {
634			m_freem(m);
635			return;
636		}
637	} else if (!ours) {
638		ip6_forward(m, 0);
639		return;
640	}
641
642	ip6 = mtod(m, struct ip6_hdr *);
643
644	/*
645	 * Malicious party may be able to use IPv4 mapped addr to confuse
646	 * tcp/udp stack and bypass security checks (act as if it was from
647	 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
648	 *
649	 * For SIIT end node behavior, you may want to disable the check.
650	 * However, you will  become vulnerable to attacks using IPv4 mapped
651	 * source.
652	 */
653	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
654	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
655		ip6stat.ip6s_badscope++;
656		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
657		goto bad;
658	}
659
660	/*
661	 * Tell launch routine the next header
662	 */
663	ip6stat.ip6s_delivered++;
664	in6_ifstat_inc(deliverifp, ifs6_in_deliver);
665	nest = 0;
666	while (nxt != IPPROTO_DONE) {
667		if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
668			ip6stat.ip6s_toomanyhdr++;
669			goto bad;
670		}
671
672		/*
673		 * protection against faulty packet - there should be
674		 * more sanity checks in header chain processing.
675		 */
676		if (m->m_pkthdr.len < off) {
677			ip6stat.ip6s_tooshort++;
678			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
679			goto bad;
680		}
681
682		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
683	}
684	return;
685 bad:
686	m_freem(m);
687}
688
689/*
690 * Hop-by-Hop options header processing. If a valid jumbo payload option is
691 * included, the real payload length will be stored in plenp.
692 */
693static int
694ip6_hopopts_input(plenp, rtalertp, mp, offp)
695	u_int32_t *plenp;
696	u_int32_t *rtalertp;	/* XXX: should be stored more smart way */
697	struct mbuf **mp;
698	int *offp;
699{
700	register struct mbuf *m = *mp;
701	int off = *offp, hbhlen;
702	struct ip6_hbh *hbh;
703	u_int8_t *opt;
704
705	/* validation of the length of the header */
706#ifndef PULLDOWN_TEST
707	IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
708	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
709	hbhlen = (hbh->ip6h_len + 1) << 3;
710
711	IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
712	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
713#else
714	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
715		sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
716	if (hbh == NULL) {
717		ip6stat.ip6s_tooshort++;
718		return -1;
719	}
720	hbhlen = (hbh->ip6h_len + 1) << 3;
721	IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
722		hbhlen);
723	if (hbh == NULL) {
724		ip6stat.ip6s_tooshort++;
725		return -1;
726	}
727#endif
728	off += hbhlen;
729	hbhlen -= sizeof(struct ip6_hbh);
730	opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
731
732	if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
733				hbhlen, rtalertp, plenp) < 0)
734		return(-1);
735
736	*offp = off;
737	*mp = m;
738	return(0);
739}
740
741/*
742 * Search header for all Hop-by-hop options and process each option.
743 * This function is separate from ip6_hopopts_input() in order to
744 * handle a case where the sending node itself process its hop-by-hop
745 * options header. In such a case, the function is called from ip6_output().
746 */
747int
748ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
749	struct mbuf *m;
750	u_int8_t *opthead;
751	int hbhlen;
752	u_int32_t *rtalertp;
753	u_int32_t *plenp;
754{
755	struct ip6_hdr *ip6;
756	int optlen = 0;
757	u_int8_t *opt = opthead;
758	u_int16_t rtalert_val;
759	u_int32_t jumboplen;
760
761	for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
762		switch(*opt) {
763		 case IP6OPT_PAD1:
764			 optlen = 1;
765			 break;
766		 case IP6OPT_PADN:
767			 if (hbhlen < IP6OPT_MINLEN) {
768				 ip6stat.ip6s_toosmall++;
769				 goto bad;
770			 }
771			 optlen = *(opt + 1) + 2;
772			 break;
773		 case IP6OPT_RTALERT:
774			 /* XXX may need check for alignment */
775			 if (hbhlen < IP6OPT_RTALERT_LEN) {
776				 ip6stat.ip6s_toosmall++;
777				 goto bad;
778			 }
779			 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
780				  /* XXX: should we discard the packet? */
781				 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
782				     *(opt + 1));
783			 optlen = IP6OPT_RTALERT_LEN;
784			 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
785			 *rtalertp = ntohs(rtalert_val);
786			 break;
787		 case IP6OPT_JUMBO:
788			/* XXX may need check for alignment */
789			if (hbhlen < IP6OPT_JUMBO_LEN) {
790				ip6stat.ip6s_toosmall++;
791				goto bad;
792			}
793			if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
794				 /* XXX: should we discard the packet? */
795				log(LOG_ERR, "length of jumbopayload opt "
796				    "is inconsistent(%d)",
797				    *(opt + 1));
798			optlen = IP6OPT_JUMBO_LEN;
799
800			/*
801			 * IPv6 packets that have non 0 payload length
802			 * must not contain a jumbo paylod option.
803			 */
804			ip6 = mtod(m, struct ip6_hdr *);
805			if (ip6->ip6_plen) {
806				ip6stat.ip6s_badoptions++;
807				icmp6_error(m, ICMP6_PARAM_PROB,
808					    ICMP6_PARAMPROB_HEADER,
809					    sizeof(struct ip6_hdr) +
810					    sizeof(struct ip6_hbh) +
811					    opt - opthead);
812				return(-1);
813			}
814
815			/*
816			 * We may see jumbolen in unaligned location, so
817			 * we'd need to perform bcopy().
818			 */
819			bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
820			jumboplen = (u_int32_t)htonl(jumboplen);
821
822#if 1
823			/*
824			 * if there are multiple jumbo payload options,
825			 * *plenp will be non-zero and the packet will be
826			 * rejected.
827			 * the behavior may need some debate in ipngwg -
828			 * multiple options does not make sense, however,
829			 * there's no explicit mention in specification.
830			 */
831			if (*plenp != 0) {
832				ip6stat.ip6s_badoptions++;
833				icmp6_error(m, ICMP6_PARAM_PROB,
834					    ICMP6_PARAMPROB_HEADER,
835					    sizeof(struct ip6_hdr) +
836					    sizeof(struct ip6_hbh) +
837					    opt + 2 - opthead);
838				return(-1);
839			}
840#endif
841
842			/*
843			 * jumbo payload length must be larger than 65535.
844			 */
845			if (jumboplen <= IPV6_MAXPACKET) {
846				ip6stat.ip6s_badoptions++;
847				icmp6_error(m, ICMP6_PARAM_PROB,
848					    ICMP6_PARAMPROB_HEADER,
849					    sizeof(struct ip6_hdr) +
850					    sizeof(struct ip6_hbh) +
851					    opt + 2 - opthead);
852				return(-1);
853			}
854			*plenp = jumboplen;
855
856			break;
857		 default:		/* unknown option */
858			 if (hbhlen < IP6OPT_MINLEN) {
859				 ip6stat.ip6s_toosmall++;
860				 goto bad;
861			 }
862			 if ((optlen = ip6_unknown_opt(opt, m,
863						       sizeof(struct ip6_hdr) +
864						       sizeof(struct ip6_hbh) +
865						       opt - opthead)) == -1)
866				 return(-1);
867			 optlen += 2;
868			 break;
869		}
870	}
871
872	return(0);
873
874  bad:
875	m_freem(m);
876	return(-1);
877}
878
879/*
880 * Unknown option processing.
881 * The third argument `off' is the offset from the IPv6 header to the option,
882 * which is necessary if the IPv6 header the and option header and IPv6 header
883 * is not continuous in order to return an ICMPv6 error.
884 */
885int
886ip6_unknown_opt(optp, m, off)
887	u_int8_t *optp;
888	struct mbuf *m;
889	int off;
890{
891	struct ip6_hdr *ip6;
892
893	switch(IP6OPT_TYPE(*optp)) {
894	 case IP6OPT_TYPE_SKIP: /* ignore the option */
895		 return((int)*(optp + 1));
896	 case IP6OPT_TYPE_DISCARD:	/* silently discard */
897		 m_freem(m);
898		 return(-1);
899	 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
900		 ip6stat.ip6s_badoptions++;
901		 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
902		 return(-1);
903	 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
904		 ip6stat.ip6s_badoptions++;
905		 ip6 = mtod(m, struct ip6_hdr *);
906		 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
907		     (m->m_flags & (M_BCAST|M_MCAST)))
908			 m_freem(m);
909		 else
910			 icmp6_error(m, ICMP6_PARAM_PROB,
911				     ICMP6_PARAMPROB_OPTION, off);
912		 return(-1);
913	}
914
915	m_freem(m);		/* XXX: NOTREACHED */
916	return(-1);
917}
918
919/*
920 * Create the "control" list for this pcb.
921 *
922 * The routine will be called from upper layer handlers like tcp6_input().
923 * Thus the routine assumes that the caller (tcp6_input) have already
924 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
925 * very first mbuf on the mbuf chain.
926 * We may want to add some infinite loop prevention or sanity checks for safety.
927 * (This applies only when you are using KAME mbuf chain restriction, i.e.
928 * you are using IP6_EXTHDR_CHECK() not m_pulldown())
929 */
930void
931ip6_savecontrol(in6p, mp, ip6, m)
932	register struct in6pcb *in6p;
933	register struct mbuf **mp;
934	register struct ip6_hdr *ip6;
935	register struct mbuf *m;
936{
937	struct proc *p = curproc;	/* XXX */
938	int privileged;
939
940	privileged = 0;
941	if (p && !suser(p))
942		privileged++;
943
944	if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
945		struct timeval tv;
946
947		microtime(&tv);
948		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
949			SCM_TIMESTAMP, SOL_SOCKET);
950		if (*mp)
951			mp = &(*mp)->m_next;
952	}
953
954#ifdef noyet
955	/* options were tossed above */
956	if (in6p->in6p_flags & IN6P_RECVOPTS)
957		/* broken */
958	/* ip6_srcroute doesn't do what we want here, need to fix */
959	if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
960		/* broken */
961#endif
962
963	/* RFC 2292 sec. 5 */
964	if (in6p->in6p_flags & IN6P_PKTINFO) {
965		struct in6_pktinfo pi6;
966		bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
967		if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
968			pi6.ipi6_addr.s6_addr16[1] = 0;
969		pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
970					? m->m_pkthdr.rcvif->if_index
971					: 0;
972		*mp = sbcreatecontrol((caddr_t) &pi6,
973			sizeof(struct in6_pktinfo), IPV6_PKTINFO,
974			IPPROTO_IPV6);
975		if (*mp)
976			mp = &(*mp)->m_next;
977	}
978	if (in6p->in6p_flags & IN6P_HOPLIMIT) {
979		int hlim = ip6->ip6_hlim & 0xff;
980		*mp = sbcreatecontrol((caddr_t) &hlim,
981			sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
982		if (*mp)
983			mp = &(*mp)->m_next;
984	}
985	/* IN6P_NEXTHOP - for outgoing packet only */
986
987	/*
988	 * IPV6_HOPOPTS socket option. We require super-user privilege
989	 * for the option, but it might be too strict, since there might
990	 * be some hop-by-hop options which can be returned to normal user.
991	 * See RFC 2292 section 6.
992	 */
993	if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
994		/*
995		 * Check if a hop-by-hop options header is contatined in the
996		 * received packet, and if so, store the options as ancillary
997		 * data. Note that a hop-by-hop options header must be
998		 * just after the IPv6 header, which fact is assured through
999		 * the IPv6 input processing.
1000		 */
1001		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1002		if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1003			struct ip6_hbh *hbh;
1004			int hbhlen;
1005
1006#ifndef PULLDOWN_TEST
1007			hbh = (struct ip6_hbh *)(ip6 + 1);
1008			hbhlen = (hbh->ip6h_len + 1) << 3;
1009#else
1010			IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1011				sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1012			if (hbh == NULL) {
1013				ip6stat.ip6s_tooshort++;
1014				return;
1015			}
1016			hbhlen = (hbh->ip6h_len + 1) << 3;
1017			IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1018				sizeof(struct ip6_hdr), hbhlen);
1019			if (hbh == NULL) {
1020				ip6stat.ip6s_tooshort++;
1021				return;
1022			}
1023#endif
1024
1025			/*
1026			 * XXX: We copy whole the header even if a jumbo
1027			 * payload option is included, which option is to
1028			 * be removed before returning in the RFC 2292.
1029			 * But it's too painful operation...
1030			 */
1031			*mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1032					      IPV6_HOPOPTS, IPPROTO_IPV6);
1033			if (*mp)
1034				mp = &(*mp)->m_next;
1035		}
1036	}
1037
1038	/* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1039	if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
1040		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1041		int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
1042
1043		/*
1044		 * Search for destination options headers or routing
1045		 * header(s) through the header chain, and stores each
1046		 * header as ancillary data.
1047		 * Note that the order of the headers remains in
1048		 * the chain of ancillary data.
1049		 */
1050		while(1) {	/* is explicit loop prevention necessary? */
1051			struct ip6_ext *ip6e;
1052			int elen;
1053
1054#ifndef PULLDOWN_TEST
1055			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1056			if (nxt == IPPROTO_AH)
1057				elen = (ip6e->ip6e_len + 2) << 2;
1058			else
1059				elen = (ip6e->ip6e_len + 1) << 3;
1060#else
1061			IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
1062				sizeof(struct ip6_ext));
1063			if (ip6e == NULL) {
1064				ip6stat.ip6s_tooshort++;
1065				return;
1066			}
1067			if (nxt == IPPROTO_AH)
1068				elen = (ip6e->ip6e_len + 2) << 2;
1069			else
1070				elen = (ip6e->ip6e_len + 1) << 3;
1071			IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen);
1072			if (ip6e == NULL) {
1073				ip6stat.ip6s_tooshort++;
1074				return;
1075			}
1076#endif
1077
1078			switch(nxt) {
1079		         case IPPROTO_DSTOPTS:
1080				 if (!in6p->in6p_flags & IN6P_DSTOPTS)
1081					 break;
1082
1083				 /*
1084				  * We also require super-user privilege for
1085				  * the option.
1086				  * See the comments on IN6_HOPOPTS.
1087				  */
1088				 if (!privileged)
1089					 break;
1090
1091				 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1092						       IPV6_DSTOPTS,
1093						       IPPROTO_IPV6);
1094				 if (*mp)
1095					 mp = &(*mp)->m_next;
1096				 break;
1097
1098			 case IPPROTO_ROUTING:
1099				 if (!in6p->in6p_flags & IN6P_RTHDR)
1100					 break;
1101
1102				 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1103						       IPV6_RTHDR,
1104						       IPPROTO_IPV6);
1105				 if (*mp)
1106					 mp = &(*mp)->m_next;
1107				 break;
1108
1109			 case IPPROTO_UDP:
1110			 case IPPROTO_TCP:
1111			 case IPPROTO_ICMPV6:
1112			 default:
1113				 /*
1114				  * stop search if we encounter an upper
1115				  * layer protocol headers.
1116				  */
1117				 goto loopend;
1118
1119			 case IPPROTO_HOPOPTS:
1120			 case IPPROTO_AH: /* is it possible? */
1121				 break;
1122			}
1123
1124			/* proceed with the next header. */
1125			off += elen;
1126			nxt = ip6e->ip6e_nxt;
1127		}
1128	  loopend:
1129	}
1130	if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1131		/* to be done */
1132	}
1133	if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
1134		/* to be done */
1135	}
1136	/* IN6P_RTHDR - to be done */
1137
1138}
1139
1140/*
1141 * Get pointer to the previous header followed by the header
1142 * currently processed.
1143 * XXX: This function supposes that
1144 *	M includes all headers,
1145 *	the next header field and the header length field of each header
1146 *	are valid, and
1147 *	the sum of each header length equals to OFF.
1148 * Because of these assumptions, this function must be called very
1149 * carefully. Moreover, it will not be used in the near future when
1150 * we develop `neater' mechanism to process extension headers.
1151 */
1152char *
1153ip6_get_prevhdr(m, off)
1154	struct mbuf *m;
1155	int off;
1156{
1157	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1158
1159	if (off == sizeof(struct ip6_hdr))
1160		return(&ip6->ip6_nxt);
1161	else {
1162		int len, nxt;
1163		struct ip6_ext *ip6e = NULL;
1164
1165		nxt = ip6->ip6_nxt;
1166		len = sizeof(struct ip6_hdr);
1167		while (len < off) {
1168			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1169
1170			switch(nxt) {
1171			case IPPROTO_FRAGMENT:
1172				len += sizeof(struct ip6_frag);
1173				break;
1174			case IPPROTO_AH:
1175				len += (ip6e->ip6e_len + 2) << 2;
1176				break;
1177			default:
1178				len += (ip6e->ip6e_len + 1) << 3;
1179				break;
1180			}
1181			nxt = ip6e->ip6e_nxt;
1182		}
1183		if (ip6e)
1184			return(&ip6e->ip6e_nxt);
1185		else
1186			return NULL;
1187	}
1188}
1189
1190/*
1191 * get next header offset.  m will be retained.
1192 */
1193int
1194ip6_nexthdr(m, off, proto, nxtp)
1195	struct mbuf *m;
1196	int off;
1197	int proto;
1198	int *nxtp;
1199{
1200	struct ip6_hdr ip6;
1201	struct ip6_ext ip6e;
1202	struct ip6_frag fh;
1203
1204	/* just in case */
1205	if (m == NULL)
1206		panic("ip6_nexthdr: m == NULL");
1207	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1208		return -1;
1209
1210	switch (proto) {
1211	case IPPROTO_IPV6:
1212		if (m->m_pkthdr.len < off + sizeof(ip6))
1213			return -1;
1214		m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1215		if (nxtp)
1216			*nxtp = ip6.ip6_nxt;
1217		off += sizeof(ip6);
1218		return off;
1219
1220	case IPPROTO_FRAGMENT:
1221		/*
1222		 * terminate parsing if it is not the first fragment,
1223		 * it does not make sense to parse through it.
1224		 */
1225		if (m->m_pkthdr.len < off + sizeof(fh))
1226			return -1;
1227		m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1228		if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
1229			return -1;
1230		if (nxtp)
1231			*nxtp = fh.ip6f_nxt;
1232		off += sizeof(struct ip6_frag);
1233		return off;
1234
1235	case IPPROTO_AH:
1236		if (m->m_pkthdr.len < off + sizeof(ip6e))
1237			return -1;
1238		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1239		if (nxtp)
1240			*nxtp = ip6e.ip6e_nxt;
1241		off += (ip6e.ip6e_len + 2) << 2;
1242		return off;
1243
1244	case IPPROTO_HOPOPTS:
1245	case IPPROTO_ROUTING:
1246	case IPPROTO_DSTOPTS:
1247		if (m->m_pkthdr.len < off + sizeof(ip6e))
1248			return -1;
1249		m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1250		if (nxtp)
1251			*nxtp = ip6e.ip6e_nxt;
1252		off += (ip6e.ip6e_len + 1) << 3;
1253		return off;
1254
1255	case IPPROTO_NONE:
1256	case IPPROTO_ESP:
1257	case IPPROTO_IPCOMP:
1258		/* give up */
1259		return -1;
1260
1261	default:
1262		return -1;
1263	}
1264
1265	return -1;
1266}
1267
1268/*
1269 * get offset for the last header in the chain.  m will be kept untainted.
1270 */
1271int
1272ip6_lasthdr(m, off, proto, nxtp)
1273	struct mbuf *m;
1274	int off;
1275	int proto;
1276	int *nxtp;
1277{
1278	int newoff;
1279	int nxt;
1280
1281	if (!nxtp) {
1282		nxt = -1;
1283		nxtp = &nxt;
1284	}
1285	while (1) {
1286		newoff = ip6_nexthdr(m, off, proto, nxtp);
1287		if (newoff < 0)
1288			return off;
1289		else if (newoff < off)
1290			return -1;	/* invalid */
1291		else if (newoff == off)
1292			return newoff;
1293
1294		off = newoff;
1295		proto = *nxtp;
1296	}
1297}
1298
1299/*
1300 * System control for IP6
1301 */
1302
1303u_char	inet6ctlerrmap[PRC_NCMDS] = {
1304	0,		0,		0,		0,
1305	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
1306	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
1307	EMSGSIZE,	EHOSTUNREACH,	0,		0,
1308	0,		0,		0,		0,
1309	ENOPROTOOPT
1310};
1311