iPXE
ipv6.h
Go to the documentation of this file.
00001 #ifndef _IPXE_IPV6_H
00002 #define _IPXE_IPV6_H
00003 
00004 /** @file
00005  *
00006  * IPv6 protocol
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <stdint.h>
00013 #include <string.h>
00014 #include <byteswap.h>
00015 #include <ipxe/in.h>
00016 #include <ipxe/list.h>
00017 #include <ipxe/netdevice.h>
00018 
00019 /** IPv6 version */
00020 #define IPV6_VER 0x60000000UL
00021 
00022 /** IPv6 version mask */
00023 #define IPV6_MASK_VER 0xf0000000UL
00024 
00025 /** IPv6 maximum hop limit */
00026 #define IPV6_HOP_LIMIT 0xff
00027 
00028 /** IPv6 default prefix length */
00029 #define IPV6_DEFAULT_PREFIX_LEN 64
00030 
00031 /** IPv6 maximum prefix length */
00032 #define IPV6_MAX_PREFIX_LEN 128
00033 
00034 /** IPv6 header */
00035 struct ipv6_header {
00036         /** Version (4 bits), Traffic class (8 bits), Flow label (20 bits) */
00037         uint32_t ver_tc_label;
00038         /** Payload length, including any extension headers */
00039         uint16_t len;
00040         /** Next header type */
00041         uint8_t next_header;
00042         /** Hop limit */
00043         uint8_t hop_limit;
00044         /** Source address */
00045         struct in6_addr src;
00046         /** Destination address */
00047         struct in6_addr dest;
00048 } __attribute__ (( packed ));
00049 
00050 /** IPv6 extension header common fields */
00051 struct ipv6_extension_header_common {
00052         /** Next header type */
00053         uint8_t next_header;
00054         /** Header extension length (excluding first 8 bytes) */
00055         uint8_t len;
00056 } __attribute__ (( packed ));
00057 
00058 /** IPv6 type-length-value options */
00059 struct ipv6_option {
00060         /** Type */
00061         uint8_t type;
00062         /** Length */
00063         uint8_t len;
00064         /** Value */
00065         uint8_t value[0];
00066 } __attribute__ (( packed ));
00067 
00068 /** IPv6 option types */
00069 enum ipv6_option_type {
00070         /** Pad1 */
00071         IPV6_OPT_PAD1 = 0x00,
00072         /** PadN */
00073         IPV6_OPT_PADN = 0x01,
00074 };
00075 
00076 /** Test if IPv6 option can be safely ignored */
00077 #define IPV6_CAN_IGNORE_OPT( type ) ( ( (type) & 0xc0 ) == 0x00 )
00078 
00079 /** IPv6 option-based extension header */
00080 struct ipv6_options_header {
00081         /** Extension header common fields */
00082         struct ipv6_extension_header_common common;
00083         /** Options */
00084         struct ipv6_option options[0];
00085 } __attribute__ (( packed ));
00086 
00087 /** IPv6 routing header */
00088 struct ipv6_routing_header {
00089         /** Extension header common fields */
00090         struct ipv6_extension_header_common common;
00091         /** Routing type */
00092         uint8_t type;
00093         /** Segments left */
00094         uint8_t remaining;
00095         /** Type-specific data */
00096         uint8_t data[0];
00097 } __attribute__ (( packed ));
00098 
00099 /** IPv6 fragment header */
00100 struct ipv6_fragment_header {
00101         /** Extension header common fields */
00102         struct ipv6_extension_header_common common;
00103         /** Fragment offset (13 bits), reserved, more fragments (1 bit) */
00104         uint16_t offset_more;
00105         /** Identification */
00106         uint32_t ident;
00107 } __attribute__ (( packed ));
00108 
00109 /** Fragment offset mask */
00110 #define IPV6_MASK_OFFSET 0xfff8
00111 
00112 /** More fragments */
00113 #define IPV6_MASK_MOREFRAGS 0x0001
00114 
00115 /** IPv6 extension header */
00116 union ipv6_extension_header {
00117         /** Extension header common fields */
00118         struct ipv6_extension_header_common common;
00119         /** Minimum size padding */
00120         uint8_t pad[8];
00121         /** Generic options header */
00122         struct ipv6_options_header options;
00123         /** Hop-by-hop options header */
00124         struct ipv6_options_header hopbyhop;
00125         /** Routing header */
00126         struct ipv6_routing_header routing;
00127         /** Fragment header */
00128         struct ipv6_fragment_header fragment;
00129         /** Destination options header */
00130         struct ipv6_options_header destination;
00131 };
00132 
00133 /** IPv6 header types */
00134 enum ipv6_header_type {
00135         /** IPv6 hop-by-hop options header type */
00136         IPV6_HOPBYHOP = 0,
00137         /** IPv6 routing header type */
00138         IPV6_ROUTING = 43,
00139         /** IPv6 fragment header type */
00140         IPV6_FRAGMENT = 44,
00141         /** IPv6 no next header type */
00142         IPV6_NO_HEADER = 59,
00143         /** IPv6 destination options header type */
00144         IPV6_DESTINATION = 60,
00145 };
00146 
00147 /** IPv6 pseudo-header */
00148 struct ipv6_pseudo_header {
00149         /** Source address */
00150         struct in6_addr src;
00151         /** Destination address */
00152         struct in6_addr dest;
00153         /** Upper-layer packet length */
00154         uint32_t len;
00155         /** Zero padding */
00156         uint8_t zero[3];
00157         /** Next header */
00158         uint8_t next_header;
00159 } __attribute__ (( packed ));
00160 
00161 /** IPv6 address scopes */
00162 enum ipv6_address_scope {
00163         /** Interface-local address scope */
00164         IPV6_SCOPE_INTERFACE_LOCAL = 0x1,
00165         /** Link-local address scope */
00166         IPV6_SCOPE_LINK_LOCAL = 0x2,
00167         /** Admin-local address scope */
00168         INV6_SCOPE_ADMIN_LOCAL = 0x4,
00169         /** Site-local address scope */
00170         IPV6_SCOPE_SITE_LOCAL = 0x5,
00171         /** Organisation-local address scope */
00172         IPV6_SCOPE_ORGANISATION_LOCAL = 0x8,
00173         /** Global address scope */
00174         IPV6_SCOPE_GLOBAL = 0xe,
00175         /** Maximum scope */
00176         IPV6_SCOPE_MAX = 0xf,
00177 };
00178 
00179 /** An IPv6 address/routing table entry */
00180 struct ipv6_miniroute {
00181         /** List of miniroutes */
00182         struct list_head list;
00183 
00184         /** Network device */
00185         struct net_device *netdev;
00186 
00187         /** IPv6 address (or prefix if no address is defined) */
00188         struct in6_addr address;
00189         /** Prefix length */
00190         unsigned int prefix_len;
00191         /** IPv6 prefix mask (derived from prefix length) */
00192         struct in6_addr prefix_mask;
00193         /** Router address */
00194         struct in6_addr router;
00195         /** Scope */
00196         unsigned int scope;
00197         /** Flags */
00198         unsigned int flags;
00199 };
00200 
00201 /** IPv6 address/routing table entry flags */
00202 enum ipv6_miniroute_flags {
00203         /** Routing table entry address is valid */
00204         IPV6_HAS_ADDRESS = 0x0001,
00205         /** Routing table entry router address is valid */
00206         IPV6_HAS_ROUTER = 0x0002,
00207 };
00208 
00209 /**
00210  * Construct local IPv6 address via EUI-64
00211  *
00212  * @v addr              Prefix to be completed
00213  * @v netdev            Network device
00214  * @ret prefix_len      Prefix length, or negative error
00215  */
00216 static inline int ipv6_eui64 ( struct in6_addr *addr,
00217                                struct net_device *netdev ) {
00218         struct ll_protocol *ll_protocol = netdev->ll_protocol;
00219         const void *ll_addr = netdev->ll_addr;
00220         int rc;
00221 
00222         if ( ( rc = ll_protocol->eui64 ( ll_addr, &addr->s6_addr[8] ) ) != 0 )
00223                 return rc;
00224         addr->s6_addr[8] ^= 0x02;
00225         return 64;
00226 }
00227 
00228 /**
00229  * Construct link-local address via EUI-64
00230  *
00231  * @v addr              Zeroed address to construct
00232  * @v netdev            Network device
00233  * @ret prefix_len      Prefix length, or negative error
00234  */
00235 static inline int ipv6_link_local ( struct in6_addr *addr,
00236                                     struct net_device *netdev ) {
00237 
00238         addr->s6_addr16[0] = htons ( 0xfe80 );
00239         return ipv6_eui64 ( addr, netdev );
00240 }
00241 
00242 /**
00243  * Construct solicited-node multicast address
00244  *
00245  * @v addr              Zeroed address to construct
00246  * @v unicast           Unicast address
00247  */
00248 static inline void ipv6_solicited_node ( struct in6_addr *addr,
00249                                          const struct in6_addr *unicast ) {
00250 
00251         addr->s6_addr16[0] = htons ( 0xff02 );
00252         addr->s6_addr[11] = 1;
00253         addr->s6_addr[12] = 0xff;
00254         memcpy ( &addr->s6_addr[13], &unicast->s6_addr[13], 3 );
00255 }
00256 
00257 /**
00258  * Construct all-routers multicast address
00259  *
00260  * @v addr              Zeroed address to construct
00261  */
00262 static inline void ipv6_all_routers ( struct in6_addr *addr ) {
00263         addr->s6_addr16[0] = htons ( 0xff02 );
00264         addr->s6_addr[15] = 2;
00265 }
00266 
00267 /**
00268  * Get multicast address scope
00269  *
00270  * @v addr              Multicast address
00271  * @ret scope           Address scope
00272  */
00273 static inline unsigned int
00274 ipv6_multicast_scope ( const struct in6_addr *addr ) {
00275 
00276         return ( addr->s6_addr[1] & 0x0f );
00277 }
00278 
00279 /** IPv6 settings sibling order */
00280 enum ipv6_settings_order {
00281         /** No address */
00282         IPV6_ORDER_PREFIX_ONLY = -4,
00283         /** Link-local address */
00284         IPV6_ORDER_LINK_LOCAL = -3,
00285         /** Address assigned via SLAAC */
00286         IPV6_ORDER_SLAAC = -2,
00287         /** Address assigned via DHCPv6 */
00288         IPV6_ORDER_DHCPV6 = -1,
00289 };
00290 
00291 /** IPv6 link-local address settings block name */
00292 #define IPV6_SETTINGS_NAME "link"
00293 
00294 extern struct list_head ipv6_miniroutes;
00295 
00296 extern struct net_protocol ipv6_protocol __net_protocol;
00297 
00298 extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
00299 extern int ipv6_add_miniroute ( struct net_device *netdev,
00300                                 struct in6_addr *address,
00301                                 unsigned int prefix_len,
00302                                 struct in6_addr *router );
00303 extern void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute );
00304 extern struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
00305                                             struct in6_addr **dest );
00306 extern int parse_ipv6_setting ( const struct setting_type *type,
00307                                 const char *value, void *buf, size_t len );
00308 extern int format_ipv6_setting ( const struct setting_type *type,
00309                                  const void *raw, size_t raw_len, char *buf,
00310                                  size_t len );
00311 
00312 #endif /* _IPXE_IPV6_H */