summaryrefslogtreecommitdiffstats
path: root/src/net/udp
diff options
context:
space:
mode:
authorMichael Brown2016-07-19 02:18:30 +0200
committerMichael Brown2016-07-19 02:20:34 +0200
commit03d19cf14d19a80aee60126f1b0099c8f201aca7 (patch)
tree60bf4ceabee9c86db1528698997e771b31b8b3ac /src/net/udp
parent[ipv6] Expose IPv6 settings acquired through NDP (diff)
downloadipxe-03d19cf14d19a80aee60126f1b0099c8f201aca7.tar.gz
ipxe-03d19cf14d19a80aee60126f1b0099c8f201aca7.tar.xz
ipxe-03d19cf14d19a80aee60126f1b0099c8f201aca7.zip
[dhcpv6] Expose IPv6 address setting acquired through DHCPv6
Originally-implemented-by: Hannes Reinecke <hare@suse.de> Originally-implemented-by: Marin Hannache <git@mareo.fr> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/udp')
-rw-r--r--src/net/udp/dhcpv6.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/src/net/udp/dhcpv6.c b/src/net/udp/dhcpv6.c
index f57ea7b8..ac701042 100644
--- a/src/net/udp/dhcpv6.c
+++ b/src/net/udp/dhcpv6.c
@@ -266,6 +266,8 @@ struct dhcpv6_settings {
struct refcnt refcnt;
/** Settings block */
struct settings settings;
+ /** Leased address */
+ struct in6_addr lease;
/** Option list */
struct dhcpv6_option_list options;
};
@@ -280,7 +282,32 @@ struct dhcpv6_settings {
static int dhcpv6_applies ( struct settings *settings __unused,
const struct setting *setting ) {
- return ( setting->scope == &dhcpv6_scope );
+ return ( ( setting->scope == &dhcpv6_scope ) ||
+ ( setting_cmp ( setting, &ip6_setting ) == 0 ) );
+}
+
+/**
+ * Fetch value of DHCPv6 leased address
+ *
+ * @v dhcpset DHCPv6 settings
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int dhcpv6_fetch_lease ( struct dhcpv6_settings *dhcpv6set,
+ void *data, size_t len ) {
+ struct in6_addr *lease = &dhcpv6set->lease;
+
+ /* Do nothing unless a leased address exists */
+ if ( IN6_IS_ADDR_UNSPECIFIED ( lease ) )
+ return -ENOENT;
+
+ /* Copy leased address */
+ if ( len > sizeof ( *lease ) )
+ len = sizeof ( *lease );
+ memcpy ( data, lease, len );
+
+ return sizeof ( *lease );
}
/**
@@ -300,6 +327,10 @@ static int dhcpv6_fetch ( struct settings *settings,
const union dhcpv6_any_option *option;
size_t option_len;
+ /* Handle leased address */
+ if ( setting_cmp ( setting, &ip6_setting ) == 0 )
+ return dhcpv6_fetch_lease ( dhcpv6set, data, len );
+
/* Find option */
option = dhcpv6_option ( &dhcpv6set->options, setting->tag );
if ( ! option )
@@ -322,11 +353,13 @@ static struct settings_operations dhcpv6_settings_operations = {
/**
* Register DHCPv6 options as network device settings
*
+ * @v lease DHCPv6 leased address
* @v options DHCPv6 option list
* @v parent Parent settings block
* @ret rc Return status code
*/
-static int dhcpv6_register ( struct dhcpv6_option_list *options,
+static int dhcpv6_register ( struct in6_addr *lease,
+ struct dhcpv6_option_list *options,
struct settings *parent ) {
struct dhcpv6_settings *dhcpv6set;
void *data;
@@ -347,6 +380,7 @@ static int dhcpv6_register ( struct dhcpv6_option_list *options,
memcpy ( data, options->data, len );
dhcpv6set->options.data = data;
dhcpv6set->options.len = len;
+ memcpy ( &dhcpv6set->lease, lease, sizeof ( dhcpv6set->lease ) );
/* Register settings */
if ( ( rc = register_settings ( &dhcpv6set->settings, parent,
@@ -848,28 +882,25 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
}
}
- /* Transition to next state or complete DHCPv6, as applicable */
+ /* Transition to next state, if applicable */
if ( dhcpv6->state->next ) {
-
- /* Transition to next state */
dhcpv6_set_state ( dhcpv6, dhcpv6->state->next );
rc = 0;
+ goto done;
+ }
- } else {
-
- /* Register settings */
- if ( ( rc = dhcpv6_register ( &options, parent ) ) != 0 ) {
- DBGC ( dhcpv6, "DHCPv6 %s could not register "
- "settings: %s\n", dhcpv6->netdev->name,
- strerror ( rc ) );
- goto done;
- }
-
- /* Mark as complete */
- dhcpv6_finished ( dhcpv6, 0 );
- DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
+ /* Register settings */
+ if ( ( rc = dhcpv6_register ( &dhcpv6->lease, &options,
+ parent ) ) != 0 ) {
+ DBGC ( dhcpv6, "DHCPv6 %s could not register settings: %s\n",
+ dhcpv6->netdev->name, strerror ( rc ) );
+ goto done;
}
+ /* Mark as complete */
+ dhcpv6_finished ( dhcpv6, 0 );
+ DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
+
done:
free_iob ( iobuf );
return rc;