|
@@ -266,6 +266,8 @@ struct dhcpv6_settings {
|
266
|
266
|
struct refcnt refcnt;
|
267
|
267
|
/** Settings block */
|
268
|
268
|
struct settings settings;
|
|
269
|
+ /** Leased address */
|
|
270
|
+ struct in6_addr lease;
|
269
|
271
|
/** Option list */
|
270
|
272
|
struct dhcpv6_option_list options;
|
271
|
273
|
};
|
|
@@ -280,7 +282,32 @@ struct dhcpv6_settings {
|
280
|
282
|
static int dhcpv6_applies ( struct settings *settings __unused,
|
281
|
283
|
const struct setting *setting ) {
|
282
|
284
|
|
283
|
|
- return ( setting->scope == &dhcpv6_scope );
|
|
285
|
+ return ( ( setting->scope == &dhcpv6_scope ) ||
|
|
286
|
+ ( setting_cmp ( setting, &ip6_setting ) == 0 ) );
|
|
287
|
+}
|
|
288
|
+
|
|
289
|
+/**
|
|
290
|
+ * Fetch value of DHCPv6 leased address
|
|
291
|
+ *
|
|
292
|
+ * @v dhcpset DHCPv6 settings
|
|
293
|
+ * @v data Buffer to fill with setting data
|
|
294
|
+ * @v len Length of buffer
|
|
295
|
+ * @ret len Length of setting data, or negative error
|
|
296
|
+ */
|
|
297
|
+static int dhcpv6_fetch_lease ( struct dhcpv6_settings *dhcpv6set,
|
|
298
|
+ void *data, size_t len ) {
|
|
299
|
+ struct in6_addr *lease = &dhcpv6set->lease;
|
|
300
|
+
|
|
301
|
+ /* Do nothing unless a leased address exists */
|
|
302
|
+ if ( IN6_IS_ADDR_UNSPECIFIED ( lease ) )
|
|
303
|
+ return -ENOENT;
|
|
304
|
+
|
|
305
|
+ /* Copy leased address */
|
|
306
|
+ if ( len > sizeof ( *lease ) )
|
|
307
|
+ len = sizeof ( *lease );
|
|
308
|
+ memcpy ( data, lease, len );
|
|
309
|
+
|
|
310
|
+ return sizeof ( *lease );
|
284
|
311
|
}
|
285
|
312
|
|
286
|
313
|
/**
|
|
@@ -300,6 +327,10 @@ static int dhcpv6_fetch ( struct settings *settings,
|
300
|
327
|
const union dhcpv6_any_option *option;
|
301
|
328
|
size_t option_len;
|
302
|
329
|
|
|
330
|
+ /* Handle leased address */
|
|
331
|
+ if ( setting_cmp ( setting, &ip6_setting ) == 0 )
|
|
332
|
+ return dhcpv6_fetch_lease ( dhcpv6set, data, len );
|
|
333
|
+
|
303
|
334
|
/* Find option */
|
304
|
335
|
option = dhcpv6_option ( &dhcpv6set->options, setting->tag );
|
305
|
336
|
if ( ! option )
|
|
@@ -322,11 +353,13 @@ static struct settings_operations dhcpv6_settings_operations = {
|
322
|
353
|
/**
|
323
|
354
|
* Register DHCPv6 options as network device settings
|
324
|
355
|
*
|
|
356
|
+ * @v lease DHCPv6 leased address
|
325
|
357
|
* @v options DHCPv6 option list
|
326
|
358
|
* @v parent Parent settings block
|
327
|
359
|
* @ret rc Return status code
|
328
|
360
|
*/
|
329
|
|
-static int dhcpv6_register ( struct dhcpv6_option_list *options,
|
|
361
|
+static int dhcpv6_register ( struct in6_addr *lease,
|
|
362
|
+ struct dhcpv6_option_list *options,
|
330
|
363
|
struct settings *parent ) {
|
331
|
364
|
struct dhcpv6_settings *dhcpv6set;
|
332
|
365
|
void *data;
|
|
@@ -347,6 +380,7 @@ static int dhcpv6_register ( struct dhcpv6_option_list *options,
|
347
|
380
|
memcpy ( data, options->data, len );
|
348
|
381
|
dhcpv6set->options.data = data;
|
349
|
382
|
dhcpv6set->options.len = len;
|
|
383
|
+ memcpy ( &dhcpv6set->lease, lease, sizeof ( dhcpv6set->lease ) );
|
350
|
384
|
|
351
|
385
|
/* Register settings */
|
352
|
386
|
if ( ( rc = register_settings ( &dhcpv6set->settings, parent,
|
|
@@ -848,28 +882,25 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
|
848
|
882
|
}
|
849
|
883
|
}
|
850
|
884
|
|
851
|
|
- /* Transition to next state or complete DHCPv6, as applicable */
|
|
885
|
+ /* Transition to next state, if applicable */
|
852
|
886
|
if ( dhcpv6->state->next ) {
|
853
|
|
-
|
854
|
|
- /* Transition to next state */
|
855
|
887
|
dhcpv6_set_state ( dhcpv6, dhcpv6->state->next );
|
856
|
888
|
rc = 0;
|
|
889
|
+ goto done;
|
|
890
|
+ }
|
857
|
891
|
|
858
|
|
- } else {
|
859
|
|
-
|
860
|
|
- /* Register settings */
|
861
|
|
- if ( ( rc = dhcpv6_register ( &options, parent ) ) != 0 ) {
|
862
|
|
- DBGC ( dhcpv6, "DHCPv6 %s could not register "
|
863
|
|
- "settings: %s\n", dhcpv6->netdev->name,
|
864
|
|
- strerror ( rc ) );
|
865
|
|
- goto done;
|
866
|
|
- }
|
867
|
|
-
|
868
|
|
- /* Mark as complete */
|
869
|
|
- dhcpv6_finished ( dhcpv6, 0 );
|
870
|
|
- DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
|
|
892
|
+ /* Register settings */
|
|
893
|
+ if ( ( rc = dhcpv6_register ( &dhcpv6->lease, &options,
|
|
894
|
+ parent ) ) != 0 ) {
|
|
895
|
+ DBGC ( dhcpv6, "DHCPv6 %s could not register settings: %s\n",
|
|
896
|
+ dhcpv6->netdev->name, strerror ( rc ) );
|
|
897
|
+ goto done;
|
871
|
898
|
}
|
872
|
899
|
|
|
900
|
+ /* Mark as complete */
|
|
901
|
+ dhcpv6_finished ( dhcpv6, 0 );
|
|
902
|
+ DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
|
|
903
|
+
|
873
|
904
|
done:
|
874
|
905
|
free_iob ( iobuf );
|
875
|
906
|
return rc;
|