diff options
Diffstat (limited to 'src/include/ipxe')
| -rw-r--r-- | src/include/ipxe/icmp6.h | 59 | ||||
| -rw-r--r-- | src/include/ipxe/icmpv6.h | 78 | ||||
| -rw-r--r-- | src/include/ipxe/in.h | 31 | ||||
| -rw-r--r-- | src/include/ipxe/ip6.h | 80 | ||||
| -rw-r--r-- | src/include/ipxe/ipv6.h | 218 | ||||
| -rw-r--r-- | src/include/ipxe/ndp.h | 97 |
6 files changed, 391 insertions, 172 deletions
diff --git a/src/include/ipxe/icmp6.h b/src/include/ipxe/icmp6.h deleted file mode 100644 index 1d433408d..000000000 --- a/src/include/ipxe/icmp6.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _IPXE_ICMP6_H -#define _IPXE_ICMP6_H - -/** @file - * - * ICMP6 protocol - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <ipxe/ip6.h> -#include <ipxe/ndp.h> - -#define ICMP6_NSOLICIT 135 -#define ICMP6_NADVERT 136 - -extern struct tcpip_protocol icmp6_protocol __tcpip_protocol; - -struct icmp6_header { - uint8_t type; - uint8_t code; - uint16_t csum; - /* Message body */ -}; - -struct neighbour_solicit { - uint8_t type; - uint8_t code; - uint16_t csum; - uint32_t reserved; - struct in6_addr target; - /* "Compulsory" options */ - uint8_t opt_type; - uint8_t opt_len; - /* FIXME: hack alert */ - uint8_t opt_ll_addr[6]; -}; - -struct neighbour_advert { - uint8_t type; - uint8_t code; - uint16_t csum; - uint8_t flags; - uint8_t reserved; - struct in6_addr target; - uint8_t opt_type; - uint8_t opt_len; - /* FIXME: hack alert */ - uint8_t opt_ll_addr[6]; -}; - -#define ICMP6_FLAGS_ROUTER 0x80 -#define ICMP6_FLAGS_SOLICITED 0x40 -#define ICMP6_FLAGS_OVERRIDE 0x20 - -int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src, struct in6_addr *dest ); - -#endif /* _IPXE_ICMP6_H */ diff --git a/src/include/ipxe/icmpv6.h b/src/include/ipxe/icmpv6.h new file mode 100644 index 000000000..c8f0be05a --- /dev/null +++ b/src/include/ipxe/icmpv6.h @@ -0,0 +1,78 @@ +#ifndef _IPXE_ICMP6_H +#define _IPXE_ICMP6_H + +/** @file + * + * ICMPv6 protocol + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/tables.h> +#include <ipxe/iobuf.h> +#include <ipxe/netdevice.h> + +/** An ICMPv6 header */ +struct icmpv6_header { + /** Type */ + uint8_t type; + /** Code */ + uint8_t code; + /** Checksum */ + uint16_t chksum; +} __attribute__ (( packed )); + +/** An ICMPv6 echo request/reply */ +struct icmpv6_echo { + /** ICMPv6 header */ + struct icmpv6_header icmp; + /** Identifier */ + uint16_t ident; + /** Sequence number */ + uint16_t sequence; + /** Data */ + uint8_t data[0]; +} __attribute__ (( packed )); + +/** An ICMPv6 handler */ +struct icmpv6_handler { + /** Type */ + unsigned int type; + /** Process received packet + * + * @v iobuf I/O buffer + * @v netdev Network device + * @v sin6_src Source socket address + * @v sin6_dest Destination socket address + * @ret rc Return status code + * + * This function takes ownership of the I/O buffer. + */ + int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev, + struct sockaddr_in6 *sin6_src, + struct sockaddr_in6 *sin6_dest ); +}; + +/** ICMPv6 handler table */ +#define ICMPV6_HANDLERS __table ( struct icmpv6_handler, "icmpv6_handlers" ) + +/** Declare an ICMPv6 handler */ +#define __icmpv6_handler __table_entry ( ICMPV6_HANDLERS, 01 ) + +/** ICMPv6 echo request */ +#define ICMPV6_ECHO_REQUEST 128 + +/** ICMPv6 echo reply */ +#define ICMPV6_ECHO_REPLY 129 + +/** ICMPv6 neighbour solicitation */ +#define ICMPV6_NDP_NEIGHBOUR_SOLICITATION 135 + +/** ICMPv6 neighbour advertisement */ +#define ICMPV6_NDP_NEIGHBOUR_ADVERTISEMENT 136 + +extern struct tcpip_protocol icmpv6_protocol __tcpip_protocol; + +#endif /* _IPXE_ICMP6_H */ diff --git a/src/include/ipxe/in.h b/src/include/ipxe/in.h index eee9159fb..a1821b1fb 100644 --- a/src/include/ipxe/in.h +++ b/src/include/ipxe/in.h @@ -50,6 +50,13 @@ struct in6_addr { #define s6_addr32 in6_u.u6_addr32 }; +#define IN6_IS_ADDR_MULTICAST( addr ) \ + ( *( ( const uint8_t * ) (addr) ) == 0xff ) + +#define IN6_IS_ADDR_LINKLOCAL( addr ) \ + ( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \ + htonl ( 0xfe80 ) ) + /** * IPv4 socket address */ @@ -90,9 +97,13 @@ struct sockaddr_in6 { uint16_t sin6_flags; /** TCP/IP port (part of struct @c sockaddr_tcpip) */ uint16_t sin6_port; - uint32_t sin6_flowinfo; /* Flow number */ - struct in6_addr sin6_addr; /* 128-bit destination address */ - uint32_t sin6_scope_id; /* Scope ID */ + /** Scope ID + * + * For link-local addresses, this is the network device index. + */ + uint16_t sin6_scope_id; + /** IPv6 address */ + struct in6_addr sin6_addr; /** Padding * * This ensures that a struct @c sockaddr_in6 is large @@ -103,20 +114,12 @@ struct sockaddr_in6 { ( sizeof ( sa_family_t ) /* sin6_family */ + sizeof ( uint16_t ) /* sin6_flags */ + sizeof ( uint16_t ) /* sin6_port */ + - sizeof ( uint32_t ) /* sin6_flowinfo */ + - sizeof ( struct in6_addr ) /* sin6_addr */ + - sizeof ( uint32_t ) /* sin6_scope_id */ ) ]; + sizeof ( uint16_t ) /* sin6_scope_id */ + + sizeof ( struct in6_addr ) /* sin6_addr */ ) ]; } __attribute__ (( may_alias )); extern int inet_aton ( const char *cp, struct in_addr *inp ); extern char * inet_ntoa ( struct in_addr in ); - -/* Adding the following for IP6 support - * - -extern int inet6_aton ( const char *cp, struct in6_addr *inp ); -extern char * inet6_ntoa ( struct in_addr in ); - - */ +extern char * inet6_ntoa ( const struct in6_addr *in6 ); #endif /* _IPXE_IN_H */ diff --git a/src/include/ipxe/ip6.h b/src/include/ipxe/ip6.h deleted file mode 100644 index e9584bd6f..000000000 --- a/src/include/ipxe/ip6.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _IPXE_IP6_H -#define _IPXE_IP6_H - -/** @file - * - * IP6 protocol - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <ipxe/in.h> -#include <ipxe/netdevice.h> -#include <ipxe/tcpip.h> - -/* IP6 constants */ - -#define IP6_VERSION 0x6 -#define IP6_HOP_LIMIT 255 - -/** - * I/O buffer contents - * This is duplicated in tcp.h and here. Ideally it should go into iobuf.h - */ -#define MAX_HDR_LEN 100 -#define MAX_IOB_LEN 1500 -#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */ - -#define IP6_EQUAL( in6_addr1, in6_addr2 ) \ - ( memcmp ( ( char* ) &( in6_addr1 ), ( char* ) &( in6_addr2 ),\ - sizeof ( struct in6_addr ) ) == 0 ) - -#define IS_UNSPECIFIED( addr ) \ - ( ( (addr).in6_u.u6_addr32[0] == 0x00000000 ) && \ - ( (addr).in6_u.u6_addr32[1] == 0x00000000 ) && \ - ( (addr).in6_u.u6_addr32[2] == 0x00000000 ) && \ - ( (addr).in6_u.u6_addr32[3] == 0x00000000 ) ) -/* IP6 header */ -struct ip6_header { - uint32_t ver_traffic_class_flow_label; - uint16_t payload_len; - uint8_t nxt_hdr; - uint8_t hop_limit; - struct in6_addr src; - struct in6_addr dest; -}; - -/* IP6 pseudo header */ -struct ipv6_pseudo_header { - struct in6_addr src; - struct in6_addr dest; - uint8_t zero_padding; - uint8_t nxt_hdr; - uint16_t len; -}; - -/* Next header numbers */ -#define IP6_HOPBYHOP 0x00 -#define IP6_ROUTING 0x43 -#define IP6_FRAGMENT 0x44 -#define IP6_AUTHENTICATION 0x51 -#define IP6_DEST_OPTS 0x60 -#define IP6_ESP 0x50 -#define IP6_ICMP6 0x58 -#define IP6_NO_HEADER 0x59 - -struct io_buffer; - -extern struct net_protocol ipv6_protocol __net_protocol; -extern struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol; -extern char * inet6_ntoa ( struct in6_addr in6 ); - -extern int add_ipv6_address ( struct net_device *netdev, - struct in6_addr prefix, int prefix_len, - struct in6_addr address, - struct in6_addr gateway ); -extern void del_ipv6_address ( struct net_device *netdev ); - -#endif /* _IPXE_IP6_H */ diff --git a/src/include/ipxe/ipv6.h b/src/include/ipxe/ipv6.h new file mode 100644 index 000000000..f404ba64e --- /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 */ diff --git a/src/include/ipxe/ndp.h b/src/include/ipxe/ndp.h index 42bb2fe00..7b98637f8 100644 --- a/src/include/ipxe/ndp.h +++ b/src/include/ipxe/ndp.h @@ -1,21 +1,80 @@ +#ifndef _IPXE_NDP_H +#define _IPXE_NDP_H + +/** @file + * + * Neighbour discovery protocol + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> -#include <byteswap.h> -#include <string.h> -#include <ipxe/icmp6.h> -#include <ipxe/ip6.h> #include <ipxe/in.h> -#include <ipxe/netdevice.h> -#include <ipxe/iobuf.h> -#include <ipxe/tcpip.h> - -#define NDP_STATE_INVALID 0 -#define NDP_STATE_INCOMPLETE 1 -#define NDP_STATE_REACHABLE 2 -#define NDP_STATE_DELAY 3 -#define NDP_STATE_PROBE 4 -#define NDP_STATE_STALE 5 - -int ndp_resolve ( struct net_device *netdev, struct in6_addr *src, - struct in6_addr *dest, void *dest_ll_addr ); -int ndp_process_advert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src, - struct sockaddr_tcpip *st_dest ); +#include <ipxe/ipv6.h> +#include <ipxe/icmpv6.h> +#include <ipxe/neighbour.h> + +/** An NDP option */ +struct ndp_option { + /** Type */ + uint8_t type; + /** Length (in blocks of 8 bytes) */ + uint8_t blocks; + /** Value */ + uint8_t value[0]; +} __attribute__ (( packed )); + +/** NDP option block size */ +#define NDP_OPTION_BLKSZ 8 + +/** An NDP header */ +struct ndp_header { + /** ICMPv6 header */ + struct icmpv6_header icmp; + /** Flags */ + uint8_t flags; + /** Reserved */ + uint8_t reserved[3]; + /** Target address */ + struct in6_addr target; + /** Options */ + struct ndp_option option[0]; +} __attribute__ (( packed )); + +/** NDP router flag */ +#define NDP_ROUTER 0x80 + +/** NDP solicited flag */ +#define NDP_SOLICITED 0x40 + +/** NDP override flag */ +#define NDP_OVERRIDE 0x20 + +/** NDP source link-layer address option */ +#define NDP_OPT_LL_SOURCE 1 + +/** NDP target link-layer address option */ +#define NDP_OPT_LL_TARGET 2 + +extern struct neighbour_discovery ndp_discovery; + +/** + * Transmit packet, determining link-layer address via NDP + * + * @v iobuf I/O buffer + * @v netdev Network device + * @v net_dest Destination network-layer address + * @v net_source Source network-layer address + * @v ll_source Source link-layer address + * @ret rc Return status code + */ +static inline int ndp_tx ( struct io_buffer *iobuf, struct net_device *netdev, + const void *net_dest, const void *net_source, + const void *ll_source ) { + + return neighbour_tx ( iobuf, netdev, &ipv6_protocol, net_dest, + &ndp_discovery, net_source, ll_source ); +} + +#endif /* _IPXE_NDP_H */ |
