diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2020-10-23 05:57:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-23 05:57:58 +0200 |
commit | 9c914c0401546a67079a22c4a928814bd645b0a5 (patch) | |
tree | b33772ffbba60d3642c595d5514a567a3c100ac7 | |
parent | network: move set-MAC and set-nomaster operations out of link_up() (diff) | |
parent | test-network: use new IPv6SendRA= setting (diff) | |
download | systemd-9c914c0401546a67079a22c4a928814bd645b0a5.tar.xz systemd-9c914c0401546a67079a22c4a928814bd645b0a5.zip |
Merge pull request #17357 from yuwata/network-dhcp6-pd-announce-17353
network: add an option to control announcement of delegated prefix
-rw-r--r-- | man/systemd.network.xml | 78 | ||||
-rw-r--r-- | src/network/networkd-address.c | 39 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 4 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 13 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 38 | ||||
-rw-r--r-- | src/network/networkd-network.c | 48 | ||||
-rw-r--r-- | src/network/networkd-network.h | 89 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 133 | ||||
-rw-r--r-- | src/network/networkd-radv.h | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-network-parser/directives.network | 15 | ||||
-rw-r--r-- | test/test-network/conf/ipv6-prefix.network | 4 | ||||
-rw-r--r-- | test/test-network/conf/ipv6ra-prefix.network | 2 |
12 files changed, 294 insertions, 170 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 5307a508d3..1eb8274e83 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -810,18 +810,24 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> </para></listitem> </varlistentry> <varlistentry> - <term><varname>IPv6PrefixDelegation=</varname></term> - <listitem><para>Whether to enable or disable Router Advertisement sending on a link. Allowed - values are <literal>static</literal> which distributes prefixes as defined in the - [IPv6PrefixDelegation] and any [IPv6Prefix] sections, <literal>dhcpv6</literal> which requests - prefixes using a DHCPv6 client configured for another link and any values configured in the - [IPv6PrefixDelegation] section while ignoring all static prefix configuration sections, - <literal>yes</literal> which uses both static configuration and DHCPv6, and - <literal>false</literal> which turns off IPv6 prefix delegation altogether. Defaults to - <literal>false</literal>. See the [IPv6PrefixDelegation] and the [IPv6Prefix] sections for more + <term><varname>IPv6SendRA=</varname></term> + <listitem><para>Whether to enable or disable Router Advertisement sending on a link. Takes a + boolean value. When enabled, prefixes configured in [IPv6Prefix] sections and routes + configured in [IPv6RoutePrefix] sections are distributed as defined in the [IPv6SendRA] + section. If <varname>DHCPv6PrefixDelegation=</varname> is enabled, then the delegated + prefixes are also distributed. See <varname>DHCPv6PrefixDelegation=</varname> setting and the + [IPv6SendRA], [IPv6Prefix], [IPv6RoutePrefix], and [DHCPv6PrefixDelegation] sections for more configuration options.</para></listitem> </varlistentry> <varlistentry> + <term><varname>DHCPv6PrefixDelegation=</varname></term> + <listitem><para>Takes a boolean value. When enabled, requests prefixes using a DHCPv6 client + configured on another link. By default, an address within each delegated prefix will be + assigned, and the prefixes will be announced through IPv6 Router Advertisement when + <varname>IPv6SendRA=</varname> is enabled. Such default settings can be configured in + [DHCPv6PrefixDelegation] section.</para></listitem> + </varlistentry> + <varlistentry> <term><varname>IPv6MTUBytes=</varname></term> <listitem><para>Configures IPv6 maximum transmission unit (MTU). An integer greater than or equal to 1280 bytes. When unset, the kernel's default will be used. @@ -1957,9 +1963,9 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <refsect1> <title>[DHCPv6PrefixDelegation] Section Options</title> - <para>The [DHCPv6PrefixDelegation] section configures delegated prefix assigned by DHCPv6 server. - The settings in this section are used only when <varname>IPv6PrefixDelegation=</varname> setting is - enabled, or set to <literal>dhcpv6</literal>.</para> + <para>The [DHCPv6PrefixDelegation] section configures delegated prefixes assigned by DHCPv6 server. + The settings in this section are used only when <varname>DHCPv6PrefixDelegation=</varname> setting + is enabled.</para> <variablelist class='network-directives'> <varlistentry> @@ -1969,9 +1975,16 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> delegation. You can either set "auto" (the default) or a specific subnet ID (as defined in <ulink url="https://tools.ietf.org/html/rfc4291#section-2.5.4">RFC 4291</ulink>, section 2.5.4), in which case the allowed value is hexadecimal, from 0 to 0x7fffffffffffffff - inclusive. This option is only effective when used together with - <varname>IPv6PrefixDelegation=</varname> and the corresponding configuration on the upstream - interface.</para> + inclusive.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>Announce=</varname></term> + <listitem> + <para>Takes a boolean. When enabled, and <varname>IPv6SendRA=</varname> in [Network] section + is enabled, the delegated prefixes are distributed through the IPv6 Router Advertisement. + Defaults to yes.</para> </listitem> </varlistentry> @@ -1979,19 +1992,22 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <term><varname>Assign=</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> + are received from the WAN interface by the DHCPv6 Prefix Delegation. When true (on LAN + interfce), the EUI-64 algorithm will be used by default to form an interface identifier from + the delegated prefixes. See also <varname>Token=</varname> setting below. Defaults to yes. + </para> </listitem> </varlistentry> <varlistentry> <term><varname>Token=</varname></term> <listitem> - <para>Specifies an optional address generation mode for <varname>Assign=</varname>. Takes an - IPv6 address. When set, the lower bits of the supplied address are combined with the upper - bits of a delegatad prefix received from the WAN interface by the - <varname>IPv6PrefixDelegation=</varname> prefixes to form a complete address.</para> + <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> </listitem> </varlistentry> </variablelist> @@ -2213,10 +2229,11 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> </refsect1> <refsect1> - <title>[IPv6PrefixDelegation] Section Options</title> - <para>The [IPv6PrefixDelegation] section contains settings for sending IPv6 Router Advertisements and - whether to act as a router, if enabled via the <varname>IPv6PrefixDelegation=</varname> option described - above. IPv6 network prefixes are defined with one or more [IPv6Prefix] sections.</para> + <title>[IPv6SendRA] Section Options</title> + <para>The [IPv6SendRA] section contains settings for sending IPv6 Router Advertisements and whether + to act as a router, if enabled via the <varname>IPv6SendRA=</varname> option described above. IPv6 + network prefixes or routes are defined with one or more [IPv6Prefix] or [IPv6RoutePrefix] sections. + </para> <variablelist class='network-directives'> @@ -3586,10 +3603,13 @@ DHCP=ipv6</programlisting> Name=enp2s0 [Network] -IPv6PrefixDelegation=dhcpv6</programlisting> +IPv6SendRA=yes +DHCPv6PrefixDelegation=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> + <para>This will enable DHCPv6-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. + The delegated prefixes are distributed by IPv6 Router Advertisement on the downstream network. + </para> </example> <example> diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 636812b556..9130fae778 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -980,6 +980,7 @@ static int static_address_configure(const Address *address, Link *link, bool upd int link_set_addresses(Link *link) { Address *ad; + Prefix *p; int r; assert(link); @@ -1000,32 +1001,28 @@ int link_set_addresses(Link *link) { return r; } - if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { - Prefix *p; + HASHMAP_FOREACH(p, link->network->prefixes_by_section) { + _cleanup_(address_freep) Address *address = NULL; - HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - _cleanup_(address_freep) Address *address = NULL; - - if (!p->assign) - continue; + if (!p->assign) + continue; - r = address_new(&address); - if (r < 0) - return log_oom(); + r = address_new(&address); + if (r < 0) + return log_oom(); - r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen); - if (r < 0) - return log_link_warning_errno(link, r, "Could not get RA prefix: %m"); + r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen); + if (r < 0) + return log_link_warning_errno(link, r, "Could not get RA prefix: %m"); - r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); - if (r < 0) - return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); + r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); + if (r < 0) + return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); - address->family = AF_INET6; - r = static_address_configure(address, link, true); - if (r < 0) - return r; - } + address->family = AF_INET6; + r = static_address_configure(address, link, true); + if (r < 0) + return r; } if (link->address_messages == 0) { diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index a881df8bb4..bb8c34f7cc 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1457,8 +1457,8 @@ int dhcp4_configure(Link *link) { return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m"); } - if (link->network->ip_service_type > 0) { - r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type); + if (link->network->dhcp_ip_service_type > 0) { + r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->dhcp_ip_service_type); if (r < 0) return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m"); } diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 5217497f98..d9cc4ccf41 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -31,7 +31,7 @@ bool link_dhcp6_pd_is_enabled(Link *link) { if (!link->network) return false; - return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6; + return link->network->dhcp6_pd; } static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { @@ -421,11 +421,14 @@ static int dhcp6_pd_assign_prefix(Link *link, const union in_addr_union *prefix, int r; assert(link); + assert(link->network); assert(prefix); - r = radv_add_prefix(link, &prefix->in6, prefix_len, lifetime_preferred, lifetime_valid); - if (r < 0) - return r; + if (link->network->dhcp6_pd_announce) { + r = radv_add_prefix(link, &prefix->in6, prefix_len, lifetime_preferred, lifetime_valid); + if (r < 0) + return r; + } r = dhcp6_set_pd_route(link, prefix, pd_prefix); if (r < 0) @@ -1424,7 +1427,7 @@ int dhcp6_configure(Link *link) { if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set ifindex: %m"); - if (link->network->rapid_commit) { + if (link->network->dhcp6_rapid_commit) { r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_RAPID_COMMIT); if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for rapid commit: %m"); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 21d2e820e9..5cc9e3e8f6 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -126,6 +126,8 @@ Network.BindCarrier, config_parse_strv, Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier) Network.IgnoreCarrierLoss, config_parse_tristate, 0, offsetof(Network, ignore_carrier_loss) Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration) +Network.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation) +Network.DHCPv6PrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp6_pd) Address.Address, config_parse_address, 0, 0 Address.Peer, config_parse_address, 0, 0 Address.Broadcast, config_parse_broadcast, 0, 0 @@ -209,14 +211,14 @@ DHCPv4.SendRelease, config_parse_bool, DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline) DHCPv4.DenyList, config_parse_dhcp_acl_ip_address, 0, 0 DHCPv4.AllowList, config_parse_dhcp_acl_ip_address, 0, 0 -DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, ip_service_type) +DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type) DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options) DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options) DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu) DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0 DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0 DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0 -DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) +DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit) DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0 DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0 DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class) @@ -280,19 +282,19 @@ BridgeMDB.VLANId, config_parse_mdb_vlan_id, BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 -Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation) DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id, 0, offsetof(Network, dhcp6_pd_subnet_id) +DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp6_pd_announce) DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign) DHCPv6PrefixDelegation.Token, config_parse_dhcp6_pd_token, 0, offsetof(Network, dhcp6_pd_token) -IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) -IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed) -IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) -IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0 -IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns) -IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0 -IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) -IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 -IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) +IPv6SendRA.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) +IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed) +IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) +IPv6SendRA.RouterPreference, config_parse_router_preference, 0, 0 +IPv6SendRA.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns) +IPv6SendRA.DNS, config_parse_radv_dns, 0, 0 +IPv6SendRA.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) +IPv6SendRA.Domains, config_parse_radv_search_domains, 0, 0 +IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) IPv6Prefix.Prefix, config_parse_prefix, 0, 0 IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0 IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 @@ -429,6 +431,16 @@ TrivialLinkEqualizer.Handle, config_parse_qdisc_handle, TrivialLinkEqualizer.Id, config_parse_trivial_link_equalizer_id, QDISC_KIND_TEQL, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) +Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation) +IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) +IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed) +IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) +IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0 +IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns) +IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0 +IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) +IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 +IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) DHCPv4.BlackList, config_parse_dhcp_acl_ip_address, 0, 0 DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0 @@ -452,7 +464,7 @@ DHCP.RouteTable, config_parse_section_route_table, DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.IAID, config_parse_iaid, 0, 0 DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) -DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) +DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit) DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 6bfc4cb9eb..426dd0a8f0 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -214,14 +214,6 @@ int network_verify(Network *network) { if (network->link_local < 0) network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6; - if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { - if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) { - log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. " - "Disabling IPv6PrefixDelegation=.", network->filename); - network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE; - } - } - if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) { log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. " @@ -235,6 +227,7 @@ int network_verify(Network *network) { network_adjust_ipv6_accept_ra(network); network_adjust_dhcp(network); + network_adjust_radv(network); if (network->mtu > 0 && network->dhcp_use_mtu) { log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. " @@ -336,7 +329,16 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .required_for_online = true, .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT, + .arp = -1, + .multicast = -1, + .allmulticast = -1, + + .configure_without_carrier = false, + .ignore_carrier_loss = -1, + .keep_configuration = _KEEP_CONFIGURATION_INVALID, + .dhcp = ADDRESS_FAMILY_NO, + .duid.type = _DUID_TYPE_INVALID, .dhcp_critical = -1, .dhcp_use_ntp = true, .dhcp_use_sip = true, @@ -358,14 +360,17 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp_use_mtu = false, /* NOTE: from man: UseTimezone=... Defaults to "no".*/ .dhcp_use_timezone = false, - .rapid_commit = true, + .dhcp_ip_service_type = -1, + .dhcp6_rapid_commit = true, .dhcp6_route_metric = DHCP_ROUTE_METRIC, .dhcp6_use_ntp = true, .dhcp6_use_dns = true, - .dhcp6_pd_subnet_id = -1, + .dhcp6_pd = -1, + .dhcp6_pd_announce = true, .dhcp6_pd_assign = true, + .dhcp6_pd_subnet_id = -1, .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true, .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true, @@ -404,17 +409,13 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID, .ipv4_accept_local = -1, - .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO, .ipv6_accept_ra = -1, .ipv6_dad_transmits = -1, .ipv6_hop_limit = -1, .ipv6_proxy_ndp = -1, - .duid.type = _DUID_TYPE_INVALID, .proxy_arp = -1, - .arp = -1, - .multicast = -1, - .allmulticast = -1, + .ipv6_accept_ra_use_dns = true, .ipv6_accept_ra_use_autonomous_prefix = true, .ipv6_accept_ra_use_onlink_prefix = true, @@ -422,15 +423,11 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv6_accept_ra_route_table_set = false, .ipv6_accept_ra_start_dhcp6_client = true, - .configure_without_carrier = false, - .ignore_carrier_loss = -1, - .keep_configuration = _KEEP_CONFIGURATION_INVALID, .can_triple_sampling = -1, .can_termination = -1, .can_listen_only = -1, .can_fd_mode = -1, .can_non_iso = -1, - .ip_service_type = -1, }; r = config_parse_many( @@ -456,6 +453,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi "BridgeFDB\0" "BridgeMDB\0" "BridgeVLAN\0" + "IPv6SendRA\0" "IPv6PrefixDelegation\0" "IPv6Prefix\0" "IPv6RoutePrefix\0" @@ -620,11 +618,11 @@ static Network *network_free(Network *network) { for (unsigned i = 0; i < network->n_dns; i++) in_addr_full_free(network->dns[i]); free(network->dns); - ordered_set_free_free(network->search_domains); - ordered_set_free_free(network->route_domains); + ordered_set_free(network->search_domains); + ordered_set_free(network->route_domains); strv_free(network->bind_carrier); - ordered_set_free_free(network->router_search_domains); + ordered_set_free(network->router_search_domains); free(network->router_dns); set_free_free(network->ndisc_deny_listed_prefix); @@ -864,8 +862,8 @@ int config_parse_domains( assert(rvalue); if (isempty(rvalue)) { - n->search_domains = ordered_set_free_free(n->search_domains); - n->route_domains = ordered_set_free_free(n->route_domains); + n->search_domains = ordered_set_free(n->search_domains); + n->route_domains = ordered_set_free(n->route_domains); return 0; } @@ -913,7 +911,7 @@ int config_parse_domains( } OrderedSet **set = is_route ? &n->route_domains : &n->search_domains; - r = ordered_set_ensure_allocated(set, &string_hash_ops); + r = ordered_set_ensure_allocated(set, &string_hash_ops_free); if (r < 0) return log_oom(); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index ccf739c851..92c7a4636f 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -57,12 +57,14 @@ typedef struct NetworkDHCPServerEmitAddress { struct Network { Manager *manager; - char *filename; + unsigned n_ref; + char *name; + char *filename; usec_t timestamp; + char *description; - unsigned n_ref; - + /* [Match] section */ Set *match_mac; Set *match_permanent_mac; char **match_path; @@ -75,8 +77,7 @@ struct Network { Set *match_bssid; LIST_HEAD(Condition, conditions); - char *description; - + /* Master or stacked netdevs */ NetDev *bridge; NetDev *bond; NetDev *vrf; @@ -87,9 +88,31 @@ struct Network { char *vrf_name; Hashmap *stacked_netdev_names; + /* [Link] section */ + struct ether_addr *mac; + uint32_t mtu; + uint32_t group; + int arp; + int multicast; + int allmulticast; + bool unmanaged; + bool required_for_online; /* Is this network required to be considered online? */ + LinkOperationalStateRange required_operstate_for_online; + + /* misc settings */ + bool configure_without_carrier; + int ignore_carrier_loss; + KeepConfiguration keep_configuration; + char **bind_carrier; + bool default_route_on_device; + bool ip_masquerade; + /* DHCP Client Support */ AddressFamily dhcp; DHCPClientIdentifier dhcp_client_identifier; + DUID duid; + uint32_t iaid; + bool iaid_set; char *dhcp_vendor_class_identifier; char *dhcp_mudurl; char **dhcp_user_class; @@ -102,7 +125,7 @@ struct Network { uint32_t dhcp_route_mtu; uint16_t dhcp_client_port; int dhcp_critical; - int ip_service_type; + int dhcp_ip_service_type; bool dhcp_anonymize; bool dhcp_send_hostname; bool dhcp_broadcast; @@ -116,7 +139,6 @@ struct Network { bool dhcp_use_routes; int dhcp_use_gateway; bool dhcp_use_timezone; - bool rapid_commit; bool dhcp_use_hostname; bool dhcp_route_table_set; bool dhcp_send_release; @@ -127,14 +149,13 @@ struct Network { Set *dhcp_request_options; OrderedHashmap *dhcp_client_send_options; OrderedHashmap *dhcp_client_send_vendor_options; - OrderedHashmap *dhcp_server_send_options; - OrderedHashmap *dhcp_server_send_vendor_options; /* DHCPv6 Client support*/ bool dhcp6_use_dns; bool dhcp6_use_dns_set; bool dhcp6_use_ntp; bool dhcp6_use_ntp_set; + bool dhcp6_rapid_commit; uint8_t dhcp6_pd_length; uint32_t dhcp6_route_metric; bool dhcp6_route_metric_set; @@ -146,6 +167,8 @@ struct Network { OrderedHashmap *dhcp6_client_send_options; OrderedHashmap *dhcp6_client_send_vendor_options; Set *dhcp6_request_options; + /* Start DHCPv6 PD also when 'O' RA flag is set, see RFC 7084, WPD-4 */ + bool dhcp6_force_pd_other_information; /* DHCP Server Support */ bool dhcp_server; @@ -156,15 +179,15 @@ struct Network { usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; uint32_t dhcp_server_pool_offset; uint32_t dhcp_server_pool_size; + OrderedHashmap *dhcp_server_send_options; + OrderedHashmap *dhcp_server_send_vendor_options; /* link local addressing support */ AddressFamily link_local; IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode; bool ipv4ll_route; - bool default_route_on_device; - - /* IPv6 prefix delegation support */ + /* IPv6 RA support */ RADVPrefixDelegation router_prefix_delegation; usec_t router_lifetime_usec; uint8_t router_preference; @@ -176,13 +199,12 @@ struct Network { struct in6_addr *router_dns; unsigned n_router_dns; OrderedSet *router_search_domains; - bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O' - RA flag is set, see RFC 7084, - WPD-4 */ /* DHCPv6 Prefix Delegation support */ - int64_t dhcp6_pd_subnet_id; + int dhcp6_pd; + bool dhcp6_pd_announce; bool dhcp6_pd_assign; + int64_t dhcp6_pd_subnet_id; union in_addr_union dhcp6_pd_token; /* Bridge Support */ @@ -201,6 +223,7 @@ struct Network { uint16_t priority; MulticastRouter multicast_router; + /* Bridge VLAN */ bool use_br_vlan; uint16_t pvid; uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN]; @@ -218,18 +241,19 @@ struct Network { int can_fd_mode; int can_non_iso; + /* sysctl settings */ AddressFamily ip_forward; - bool ip_masquerade; int ipv4_accept_local; - - int ipv6_accept_ra; int ipv6_dad_transmits; int ipv6_hop_limit; - int ipv6_proxy_ndp; - Set *ipv6_proxy_ndp_addresses; int proxy_arp; uint32_t ipv6_mtu; + IPv6PrivacyExtensions ipv6_privacy_extensions; + int ipv6_proxy_ndp; + Set *ipv6_proxy_ndp_addresses; + /* IPv6 accept RA */ + int ipv6_accept_ra; bool ipv6_accept_ra_use_dns; bool ipv6_accept_ra_use_autonomous_prefix; bool ipv6_accept_ra_use_onlink_prefix; @@ -242,26 +266,6 @@ struct Network { Set *ndisc_deny_listed_prefix; OrderedSet *ipv6_tokens; - IPv6PrivacyExtensions ipv6_privacy_extensions; - - struct ether_addr *mac; - uint32_t mtu; - uint32_t group; - int arp; - int multicast; - int allmulticast; - bool unmanaged; - bool configure_without_carrier; - int ignore_carrier_loss; - KeepConfiguration keep_configuration; - uint32_t iaid; - DUID duid; - - bool iaid_set; - - bool required_for_online; /* Is this network required to be considered online? */ - LinkOperationalStateRange required_operstate_for_online; - /* LLDP support */ LLDPMode lldp_mode; /* LLDP reception */ LLDPEmit lldp_emit; /* LLDP transmission */ @@ -284,7 +288,6 @@ struct Network { struct in_addr_full **dns; unsigned n_dns; OrderedSet *search_domains, *route_domains; - int dns_default_route; ResolveSupport llmnr; ResolveSupport mdns; @@ -292,8 +295,8 @@ struct Network { DnsOverTlsMode dns_over_tls_mode; Set *dnssec_negative_trust_anchors; + /* NTP */ char **ntp; - char **bind_carrier; }; Network *network_ref(Network *network); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index bb80e91b6c..eb10f21cbd 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -180,6 +180,35 @@ void network_drop_invalid_route_prefixes(Network *network) { route_prefix_free(prefix); } +void network_adjust_radv(Network *network) { + assert(network); + + /* After this function is called, network->router_prefix_delegation can be treated as a boolean. */ + + if (network->dhcp6_pd < 0) + /* For backward compatibility. */ + network->dhcp6_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6); + + if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { + if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) + log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. " + "Disabling IPv6PrefixDelegation=.", network->filename); + + network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE; + } + + if (network->router_prefix_delegation == RADV_PREFIX_DELEGATION_NONE) { + network->n_router_dns = 0; + network->router_dns = mfree(network->router_dns); + network->router_search_domains = ordered_set_free(network->router_search_domains); + } + + if (!FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_STATIC)) { + network->prefixes_by_section = hashmap_free_with_destructor(network->prefixes_by_section, prefix_free); + network->route_prefixes_by_section = hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free); + } +} + int config_parse_prefix( const char *unit, const char *filename, @@ -608,10 +637,12 @@ static bool link_radv_enabled(Link *link) { if (!link_ipv6ll_enabled(link)) return false; - return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE; + return link->network->router_prefix_delegation; } int radv_configure(Link *link) { + RoutePrefix *q; + Prefix *p; int r; assert(link); @@ -658,29 +689,24 @@ int radv_configure(Link *link) { return r; } - if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { - RoutePrefix *q; - Prefix *p; - - HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); - if (r == -EEXIST) - continue; - if (r == -ENOEXEC) { - log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section."); - continue; - } - if (r < 0) - return r; + HASHMAP_FOREACH(p, link->network->prefixes_by_section) { + r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); + if (r == -EEXIST) + continue; + if (r == -ENOEXEC) { + log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section."); + continue; } + if (r < 0) + return r; + } - HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) { - r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false); - if (r == -EEXIST) - continue; - if (r < 0) - return r; - } + HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) { + r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false); + if (r == -EEXIST) + continue; + if (r < 0) + return r; } return 0; @@ -771,6 +797,12 @@ int config_parse_radv_dns( assert(lvalue); assert(rvalue); + if (isempty(rvalue)) { + n->n_router_dns = 0; + n->router_dns = mfree(n->router_dns); + return 0; + } + for (const char *p = rvalue;;) { _cleanup_free_ char *w = NULL; union in_addr_union a; @@ -832,6 +864,11 @@ int config_parse_radv_search_domains( assert(lvalue); assert(rvalue); + if (isempty(rvalue)) { + n->router_search_domains = ordered_set_free(n->router_search_domains); + return 0; + } + for (const char *p = rvalue;;) { _cleanup_free_ char *w = NULL, *idna = NULL; @@ -855,7 +892,7 @@ int config_parse_radv_search_domains( /* transfer ownership to simplify subsequent operations */ idna = TAKE_PTR(w); - r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops); + r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops_free); if (r < 0) return log_oom(); @@ -877,11 +914,51 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( RADVPrefixDelegation, RADV_PREFIX_DELEGATION_BOTH); -DEFINE_CONFIG_PARSE_ENUM( - config_parse_router_prefix_delegation, - radv_prefix_delegation, - RADVPrefixDelegation, - "Invalid router prefix delegation"); +int config_parse_router_prefix_delegation( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + RADVPrefixDelegation val, *ra = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(lvalue, "IPv6SendRA")) { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users + * need to explicitly enable DHCPv6PrefixDelegation=. */ + *ra = r ? RADV_PREFIX_DELEGATION_STATIC : RADV_PREFIX_DELEGATION_NONE; + return 0; + } + + /* For backward compatibility */ + val = radv_prefix_delegation_from_string(rvalue); + if (val < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + *ra = val; + return 0; +} int config_parse_router_preference( const char *unit, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index fbb93a9acc..75c606d15e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -47,6 +47,7 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix); void network_drop_invalid_prefixes(Network *network); void network_drop_invalid_route_prefixes(Network *network); +void network_adjust_radv(Network *network); int radv_emit_dns(Link *link); int radv_configure(Link *link); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 1494daa0c1..cb0c3205a0 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -137,6 +137,7 @@ SendVendorOption= RouteMetric= [DHCPv6PrefixDelegation] SubnetId= +Announce= Assign= Token= [Route] @@ -190,6 +191,7 @@ DNSOverTLS= Bond= IPv6ProxyNDP= DNS= +DNSDefaultRoute= ActiveSlave= LLMNR= DNSSEC= @@ -207,6 +209,7 @@ ConfigureWithoutCarrier= NTP= DHCP= Domains= +IPv6SendRA= IPv6PrefixDelegation= VLAN= DHCPServer= @@ -214,6 +217,7 @@ BindCarrier= VRF= IgnoreCarrierLoss= KeepConfiguration= +DHCPv6PrefixDelegation= [IPv6Prefix] Prefix= OnLink= @@ -270,11 +274,20 @@ InvertRule= Family= SuppressPrefixLength= User= +[IPv6SendRA] +RouterPreference= +DNSLifetimeSec= +DNS= +RouterLifetimeSec= +Domains= +EmitDNS= +EmitDomains= +Managed= +OtherInformation= [IPv6PrefixDelegation] RouterPreference= DNSLifetimeSec= DNS= -DNSDefaultRoute= RouterLifetimeSec= Domains= EmitDNS= diff --git a/test/test-network/conf/ipv6-prefix.network b/test/test-network/conf/ipv6-prefix.network index 9de0e3147b..aec1d1b2c3 100644 --- a/test/test-network/conf/ipv6-prefix.network +++ b/test/test-network/conf/ipv6-prefix.network @@ -2,9 +2,9 @@ Name=veth-peer [Network] -IPv6PrefixDelegation=yes +IPv6SendRA=yes -[IPv6PrefixDelegation] +[IPv6SendRA] DNS=_link_local 2002:da8:1:0::1 DNSLifetimeSec=1min diff --git a/test/test-network/conf/ipv6ra-prefix.network b/test/test-network/conf/ipv6ra-prefix.network index 9dc32cb4da..a0ac1e4537 100644 --- a/test/test-network/conf/ipv6ra-prefix.network +++ b/test/test-network/conf/ipv6ra-prefix.network @@ -3,7 +3,7 @@ Name=veth99 [Network] DHCP=no -IPv6PrefixDelegation=yes +IPv6SendRA=yes [IPv6Prefix] Prefix=2001:db8:0:1::/64 |