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