162587Sitojun/*	$FreeBSD$	*/
278064Sume/*	$KAME: ip6.h,v 1.18 2001/03/29 05:34:30 itojun Exp $	*/
362587Sitojun
4139823Simp/*-
562587Sitojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
653541Sshin * All rights reserved.
753541Sshin *
853541Sshin * Redistribution and use in source and binary forms, with or without
953541Sshin * modification, are permitted provided that the following conditions
1053541Sshin * are met:
1153541Sshin * 1. Redistributions of source code must retain the above copyright
1253541Sshin *    notice, this list of conditions and the following disclaimer.
1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1453541Sshin *    notice, this list of conditions and the following disclaimer in the
1553541Sshin *    documentation and/or other materials provided with the distribution.
1653541Sshin * 3. Neither the name of the project nor the names of its contributors
1753541Sshin *    may be used to endorse or promote products derived from this software
1853541Sshin *    without specific prior written permission.
1953541Sshin *
2053541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2153541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2253541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2353541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2453541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2553541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2653541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2753541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2853541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2953541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3053541Sshin * SUCH DAMAGE.
3162587Sitojun */
3262587Sitojun
33139823Simp/*-
3462587Sitojun * Copyright (c) 1982, 1986, 1993
3562587Sitojun *	The Regents of the University of California.  All rights reserved.
3653541Sshin *
3762587Sitojun * Redistribution and use in source and binary forms, with or without
3862587Sitojun * modification, are permitted provided that the following conditions
3962587Sitojun * are met:
4062587Sitojun * 1. Redistributions of source code must retain the above copyright
4162587Sitojun *    notice, this list of conditions and the following disclaimer.
4262587Sitojun * 2. Redistributions in binary form must reproduce the above copyright
4362587Sitojun *    notice, this list of conditions and the following disclaimer in the
4462587Sitojun *    documentation and/or other materials provided with the distribution.
4562587Sitojun * 4. Neither the name of the University nor the names of its contributors
4662587Sitojun *    may be used to endorse or promote products derived from this software
4762587Sitojun *    without specific prior written permission.
4862587Sitojun *
4962587Sitojun * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5062587Sitojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5162587Sitojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5262587Sitojun * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5362587Sitojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5462587Sitojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5562587Sitojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5662587Sitojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5762587Sitojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5862587Sitojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5962587Sitojun * SUCH DAMAGE.
6062587Sitojun *
6162587Sitojun *	@(#)ip.h	8.1 (Berkeley) 6/10/93
6253541Sshin */
6353541Sshin
6462587Sitojun#ifndef _NETINET_IP6_H_
6562587Sitojun#define _NETINET_IP6_H_
6662587Sitojun
6762587Sitojun/*
6862587Sitojun * Definition for internet protocol version 6.
6962587Sitojun * RFC 2460
7062587Sitojun */
7162587Sitojun
7262587Sitojunstruct ip6_hdr {
7362587Sitojun	union {
7462587Sitojun		struct ip6_hdrctl {
7562587Sitojun			u_int32_t ip6_un1_flow;	/* 20 bits of flow-ID */
7662587Sitojun			u_int16_t ip6_un1_plen;	/* payload length */
7762587Sitojun			u_int8_t  ip6_un1_nxt;	/* next header */
7862587Sitojun			u_int8_t  ip6_un1_hlim;	/* hop limit */
7962587Sitojun		} ip6_un1;
8062587Sitojun		u_int8_t ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
8162587Sitojun	} ip6_ctlun;
8262587Sitojun	struct in6_addr ip6_src;	/* source address */
8362587Sitojun	struct in6_addr ip6_dst;	/* destination address */
84121499Sume} __packed;
8562587Sitojun
8662587Sitojun#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
8762587Sitojun#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
8862587Sitojun#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
8962587Sitojun#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt
9062587Sitojun#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
9162587Sitojun#define ip6_hops	ip6_ctlun.ip6_un1.ip6_un1_hlim
9262587Sitojun
9362587Sitojun#define IPV6_VERSION		0x60
9462587Sitojun#define IPV6_VERSION_MASK	0xf0
9562587Sitojun
9662587Sitojun#if BYTE_ORDER == BIG_ENDIAN
9762587Sitojun#define IPV6_FLOWINFO_MASK	0x0fffffff	/* flow info (28 bits) */
9862587Sitojun#define IPV6_FLOWLABEL_MASK	0x000fffff	/* flow label (20 bits) */
9962587Sitojun#else
10062587Sitojun#if BYTE_ORDER == LITTLE_ENDIAN
10162587Sitojun#define IPV6_FLOWINFO_MASK	0xffffff0f	/* flow info (28 bits) */
10262587Sitojun#define IPV6_FLOWLABEL_MASK	0xffff0f00	/* flow label (20 bits) */
10362587Sitojun#endif /* LITTLE_ENDIAN */
10462587Sitojun#endif
10578064Sume#if 1
10662587Sitojun/* ECN bits proposed by Sally Floyd */
10762587Sitojun#define IP6TOS_CE		0x01	/* congestion experienced */
10862587Sitojun#define IP6TOS_ECT		0x02	/* ECN-capable transport */
10978064Sume#endif
11062587Sitojun
11162587Sitojun/*
11262587Sitojun * Extension Headers
11362587Sitojun */
11462587Sitojun
11562587Sitojunstruct	ip6_ext {
11678064Sume	u_int8_t ip6e_nxt;
11778064Sume	u_int8_t ip6e_len;
118121499Sume} __packed;
11962587Sitojun
12062587Sitojun/* Hop-by-Hop options header */
12162587Sitojun/* XXX should we pad it to force alignment on an 8-byte boundary? */
12262587Sitojunstruct ip6_hbh {
12362587Sitojun	u_int8_t ip6h_nxt;	/* next header */
12462587Sitojun	u_int8_t ip6h_len;	/* length in units of 8 octets */
12562587Sitojun	/* followed by options */
126121499Sume} __packed;
12762587Sitojun
12862587Sitojun/* Destination options header */
12962587Sitojun/* XXX should we pad it to force alignment on an 8-byte boundary? */
13062587Sitojunstruct ip6_dest {
13162587Sitojun	u_int8_t ip6d_nxt;	/* next header */
13262587Sitojun	u_int8_t ip6d_len;	/* length in units of 8 octets */
13362587Sitojun	/* followed by options */
134121499Sume} __packed;
13562587Sitojun
13662587Sitojun/* Option types and related macros */
13762587Sitojun#define IP6OPT_PAD1		0x00	/* 00 0 00000 */
13862587Sitojun#define IP6OPT_PADN		0x01	/* 00 0 00001 */
13962587Sitojun#define IP6OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
14078064Sume#define IP6OPT_NSAP_ADDR	0xC3	/* 11 0 00011 */
14178064Sume#define IP6OPT_TUNNEL_LIMIT	0x04	/* 00 0 00100 */
142121472Sume#ifndef _KERNEL
14378064Sume#define IP6OPT_RTALERT		0x05	/* 00 0 00101 (KAME definition) */
144121472Sume#endif
145148169Sume#define IP6OPT_ROUTER_ALERT	0x05	/* 00 0 00101 (RFC3542, recommended) */
14678064Sume
14762587Sitojun#define IP6OPT_RTALERT_LEN	4
14862587Sitojun#define IP6OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
14962587Sitojun#define IP6OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
15062587Sitojun#define IP6OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
15162587Sitojun#define IP6OPT_MINLEN		2
15262587Sitojun
15378064Sume#define IP6OPT_EID		0x8a	/* 10 0 01010 */
15478064Sume
15562587Sitojun#define IP6OPT_TYPE(o)		((o) & 0xC0)
15662587Sitojun#define IP6OPT_TYPE_SKIP	0x00
15762587Sitojun#define IP6OPT_TYPE_DISCARD	0x40
15862587Sitojun#define IP6OPT_TYPE_FORCEICMP	0x80
15962587Sitojun#define IP6OPT_TYPE_ICMP	0xC0
16062587Sitojun
16162587Sitojun#define IP6OPT_MUTABLE		0x20
16262587Sitojun
163148176Sume/* IPv6 options: common part */
164148176Sumestruct ip6_opt {
165148176Sume	u_int8_t ip6o_type;
166148176Sume	u_int8_t ip6o_len;
167148176Sume} __packed;
168148176Sume
169148176Sume/* Jumbo Payload Option */
170148176Sumestruct ip6_opt_jumbo {
171148176Sume	u_int8_t ip6oj_type;
172148176Sume	u_int8_t ip6oj_len;
173148176Sume	u_int8_t ip6oj_jumbo_len[4];
174148176Sume} __packed;
17578064Sume#define IP6OPT_JUMBO_LEN	6
17678064Sume
177148176Sume/* NSAP Address Option */
178148176Sumestruct ip6_opt_nsap {
179148176Sume	u_int8_t ip6on_type;
180148176Sume	u_int8_t ip6on_len;
181148176Sume	u_int8_t ip6on_src_nsap_len;
182148176Sume	u_int8_t ip6on_dst_nsap_len;
183148176Sume	/* followed by source NSAP */
184148176Sume	/* followed by destination NSAP */
185148176Sume} __packed;
186148176Sume
187148176Sume/* Tunnel Limit Option */
188148176Sumestruct ip6_opt_tunnel {
189148176Sume	u_int8_t ip6ot_type;
190148176Sume	u_int8_t ip6ot_len;
191148176Sume	u_int8_t ip6ot_encap_limit;
192148176Sume} __packed;
193148176Sume
194148176Sume/* Router Alert Option */
195148176Sumestruct ip6_opt_router {
196148176Sume	u_int8_t ip6or_type;
197148176Sume	u_int8_t ip6or_len;
198148176Sume	u_int8_t ip6or_value[2];
199148176Sume} __packed;
200148176Sume/* Router alert values (in network byte order) */
201148176Sume#if BYTE_ORDER == BIG_ENDIAN
202148176Sume#define IP6_ALERT_MLD	0x0000
203148176Sume#define IP6_ALERT_RSVP	0x0001
204148176Sume#define IP6_ALERT_AN	0x0002
205148176Sume#else
206148176Sume#if BYTE_ORDER == LITTLE_ENDIAN
207148176Sume#define IP6_ALERT_MLD	0x0000
208148176Sume#define IP6_ALERT_RSVP	0x0100
209148176Sume#define IP6_ALERT_AN	0x0200
210148176Sume#endif /* LITTLE_ENDIAN */
211148176Sume#endif
212148176Sume
21362587Sitojun/* Routing header */
21462587Sitojunstruct ip6_rthdr {
21562587Sitojun	u_int8_t  ip6r_nxt;	/* next header */
21662587Sitojun	u_int8_t  ip6r_len;	/* length in units of 8 octets */
21762587Sitojun	u_int8_t  ip6r_type;	/* routing type */
21862587Sitojun	u_int8_t  ip6r_segleft;	/* segments left */
21962587Sitojun	/* followed by routing type specific data */
220121499Sume} __packed;
22162587Sitojun
222189303Sbz/* Type 0 Routing header, deprecated by RFC 5095. */
22362587Sitojunstruct ip6_rthdr0 {
22462587Sitojun	u_int8_t  ip6r0_nxt;		/* next header */
22562587Sitojun	u_int8_t  ip6r0_len;		/* length in units of 8 octets */
22662587Sitojun	u_int8_t  ip6r0_type;		/* always zero */
22762587Sitojun	u_int8_t  ip6r0_segleft;	/* segments left */
228121478Sume	u_int32_t  ip6r0_reserved;	/* reserved field */
229121478Sume	/* followed by up to 127 struct in6_addr */
230121499Sume} __packed;
23162587Sitojun
23262587Sitojun/* Fragment header */
23362587Sitojunstruct ip6_frag {
23462587Sitojun	u_int8_t  ip6f_nxt;		/* next header */
23562587Sitojun	u_int8_t  ip6f_reserved;	/* reserved field */
23662587Sitojun	u_int16_t ip6f_offlg;		/* offset, reserved, and flag */
23762587Sitojun	u_int32_t ip6f_ident;		/* identification */
238121499Sume} __packed;
23962587Sitojun
24062587Sitojun#if BYTE_ORDER == BIG_ENDIAN
24162587Sitojun#define IP6F_OFF_MASK		0xfff8	/* mask out offset from _offlg */
24262587Sitojun#define IP6F_RESERVED_MASK	0x0006	/* reserved bits in ip6f_offlg */
24362587Sitojun#define IP6F_MORE_FRAG		0x0001	/* more-fragments flag */
24462587Sitojun#else /* BYTE_ORDER == LITTLE_ENDIAN */
24562587Sitojun#define IP6F_OFF_MASK		0xf8ff	/* mask out offset from _offlg */
24662587Sitojun#define IP6F_RESERVED_MASK	0x0600	/* reserved bits in ip6f_offlg */
24762587Sitojun#define IP6F_MORE_FRAG		0x0100	/* more-fragments flag */
24862587Sitojun#endif /* BYTE_ORDER == LITTLE_ENDIAN */
24962587Sitojun
25062587Sitojun/*
25162587Sitojun * Internet implementation parameters.
25262587Sitojun */
253148169Sume#define IPV6_MAXHLIM	255	/* maximum hoplimit */
25462587Sitojun#define IPV6_DEFHLIM	64	/* default hlim */
25562587Sitojun#define IPV6_FRAGTTL	120	/* ttl for fragment packets, in slowtimo tick */
256148169Sume#define IPV6_HLIMDEC	1	/* subtracted when forwarding */
25762587Sitojun
25862587Sitojun#define IPV6_MMTU	1280	/* minimal MTU and reassembly. 1024 + 256 */
25962587Sitojun#define IPV6_MAXPACKET	65535	/* ip6 max packet size without Jumbo payload*/
260127463Sume#define IPV6_MAXOPTHDR	2048	/* max option header size, 256 64-bit words */
26162587Sitojun
26262587Sitojun#ifdef _KERNEL
26362587Sitojun/*
26462587Sitojun * IP6_EXTHDR_CHECK ensures that region between the IP6 header and the
26562587Sitojun * target header (including IPv6 itself, extension headers and
266215956Sbrucec * TCP/UDP/ICMP6 headers) are contiguous. KAME requires drivers
26762587Sitojun * to store incoming data into one internal mbuf or one or more external
26862587Sitojun * mbufs(never into two or more internal mbufs). Thus, the third case is
26962587Sitojun * supposed to never be matched but is prepared just in case.
27062587Sitojun */
27162587Sitojun
27262587Sitojun#define IP6_EXTHDR_CHECK(m, off, hlen, ret)				\
27362587Sitojundo {									\
27462587Sitojun    if ((m)->m_next != NULL) {						\
27562587Sitojun	if (((m)->m_flags & M_LOOP) &&					\
27662587Sitojun	    ((m)->m_len < (off) + (hlen)) &&				\
27762587Sitojun	    (((m) = m_pullup((m), (off) + (hlen))) == NULL)) {		\
278250044Sae		IP6STAT_INC(ip6s_exthdrtoolong);				\
27962587Sitojun		return ret;						\
28062587Sitojun	} else if ((m)->m_flags & M_EXT) {				\
28162587Sitojun		if ((m)->m_len < (off) + (hlen)) {			\
282250044Sae			IP6STAT_INC(ip6s_exthdrtoolong);			\
28362587Sitojun			m_freem(m);					\
28462587Sitojun			return ret;					\
28562587Sitojun		}							\
28662587Sitojun	} else {							\
28762587Sitojun		if ((m)->m_len < (off) + (hlen)) {			\
288250044Sae			IP6STAT_INC(ip6s_exthdrtoolong);			\
28962587Sitojun			m_freem(m);					\
29062587Sitojun			return ret;					\
29162587Sitojun		}							\
29262587Sitojun	}								\
29362587Sitojun    } else {								\
29462587Sitojun	if ((m)->m_len < (off) + (hlen)) {				\
295250044Sae		IP6STAT_INC(ip6s_tooshort);				\
29662587Sitojun		in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);	\
29762587Sitojun		m_freem(m);						\
29862587Sitojun		return ret;						\
29962587Sitojun	}								\
30062587Sitojun    }									\
301120435Sume} while (/*CONSTCOND*/ 0)
30262587Sitojun
30362587Sitojun/*
30462587Sitojun * IP6_EXTHDR_GET ensures that intermediate protocol header (from "off" to
30562587Sitojun * "len") is located in single mbuf, on contiguous memory region.
30662587Sitojun * The pointer to the region will be returned to pointer variable "val",
30762587Sitojun * with type "typ".
30862587Sitojun * IP6_EXTHDR_GET0 does the same, except that it aligns the structure at the
30962587Sitojun * very top of mbuf.  GET0 is likely to make memory copy than GET.
31062587Sitojun *
31162587Sitojun * XXX we're now testing this, needs m_pulldown()
31262587Sitojun */
31362587Sitojun#define IP6_EXTHDR_GET(val, typ, m, off, len) \
31462587Sitojundo {									\
31562587Sitojun	struct mbuf *t;							\
31662587Sitojun	int tmp;							\
31762587Sitojun	if ((m)->m_len >= (off) + (len))				\
31862587Sitojun		(val) = (typ)(mtod((m), caddr_t) + (off));		\
31962587Sitojun	else {								\
32062587Sitojun		t = m_pulldown((m), (off), (len), &tmp);		\
32162587Sitojun		if (t) {						\
32262587Sitojun			if (t->m_len < tmp + (len))			\
32362587Sitojun				panic("m_pulldown malfunction");	\
32462587Sitojun			(val) = (typ)(mtod(t, caddr_t) + tmp);		\
32562587Sitojun		} else {						\
32662587Sitojun			(val) = (typ)NULL;				\
32762587Sitojun			(m) = NULL;					\
32862587Sitojun		}							\
32962587Sitojun	}								\
330120435Sume} while (/*CONSTCOND*/ 0)
33162587Sitojun
33262587Sitojun#define IP6_EXTHDR_GET0(val, typ, m, off, len) \
33362587Sitojundo {									\
33462587Sitojun	struct mbuf *t;							\
33562587Sitojun	if ((off) == 0)							\
33662587Sitojun		(val) = (typ)mtod(m, caddr_t);				\
33762587Sitojun	else {								\
33862587Sitojun		t = m_pulldown((m), (off), (len), NULL);		\
33962587Sitojun		if (t) {						\
34062587Sitojun			if (t->m_len < (len))				\
34162587Sitojun				panic("m_pulldown malfunction");	\
34262587Sitojun			(val) = (typ)mtod(t, caddr_t);			\
34362587Sitojun		} else {						\
34462587Sitojun			(val) = (typ)NULL;				\
34562587Sitojun			(m) = NULL;					\
34662587Sitojun		}							\
34762587Sitojun	}								\
348120435Sume} while (/*CONSTCOND*/ 0)
349183550Szec
35062587Sitojun#endif /*_KERNEL*/
35162587Sitojun
35262587Sitojun#endif /* not _NETINET_IP6_H_ */
353