diff options
author | Michael Brown <mcb30@ipxe.org> | 2013-08-26 14:23:54 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2013-09-03 16:30:46 +0100 |
commit | f7f3087cc542d76f19ba6362b0837dcf1baf86b8 (patch) | |
tree | 8d2a920c16a2255f9e9ac57d2b333d8d01edc556 /src/include/ipxe/ipv6.h | |
parent | 43307b4e39300f6602a975bbb710b443e5fcd2b5 (diff) | |
download | ipxe-f7f3087cc542d76f19ba6362b0837dcf1baf86b8.zip ipxe-f7f3087cc542d76f19ba6362b0837dcf1baf86b8.tar.gz ipxe-f7f3087cc542d76f19ba6362b0837dcf1baf86b8.tar.bz2 |
[ipv6] Replace IPv6 stack
Replace the existing partially-implemented IPv6 stack with a fresh
implementation.
This implementation is not yet complete. The IPv6 transmit and
receive datapaths are functional (including fragment reassembly and
parsing of arbitrary extension headers). NDP neighbour solicitations
and advertisements are supported. ICMPv6 echo is supported.
At present, only link-local addresses may be used, and there is no way
to specify an IPv6 address as part of a URI (either directly or via
a DNS lookup).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/ipxe/ipv6.h')
-rw-r--r-- | src/include/ipxe/ipv6.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/include/ipxe/ipv6.h b/src/include/ipxe/ipv6.h new file mode 100644 index 0000000..f404ba6 --- /dev/null +++ b/src/include/ipxe/ipv6.h @@ -0,0 +1,218 @@ +#ifndef _IPXE_IPV6_H +#define _IPXE_IPV6_H + +/** @file + * + * IPv6 protocol + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <string.h> +#include <byteswap.h> +#include <ipxe/in.h> +#include <ipxe/list.h> +#include <ipxe/netdevice.h> + +/** IPv6 version */ +#define IPV6_VER 0x60000000UL + +/** IPv6 version mask */ +#define IPV6_MASK_VER 0xf0000000UL + +/** IPv6 maximum hop limit */ +#define IPV6_HOP_LIMIT 0xff + +/** IPv6 header */ +struct ipv6_header { + /** Version (4 bits), Traffic class (8 bits), Flow label (20 bits) */ + uint32_t ver_tc_label; + /** Payload length, including any extension headers */ + uint16_t len; + /** Next header type */ + uint8_t next_header; + /** Hop limit */ + uint8_t hop_limit; + /** Source address */ + struct in6_addr src; + /** Destination address */ + struct in6_addr dest; +} __attribute__ (( packed )); + +/** IPv6 extension header common fields */ +struct ipv6_extension_header_common { + /** Next header type */ + uint8_t next_header; + /** Header extension length (excluding first 8 bytes) */ + uint8_t len; +} __attribute__ (( packed )); + +/** IPv6 type-length-value options */ +struct ipv6_option { + /** Type */ + uint8_t type; + /** Length */ + uint8_t len; + /** Value */ + uint8_t value[0]; +} __attribute__ (( packed )); + +/** IPv6 option types */ +enum ipv6_option_type { + /** Pad1 */ + IPV6_OPT_PAD1 = 0x00, + /** PadN */ + IPV6_OPT_PADN = 0x01, +}; + +/** Test if IPv6 option can be safely ignored */ +#define IPV6_CAN_IGNORE_OPT( type ) ( ( (type) & 0xc0 ) == 0x00 ) + +/** IPv6 option-based extension header */ +struct ipv6_options_header { + /** Extension header common fields */ + struct ipv6_extension_header_common common; + /** Options */ + struct ipv6_option options[0]; +} __attribute__ (( packed )); + +/** IPv6 routing header */ +struct ipv6_routing_header { + /** Extension header common fields */ + struct ipv6_extension_header_common common; + /** Routing type */ + uint8_t type; + /** Segments left */ + uint8_t remaining; + /** Type-specific data */ + uint8_t data[0]; +} __attribute__ (( packed )); + +/** IPv6 fragment header */ +struct ipv6_fragment_header { + /** Extension header common fields */ + struct ipv6_extension_header_common common; + /** Fragment offset (13 bits), reserved, more fragments (1 bit) */ + uint16_t offset_more; + /** Identification */ + uint32_t ident; +} __attribute__ (( packed )); + +/** Fragment offset mask */ +#define IPV6_MASK_OFFSET 0xfff8 + +/** More fragments */ +#define IPV6_MASK_MOREFRAGS 0x0001 + +/** IPv6 extension header */ +union ipv6_extension_header { + /** Extension header common fields */ + struct ipv6_extension_header_common common; + /** Minimum size padding */ + uint8_t pad[8]; + /** Generic options header */ + struct ipv6_options_header options; + /** Hop-by-hop options header */ + struct ipv6_options_header hopbyhop; + /** Routing header */ + struct ipv6_routing_header routing; + /** Fragment header */ + struct ipv6_fragment_header fragment; + /** Destination options header */ + struct ipv6_options_header destination; +}; + +/** IPv6 header types */ +enum ipv6_header_type { + /** IPv6 hop-by-hop options header type */ + IPV6_HOPBYHOP = 0, + /** IPv6 routing header type */ + IPV6_ROUTING = 43, + /** IPv6 fragment header type */ + IPV6_FRAGMENT = 44, + /** IPv6 no next header type */ + IPV6_NO_HEADER = 59, + /** IPv6 destination options header type */ + IPV6_DESTINATION = 60, +}; + +/** IPv6 pseudo-header */ +struct ipv6_pseudo_header { + /** Source address */ + struct in6_addr src; + /** Destination address */ + struct in6_addr dest; + /** Upper-layer packet length */ + uint32_t len; + /** Zero padding */ + uint8_t zero[3]; + /** Next header */ + uint8_t next_header; +} __attribute__ (( packed )); + +/** An IPv6 address/routing table entry */ +struct ipv6_miniroute { + /** List of miniroutes */ + struct list_head list; + + /** Network device */ + struct net_device *netdev; + + /** IPv6 address */ + struct in6_addr address; + /** Prefix length */ + unsigned int prefix_len; + /** IPv6 prefix mask (derived from prefix length) */ + struct in6_addr prefix_mask; + /** Router address is present */ + int has_router; + /** Router address */ + struct in6_addr router; +}; + +/** + * Construct link-local address (via EUI-64) + * + * @v addr Address to construct + * @v netdev Network device + * @ret prefix_len Prefix length, or negative error + */ +static inline int ipv6_link_local ( struct in6_addr *addr, + struct net_device *netdev ) { + struct ll_protocol *ll_protocol = netdev->ll_protocol; + const void *ll_addr = netdev->ll_addr; + int rc; + + memset ( addr, 0, sizeof ( *addr ) ); + addr->s6_addr16[0] = htons ( 0xfe80 ); + if ( ( rc = ll_protocol->eui64 ( ll_addr, &addr->s6_addr[8] ) ) != 0 ) + return rc; + addr->s6_addr[8] ^= 0x02; + return 64; +} + +/** + * Construct solicited-node multicast address + * + * @v addr Address to construct + * @v unicast Unicast address + */ +static inline void ipv6_solicited_node ( struct in6_addr *addr, + const struct in6_addr *unicast ) { + + memset ( addr, 0, sizeof ( *addr ) ); + addr->s6_addr16[0] = htons ( 0xff02 ); + addr->s6_addr[11] = 1; + addr->s6_addr[12] = 0xff; + memcpy ( &addr->s6_addr[13], &unicast->s6_addr[13], 3 ); +} + +extern struct list_head ipv6_miniroutes; + +extern struct net_protocol ipv6_protocol __net_protocol; + +extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr ); + +#endif /* _IPXE_IPV6_H */ |