xref: /freebsd/sys/netinet6/ip6_input.c (revision 2eb8169a1ad3bd8c7960767a5bc471c8d8bc677e)
1 /*	$FreeBSD$	*/
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 
120 extern struct domain inet6domain;
121 extern struct ip6protosw inet6sw[];
122 
123 u_char ip6_protox[IPPROTO_MAX];
124 static int ip6qmaxlen = IFQ_MAXLEN;
125 struct in6_ifaddr *in6_ifaddr;
126 
127 int ip6_forward_srcrt;			/* XXX */
128 int ip6_sourcecheck;			/* XXX */
129 int ip6_sourcecheck_interval;		/* XXX */
130 const int int6intrq_present = 1;
131 
132 /* firewall hooks */
133 ip6_fw_chk_t *ip6_fw_chk_ptr;
134 ip6_fw_ctl_t *ip6_fw_ctl_ptr;
135 int ip6_fw_enable = 1;
136 
137 struct ip6stat ip6stat;
138 
139 static void ip6_init2 __P((void *));
140 
141 static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
142 #ifdef PULLDOWN_TEST
143 static 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  */
150 void
151 ip6_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 
180 static void
181 ip6_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 */
199 SYSINIT(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  */
204 void
205 ip6intr()
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 
220 extern struct	route_in6 ip6_forward_rt;
221 
222 void
223 ip6_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  */
693 static int
694 ip6_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  */
747 int
748 ip6_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  */
885 int
886 ip6_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  */
930 void
931 ip6_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  */
1152 char *
1153 ip6_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  */
1193 int
1194 ip6_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  */
1271 int
1272 ip6_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 
1303 u_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