diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1eaa452786..e8f3f364f1 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1781,6 +1781,15 @@ + + AssignAcquiredDelegatedPrefixAddress= + + Takes a boolean. Specifies whether to add an address from the delegated prefixes which are received + from the WAN interface by the IPv6PrefixDelegation=. When true (on LAN interfce), the EUI-64 + algorithm will be used to form an interface identifier from the delegated prefixes. Defaults to true. + + + PrefixDelegationHint= @@ -3301,7 +3310,10 @@ DHCP=ipv6 Name=enp2s0 [Network] -IPv6PrefixDelegation=dhcpv6 +IPv6PrefixDelegation=dhcpv6 + +[DHCPv6] +AssignAcquiredDelegatedPrefixAddress=yes 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. diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index b3ebdc8cd7..d0972f3593 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -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; +} diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 484705f488..8a549110fa 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index e8d67e0d64..c793a37df7 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -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); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 79799e7dde..d318b7d891 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 781bbaa881..ae466a2310 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 45b9df647d..441bba1273 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -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; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 178bd9aaae..a1a6cdd233 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -119,6 +119,7 @@ SendOption= RequestOptions= UserClass= VendorClass= +AssignAcquiredDelegatedPrefixAddress= [Route] Destination= Protocol=