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