[ipv6] Support stateless address autoconfiguration (SLAAC)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2013-10-23 14:00:12 +01:00
parent 2dca2e6ade
commit 33652880a7
4 changed files with 237 additions and 72 deletions

View File

@@ -173,7 +173,26 @@ struct ipv6_miniroute {
};
/**
* Construct link-local address (via EUI-64)
* Construct local IPv6 address via EUI-64
*
* @v addr Prefix to be completed
* @v netdev Network device
* @ret prefix_len Prefix length, or negative error
*/
static inline int ipv6_eui64 ( 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;
if ( ( rc = ll_protocol->eui64 ( ll_addr, &addr->s6_addr[8] ) ) != 0 )
return rc;
addr->s6_addr[8] ^= 0x02;
return 64;
}
/**
* Construct link-local address via EUI-64
*
* @v addr Address to construct
* @v netdev Network device
@@ -181,16 +200,10 @@ struct ipv6_miniroute {
*/
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;
return ipv6_eui64 ( addr, netdev );
}
/**
@@ -214,5 +227,7 @@ 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 );
extern int ipv6_slaac ( struct net_device *netdev, struct in6_addr *prefix,
unsigned int prefix_len, struct in6_addr *router );
#endif /* _IPXE_IPV6_H */

View File

@@ -15,19 +15,68 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/icmpv6.h>
#include <ipxe/neighbour.h>
/** An NDP option */
struct ndp_option {
/** An NDP option header */
struct ndp_option_header {
/** 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
/** NDP source link-layer address option */
#define NDP_OPT_LL_SOURCE 1
/** NDP target link-layer address option */
#define NDP_OPT_LL_TARGET 2
/** NDP source or target link-layer address option */
struct ndp_ll_addr_option {
/** NDP option header */
struct ndp_option_header header;
/** Link-layer address */
uint8_t ll_addr[0];
} __attribute__ (( packed ));
/** NDP prefix information option */
#define NDP_OPT_PREFIX 3
/** NDP prefix information */
struct ndp_prefix_information_option {
/** NDP option header */
struct ndp_option_header header;
/** Prefix length */
uint8_t prefix_len;
/** Flags */
uint8_t flags;
/** Valid lifetime */
uint32_t valid;
/** Preferred lifetime */
uint32_t preferred;
/** Reserved */
uint32_t reserved;
/** Prefix */
struct in6_addr prefix;
} __attribute__ (( packed ));
/** NDP on-link flag */
#define NDP_PREFIX_ON_LINK 0x80
/** NDP autonomous address configuration flag */
#define NDP_PREFIX_AUTONOMOUS 0x40
/** An NDP option */
union ndp_option {
/** Option header */
struct ndp_option_header header;
/** Source or target link-layer address option */
struct ndp_ll_addr_option ll_addr;
/** Prefix information option */
struct ndp_prefix_information_option prefix;
} __attribute__ (( packed ));
/** An NDP neighbour solicitation or advertisement header */
struct ndp_neighbour_header {
/** ICMPv6 header */
@@ -39,7 +88,7 @@ struct ndp_neighbour_header {
/** Target address */
struct in6_addr target;
/** Options */
struct ndp_option option[0];
union ndp_option option[0];
} __attribute__ (( packed ));
/** NDP router flag */
@@ -66,7 +115,7 @@ struct ndp_router_advertisement_header {
/** Retransmission timer */
uint32_t retransmit;
/** Options */
struct ndp_option option[0];
union ndp_option option[0];
} __attribute__ (( packed ));
/** NDP managed address configuration */
@@ -85,12 +134,6 @@ union ndp_header {
struct ndp_router_advertisement_header radv;
} __attribute__ (( packed ));
/** 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;
/**