diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 299c56df0a..e568ef9b45 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1770,6 +1770,15 @@ IPv6Token=prefixstable:2002:da8:1::
+
+ Label=
+
+ Specifies the label for the IPv4 address received from the DHCP server.
+ The label must be a 7-bit ASCII string with a length of 1…15 characters.
+ Defaults to unset.
+
+
+
UseDNS=
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 12fb85bf90..c35b5514a5 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -992,6 +992,12 @@ static int dhcp4_request_address(Link *link, bool announce) {
addr->route_metric = link->network->dhcp_route_metric;
addr->duplicate_address_detection = link->network->dhcp_send_decline ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO;
+ if (link->network->dhcp_label) {
+ addr->label = strdup(link->network->dhcp_label);
+ if (!addr->label)
+ return log_oom();
+ }
+
if (address_get(link, addr, NULL) < 0)
link->dhcp4_configured = false;
@@ -1876,6 +1882,39 @@ int config_parse_dhcp_fallback_lease_lifetime(const char *unit,
return 0;
}
+int config_parse_dhcp_label(
+ 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) {
+
+ char **label = data;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *label = mfree(*label);
+ return 0;
+ }
+
+ if (!address_label_valid(rvalue)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Address label is too long or invalid, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ return free_and_strdup_warn(label, rvalue);
+}
+
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
[DHCP_CLIENT_ID_DUID] = "duid",
diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h
index 152c2213b4..541fd62aa2 100644
--- a/src/network/networkd-dhcp4.h
+++ b/src/network/networkd-dhcp4.h
@@ -33,3 +33,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_fallback_lease_lifetime);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_label);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 9166376aaa..d5c8c1ff4b 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -212,6 +212,7 @@ DHCPv4.RequestOptions, config_parse_dhcp_request_options,
DHCPv4.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize)
DHCPv4.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname)
DHCPv4.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
+DHCPv4.Label, config_parse_dhcp_label, 0, offsetof(Network, dhcp_label)
DHCPv4.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)
DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCPv4.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp_mudurl)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index f16553a6d9..945ac60033 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -585,6 +585,7 @@ static Network *network_free(Network *network) {
free(network->dhcp_mudurl);
strv_free(network->dhcp_user_class);
free(network->dhcp_hostname);
+ free(network->dhcp_label);
set_free(network->dhcp_deny_listed_ip);
set_free(network->dhcp_allow_listed_ip);
set_free(network->dhcp_request_options);
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index bf0e1a733e..8b0b53b4f5 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -129,6 +129,7 @@ struct Network {
char *dhcp_mudurl;
char **dhcp_user_class;
char *dhcp_hostname;
+ char *dhcp_label;
uint64_t dhcp_max_attempts;
uint32_t dhcp_route_metric;
bool dhcp_route_metric_set;
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 2dca1cda3a..a05260b3b5 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -107,6 +107,7 @@ VendorClassIdentifier=
Hostname=
DUIDType=
UseHostname=
+Label=
CriticalConnection=
DUIDRawData=
RequestBroadcast=
diff --git a/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network
index 41d6ea40fa..5352956e7e 100644
--- a/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network
+++ b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network
@@ -14,3 +14,4 @@ Hostname=test-hostname
ClientIdentifier=mac
VendorClassIdentifier=SusantVendorTest
RouteTable=211
+Label=test-label
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index dffd728881..c74fb226be 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -4150,6 +4150,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
self.assertRegex(output, '12:34:56:78:9a:bc')
self.assertRegex(output, '192.168.5')
self.assertRegex(output, '1492')
+ self.assertRegex(output, 'test-label')
print('## ip route show table main dev veth99')
output = check_output('ip route show table main dev veth99')