]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dhcpv6] Expose IPv6 address setting acquired through DHCPv6
authorMichael Brown <mcb30@ipxe.org>
Tue, 19 Jul 2016 00:18:30 +0000 (01:18 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 19 Jul 2016 00:20:34 +0000 (01:20 +0100)
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Originally-implemented-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/udp/dhcpv6.c

index f57ea7b8af66b5299fd8dfc7b72f31699335037c..ac7010422784b558450961a6209c7a6493101cf9 100644 (file)
@@ -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;