network: DHCPv6 Assign delegated prefix to LAN interface

In DHCPv6-PD environment, where WAN interface requests IPv6 via DHCPv6,
receives the address as well as delegated prefixes, with LAN interfaces
serving those delegated prefixes in their router advertisement messages.
The LAN interfaces on the router themselves do not have
the IPv6 addresses assigned by networkd from the prefix it
serves on that interface. Now this patch enables it.
This commit is contained in:
Susant Sahani 2020-04-04 20:07:18 +02:00 committed by Yu Watanabe
parent 5c95a9134a
commit 9efa8a3cff
8 changed files with 70 additions and 2 deletions

View File

@ -1781,6 +1781,15 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AssignAcquiredDelegatedPrefixAddress=</varname></term>
<listitem>
<para>Takes a boolean. Specifies whether to add an address from the delegated prefixes which are received
from the WAN interface by the <varname>IPv6PrefixDelegation=</varname>. When true (on LAN interfce), the EUI-64
algorithm will be used to form an interface identifier from the delegated prefixes. Defaults to true.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PrefixDelegationHint=</varname></term>
<listitem>
@ -3301,7 +3310,10 @@ DHCP=ipv6</programlisting>
Name=enp2s0
[Network]
IPv6PrefixDelegation=dhcpv6</programlisting>
IPv6PrefixDelegation=dhcpv6
[DHCPv6]
AssignAcquiredDelegatedPrefixAddress=yes</programlisting>
<para>This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the
DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.</para>

View File

@ -26,6 +26,10 @@ static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
static int dhcp6_prefix_remove_all(Manager *m, Link *link);
static bool dhcp6_link_has_dhcpv6_prefix(Link *link);
static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *prefix,
uint8_t prefix_len,
uint32_t lifetime_preferred,
uint32_t lifetime_valid);
static bool dhcp6_get_prefix_delegation(Link *link) {
if (!link->network)
@ -191,6 +195,12 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
if (r < 0)
return r;
if (link->network->dhcp6_pd_assign_prefix) {
r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid);
if (r < 0)
return r;
}
return sd_radv_start(radv);
}
@ -1018,3 +1028,43 @@ static bool dhcp6_link_has_dhcpv6_prefix(Link *link) {
return false;
}
static int dhcp6_assign_delegated_prefix(Link *link,
const struct in6_addr *prefix,
uint8_t prefix_len,
uint32_t lifetime_preferred,
uint32_t lifetime_valid) {
_cleanup_(address_freep) Address *address = NULL;
int r;
assert(link);
assert(link->network);
assert(prefix);
if (!link->network->dhcp6_pd_assign_prefix)
return 0;
r = address_new(&address);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate address: %m");
address->in_addr.in6 = *prefix;
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to generate EUI64 address for DHCPv6 acquired delegated prefix: %m");
address->prefixlen = prefix_len;
address->family = AF_INET6;
address->cinfo.ifa_prefered = lifetime_preferred;
address->cinfo.ifa_valid = lifetime_valid;
link_set_state(link, LINK_STATE_CONFIGURING);
r = address_configure(address, link, address_handler, true);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set addresses: %m");
if (r > 0)
link->address_messages++;
return 0;
}

View File

@ -1173,7 +1173,7 @@ static int link_request_set_neighbors(Link *link) {
return 0;
}
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(rtnl);

View File

@ -228,6 +228,7 @@ int link_request_set_routes(Link *link);
int link_request_set_nexthop(Link *link);
int link_reconfigure(Link *link, bool force);
int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_link_ipv6_address_gen_mode);

View File

@ -199,6 +199,7 @@ DHCPv6.RequestOptions, config_parse_dhcp_request_options,
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class)
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign_prefix)
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options)

View File

@ -412,6 +412,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp6_use_ntp = true,
.dhcp6_use_dns = true,
.dhcp6_pd_assign_prefix = true,
.dhcp_server_emit_dns = true,
.dhcp_server_emit_ntp = true,
.dhcp_server_emit_sip = true,

View File

@ -192,6 +192,7 @@ struct Network {
bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
RA flag is set, see RFC 7084,
WPD-4 */
bool dhcp6_pd_assign_prefix;
/* Bridge Support */
int use_bpdu;

View File

@ -119,6 +119,7 @@ SendOption=
RequestOptions=
UserClass=
VendorClass=
AssignAcquiredDelegatedPrefixAddress=
[Route]
Destination=
Protocol=