diff options
author | Michael Brown | 2013-11-08 15:35:29 +0100 |
---|---|---|
committer | Michael Brown | 2013-11-14 13:35:43 +0100 |
commit | 2fa34085e28992dd7409496709af822776bd8fc6 (patch) | |
tree | 39a5bccb33c9b67eb2c93c950be39927f146a543 /src/net/ndp.c | |
parent | [ipv6] Add "ipv6" setting type (diff) | |
download | ipxe-2fa34085e28992dd7409496709af822776bd8fc6.tar.gz ipxe-2fa34085e28992dd7409496709af822776bd8fc6.tar.xz ipxe-2fa34085e28992dd7409496709af822776bd8fc6.zip |
[dhcpv6] Add basic support for stateful and stateless DHCPv6
Add support for the stateful and stateless variants of the DHCPv6
protocol. The resulting settings block is registered as
"net<x>.dhcpv6", and DHCPv6 options can be obtained using
e.g. "${net0.dhcpv6/23:ipv6}" to obtain the IPv6 DNS server address.
IPv6 addresses obtained via stateful DHCPv6 are not yet applied to the
network device.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/ndp.c')
-rw-r--r-- | src/net/ndp.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/src/net/ndp.c b/src/net/ndp.c index 1b1109ed..f56bbe92 100644 --- a/src/net/ndp.c +++ b/src/net/ndp.c @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/ipv6.h> #include <ipxe/icmpv6.h> #include <ipxe/neighbour.h> +#include <ipxe/dhcpv6.h> #include <ipxe/ndp.h> /** @file @@ -596,6 +597,8 @@ struct ipv6conf { /** Job control interface */ struct interface job; + /** DHCPv6 interface */ + struct interface dhcp; /** Network device being configured */ struct net_device *netdev; @@ -646,6 +649,7 @@ static void ipv6conf_done ( struct ipv6conf *ipv6conf, int rc ) { /* Shut down interfaces */ intf_shutdown ( &ipv6conf->job, rc ); + intf_shutdown ( &ipv6conf->dhcp, rc ); /* Stop timer */ stop_timer ( &ipv6conf->timer ); @@ -686,6 +690,8 @@ static void ipv6conf_expired ( struct retry_timer *timer, int fail ) { static int ipv6conf_rx_router_advertisement ( struct net_device *netdev, unsigned int flags ) { struct ipv6conf *ipv6conf; + int stateful; + int rc; /* Identify IPv6 configurator, if any */ ipv6conf = ipv6conf_demux ( netdev ); @@ -697,13 +703,28 @@ static int ipv6conf_rx_router_advertisement ( struct net_device *netdev, return 0; } - /* Fail if stateful address autoconfiguration is required */ - if ( flags & NDP_ROUTER_MANAGED ) { - ipv6conf_done ( ipv6conf, -ENOTSUP ); - return -ENOTSUP; + /* If this is not the first solicited router advertisement, ignore it */ + if ( ! timer_running ( &ipv6conf->timer ) ) + return 0; + + /* Stop router solicitation timer */ + stop_timer ( &ipv6conf->timer ); + + /* Start DHCPv6 if required */ + if ( flags & ( NDP_ROUTER_MANAGED | NDP_ROUTER_OTHER ) ) { + stateful = ( flags & NDP_ROUTER_MANAGED ); + if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev, + stateful ) ) != 0 ) { + DBGC ( netdev, "NDP could not start state%s DHCPv6: " + "%s\n", ( stateful ? "ful" : "less" ), + strerror ( rc ) ); + ipv6conf_done ( ipv6conf, rc ); + return rc; + } + return 0; } - /* Mark autoconfiguration as complete */ + /* Otherwise, terminate autoconfiguration */ ipv6conf_done ( ipv6conf, 0 ); return 0; @@ -718,6 +739,15 @@ static struct interface_operation ipv6conf_job_op[] = { static struct interface_descriptor ipv6conf_job_desc = INTF_DESC ( struct ipv6conf, job, ipv6conf_job_op ); +/** IPv6 configurator DHCPv6 interface operations */ +static struct interface_operation ipv6conf_dhcp_op[] = { + INTF_OP ( intf_close, struct ipv6conf *, ipv6conf_done ), +}; + +/** IPv6 configurator DHCPv6 interface descriptor */ +static struct interface_descriptor ipv6conf_dhcp_desc = + INTF_DESC ( struct ipv6conf, dhcp, ipv6conf_dhcp_op ); + /** * Start IPv6 autoconfiguration * @@ -734,6 +764,7 @@ int start_ipv6conf ( struct interface *job, struct net_device *netdev ) { return -ENOMEM; ref_init ( &ipv6conf->refcnt, ipv6conf_free ); intf_init ( &ipv6conf->job, &ipv6conf_job_desc, &ipv6conf->refcnt ); + intf_init ( &ipv6conf->dhcp, &ipv6conf_dhcp_desc, &ipv6conf->refcnt ); timer_init ( &ipv6conf->timer, ipv6conf_expired, &ipv6conf->refcnt ); ipv6conf->netdev = netdev_get ( netdev ); |