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 /** IPv6 address scopes */
162 enum ipv6_address_scope {
163 /** Interface-local address scope */
164 IPV6_SCOPE_INTERFACE_LOCAL = 0x1,
165 /** Link-local address scope */
166 IPV6_SCOPE_LINK_LOCAL = 0x2,
167 /** Admin-local address scope */
168 INV6_SCOPE_ADMIN_LOCAL = 0x4,
169 /** Site-local address scope */
170 IPV6_SCOPE_SITE_LOCAL = 0x5,
171 /** Organisation-local address scope */
172 IPV6_SCOPE_ORGANISATION_LOCAL = 0x8,
173 /** Global address scope */
174 IPV6_SCOPE_GLOBAL = 0xe,
175 /** Maximum scope */
176 IPV6_SCOPE_MAX = 0xf,
177 };
178
179 /** An IPv6 address/routing table entry */
180 struct ipv6_miniroute {
181 /** List of miniroutes */
182 struct list_head list;
183
184 /** Network device */
185 struct net_device *netdev;
186
187 /** IPv6 address (or prefix if no address is defined) */
188 struct in6_addr address;
189 /** Prefix length */
190 unsigned int prefix_len;
191 /** IPv6 prefix mask (derived from prefix length) */
192 struct in6_addr prefix_mask;
193 /** Router address */
194 struct in6_addr router;
195 /** Scope */
196 unsigned int scope;
197 /** Flags */
198 unsigned int flags;
199 };
200
201 /** IPv6 address/routing table entry flags */
202 enum ipv6_miniroute_flags {
203 /** Routing table entry address is valid */
204 IPV6_HAS_ADDRESS = 0x0001,
205 /** Routing table entry router address is valid */
206 IPV6_HAS_ROUTER = 0x0002,
207 };
208
209 /**
210 * Construct local IPv6 address via EUI-64
211 *
212 * @v addr Prefix to be completed
213 * @v netdev Network device
214 * @ret prefix_len Prefix length, or negative error
215 */
ipv6_eui64(struct in6_addr * addr,struct net_device * netdev)216 static inline int ipv6_eui64 ( struct in6_addr *addr,
217 struct net_device *netdev ) {
218 struct ll_protocol *ll_protocol = netdev->ll_protocol;
219 const void *ll_addr = netdev->ll_addr;
220 int rc;
221
222 if ( ( rc = ll_protocol->eui64 ( ll_addr, &addr->s6_addr[8] ) ) != 0 )
223 return rc;
224 addr->s6_addr[8] ^= 0x02;
225 return 64;
226 }
227
228 /**
229 * Construct link-local address via EUI-64
230 *
231 * @v addr Zeroed address to construct
232 * @v netdev Network device
233 * @ret prefix_len Prefix length, or negative error
234 */
ipv6_link_local(struct in6_addr * addr,struct net_device * netdev)235 static inline int ipv6_link_local ( struct in6_addr *addr,
236 struct net_device *netdev ) {
237
238 addr->s6_addr16[0] = htons ( 0xfe80 );
239 return ipv6_eui64 ( addr, netdev );
240 }
241
242 /**
243 * Construct solicited-node multicast address
244 *
245 * @v addr Zeroed address to construct
246 * @v unicast Unicast address
247 */
ipv6_solicited_node(struct in6_addr * addr,const struct in6_addr * unicast)248 static inline void ipv6_solicited_node ( struct in6_addr *addr,
249 const struct in6_addr *unicast ) {
250
251 addr->s6_addr16[0] = htons ( 0xff02 );
252 addr->s6_addr[11] = 1;
253 addr->s6_addr[12] = 0xff;
254 memcpy ( &addr->s6_addr[13], &unicast->s6_addr[13], 3 );
255 }
256
257 /**
258 * Construct all-routers multicast address
259 *
260 * @v addr Zeroed address to construct
261 */
ipv6_all_routers(struct in6_addr * addr)262 static inline void ipv6_all_routers ( struct in6_addr *addr ) {
263 addr->s6_addr16[0] = htons ( 0xff02 );
264 addr->s6_addr[15] = 2;
265 }
266
267 /**
268 * Get multicast address scope
269 *
270 * @v addr Multicast address
271 * @ret scope Address scope
272 */
273 static inline unsigned int
ipv6_multicast_scope(const struct in6_addr * addr)274 ipv6_multicast_scope ( const struct in6_addr *addr ) {
275
276 return ( addr->s6_addr[1] & 0x0f );
277 }
278
279 /** IPv6 settings sibling order */
280 enum ipv6_settings_order {
281 /** No address */
282 IPV6_ORDER_PREFIX_ONLY = -4,
283 /** Link-local address */
284 IPV6_ORDER_LINK_LOCAL = -3,
285 /** Address assigned via SLAAC */
286 IPV6_ORDER_SLAAC = -2,
287 /** Address assigned via DHCPv6 */
288 IPV6_ORDER_DHCPV6 = -1,
289 };
290
291 /** IPv6 link-local address settings block name */
292 #define IPV6_SETTINGS_NAME "link"
293
294 extern struct list_head ipv6_miniroutes;
295
296 extern struct net_protocol ipv6_protocol __net_protocol;
297
298 extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
299 extern int ipv6_add_miniroute ( struct net_device *netdev,
300 struct in6_addr *address,
301 unsigned int prefix_len,
302 struct in6_addr *router );
303 extern void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute );
304 extern struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
305 struct in6_addr **dest );
306 extern int parse_ipv6_setting ( const struct setting_type *type,
307 const char *value, void *buf, size_t len );
308 extern int format_ipv6_setting ( const struct setting_type *type,
309 const void *raw, size_t raw_len, char *buf,
310 size_t len );
311
312 #endif /* _IPXE_IPV6_H */
313