diff options
author | Michael Brown <mcb30@ipxe.org> | 2013-10-23 14:00:12 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2013-10-23 14:07:57 +0100 |
commit | 33652880a7b5881d3f2181fea94bed2ba525d44b (patch) | |
tree | 0dc21f0a479a0865155a21866e0a2d3cdcb9291f /src/net/ipv6.c | |
parent | 2dca2e6ade6ed89029b2812a0a6f07276cdace76 (diff) | |
download | ipxe-33652880a7b5881d3f2181fea94bed2ba525d44b.tar.gz |
[ipv6] Support stateless address autoconfiguration (SLAAC)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/ipv6.c')
-rw-r--r-- | src/net/ipv6.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/net/ipv6.c b/src/net/ipv6.c index c5f8d2d91..4cd672092 100644 --- a/src/net/ipv6.c +++ b/src/net/ipv6.c @@ -863,6 +863,53 @@ struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = { }; /** + * Perform IPv6 stateless address autoconfiguration (SLAAC) + * + * @v netdev Network device + * @v prefix Prefix + * @v prefix_len Prefix length + * @v router Router address (or NULL) + * @ret rc Return status code + */ +int ipv6_slaac ( struct net_device *netdev, struct in6_addr *prefix, + unsigned int prefix_len, struct in6_addr *router ) { + struct ipv6_miniroute *miniroute; + struct ipv6_miniroute *tmp; + struct in6_addr address; + int check_prefix_len; + int rc; + + /* Construct local address */ + memcpy ( &address, prefix, sizeof ( address ) ); + check_prefix_len = ipv6_eui64 ( &address, netdev ); + if ( check_prefix_len < 0 ) { + rc = check_prefix_len; + DBGC ( netdev, "IPv6 %s could not construct SLAAC address: " + "%s\n", netdev->name, strerror ( rc ) ); + return rc; + } + if ( check_prefix_len != ( int ) prefix_len ) { + DBGC ( netdev, "IPv6 %s incorrect SLAAC prefix length %d " + "(expected %d)\n", netdev->name, prefix_len, + check_prefix_len ); + return -EINVAL; + } + + /* Delete any existing SLAAC miniroutes for this prefix */ + list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list ) { + if ( ipv6_is_local ( miniroute, &address ) ) + del_ipv6_miniroute ( miniroute ); + } + + /* Add miniroute */ + miniroute = add_ipv6_miniroute ( netdev, &address, prefix_len, router ); + if ( ! miniroute ) + return -ENOMEM; + + return 0; +} + +/** * Create IPv6 network device * * @v netdev Network device |