Home | History | Annotate | Line # | Download | only in netinet6
ip6_input.c revision 1.6
      1 /*	$NetBSD: ip6_input.c,v 1.6 1999/07/31 18:41:16 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 #ifdef __NetBSD__
     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 <netinet6/in6_var.h>
    101 #include <netinet/in_systm.h>
    102 #include <netinet6/ip6.h>
    103 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
    104 #include <netinet6/in6_pcb.h>
    105 #else
    106 #include <netinet/in_pcb.h>
    107 #endif
    108 #include <netinet6/ip6_var.h>
    109 #include <netinet6/icmp6.h>
    110 #include <netinet6/in6_ifattach.h>
    111 #include <netinet6/nd6.h>
    112 
    113 #ifdef INET
    114 #include <netinet/ip.h>
    115 #include <netinet/ip_icmp.h>
    116 #endif /*INET*/
    117 
    118 #include <netinet6/ip6protosw.h>
    119 
    120 /* we need it for NLOOP. */
    121 #include "loop.h"
    122 #include "faith.h"
    123 
    124 #include "gif.h"
    125 #include "bpfilter.h"
    126 
    127 extern struct domain inet6domain;
    128 extern struct ip6protosw inet6sw[];
    129 #ifdef __bsdi__
    130 extern struct ifnet loif;
    131 #endif
    132 
    133 u_char ip6_protox[IPPROTO_MAX];
    134 static int ip6qmaxlen = IFQ_MAXLEN;
    135 struct in6_ifaddr *in6_ifaddr;
    136 struct ifqueue ip6intrq;
    137 
    138 #ifdef __NetBSD__
    139 extern struct ifnet loif[NLOOP];
    140 int ip6_forward_srcrt;			/* XXX */
    141 int ip6_sourcecheck;			/* XXX */
    142 int ip6_sourcecheck_interval;		/* XXX */
    143 #endif
    144 
    145 struct ip6stat ip6stat;
    146 
    147 static void ip6_init2 __P((void *));
    148 
    149 static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
    150 
    151 /*
    152  * IP6 initialization: fill in IP6 protocol switch table.
    153  * All protocols not implemented in kernel go to raw IP6 protocol handler.
    154  */
    155 void
    156 ip6_init()
    157 {
    158 	register struct ip6protosw *pr;
    159 	register int i;
    160 	struct timeval tv;
    161 
    162 	pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
    163 	if (pr == 0)
    164 		panic("ip6_init");
    165 	for (i = 0; i < IPPROTO_MAX; i++)
    166 		ip6_protox[i] = pr - inet6sw;
    167 	for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
    168 	    pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
    169 		if (pr->pr_domain->dom_family == PF_INET6 &&
    170 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
    171 			ip6_protox[pr->pr_protocol] = pr - inet6sw;
    172 	ip6intrq.ifq_maxlen = ip6qmaxlen;
    173 	nd6_init();
    174 	frag6_init();
    175 	/*
    176 	 * in many cases, random() here does NOT return random number
    177 	 * as initialization during bootstrap time occur in fixed order.
    178 	 */
    179 	microtime(&tv);
    180 	ip6_flow_seq = random() ^ tv.tv_usec;
    181 	in6_iflladdr = malloc(i, M_IFADDR, M_WAITOK);
    182 	bzero(in6_iflladdr, i);
    183 
    184 	ip6_init2((void *)0);
    185 }
    186 
    187 static void
    188 ip6_init2(dummy)
    189 	void *dummy;
    190 {
    191 	int i;
    192 
    193 	/*
    194 	 * to route local address of p2p link to loopback,
    195 	 * assign loopback address first.
    196 	 */
    197 	for (i = 0; i < NLOOP; i++)
    198 		in6_ifattach(&loif[i], IN6_IFT_LOOP, NULL, 0);
    199 
    200 	/* get EUI64 from somewhere, attach pseudo interfaces */
    201 	if (in6_ifattach_getifid(NULL) == 0)
    202 		in6_ifattach_p2p();
    203 
    204 	/* nd6_timer_init */
    205 	timeout(nd6_timer, (caddr_t)0, hz);
    206 }
    207 
    208 #ifdef __FreeBSD__
    209 /* cheat */
    210 SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init2, NULL);
    211 #endif
    212 
    213 /*
    214  * IP6 input interrupt handling. Just pass the packet to ip6_input.
    215  */
    216 void
    217 ip6intr()
    218 {
    219 	int s;
    220 	struct mbuf *m;
    221 
    222 	for (;;) {
    223 		s = splimp();
    224 		IF_DEQUEUE(&ip6intrq, m);
    225 		splx(s);
    226 		if (m == 0)
    227 			return;
    228 		ip6_input(m);
    229 	}
    230 }
    231 
    232 #ifdef __FreeBSD__
    233 NETISR_SET(NETISR_IPV6, ip6intr);
    234 #endif
    235 
    236 extern struct	route_in6 ip6_forward_rt;
    237 
    238 void
    239 ip6_input(m)
    240 	struct mbuf *m;
    241 {
    242 	register struct ip6_hdr *ip6;
    243 	int off = sizeof(struct ip6_hdr), nest;
    244 	u_int32_t plen;
    245 	u_int32_t rtalert = ~0;
    246 	int nxt, ours = 0;
    247 
    248 #ifdef IPSEC
    249 	/*
    250 	 * should the inner packet be considered authentic?
    251 	 * see comment in ah4_input().
    252 	 */
    253 	if (m) {
    254 		m->m_flags &= ~M_AUTHIPHDR;
    255 		m->m_flags &= ~M_AUTHIPDGM;
    256 	}
    257 #endif
    258 	/*
    259 	 * mbuf statistics by kazu
    260 	 */
    261 	if (m->m_flags & M_EXT) {
    262 		if (m->m_next)
    263 			ip6stat.ip6s_mext2m++;
    264 		else
    265 			ip6stat.ip6s_mext1++;
    266 	} else {
    267 		if (m->m_next) {
    268 			if (m->m_flags & M_LOOP)
    269 				ip6stat.ip6s_m2m[loif[0].if_index]++;	/*XXX*/
    270 			else if (m->m_pkthdr.rcvif->if_index <= 31)
    271 				ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
    272 			else
    273 				ip6stat.ip6s_m2m[0]++;
    274 		} else
    275 			ip6stat.ip6s_m1++;
    276 	}
    277 
    278 	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
    279 
    280 	ip6stat.ip6s_total++;
    281 
    282 	if (m->m_len < sizeof(struct ip6_hdr) &&
    283 	    (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
    284 		ip6stat.ip6s_toosmall++;
    285 		return;
    286 	}
    287 
    288 	ip6 = mtod(m, struct ip6_hdr *);
    289 
    290 	if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
    291 		ip6stat.ip6s_badvers++;
    292 		goto bad;
    293 	}
    294 
    295 	ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
    296 
    297 	/*
    298 	 * Scope check
    299 	 */
    300 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
    301 	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
    302 		ip6stat.ip6s_badscope++;
    303 		goto bad;
    304 	}
    305 	if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
    306 	    IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
    307 		if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
    308 			ours = 1;
    309 			goto hbhcheck;
    310 		} else {
    311 			ip6stat.ip6s_badscope++;
    312 			goto bad;
    313 		}
    314 	}
    315 
    316 	if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
    317 		if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
    318 			ours = 1;
    319 			goto hbhcheck;
    320 		}
    321 	} else {
    322 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
    323 			ip6->ip6_src.s6_addr16[1]
    324 				= htons(m->m_pkthdr.rcvif->if_index);
    325 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
    326 			ip6->ip6_dst.s6_addr16[1]
    327 				= htons(m->m_pkthdr.rcvif->if_index);
    328 	}
    329 
    330 	/*
    331 	 * Multicast check
    332 	 */
    333 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
    334 	  	struct	in6_multi *in6m = 0;
    335 		/*
    336 		 * See if we belong to the destination multicast group on the
    337 		 * arrival interface.
    338 		 */
    339 		IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
    340 		if (in6m)
    341 			ours = 1;
    342 		else if (!ip6_mrouter) {
    343 			ip6stat.ip6s_notmember++;
    344 			ip6stat.ip6s_cantforward++;
    345 			goto bad;
    346 		}
    347 		goto hbhcheck;
    348 	}
    349 
    350 	/*
    351 	 *  Unicast check
    352 	 */
    353 	if (ip6_forward_rt.ro_rt == 0 ||
    354 	    !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
    355 				&ip6_forward_rt.ro_dst.sin6_addr)) {
    356 		if (ip6_forward_rt.ro_rt) {
    357 			RTFREE(ip6_forward_rt.ro_rt);
    358 			ip6_forward_rt.ro_rt = 0;
    359 		}
    360 		bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
    361 		ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
    362 		ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
    363 		ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
    364 
    365 #if defined(__bsdi__) || defined(__NetBSD__)
    366 		rtalloc((struct route *)&ip6_forward_rt);
    367 #endif
    368 #ifdef __FreeBSD__
    369 		rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
    370 #endif
    371 	}
    372 
    373 #define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
    374 
    375 	/*
    376 	 * Accept the packet if the forwarding interface to the destination
    377 	 * according to the routing table is the loopback interface,
    378 	 * unless the associated route has a gateway.
    379 	 * Note that this approach causes to accept a packet if there is a
    380 	 * route to the loopback interface for the destination of the packet.
    381 	 * But we think it's even useful in some situations, e.g. when using
    382 	 * a special daemon which wants to intercept the packet.
    383 	 */
    384 	if (ip6_forward_rt.ro_rt &&
    385 	    (ip6_forward_rt.ro_rt->rt_flags &
    386 	     (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
    387 #if 0
    388 	    /*
    389 	     * The check below is redundant since the comparison of
    390 	     * the destination and the key of the rtentry has
    391 	     * already done through looking up the routing table.
    392 	     */
    393 	    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
    394 			       &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
    395 #endif
    396 #ifdef __bsdi__
    397 	    ip6_foward.rt.ro_rt->rt_ifp == &loif
    398 #else
    399 	    ip6_forward_rt.ro_rt->rt_ifp == &loif[0]
    400 #endif
    401 		) {
    402 		struct in6_ifaddr *ia6 =
    403 			(struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
    404 		/* packet to tentative address must not be received */
    405 		if (ia6->ia6_flags & IN6_IFF_ANYCAST)
    406 			m->m_flags |= M_ANYCAST6;
    407 		if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
    408 			/* this interface is ready */
    409 			ours = 1;
    410 			goto hbhcheck;
    411 		} else {
    412 			/* this interface is not ready, fall through */
    413 		}
    414 	}
    415 
    416 	/*
    417 	 * FAITH(Firewall Aided Internet Translator)
    418 	 */
    419 #if defined(NFAITH) && 0 < NFAITH
    420 	if (ip6_keepfaith) {
    421 		if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
    422 		 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
    423 			/* XXX do we need more sanity checks? */
    424 			ours = 1;
    425 			goto hbhcheck;
    426 		}
    427 	}
    428 #endif
    429 
    430 	/*
    431 	 * Now there is no reason to process the packet if it's not our own
    432 	 * and we're not a router.
    433 	 */
    434 	if (!ip6_forwarding) {
    435 		ip6stat.ip6s_cantforward++;
    436 		goto bad;
    437 	}
    438 
    439   hbhcheck:
    440 	/*
    441 	 * Process Hop-by-Hop options header if it's contained.
    442 	 * m may be modified in ip6_hopopts_input().
    443 	 * If a JumboPayload option is included, plen will also be modified.
    444 	 */
    445 	plen = (u_int32_t)ntohs(ip6->ip6_plen);
    446 	if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
    447 		if (ip6_hopopts_input(&plen, &rtalert, &m, &off))
    448 			return;	/* m have already been freed */
    449 		/* adjust pointer */
    450 		ip6 = mtod(m, struct ip6_hdr *);
    451 		nxt = ((struct ip6_hbh *)(ip6 + 1))->ip6h_nxt;
    452 
    453 		/*
    454 		 * accept the packet if a router alert option is included
    455 		 * and we act as an IPv6 router.
    456 		 */
    457 		if (rtalert != ~0 && ip6_forwarding)
    458 			ours = 1;
    459 	} else
    460 		nxt = ip6->ip6_nxt;
    461 
    462 	/*
    463 	 * Check that the amount of data in the buffers
    464 	 * is as at least much as the IPv6 header would have us expect.
    465 	 * Trim mbufs if longer than we expect.
    466 	 * Drop packet if shorter than we expect.
    467 	 */
    468 	if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
    469 		ip6stat.ip6s_tooshort++;
    470 		goto bad;
    471 	}
    472 	if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
    473 		if (m->m_len == m->m_pkthdr.len) {
    474 			m->m_len = sizeof(struct ip6_hdr) + plen;
    475 			m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
    476 		} else
    477 			m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
    478 	}
    479 
    480 	/*
    481 	 * Forward if desirable.
    482 	 */
    483 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
    484 		/*
    485 		 * If we are acting as a multicast router, all
    486 		 * incoming multicast packets are passed to the
    487 		 * kernel-level multicast forwarding function.
    488 		 * The packet is returned (relatively) intact; if
    489 		 * ip6_mforward() returns a non-zero value, the packet
    490 		 * must be discarded, else it may be accepted below.
    491 		 */
    492 		if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
    493 			ip6stat.ip6s_cantforward++;
    494 			m_freem(m);
    495 			return;
    496 		}
    497 		if (!ours) {
    498 			m_freem(m);
    499 			return;
    500 		}
    501 	}
    502 	else if (!ours) {
    503 		ip6_forward(m, 0);
    504 		return;
    505 	}
    506 
    507 	/*
    508 	 * Tell launch routine the next header
    509 	 */
    510 	ip6stat.ip6s_delivered++;
    511 	nest = 0;
    512 	while (nxt != IPPROTO_DONE) {
    513 		if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
    514 			ip6stat.ip6s_toomanyhdr++;
    515 			goto bad;
    516 		}
    517 		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
    518 	}
    519 	return;
    520  bad:
    521 	m_freem(m);
    522 }
    523 
    524 /*
    525  * Hop-by-Hop options header processing. If a valid jumbo payload option is
    526  * included, the real payload length will be stored in plenp.
    527  */
    528 static int
    529 ip6_hopopts_input(plenp, rtalertp, mp, offp)
    530 	u_int32_t *plenp;
    531 	u_int32_t *rtalertp;	/* XXX: should be stored more smart way */
    532 	struct mbuf **mp;
    533 	int *offp;
    534 {
    535 	register struct mbuf *m = *mp;
    536 	int off = *offp, hbhlen;
    537 	struct ip6_hbh *hbh;
    538 	u_int8_t *opt;
    539 
    540 	/* validation of the length of the header */
    541 	IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
    542 	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
    543 	hbhlen = (hbh->ip6h_len + 1) << 3;
    544 
    545 	IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
    546 	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
    547 	off += hbhlen;
    548 	hbhlen -= sizeof(struct ip6_hbh);
    549 	opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
    550 
    551 	if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
    552 				hbhlen, rtalertp, plenp) < 0)
    553 		return(-1);
    554 
    555 	*offp = off;
    556 	*mp = m;
    557 	return(0);
    558 }
    559 
    560 /*
    561  * Search header for all Hop-by-hop options and process each option.
    562  * This function is separate from ip6_hopopts_input() in order to
    563  * handle a case where the sending node itself process its hop-by-hop
    564  * options header. In such a case, the function is called from ip6_output().
    565  */
    566 int
    567 ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
    568 	struct mbuf *m;
    569 	u_int8_t *opthead;
    570 	int hbhlen;
    571 	u_int32_t *rtalertp;
    572 	u_int32_t *plenp;
    573 {
    574 	struct ip6_hdr *ip6;
    575 	int optlen = 0;
    576 	u_int8_t *opt = opthead;
    577 	u_int16_t rtalert_val;
    578 
    579 	for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
    580 		switch(*opt) {
    581 		 case IP6OPT_PAD1:
    582 			 optlen = 1;
    583 			 break;
    584 		 case IP6OPT_PADN:
    585 			 if (hbhlen < IP6OPT_MINLEN) {
    586 				 ip6stat.ip6s_toosmall++;
    587 				 goto bad;
    588 			 }
    589 			 optlen = *(opt + 1) + 2;
    590 			 break;
    591 		 case IP6OPT_RTALERT:
    592 			 if (hbhlen < IP6OPT_RTALERT_LEN) {
    593 				 ip6stat.ip6s_toosmall++;
    594 				 goto bad;
    595 			 }
    596 			 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
    597 				  /* XXX: should we discard the packet? */
    598 				 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
    599 				     *(opt + 1));
    600 			 optlen = IP6OPT_RTALERT_LEN;
    601 			 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
    602 			 *rtalertp = ntohs(rtalert_val);
    603 			 break;
    604 		 case IP6OPT_JUMBO:
    605 			 if (hbhlen < IP6OPT_JUMBO_LEN) {
    606 				 ip6stat.ip6s_toosmall++;
    607 				 goto bad;
    608 			 }
    609 			 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
    610 				  /* XXX: should we discard the packet? */
    611 				 log(LOG_ERR, "length of jumbopayload opt "
    612 				     "is inconsistent(%d)",
    613 				     *(opt + 1));
    614 			 optlen = IP6OPT_JUMBO_LEN;
    615 
    616 			 /*
    617 			  * We can simply cast because of the alignment
    618 			  * requirement of the jumbo payload option.
    619 			  */
    620 			 *plenp = ntohl(*(u_int32_t *)(opt + 2));
    621 			 if (*plenp <= IPV6_MAXPACKET) {
    622 				 /*
    623 				  * jumbo payload length must be larger
    624 				  * than 65535
    625 				  */
    626 				 ip6stat.ip6s_badoptions++;
    627 				 icmp6_error(m, ICMP6_PARAM_PROB,
    628 					     ICMP6_PARAMPROB_HEADER,
    629 					     sizeof(struct ip6_hdr) +
    630 					     sizeof(struct ip6_hbh) +
    631 					     opt + 2 - opthead);
    632 				 return(-1);
    633 			 }
    634 
    635 			 ip6 = mtod(m, struct ip6_hdr *);
    636 			 if (ip6->ip6_plen) {
    637 				 /*
    638 				  * IPv6 packets that have non 0 payload length
    639 				  * must not contain a jumbo paylod option.
    640 				  */
    641 				 ip6stat.ip6s_badoptions++;
    642 				 icmp6_error(m, ICMP6_PARAM_PROB,
    643 					     ICMP6_PARAMPROB_HEADER,
    644 					     sizeof(struct ip6_hdr) +
    645 					     sizeof(struct ip6_hbh) +
    646 					     opt - opthead);
    647 				 return(-1);
    648 			 }
    649 			 break;
    650 		 default:		/* unknown option */
    651 			 if (hbhlen < IP6OPT_MINLEN) {
    652 				 ip6stat.ip6s_toosmall++;
    653 				 goto bad;
    654 			 }
    655 			 if ((optlen = ip6_unknown_opt(opt, m,
    656 						       sizeof(struct ip6_hdr) +
    657 						       sizeof(struct ip6_hbh) +
    658 						       opt - opthead)) == -1)
    659 				 return(-1);
    660 			 optlen += 2;
    661 			 break;
    662 		}
    663 	}
    664 
    665 	return(0);
    666 
    667   bad:
    668 	m_freem(m);
    669 	return(-1);
    670 }
    671 
    672 /*
    673  * Unknown option processing.
    674  * The third argument `off' is the offset from the IPv6 header to the option,
    675  * which is necessary if the IPv6 header the and option header and IPv6 header
    676  * is not continuous in order to return an ICMPv6 error.
    677  */
    678 int
    679 ip6_unknown_opt(optp, m, off)
    680 	u_int8_t *optp;
    681 	struct mbuf *m;
    682 	int off;
    683 {
    684 	struct ip6_hdr *ip6;
    685 
    686 	switch(IP6OPT_TYPE(*optp)) {
    687 	 case IP6OPT_TYPE_SKIP: /* ignore the option */
    688 		 return((int)*(optp + 1));
    689 	 case IP6OPT_TYPE_DISCARD:	/* silently discard */
    690 		 m_freem(m);
    691 		 return(-1);
    692 	 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
    693 		 ip6stat.ip6s_badoptions++;
    694 		 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
    695 		 return(-1);
    696 	 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
    697 		 ip6stat.ip6s_badoptions++;
    698 		 ip6 = mtod(m, struct ip6_hdr *);
    699 		 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
    700 		     (m->m_flags & (M_BCAST|M_MCAST)))
    701 			 m_freem(m);
    702 		 else
    703 			 icmp6_error(m, ICMP6_PARAM_PROB,
    704 				     ICMP6_PARAMPROB_OPTION, off);
    705 		 return(-1);
    706 	}
    707 
    708 	m_freem(m);		/* XXX: NOTREACHED */
    709 	return(-1);
    710 }
    711 
    712 /*
    713  * Create the "control" list for this pcb
    714  */
    715 void
    716 ip6_savecontrol(in6p, mp, ip6, m)
    717 	register struct in6pcb *in6p;
    718 	register struct mbuf **mp;
    719 	register struct ip6_hdr *ip6;
    720 	register struct mbuf *m;
    721 {
    722 #ifdef __NetBSD__
    723 	struct proc *p = curproc;	/* XXX */
    724 #endif
    725 #ifdef __bsdi__
    726 # define sbcreatecontrol	so_cmsg
    727 #endif
    728 
    729 	if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
    730 		struct timeval tv;
    731 
    732 		microtime(&tv);
    733 		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
    734 			SCM_TIMESTAMP, SOL_SOCKET);
    735 		if (*mp)
    736 			mp = &(*mp)->m_next;
    737 	}
    738 	if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
    739 		*mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
    740 			sizeof(struct in6_addr), IPV6_RECVDSTADDR,
    741 			IPPROTO_IPV6);
    742 		if (*mp)
    743 			mp = &(*mp)->m_next;
    744 	}
    745 
    746 #ifdef noyet
    747 	/* options were tossed above */
    748 	if (in6p->in6p_flags & IN6P_RECVOPTS)
    749 		/* broken */
    750 	/* ip6_srcroute doesn't do what we want here, need to fix */
    751 	if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
    752 		/* broken */
    753 #endif
    754 
    755 	/* RFC 2292 sec. 5 */
    756 	if (in6p->in6p_flags & IN6P_PKTINFO) {
    757 		struct in6_pktinfo pi6;
    758 		bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
    759 		if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
    760 			pi6.ipi6_addr.s6_addr16[1] = 0;
    761 		pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
    762 					? m->m_pkthdr.rcvif->if_index
    763 					: 0;
    764 		*mp = sbcreatecontrol((caddr_t) &pi6,
    765 			sizeof(struct in6_pktinfo), IPV6_PKTINFO,
    766 			IPPROTO_IPV6);
    767 		if (*mp)
    768 			mp = &(*mp)->m_next;
    769 	}
    770 	if (in6p->in6p_flags & IN6P_HOPLIMIT) {
    771 		int hlim = ip6->ip6_hlim & 0xff;
    772 		*mp = sbcreatecontrol((caddr_t) &hlim,
    773 			sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
    774 		if (*mp)
    775 			mp = &(*mp)->m_next;
    776 	}
    777 	/* IN6P_NEXTHOP - for outgoing packet only */
    778 
    779 	/*
    780 	 * IPV6_HOPOPTS socket option. We require super-user privilege
    781 	 * for the option, but it might be too strict, since there might
    782 	 * be some hop-by-hop options which can be returned to normal user.
    783 	 * See RFC 2292 section 6.
    784 	 */
    785 	if ((in6p->in6p_flags & IN6P_HOPOPTS) &&
    786 	    p && !suser(p->p_ucred, &p->p_acflag)) {
    787 		/*
    788 		 * Check if a hop-by-hop options header is contatined in the
    789 		 * received packet, and if so, store the options as ancillary
    790 		 * data. Note that a hop-by-hop options header must be
    791 		 * just after the IPv6 header, which fact is assured through
    792 		 * the IPv6 input processing.
    793 		 */
    794 		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
    795 		if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
    796 			struct ip6_hbh *hbh = (struct ip6_hbh *)(ip6 + 1);
    797 
    798 			/*
    799 			 * XXX: We copy whole the header even if a jumbo
    800 			 * payload option is included, which option is to
    801 			 * be removed before returning in the RFC 2292.
    802 			 * But it's too painful operation...
    803 			 */
    804 			*mp = sbcreatecontrol((caddr_t)hbh,
    805 					      (hbh->ip6h_len + 1) << 3,
    806 					      IPV6_HOPOPTS, IPPROTO_IPV6);
    807 			if (*mp)
    808 				mp = &(*mp)->m_next;
    809 		}
    810 	}
    811 
    812 	/* IPV6_DSTOPTS and IPV6_RTHDR socket options */
    813 	if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
    814 		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
    815 		int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
    816 
    817 		/*
    818 		 * Search for destination options headers or routing
    819 		 * header(s) through the header chain, and stores each
    820 		 * header as ancillary data.
    821 		 * Note that the order of the headers remains in
    822 		 * the chain of ancillary data.
    823 		 */
    824 		while(1) {	/* is explicit loop prevention necessary? */
    825 			struct ip6_ext *ip6e =
    826 				(struct ip6_ext *)(mtod(m, caddr_t) + off);
    827 
    828 			switch(nxt) {
    829 		         case IPPROTO_DSTOPTS:
    830 				 if (!in6p->in6p_flags & IN6P_DSTOPTS)
    831 					 break;
    832 
    833 				 /*
    834 				  * We also require super-user privilege for
    835 				  * the option.
    836 				  * See the comments on IN6_HOPOPTS.
    837 				  */
    838 				 if (!p || !suser(p->p_ucred, &p->p_acflag))
    839 					 break;
    840 
    841 				 *mp = sbcreatecontrol((caddr_t)ip6e,
    842 						       (ip6e->ip6e_len + 1) << 3,
    843 						       IPV6_DSTOPTS,
    844 						       IPPROTO_IPV6);
    845 				 if (*mp)
    846 					 mp = &(*mp)->m_next;
    847 				 break;
    848 
    849 			 case IPPROTO_ROUTING:
    850 				 if (!in6p->in6p_flags & IN6P_RTHDR)
    851 					 break;
    852 
    853 				 *mp = sbcreatecontrol((caddr_t)ip6e,
    854 						       (ip6e->ip6e_len + 1) << 3,
    855 						       IPV6_RTHDR,
    856 						       IPPROTO_IPV6);
    857 				 if (*mp)
    858 					 mp = &(*mp)->m_next;
    859 				 break;
    860 
    861 			 case IPPROTO_UDP:
    862 			 case IPPROTO_TCP:
    863 			 case IPPROTO_ICMPV6:
    864 			 default:
    865 				 /*
    866 				  * stop search if we encounter an upper
    867 				  * layer protocol headers.
    868 				  */
    869 				 goto loopend;
    870 
    871 			 case IPPROTO_HOPOPTS:
    872 			 case IPPROTO_AH: /* is it possible? */
    873 				 break;
    874 			}
    875 
    876 			/* proceed with the next header. */
    877 			if (nxt == IPPROTO_AH)
    878 				off += (ip6e->ip6e_len + 2) << 2;
    879 			else
    880 				off += (ip6e->ip6e_len + 1) << 3;
    881 			nxt = ip6e->ip6e_nxt;
    882 		}
    883 	  loopend:
    884 	}
    885 	if ((in6p->in6p_flags & IN6P_HOPOPTS)
    886 	 && p && !suser(p->p_ucred, &p->p_acflag)) {
    887 		/* to be done */
    888 	}
    889 	if ((in6p->in6p_flags & IN6P_DSTOPTS)
    890 	 && p && !suser(p->p_ucred, &p->p_acflag)) {
    891 		/* to be done */
    892 	}
    893 	/* IN6P_RTHDR - to be done */
    894 
    895 #ifdef __bsdi__
    896 # undef sbcreatecontrol
    897 #endif
    898 }
    899 
    900 /*
    901  * Get pointer to the previous header followed by the header
    902  * currently processed.
    903  * XXX: This function supposes that
    904  *	M includes all headers,
    905  *	the next header field and the header length field of each header
    906  *	are valid, and
    907  *	the sum of each header length equals to OFF.
    908  * Because of these assumptions, this function must be called very
    909  * carefully. Moreover, it will not be used in the near future when
    910  * we develop `neater' mechanism to process extension headers.
    911  */
    912 char *
    913 ip6_get_prevhdr(m, off)
    914 	struct mbuf *m;
    915 	int off;
    916 {
    917 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
    918 
    919 	if (off == sizeof(struct ip6_hdr))
    920 		return(&ip6->ip6_nxt);
    921 	else {
    922 		int len, nxt;
    923 		struct ip6_ext *ip6e = NULL;
    924 
    925 		nxt = ip6->ip6_nxt;
    926 		len = sizeof(struct ip6_hdr);
    927 		while (len < off) {
    928 			ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
    929 
    930 			switch(nxt) {
    931 			case IPPROTO_FRAGMENT:
    932 				len += sizeof(struct ip6_frag);
    933 				break;
    934 			case IPPROTO_AH:
    935 				len += (ip6e->ip6e_len + 2) << 2;
    936 				break;
    937 			default:
    938 				len += (ip6e->ip6e_len + 1) << 3;
    939 				break;
    940 			}
    941 			nxt = ip6e->ip6e_nxt;
    942 		}
    943 		if (ip6e)
    944 			return(&ip6e->ip6e_nxt);
    945 		else
    946 			return NULL;
    947 	}
    948 }
    949 
    950 /*
    951  * System control for IP6
    952  */
    953 
    954 u_char	inet6ctlerrmap[PRC_NCMDS] = {
    955 	0,		0,		0,		0,
    956 	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
    957 	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
    958 	EMSGSIZE,	EHOSTUNREACH,	0,		0,
    959 	0,		0,		0,		0,
    960 	ENOPROTOOPT
    961 };
    962 
    963 #ifdef __NetBSD__
    964 #include <vm/vm.h>
    965 #include <sys/sysctl.h>
    966 
    967 int
    968 ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
    969 	int *name;
    970 	u_int namelen;
    971 	void *oldp;
    972 	size_t *oldlenp;
    973 	void *newp;
    974 	size_t newlen;
    975 {
    976 	/* All sysctl names at this level are terminal. */
    977 	if (namelen != 1)
    978 		return ENOTDIR;
    979 
    980 	switch (name[0]) {
    981 
    982 	case IPV6CTL_FORWARDING:
    983 		return sysctl_int(oldp, oldlenp, newp, newlen,
    984 				  &ip6_forwarding);
    985 	case IPV6CTL_SENDREDIRECTS:
    986 		return sysctl_int(oldp, oldlenp, newp, newlen,
    987 				&ip6_sendredirects);
    988 	case IPV6CTL_DEFHLIM:
    989 		return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_defhlim);
    990 	case IPV6CTL_MAXFRAGPACKETS:
    991 		return sysctl_int(oldp, oldlenp, newp, newlen,
    992 				&ip6_maxfragpackets);
    993 	case IPV6CTL_ACCEPT_RTADV:
    994 		return sysctl_int(oldp, oldlenp, newp, newlen,
    995 				&ip6_accept_rtadv);
    996 	case IPV6CTL_KEEPFAITH:
    997 		return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_keepfaith);
    998 	case IPV6CTL_LOG_INTERVAL:
    999 		return sysctl_int(oldp, oldlenp, newp, newlen,
   1000 				&ip6_log_interval);
   1001 	case IPV6CTL_HDRNESTLIMIT:
   1002 		return sysctl_int(oldp, oldlenp, newp, newlen,
   1003 				&ip6_hdrnestlimit);
   1004 	case IPV6CTL_DAD_COUNT:
   1005 		return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_dad_count);
   1006 	case IPV6CTL_AUTO_FLOWLABEL:
   1007 		return sysctl_int(oldp, oldlenp, newp, newlen,
   1008 				&ip6_auto_flowlabel);
   1009 	case IPV6CTL_DEFMCASTHLIM:
   1010 		return sysctl_int(oldp, oldlenp, newp, newlen,
   1011 				&ip6_defmcasthlim);
   1012 	case IPV6CTL_GIF_HLIM:
   1013 		return sysctl_int(oldp, oldlenp, newp, newlen,
   1014 				&ip6_gif_hlim);
   1015 	case IPV6CTL_KAME_VERSION:
   1016 		return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
   1017 	default:
   1018 		return EOPNOTSUPP;
   1019 	}
   1020 	/* NOTREACHED */
   1021 }
   1022 #endif /* __NetBSD__ */
   1023