summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/ipxe')
-rw-r--r--src/include/ipxe/icmp6.h59
-rw-r--r--src/include/ipxe/icmpv6.h78
-rw-r--r--src/include/ipxe/in.h31
-rw-r--r--src/include/ipxe/ip6.h80
-rw-r--r--src/include/ipxe/ipv6.h218
-rw-r--r--src/include/ipxe/ndp.h97
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 */