From: Susant Sahani Date: Sat, 4 Apr 2020 18:07:18 +0000 (+0200) Subject: network: DHCPv6 Assign delegated prefix to LAN interface X-Git-Tag: v246-rc1~253 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9efa8a3cff9948d3a78597b74dca75c805716de4;p=thirdparty%2Fsystemd.git 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. --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1eaa452786f..e8f3f364f1e 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 b3ebdc8cd70..d0972f3593d 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 484705f4882..8a549110fa1 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 e8d67e0d64f..c793a37df74 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 79799e7dde5..d318b7d891d 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 781bbaa8811..ae466a23101 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 45b9df647d6..441bba12732 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 178bd9aaae3..a1a6cdd2330 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=