]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: NetLabel integration
authorTopi Miettinen <toiwoton@gmail.com>
Sat, 20 Aug 2022 17:52:48 +0000 (20:52 +0300)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 29 Aug 2022 05:23:17 +0000 (14:23 +0900)
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"
...
```

14 files changed:
man/systemd.network.xml
src/network/meson.build
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-ndisc.c
src/network/networkd-netlabel.c [new file with mode: 0644]
src/network/networkd-netlabel.h [new file with mode: 0644]
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives

index b9d74d6097799838ef83e8423067702e9c7a7e4c..4f516748edb9175a774e6cc95887686d8b5cdfb3 100644 (file)
@@ -1121,6 +1121,62 @@ Table=1234</programlisting></para>
           Defaults to <literal>no</literal>.</para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>NetLabel=</varname><replaceable>label</replaceable></term>
+        <listitem>
+
+          <para>This setting provides a method for integrating static and dynamic network configuration into
+          Linux <ulink url="https://docs.kernel.org/netlabel/index.html">NetLabel</ulink> subsystem rules,
+          used by <ulink url="https://en.wikipedia.org/wiki/Linux_Security_Modules">Linux Security Modules
+          (LSMs)</ulink> 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
+          <citerefentry
+          project='man-pages'><refentrytitle>netlabelctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+          and the per-interface configuration with <command>systemd-networkd</command> once the interfaces
+          appear later. Currently this feature is only implemented for SELinux.</para>
+
+          <para>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 <ulink
+          url="https://github.com/SELinuxProject/selinux-notebook/blob/main/src/network_support.md">NetLabel
+          Fallback Peer Labeling</ulink> rules. They will be removed when the interface is
+          deconfigured. Failures to manage the labels will be ignored.</para>
+
+          <para>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 <citerefentry
+          project='man-pages'><refentrytitle>netlabelctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+          is needed.</para>
+
+          <para>Example:
+          <programlisting>[Address]
+NetLabel=system_u:object_r:localnet_peer_t:s0</programlisting>
+
+          With the example rules applying for interface <literal>eth0</literal>, when the interface is
+          configured with an IPv4 address of 10.0.0.123/8, <command>systemd-networkd</command> performs the
+          equivalent of <command>netlabelctl</command> operation
+
+          <programlisting>netlabelctl unlbl add interface eth0 address:10.0.0.0/8 label:system_u:object_r:localnet_peer_t:s0</programlisting>
+
+          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
+          <literal>peer</literal> class. For example:
+
+          <programlisting>type localnet_peer_t;
+allow my_server_t localnet_peer_t:peer recv;</programlisting>
+
+          The effect of the above configuration and rules (in absence of other rules as may be the case) is
+          to only allow <literal>my_server_t</literal> (and nothing else) to receive data from local subnet
+          10.0.0.0/8 of interface <literal>eth0</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
@@ -2071,6 +2127,15 @@ Table=1234</programlisting></para>
           <ulink url="https://tools.ietf.org/html/rfc5227">RFC 5227</ulink>. Defaults to false.</para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>NetLabel=</varname></term>
+        <listitem>
+          <para>This applies the NetLabel for the addresses received with DHCP, like
+          <varname>NetLabel=</varname> in [Address] section applies it to statically configured
+          addresses. See <varname>NetLabel=</varname> in [Address] section for more details.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
@@ -2197,6 +2262,7 @@ Table=1234</programlisting></para>
         <term><varname>UseNTP=</varname></term>
         <term><varname>UseHostname=</varname></term>
         <term><varname>UseDomains=</varname></term>
+        <term><varname>NetLabel=</varname></term>
         <listitem>
           <para>As in the [DHCPv4] section.</para>
         </listitem>
@@ -2298,6 +2364,15 @@ Table=1234</programlisting></para>
           </para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>NetLabel=</varname></term>
+        <listitem>
+          <para>This applies the NetLabel for the addresses received with DHCP, like
+          <varname>NetLabel=</varname> in [Address] section applies it to statically configured
+          addresses. See <varname>NetLabel=</varname> in [Address] section for more details.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
@@ -2555,6 +2630,15 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
           specified. Defaults to true.</para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>NetLabel=</varname></term>
+        <listitem>
+          <para>This applies the NetLabel for the addresses received with RA, like
+          <varname>NetLabel=</varname> in [Address] section applies it to statically configured
+          addresses. See <varname>NetLabel=</varname> in [Address] section for more details.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index 2315b56a3337b4187a71481263274aa638c227f3..e4def6bc51e2cdd61ec81d90f748362aad3cf75d 100644 (file)
@@ -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',
index 0cd6c1498da854a4d0a21c22ce3f2a786b199444..d7333b634eea5f396cce7930e9631c3628daa8fc 100644 (file)
@@ -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;
index f97342504cf452cae5fe50638b433d9d0e521d92..d1eff9090a9a593dd53212d3b0049514b246c582 100644 (file)
@@ -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);
index 62f0192bcbb0a0f8aeeded717bb462501201da6c..5c883ba37d021d16cf6ff0ed67a06432742af696 100644 (file)
@@ -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
index 4df2848c546718afd9203470f9d346e6db5f815e..02deac00338d22af05f2dfb9c7bc21dddd50c045 100644 (file)
@@ -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
index 4293eb624215de4563de9fc53c31671c6e716522..501e210d5fb9c35b96548f6102e3c2226e506fca 100644 (file)
@@ -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
index 579282136f2c8f1e6dee2afaeb9443d559b514ad..12168a20fb4a43374f5f8ac3201c12f14165b5ed 100644 (file)
@@ -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 (file)
index 0000000..94bf8f5
--- /dev/null
@@ -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 (file)
index 0000000..2f30b8f
--- /dev/null
@@ -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);
index dce7339d2f092cde4c6914d1cdf5bf3724bb2ed6..aec5452849822ed95dc9ce0198e394779338f181 100644 (file)
@@ -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)
index 61b900ada2dfcb13df33f8e891c5ee9dca57469e..00bbaf6eab5687021baf4b8318ae9fdc9c51bb8e 100644 (file)
@@ -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);
index 3df7eee555e3b71e210ed38a5d3627f90edde2df..a2743f97434b3734a853ee422f36b917d609e5de 100644 (file)
@@ -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 */
index 6f76f7ee18c64f50317c434fccbb60ae086e3a3b..171322ef2043773e27b3ada4ac6ac044f90ac0fe 100644 (file)
@@ -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=