<term><varname>Token=</varname></term>
<listitem>
<para>Specifies an optional address generation mode for assigning an address in each
- delegated prefix. Takes an IPv6 address. When set, the lower bits of the supplied address is
- combined with the upper bits of each delegatad prefix received from the WAN interface by the
- DHCPv6 Prefix Delegation to form a complete address. When <varname>Assign=</varname> is
- disabled, this setting is ignored. When unset, the EUI-64 algorithm will be used to form
- addresses. Defaults to unset.</para>
+ delegated prefix. This accepts the same syntax as <varname>Token=</varname> in the
+ [IPv6AcceptRA] section. If <varname>Assign=</varname> is set to false, then this setting will
+ be ignored. Defaults to unset, which means the EUI-64 algorithm will be used.</para>
</listitem>
</varlistentry>
#define RESERVED_SUBNET_ANYCAST_ADDRESSES ((const struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80 } })
#define RESERVED_SUBNET_ANYCAST_PREFIXLEN 57
+#define DHCP6PD_APP_ID SD_ID128_MAKE(fb,b9,37,ca,4a,ed,4a,4d,b0,70,7f,aa,71,c0,c9,85)
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
typedef enum AddressGenerationType {
return 0;
}
+int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret) {
+ return generate_addresses(link, link->network->dhcp6_pd_tokens, &DHCP6PD_APP_ID, prefix, 64, ret);
+}
+
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
return generate_addresses(link, link->network->ndisc_tokens, &NDISC_APP_ID, prefix, prefixlen, ret);
}
void generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret);
+int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret);
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type);
uint32_t lifetime_preferred,
uint32_t lifetime_valid) {
- _cleanup_(address_freep) Address *address = NULL;
- Address *existing;
+ _cleanup_set_free_ Set *addresses = NULL;
+ struct in6_addr *a;
int r;
assert(link);
if (!link->network->dhcp6_pd_assign)
return 0;
- r = address_new(&address);
+ r = dhcp6_pd_generate_addresses(link, prefix, &addresses);
if (r < 0)
- return log_link_error_errno(link, r, "Failed to allocate address for DHCPv6 delegated prefix: %m");
+ return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCPv6 delegated prefix: %m");
- if (in6_addr_is_set(&link->network->dhcp6_pd_token)) {
- memcpy(address->in_addr.in6.s6_addr, prefix->s6_addr, 8);
- memcpy(address->in_addr.in6.s6_addr + 8, link->network->dhcp6_pd_token.s6_addr + 8, 8);
- } else
- generate_eui64_address(link, prefix, &address->in_addr.in6);
+ SET_FOREACH(a, addresses) {
+ _cleanup_(address_freep) Address *address = NULL;
+ Address *existing;
- address->source = NETWORK_CONFIG_SOURCE_DHCP6PD;
- address->prefixlen = 64;
- address->family = AF_INET6;
- address->cinfo.ifa_prefered = lifetime_preferred;
- address->cinfo.ifa_valid = lifetime_valid;
- SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
- address->route_metric = link->network->dhcp6_pd_route_metric;
+ r = address_new(&address);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to allocate address for DHCPv6 delegated prefix: %m");
- log_dhcp6_pd_address(link, address);
+ address->source = NETWORK_CONFIG_SOURCE_DHCP6PD;
+ address->family = AF_INET6;
+ address->in_addr.in6 = *a;
+ address->prefixlen = 64;
+ address->cinfo.ifa_prefered = lifetime_preferred;
+ address->cinfo.ifa_valid = lifetime_valid;
+ SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
+ address->route_metric = link->network->dhcp6_pd_route_metric;
- if (address_get(link, address, &existing) < 0)
- link->dhcp6_pd_configured = false;
- else
- address_unmark(existing);
+ log_dhcp6_pd_address(link, address);
- r = link_request_address(link, TAKE_PTR(address), true, &link->dhcp6_pd_messages,
- dhcp6_pd_address_handler, NULL);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to request DHCPv6 delegated prefix address: %m");
+ if (address_get(link, address, &existing) < 0)
+ link->dhcp6_pd_configured = false;
+ else
+ address_unmark(existing);
+
+ r = link_request_address(link, TAKE_PTR(address), true, &link->dhcp6_pd_messages,
+ dhcp6_pd_address_handler, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to request DHCPv6 delegated prefix address: %m");
+ }
return 0;
}
DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp6_pd_announce)
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign)
DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_manage_temporary_address)
-DHCPv6PrefixDelegation.Token, config_parse_in_addr_non_null, AF_INET6, offsetof(Network, dhcp6_pd_token)
+DHCPv6PrefixDelegation.Token, config_parse_address_generation_type, 0, offsetof(Network, dhcp6_pd_tokens)
DHCPv6PrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp6_pd_route_metric)
IPv6SendRA.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
ordered_hashmap_free(network->dhcp_server_send_vendor_options);
ordered_hashmap_free(network->dhcp6_client_send_options);
ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
+ set_free(network->dhcp6_pd_tokens);
set_free(network->ndisc_tokens);
return mfree(network);
bool dhcp6_pd_manage_temporary_address;
int64_t dhcp6_pd_subnet_id;
uint32_t dhcp6_pd_route_metric;
- struct in6_addr dhcp6_pd_token;
+ Set *dhcp6_pd_tokens;
/* Bridge Support */
int use_bpdu;