[ipv6] Create routing table based on IPv6 settings
[ipxe.git] / src / include / ipxe / ipv6.h
1 #ifndef _IPXE_IPV6_H
2 #define _IPXE_IPV6_H
3
4 /** @file
5 *
6 * IPv6 protocol
7 *
8 */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stdint.h>
13 #include <string.h>
14 #include <byteswap.h>
15 #include <ipxe/in.h>
16 #include <ipxe/list.h>
17 #include <ipxe/netdevice.h>
18
19 /** IPv6 version */
20 #define IPV6_VER 0x60000000UL
21
22 /** IPv6 version mask */
23 #define IPV6_MASK_VER 0xf0000000UL
24
25 /** IPv6 maximum hop limit */
26 #define IPV6_HOP_LIMIT 0xff
27
28 /** IPv6 default prefix length */
29 #define IPV6_DEFAULT_PREFIX_LEN 64
30
31 /** IPv6 maximum prefix length */
32 #define IPV6_MAX_PREFIX_LEN 128
33
34 /** IPv6 header */
35 struct ipv6_header {
36 /** Version (4 bits), Traffic class (8 bits), Flow label (20 bits) */
37 uint32_t ver_tc_label;
38 /** Payload length, including any extension headers */
39 uint16_t len;
40 /** Next header type */
41 uint8_t next_header;
42 /** Hop limit */
43 uint8_t hop_limit;
44 /** Source address */
45 struct in6_addr src;
46 /** Destination address */
47 struct in6_addr dest;
48 } __attribute__ (( packed ));
49
50 /** IPv6 extension header common fields */
51 struct ipv6_extension_header_common {
52 /** Next header type */
53 uint8_t next_header;
54 /** Header extension length (excluding first 8 bytes) */
55 uint8_t len;
56 } __attribute__ (( packed ));
57
58 /** IPv6 type-length-value options */
59 struct ipv6_option {
60 /** Type */
61 uint8_t type;
62 /** Length */
63 uint8_t len;
64 /** Value */
65 uint8_t value[0];
66 } __attribute__ (( packed ));
67
68 /** IPv6 option types */
69 enum ipv6_option_type {
70 /** Pad1 */
71 IPV6_OPT_PAD1 = 0x00,
72 /** PadN */
73 IPV6_OPT_PADN = 0x01,
74 };
75
76 /** Test if IPv6 option can be safely ignored */
77 #define IPV6_CAN_IGNORE_OPT( type ) ( ( (type) & 0xc0 ) == 0x00 )
78
79 /** IPv6 option-based extension header */
80 struct ipv6_options_header {
81 /** Extension header common fields */
82 struct ipv6_extension_header_common common;
83 /** Options */
84 struct ipv6_option options[0];
85 } __attribute__ (( packed ));
86
87 /** IPv6 routing header */
88 struct ipv6_routing_header {
89 /** Extension header common fields */
90 struct ipv6_extension_header_common common;
91 /** Routing type */
92 uint8_t type;
93 /** Segments left */
94 uint8_t remaining;
95 /** Type-specific data */
96 uint8_t data[0];
97 } __attribute__ (( packed ));
98
99 /** IPv6 fragment header */
100 struct ipv6_fragment_header {
101 /** Extension header common fields */
102 struct ipv6_extension_header_common common;
103 /** Fragment offset (13 bits), reserved, more fragments (1 bit) */
104 uint16_t offset_more;
105 /** Identification */
106 uint32_t ident;
107 } __attribute__ (( packed ));
108
109 /** Fragment offset mask */
110 #define IPV6_MASK_OFFSET 0xfff8
111
112 /** More fragments */
113 #define IPV6_MASK_MOREFRAGS 0x0001
114
115 /** IPv6 extension header */
116 union ipv6_extension_header {
117 /** Extension header common fields */
118 struct ipv6_extension_header_common common;
119 /** Minimum size padding */
120 uint8_t pad[8];
121 /** Generic options header */
122 struct ipv6_options_header options;
123 /** Hop-by-hop options header */
124 struct ipv6_options_header hopbyhop;
125 /** Routing header */
126 struct ipv6_routing_header routing;
127 /** Fragment header */
128 struct ipv6_fragment_header fragment;
129 /** Destination options header */
130 struct ipv6_options_header destination;
131 };
132
133 /** IPv6 header types */
134 enum ipv6_header_type {
135 /** IPv6 hop-by-hop options header type */
136 IPV6_HOPBYHOP = 0,
137 /** IPv6 routing header type */
138 IPV6_ROUTING = 43,
139 /** IPv6 fragment header type */
140 IPV6_FRAGMENT = 44,
141 /** IPv6 no next header type */
142 IPV6_NO_HEADER = 59,
143 /** IPv6 destination options header type */
144 IPV6_DESTINATION = 60,
145 };
146
147 /** IPv6 pseudo-header */
148 struct ipv6_pseudo_header {
149 /** Source address */
150 struct in6_addr src;
151 /** Destination address */
152 struct in6_addr dest;
153 /** Upper-layer packet length */
154 uint32_t len;
155 /** Zero padding */
156 uint8_t zero[3];
157 /** Next header */
158 uint8_t next_header;
159 } __attribute__ (( packed ));
160
161 /** An IPv6 address/routing table entry */
162 struct ipv6_miniroute {
163 /** List of miniroutes */
164 struct list_head list;
165
166 /** Network device */
167 struct net_device *netdev;
168
169 /** IPv6 address (or prefix if no address is defined) */
170 struct in6_addr address;
171 /** Prefix length */
172 unsigned int prefix_len;
173 /** IPv6 prefix mask (derived from prefix length) */
174 struct in6_addr prefix_mask;
175 /** Router address */
176 struct in6_addr router;
177 /** Flags */
178 unsigned int flags;
179 };
180
181 /** IPv6 address/routing table entry flags */
182 enum ipv6_miniroute_flags {
183 /** Routing table entry address is valid */
184 IPV6_HAS_ADDRESS = 0x0001,
185 /** Routing table entry router address is valid */
186 IPV6_HAS_ROUTER = 0x0002,
187 };
188
189 /**
190 * Construct local IPv6 address via EUI-64
191 *
192 * @v addr Prefix to be completed
193 * @v netdev Network device
194 * @ret prefix_len Prefix length, or negative error
195 */
196 static inline int ipv6_eui64 ( struct in6_addr *addr,
197 struct net_device *netdev ) {
198 struct ll_protocol *ll_protocol = netdev->ll_protocol;
199 const void *ll_addr = netdev->ll_addr;
200 int rc;
201
202 if ( ( rc = ll_protocol->eui64 ( ll_addr, &addr->s6_addr[8] ) ) != 0 )
203 return rc;
204 addr->s6_addr[8] ^= 0x02;
205 return 64;
206 }
207
208 /**
209 * Construct link-local address via EUI-64
210 *
211 * @v addr Zeroed address to construct
212 * @v netdev Network device
213 * @ret prefix_len Prefix length, or negative error
214 */
215 static inline int ipv6_link_local ( struct in6_addr *addr,
216 struct net_device *netdev ) {
217
218 addr->s6_addr16[0] = htons ( 0xfe80 );
219 return ipv6_eui64 ( addr, netdev );
220 }
221
222 /**
223 * Construct solicited-node multicast address
224 *
225 * @v addr Zeroed address to construct
226 * @v unicast Unicast address
227 */
228 static inline void ipv6_solicited_node ( struct in6_addr *addr,
229 const struct in6_addr *unicast ) {
230
231 addr->s6_addr16[0] = htons ( 0xff02 );
232 addr->s6_addr[11] = 1;
233 addr->s6_addr[12] = 0xff;
234 memcpy ( &addr->s6_addr[13], &unicast->s6_addr[13], 3 );
235 }
236
237 /**
238 * Construct all-routers multicast address
239 *
240 * @v addr Zeroed address to construct
241 */
242 static inline void ipv6_all_routers ( struct in6_addr *addr ) {
243 addr->s6_addr16[0] = htons ( 0xff02 );
244 addr->s6_addr[15] = 2;
245 }
246
247 /** IPv6 settings sibling order */
248 enum ipv6_settings_order {
249 /** No address */
250 IPV6_ORDER_PREFIX_ONLY = -4,
251 /** Link-local address */
252 IPV6_ORDER_LINK_LOCAL = -3,
253 /** Address assigned via SLAAC */
254 IPV6_ORDER_SLAAC = -2,
255 /** Address assigned via DHCPv6 */
256 IPV6_ORDER_DHCPV6 = -1,
257 };
258
259 /** IPv6 link-local address settings block name */
260 #define IPV6_SETTINGS_NAME "link"
261
262 extern struct list_head ipv6_miniroutes;
263
264 extern struct net_protocol ipv6_protocol __net_protocol;
265
266 extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
267 extern int parse_ipv6_setting ( const struct setting_type *type,
268 const char *value, void *buf, size_t len );
269 extern int format_ipv6_setting ( const struct setting_type *type,
270 const void *raw, size_t raw_len, char *buf,
271 size_t len );
272
273 #endif /* _IPXE_IPV6_H */