From: Topi Miettinen Date: Sat, 20 Aug 2022 17:52:48 +0000 (+0300) Subject: network: NetLabel integration X-Git-Tag: v252-rc1~297^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b3590c32457c938b0e351053069ddb344f35b31;p=thirdparty%2Fsystemd.git network: NetLabel integration New directive `NetLabel=` provides a method for integrating static and dynamic network configuration into Linux NetLabel subsystem rules, used by Linux Security Modules (LSMs) for network access control. The label, with suitable LSM rules, can be used to control connectivity of (for example) a service with peers in the local network. At least with SELinux, only the ingress can be controlled but not egress. The benefit of using this setting is that it may be possible to apply interface independent part of NetLabel configuration at very early stage of system boot sequence, at the time when the network interfaces are not available yet, with netlabelctl(8), and the per-interface configuration with systemd-networkd once the interfaces appear later. Currently this feature is only implemented for SELinux. The option expects a single NetLabel label. The label must conform to lexical restrictions of LSM labels. When an interface is configured with IP addresses, the addresses and subnetwork masks will be appended to the NetLabel Fallback Peer Labeling rules. They will be removed when the interface is deconfigured. Failures to manage the labels will be ignored. Example: ``` [DHCPv4] NetLabel=system_u:object_r:localnet_peer_t:s0 ``` With the above rules for interface `eth0`, when the interface is configured with an IPv4 address of 10.0.0.123/8, `systemd-networkd` performs the equivalent of `netlabelctl` operation ``` $ sudo netlabelctl unlbl add interface eth0 address:10.0.0.0/8 label:system_u:object_r:localnet_peer_t:s0 ``` Result: ``` $ sudo netlabelctl -p unlbl list ... interface: eth0 address: 10.0.0.0/8 label: "system_u:object_r:localnet_peer_t:s0" ... ``` --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index b9d74d60977..4f516748edb 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1121,6 +1121,62 @@ Table=1234 Defaults to no. + + + NetLabel=label + + + This setting provides a method for integrating static and dynamic network configuration into + Linux NetLabel subsystem rules, + used by Linux Security Modules + (LSMs) for network access control. The label, with suitable LSM rules, can be used to + control connectivity of (for example) a service with peers in the local network. At least with + SELinux, only the ingress can be controlled but not egress. The benefit of using this setting is + that it may be possible to apply interface independent part of NetLabel configuration at very early + stage of system boot sequence, at the time when the network interfaces are not available yet, with + netlabelctl8, + and the per-interface configuration with systemd-networkd once the interfaces + appear later. Currently this feature is only implemented for SELinux. + + The option expects a single NetLabel label. The label must conform to lexical restrictions of + LSM labels. When an interface is configured with IP addresses, the addresses and subnetwork masks + will be appended to the NetLabel + Fallback Peer Labeling rules. They will be removed when the interface is + deconfigured. Failures to manage the labels will be ignored. + + Warning: Once labeling is enabled for network traffic, a lot of LSM access control points in + Linux networking stack go from dormant to active. Care should be taken to avoid getting into a + situation where for example remote connectivity is broken, when the security policy hasn't been + updated to consider LSM per-packet access controls and no rules would allow any network + traffic. Also note that additional configuration with netlabelctl8 + is needed. + + Example: + [Address] +NetLabel=system_u:object_r:localnet_peer_t:s0 + + With the example rules applying for interface eth0, when the interface is + configured with an IPv4 address of 10.0.0.123/8, systemd-networkd performs the + equivalent of netlabelctl operation + + netlabelctl unlbl add interface eth0 address:10.0.0.0/8 label:system_u:object_r:localnet_peer_t:s0 + + and the reverse operation when the IPv4 address is deconfigured. The configuration can be used with + LSM rules; in case of SELinux to allow a SELinux domain to receive data from objects of SELinux + peer class. For example: + + type localnet_peer_t; +allow my_server_t localnet_peer_t:peer recv; + + The effect of the above configuration and rules (in absence of other rules as may be the case) is + to only allow my_server_t (and nothing else) to receive data from local subnet + 10.0.0.0/8 of interface eth0. + + + @@ -2071,6 +2127,15 @@ Table=1234 RFC 5227. Defaults to false. + + + NetLabel= + + This applies the NetLabel for the addresses received with DHCP, like + NetLabel= in [Address] section applies it to statically configured + addresses. See NetLabel= in [Address] section for more details. + + @@ -2197,6 +2262,7 @@ Table=1234 UseNTP= UseHostname= UseDomains= + NetLabel= As in the [DHCPv4] section. @@ -2298,6 +2364,15 @@ Table=1234 + + + NetLabel= + + This applies the NetLabel for the addresses received with DHCP, like + NetLabel= in [Address] section applies it to statically configured + addresses. See NetLabel= in [Address] section for more details. + + @@ -2555,6 +2630,15 @@ Token=prefixstable:2002:da8:1:: specified. Defaults to true. + + + NetLabel= + + This applies the NetLabel for the addresses received with RA, like + NetLabel= in [Address] section applies it to statically configured + addresses. See NetLabel= in [Address] section for more details. + + diff --git a/src/network/meson.build b/src/network/meson.build index 2315b56a333..e4def6bc51e 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -115,6 +115,8 @@ sources = files( 'networkd-ndisc.h', 'networkd-neighbor.c', 'networkd-neighbor.h', + 'networkd-netlabel.c', + 'networkd-netlabel.h', 'networkd-network-bus.c', 'networkd-network-bus.h', 'networkd-network.c', diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 0cd6c1498da..d7333b634ee 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -12,6 +12,7 @@ #include "networkd-dhcp-server.h" #include "networkd-ipv4acd.h" #include "networkd-manager.h" +#include "networkd-netlabel.h" #include "networkd-network.h" #include "networkd-queue.h" #include "networkd-route-util.h" @@ -137,6 +138,7 @@ Address *address_free(Address *address) { config_section_free(address->section); free(address->label); + free(address->netlabel); return mfree(address); } @@ -392,6 +394,7 @@ int address_dup(const Address *src, Address **ret) { dest->link = NULL; dest->label = NULL; dest->acd = NULL; + dest->netlabel = NULL; if (src->family == AF_INET) { r = free_and_strdup(&dest->label, src->label); @@ -399,6 +402,10 @@ int address_dup(const Address *src, Address **ret) { return r; } + r = free_and_strdup(&dest->netlabel, src->netlabel); + if (r < 0) + return r; + *ret = TAKE_PTR(dest); return 0; } @@ -485,6 +492,8 @@ static int address_update(Address *address) { if (r < 0) return log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); + address_add_netlabel(address); + if (address_is_ready(address) && address->callback) { r = address->callback(address); if (r < 0) @@ -511,6 +520,8 @@ static int address_drop(Address *address) { if (r < 0) log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m"); + address_del_netlabel(address); + if (address->state == 0) address_free(address); @@ -1941,6 +1952,47 @@ int config_parse_duplicate_address_detection( return 0; } +int config_parse_address_netlabel( + 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) { + + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + assert(network); + + r = address_new_static(network, filename, section_line, &n); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to allocate new address, ignoring assignment: %m"); + return 0; + } + + r = config_parse_string(unit, filename, line, section, section_line, + lvalue, CONFIG_PARSE_STRING_SAFE, rvalue, &n->netlabel, network); + if (r < 0) + return r; + + TAKE_PTR(n); + return 0; +} + static int address_section_verify(Address *address) { if (section_is_invalid(address->section)) return -EINVAL; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index f97342504cf..d1eff9090a9 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -38,7 +38,7 @@ struct Address { unsigned char scope; uint32_t flags; uint32_t route_metric; /* route metric for prefix route */ - char *label; + char *label, *netlabel; int set_broadcast; struct in_addr broadcast; @@ -130,3 +130,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_address_flags); CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric); CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection); +CONFIG_PARSER_PROTOTYPE(config_parse_address_netlabel); diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 62f0192bcbb..5c883ba37d0 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -412,6 +412,10 @@ static int dhcp_pd_request_address( log_dhcp_pd_address(link, address); + r = free_and_strdup_warn(&address->netlabel, link->network->dhcp_pd_netlabel); + if (r < 0) + return r; + if (address_get(link, address, &existing) < 0) link->dhcp_pd_configured = false; else diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 4df2848c546..02deac00338 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -877,6 +877,10 @@ static int dhcp4_request_address(Link *link, bool announce) { if (r < 0) return r; + r = free_and_strdup_warn(&addr->netlabel, link->network->dhcp_netlabel); + if (r < 0) + return r; + if (address_get(link, addr, &existing) < 0) /* The address is new. */ link->dhcp4_configured = false; else diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 4293eb62421..501e210d5fb 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -224,6 +224,10 @@ static int dhcp6_request_address( if (verify_dhcp6_address(link, addr) < 0) return 0; + r = free_and_strdup_warn(&addr->netlabel, link->network->dhcp6_netlabel); + if (r < 0) + return r; + if (address_get(link, addr, &existing) < 0) link->dhcp6_configured = false; else diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 579282136f2..12168a20fb4 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -278,6 +278,10 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) { address->source = NETWORK_CONFIG_SOURCE_NDISC; address->provider.in6 = router; + r = free_and_strdup_warn(&address->netlabel, link->network->ndisc_netlabel); + if (r < 0) + return r; + if (address_get(link, address, &existing) < 0) link->ndisc_configured = false; else diff --git a/src/network/networkd-netlabel.c b/src/network/networkd-netlabel.c new file mode 100644 index 00000000000..94bf8f5d268 --- /dev/null +++ b/src/network/networkd-netlabel.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "escape.h" +#include "netlink-util.h" +#include "networkd-address.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-netlabel.h" +#include "networkd-network.h" + +static int netlabel_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert_se(rtnl); + assert_se(m); + assert_se(link); + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_link_message_warning_errno(link, m, r, "NetLabel operation failed, ignoring"); + return 1; + } + + log_link_debug(link, "NetLabel operation successful"); + + return 1; +} + +static int netlabel_command(uint16_t command, const char *label, const Address *address) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(command != NLBL_UNLABEL_C_UNSPEC && command < __NLBL_UNLABEL_C_MAX); + assert(address); + assert(address->link); + assert(address->link->ifname); + assert(address->link->manager); + assert(address->link->manager->genl); + assert(IN_SET(address->family, AF_INET, AF_INET6)); + + r = sd_genl_message_new(address->link->manager->genl, NETLBL_NLTYPE_UNLABELED_NAME, command, &m); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(m, NLBL_UNLABEL_A_IFACE, address->link->ifname); + if (r < 0) + return r; + + if (command == NLBL_UNLABEL_C_STATICADD) { + assert(label); + r = sd_netlink_message_append_string(m, NLBL_UNLABEL_A_SECCTX, label); + if (r < 0) + return r; + } + + union in_addr_union netmask, masked_addr; + r = in_addr_prefixlen_to_netmask(address->family, &netmask, address->prefixlen); + if (r < 0) + return r; + + /* + * When adding rules, kernel adds the address to its hash table _applying also the netmask_, but on + * removal, an exact match is required _without netmask applied_, so apply the mask on both + * operations. + */ + masked_addr = address->in_addr; + r = in_addr_mask(address->family, &masked_addr, address->prefixlen); + if (r < 0) + return r; + + if (address->family == AF_INET) { + r = sd_netlink_message_append_in_addr(m, NLBL_UNLABEL_A_IPV4ADDR, &masked_addr.in); + if (r < 0) + return r; + + r = sd_netlink_message_append_in_addr(m, NLBL_UNLABEL_A_IPV4MASK, &netmask.in); + } else if (address->family == AF_INET6) { + r = sd_netlink_message_append_in6_addr(m, NLBL_UNLABEL_A_IPV6ADDR, &masked_addr.in6); + if (r < 0) + return r; + + r = sd_netlink_message_append_in6_addr(m, NLBL_UNLABEL_A_IPV6MASK, &netmask.in6); + } + if (r < 0) + return r; + + r = netlink_call_async(address->link->manager->genl, NULL, m, netlabel_handler, link_netlink_destroy_callback, + address->link); + if (r < 0) + return r; + + link_ref(address->link); + return 0; +} + +void address_add_netlabel(const Address *address) { + int r; + + assert(address); + + if (!address->netlabel) + return; + + r = netlabel_command(NLBL_UNLABEL_C_STATICADD, address->netlabel, address); + if (r < 0) + log_link_warning_errno(address->link, r, "Adding NetLabel %s for IP address %s failed, ignoring", address->netlabel, + IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); + else + log_link_debug(address->link, "Adding NetLabel %s for IP address %s", address->netlabel, + IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); +} + +void address_del_netlabel(const Address *address) { + int r; + + assert(address); + + if (!address->netlabel) + return; + + r = netlabel_command(NLBL_UNLABEL_C_STATICREMOVE, address->netlabel, address); + if (r < 0) + log_link_warning_errno(address->link, r, "Deleting NetLabel %s for IP address %s failed, ignoring", address->netlabel, + IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); + else + log_link_debug(address->link, "Deleting NetLabel %s for IP address %s", address->netlabel, + IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); +} diff --git a/src/network/networkd-netlabel.h b/src/network/networkd-netlabel.h new file mode 100644 index 00000000000..2f30b8fedae --- /dev/null +++ b/src/network/networkd-netlabel.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +void address_add_netlabel(const Address *address); +void address_del_netlabel(const Address *address); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index dce7339d2f0..aec54528498 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -25,6 +25,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-ipv6ll.h" #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" +#include "networkd-netlabel.h" #include "networkd-network.h" #include "networkd-neighbor.h" #include "networkd-nexthop.h" @@ -158,6 +159,7 @@ Address.AutoJoin, config_parse_address_flags, Address.DuplicateAddressDetection, config_parse_duplicate_address_detection, 0, 0 Address.Scope, config_parse_address_scope, 0, 0 Address.RouteMetric, config_parse_address_route_metric, 0, 0 +Address.NetLabel, config_parse_address_netlabel, 0, 0 IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 IPv6AddressLabel.Label, config_parse_address_label, 0, 0 Neighbor.Address, config_parse_neighbor_address, 0, 0 @@ -246,6 +248,7 @@ DHCPv4.SendVendorOption, config_parse_dhcp_send_option, DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu) DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0 DHCPv4.Use6RD, config_parse_bool, 0, offsetof(Network, dhcp_use_6rd) +DHCPv4.NetLabel, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp_netlabel) DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address) DHCPv6.UseDelegatedPrefix, config_parse_bool, 0, offsetof(Network, dhcp6_use_pd_prefix) DHCPv6.UseDNS, config_parse_dhcp_use_dns, AF_INET6, 0 @@ -264,6 +267,7 @@ DHCPv6.IAID, config_parse_iaid, DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid) DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, dhcp6_duid) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_use_rapid_commit) +DHCPv6.NetLabel, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp6_netlabel) IPv6AcceptRA.UseGateway, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_gateway) IPv6AcceptRA.UseRoutePrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_route_prefix) IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) @@ -281,6 +285,7 @@ IPv6AcceptRA.PrefixDenyList, config_parse_in_addr_prefixes, IPv6AcceptRA.RouteAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_route_prefix) IPv6AcceptRA.RouteDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_route_prefix) IPv6AcceptRA.Token, config_parse_address_generation_type, 0, offsetof(Network, ndisc_tokens) +IPv6AcceptRA.NetLabel, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, ndisc_netlabel) DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0 DHCPServer.UplinkInterface, config_parse_uplink, 0, 0 DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target) @@ -347,6 +352,7 @@ DHCPPrefixDelegation.Assign, config_parse_bool, DHCPPrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp_pd_manage_temporary_address) DHCPPrefixDelegation.Token, config_parse_address_generation_type, 0, offsetof(Network, dhcp_pd_tokens) DHCPPrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp_pd_route_metric) +DHCPPrefixDelegation.NetLabel, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp_pd_netlabel) IPv6SendRA.RouterLifetimeSec, config_parse_router_lifetime, 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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 61b900ada2d..00bbaf6eab5 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -712,6 +712,7 @@ static Network *network_free(Network *network) { set_free(network->dhcp_request_options); ordered_hashmap_free(network->dhcp_client_send_options); ordered_hashmap_free(network->dhcp_client_send_vendor_options); + free(network->dhcp_netlabel); /* DHCPv6 client */ free(network->dhcp6_mudurl); @@ -720,10 +721,12 @@ static Network *network_free(Network *network) { set_free(network->dhcp6_request_options); ordered_hashmap_free(network->dhcp6_client_send_options); ordered_hashmap_free(network->dhcp6_client_send_vendor_options); + free(network->dhcp6_netlabel); /* DHCP PD */ free(network->dhcp_pd_uplink_name); set_free(network->dhcp_pd_tokens); + free(network->dhcp_pd_netlabel); /* Router advertisement */ ordered_set_free(network->router_search_domains); @@ -738,6 +741,7 @@ static Network *network_free(Network *network) { set_free(network->ndisc_deny_listed_route_prefix); set_free(network->ndisc_allow_listed_route_prefix); set_free(network->ndisc_tokens); + free(network->ndisc_netlabel); /* LLDP */ free(network->lldp_mudurl); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 3df7eee555e..a2743f97434 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -155,6 +155,7 @@ struct Network { Set *dhcp_request_options; OrderedHashmap *dhcp_client_send_options; OrderedHashmap *dhcp_client_send_vendor_options; + char *dhcp_netlabel; /* DHCPv6 Client support */ bool dhcp6_use_address; @@ -180,6 +181,7 @@ struct Network { OrderedHashmap *dhcp6_client_send_options; OrderedHashmap *dhcp6_client_send_vendor_options; Set *dhcp6_request_options; + char *dhcp6_netlabel; /* DHCP Server Support */ bool dhcp_server; @@ -237,6 +239,7 @@ struct Network { Set *dhcp_pd_tokens; int dhcp_pd_uplink_index; char *dhcp_pd_uplink_name; + char *dhcp_pd_netlabel; /* Bridge Support */ int use_bpdu; @@ -321,6 +324,7 @@ struct Network { Set *ndisc_deny_listed_route_prefix; Set *ndisc_allow_listed_route_prefix; Set *ndisc_tokens; + char *ndisc_netlabel; /* LLDP support */ LLDPMode lldp_mode; /* LLDP reception */ diff --git a/test/fuzz/fuzz-network-parser/directives b/test/fuzz/fuzz-network-parser/directives index 6f76f7ee18c..171322ef204 100644 --- a/test/fuzz/fuzz-network-parser/directives +++ b/test/fuzz/fuzz-network-parser/directives @@ -132,6 +132,7 @@ MUDURL= RouteMTUBytes= FallbackLeaseLifetimeSec= Use6RD= +NetLabel= [DHCPv6] UseAddress= UseDelegatedPrefix= @@ -153,6 +154,7 @@ RouteMetric= IAID= DUIDType= DUIDRawData= +NetLabel= [DHCPv6PrefixDelegation] SubnetId= Announce= @@ -160,6 +162,7 @@ Assign= ManageTemporaryAddress= Token= RouteMetric= +NetLabel= [DHCPPrefixDelegation] UplinkInterface= SubnetId= @@ -168,6 +171,7 @@ Assign= ManageTemporaryAddress= Token= RouteMetric= +NetLabel= [Route] Destination= Protocol= @@ -346,6 +350,7 @@ EmitDomains= Managed= OtherInformation= UplinkInterface= +NetLabel= [IPv6PrefixDelegation] RouterPreference= DNSLifetimeSec=