1/*
2 * ip6.h
3 *
4 * Internet Protocol, Version 6 (RFC 2460).
5 *
6 * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
7 *
8 * $Id: ip6.h,v 1.6 2004/02/23 10:01:15 dugsong Exp $
9 */
10
11#ifndef DNET_IP6_H
12#define DNET_IP6_H
13
14#define IP6_ADDR_LEN	16
15#define IP6_ADDR_BITS	128
16
17#define IP6_HDR_LEN	40		/* IPv6 header length */
18#define IP6_LEN_MIN	IP6_HDR_LEN
19#define IP6_LEN_MAX	65535		/* non-jumbo payload */
20
21#define IP6_MTU_MIN	1280		/* minimum MTU (1024 + 256) */
22
23typedef struct ip6_addr {
24        uint8_t         data[IP6_ADDR_LEN];
25} ip6_addr_t;
26
27#ifndef __GNUC__
28# define __attribute__(x)
29# pragma pack(1)
30#endif
31
32/*
33 * IPv6 header
34 */
35struct ip6_hdr {
36        union {
37                struct ip6_hdr_ctl {
38                        uint32_t	ip6_un1_flow; /* 20 bits of flow ID */
39                        uint16_t	ip6_un1_plen; /* payload length */
40                        uint8_t		ip6_un1_nxt;  /* next header */
41                        uint8_t		ip6_un1_hlim; /* hop limit */
42                } ip6_un1;
43                uint8_t	ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
44        } ip6_ctlun;
45        ip6_addr_t	ip6_src;
46        ip6_addr_t	ip6_dst;
47} __attribute__((__packed__));
48
49#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
50#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
51#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
52#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt	/* IP_PROTO_* */
53#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
54
55#define IP6_VERSION		0x60
56#define IP6_VERSION_MASK	0xf0		/* ip6_vfc version */
57
58#if DNET_BYTESEX == DNET_BIG_ENDIAN
59#define IP6_FLOWINFO_MASK	0x0fffffff	/* ip6_flow info (28 bits) */
60#define IP6_FLOWLABEL_MASK	0x000fffff	/* ip6_flow label (20 bits) */
61#elif DNET_BYTESEX == DNET_LIL_ENDIAN
62#define IP6_FLOWINFO_MASK	0xffffff0f	/* ip6_flow info (28 bits) */
63#define IP6_FLOWLABEL_MASK	0xffff0f00	/* ip6_flow label (20 bits) */
64#endif
65
66/*
67 * Hop limit (ip6_hlim)
68 */
69#define IP6_HLIM_DEFAULT	64
70#define IP6_HLIM_MAX		255
71
72/*
73 * Preferred extension header order from RFC 2460, 4.1:
74 *
75 * IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING,
76 * IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS, IP_PROTO_*
77 */
78
79/*
80 * Routing header data (IP_PROTO_ROUTING)
81 */
82struct ip6_ext_data_routing {
83        uint8_t  type;			/* routing type */
84        uint8_t  segleft;		/* segments left */
85        /* followed by routing type specific data */
86} __attribute__((__packed__));
87
88struct ip6_ext_data_routing0 {
89        uint8_t  type;			/* always zero */
90        uint8_t  segleft;		/* segments left */
91        uint8_t  reserved;		/* reserved field */
92        uint8_t  slmap[3];		/* strict/loose bit map */
93        ip6_addr_t  addr[1];		/* up to 23 addresses */
94} __attribute__((__packed__));
95
96/*
97 * Fragment header data (IP_PROTO_FRAGMENT)
98 */
99struct ip6_ext_data_fragment {
100        uint16_t  offlg;		/* offset, reserved, and flag */
101        uint32_t  ident;		/* identification */
102} __attribute__((__packed__));
103
104/*
105 * Fragmentation offset, reserved, and flags (offlg)
106 */
107#if DNET_BYTESEX == DNET_BIG_ENDIAN
108#define IP6_OFF_MASK		0xfff8	/* mask out offset from offlg */
109#define IP6_RESERVED_MASK	0x0006	/* reserved bits in offlg */
110#define IP6_MORE_FRAG		0x0001	/* more-fragments flag */
111#elif DNET_BYTESEX == DNET_LIL_ENDIAN
112#define IP6_OFF_MASK		0xf8ff	/* mask out offset from offlg */
113#define IP6_RESERVED_MASK	0x0600	/* reserved bits in offlg */
114#define IP6_MORE_FRAG		0x0100	/* more-fragments flag */
115#endif
116
117/*
118 * Option types, for IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS headers
119 */
120#define IP6_OPT_PAD1		0x00	/* 00 0 00000 */
121#define IP6_OPT_PADN		0x01	/* 00 0 00001 */
122#define IP6_OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
123#define IP6_OPT_JUMBO_LEN	6
124#define IP6_OPT_RTALERT		0x05	/* 00 0 00101 */
125#define IP6_OPT_RTALERT_LEN	4
126#define IP6_OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
127#define IP6_OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
128#define IP6_OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
129#define IP6_OPT_LEN_MIN		2
130
131#define IP6_OPT_TYPE(o)		((o) & 0xC0)	/* high 2 bits of opt_type */
132#define IP6_OPT_TYPE_SKIP	0x00	/* continue processing on failure */
133#define IP6_OPT_TYPE_DISCARD	0x40	/* discard packet on failure */
134#define IP6_OPT_TYPE_FORCEICMP	0x80	/* discard and send ICMP on failure */
135#define IP6_OPT_TYPE_ICMP	0xC0	/* ...only if non-multicast dst */
136
137#define IP6_OPT_MUTABLE		0x20	/* option data may change en route */
138
139/*
140 * Extension header (chained via {ip6,ext}_nxt, following IPv6 header)
141 */
142struct ip6_ext_hdr {
143        uint8_t  ext_nxt;	/* next header */
144        uint8_t  ext_len;	/* following length in units of 8 octets */
145        union {
146                struct ip6_ext_data_routing	routing;
147                struct ip6_ext_data_fragment	fragment;
148        } ext_data;
149} __attribute__((__packed__));
150
151#ifndef __GNUC__
152# pragma pack()
153#endif
154
155/*
156 * Reserved addresses
157 */
158#define IP6_ADDR_UNSPEC	\
159        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
160#define IP6_ADDR_LOOPBACK \
161        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
162
163#define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do {	\
164        struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr);			\
165        ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) &			\
166            (IP6_FLOWLABEL_MASK | (fl)));				\
167        ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4));			\
168        ip6->ip6_plen = htons((plen));					\
169        ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim);			\
170        memmove(&ip6->ip6_src, &(src), IP6_ADDR_LEN);			\
171        memmove(&ip6->ip6_dst, &(dst), IP6_ADDR_LEN);			\
172} while (0);
173
174__BEGIN_DECLS
175char	*ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t size);
176int	 ip6_pton(const char *src, ip6_addr_t *dst);
177char	*ip6_ntoa(const ip6_addr_t *ip6);
178#define	 ip6_aton ip6_pton
179
180void	 ip6_checksum(void *buf, size_t len);
181__END_DECLS
182
183#endif /* DNET_IP6_H */
184