summaryrefslogtreecommitdiff
path: root/ext/dnet/ip6.h
blob: 7fae29b47f502c22ab09cca3b35b89ea95047e5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * ip6.h
 *
 * Internet Protocol, Version 6 (RFC 2460).
 *
 * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
 *
 * $Id: ip6.h,v 1.6 2004/02/23 10:01:15 dugsong Exp $
 */

#ifndef DNET_IP6_H
#define DNET_IP6_H

#define IP6_ADDR_LEN	16
#define IP6_ADDR_BITS	128

#define IP6_HDR_LEN	40		/* IPv6 header length */
#define IP6_LEN_MIN	IP6_HDR_LEN
#define IP6_LEN_MAX	65535		/* non-jumbo payload */

#define IP6_MTU_MIN	1280		/* minimum MTU (1024 + 256) */

typedef struct ip6_addr {
        uint8_t         data[IP6_ADDR_LEN];
} ip6_addr_t;

#ifndef __GNUC__
# define __attribute__(x)
# pragma pack(1)
#endif

/*
 * IPv6 header
 */
struct ip6_hdr {
        union {
                struct ip6_hdr_ctl {
                        uint32_t	ip6_un1_flow; /* 20 bits of flow ID */
                        uint16_t	ip6_un1_plen; /* payload length */
                        uint8_t		ip6_un1_nxt;  /* next header */
                        uint8_t		ip6_un1_hlim; /* hop limit */
                } ip6_un1;
                uint8_t	ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
        } ip6_ctlun;
        ip6_addr_t	ip6_src;
        ip6_addr_t	ip6_dst;
} __attribute__((__packed__));

#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt	/* IP_PROTO_* */
#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim

#define IP6_VERSION		0x60
#define IP6_VERSION_MASK	0xf0		/* ip6_vfc version */

#if DNET_BYTESEX == DNET_BIG_ENDIAN
#define IP6_FLOWINFO_MASK	0x0fffffff	/* ip6_flow info (28 bits) */
#define IP6_FLOWLABEL_MASK	0x000fffff	/* ip6_flow label (20 bits) */
#elif DNET_BYTESEX == DNET_LIL_ENDIAN
#define IP6_FLOWINFO_MASK	0xffffff0f	/* ip6_flow info (28 bits) */
#define IP6_FLOWLABEL_MASK	0xffff0f00	/* ip6_flow label (20 bits) */
#endif

/*
 * Hop limit (ip6_hlim)
 */
#define IP6_HLIM_DEFAULT	64
#define IP6_HLIM_MAX		255

/*
 * Preferred extension header order from RFC 2460, 4.1:
 *
 * IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING,
 * IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS, IP_PROTO_*
 */

/*
 * Routing header data (IP_PROTO_ROUTING)
 */
struct ip6_ext_data_routing {
        uint8_t  type;			/* routing type */
        uint8_t  segleft;		/* segments left */
        /* followed by routing type specific data */
} __attribute__((__packed__));

struct ip6_ext_data_routing0 {
        uint8_t  type;			/* always zero */
        uint8_t  segleft;		/* segments left */
        uint8_t  reserved;		/* reserved field */
        uint8_t  slmap[3];		/* strict/loose bit map */
        ip6_addr_t  addr[1];		/* up to 23 addresses */
} __attribute__((__packed__));

/*
 * Fragment header data (IP_PROTO_FRAGMENT)
 */
struct ip6_ext_data_fragment {
        uint16_t  offlg;		/* offset, reserved, and flag */
        uint32_t  ident;		/* identification */
} __attribute__((__packed__));

/*
 * Fragmentation offset, reserved, and flags (offlg)
 */
#if DNET_BYTESEX == DNET_BIG_ENDIAN
#define IP6_OFF_MASK		0xfff8	/* mask out offset from offlg */
#define IP6_RESERVED_MASK	0x0006	/* reserved bits in offlg */
#define IP6_MORE_FRAG		0x0001	/* more-fragments flag */
#elif DNET_BYTESEX == DNET_LIL_ENDIAN
#define IP6_OFF_MASK		0xf8ff	/* mask out offset from offlg */
#define IP6_RESERVED_MASK	0x0600	/* reserved bits in offlg */
#define IP6_MORE_FRAG		0x0100	/* more-fragments flag */
#endif

/*
 * Option types, for IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS headers
 */
#define IP6_OPT_PAD1		0x00	/* 00 0 00000 */
#define IP6_OPT_PADN		0x01	/* 00 0 00001 */
#define IP6_OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
#define IP6_OPT_JUMBO_LEN	6
#define IP6_OPT_RTALERT		0x05	/* 00 0 00101 */
#define IP6_OPT_RTALERT_LEN	4
#define IP6_OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
#define IP6_OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
#define IP6_OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
#define IP6_OPT_LEN_MIN		2

#define IP6_OPT_TYPE(o)		((o) & 0xC0)	/* high 2 bits of opt_type */
#define IP6_OPT_TYPE_SKIP	0x00	/* continue processing on failure */
#define IP6_OPT_TYPE_DISCARD	0x40	/* discard packet on failure */
#define IP6_OPT_TYPE_FORCEICMP	0x80	/* discard and send ICMP on failure */
#define IP6_OPT_TYPE_ICMP	0xC0	/* ...only if non-multicast dst */

#define IP6_OPT_MUTABLE		0x20	/* option data may change en route */

/*
 * Extension header (chained via {ip6,ext}_nxt, following IPv6 header)
 */
struct ip6_ext_hdr {
        uint8_t  ext_nxt;	/* next header */
        uint8_t  ext_len;	/* following length in units of 8 octets */
        union {
                struct ip6_ext_data_routing	routing;
                struct ip6_ext_data_fragment	fragment;
        } ext_data;
} __attribute__((__packed__));

#ifndef __GNUC__
# pragma pack()
#endif

/*
 * Reserved addresses
 */
#define IP6_ADDR_UNSPEC	\
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
#define IP6_ADDR_LOOPBACK \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"

#define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do {	\
        struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr);			\
        ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) &			\
            (IP6_FLOWLABEL_MASK | (fl)));				\
        ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4));			\
        ip6->ip6_plen = htons((plen));					\
        ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim);			\
        memmove(&ip6->ip6_src, &(src), IP6_ADDR_LEN);			\
        memmove(&ip6->ip6_dst, &(dst), IP6_ADDR_LEN);			\
} while (0);

__BEGIN_DECLS
char	*ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t size);
int	 ip6_pton(const char *src, ip6_addr_t *dst);
char	*ip6_ntoa(const ip6_addr_t *ip6);
#define	 ip6_aton ip6_pton

void	 ip6_checksum(void *buf, size_t len);
__END_DECLS

#endif /* DNET_IP6_H */