diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 75a581816d..9dc9a4673d 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1945,6 +1945,15 @@
DNS=.
+
+ LPRServers=
+
+ Similar to the DNS= setting described above, this
+ setting configures whether and what LPR (line printer) server information shall be emitted
+ as part of the DHCP lease. The same syntax, propagation semantics and defaults apply as for
+ DNS=.
+
+
EmitRouter=
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index ce2244a8fe..be723ddbbc 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -127,6 +127,11 @@ static int link_push_uplink_to_dhcp_server(
lease_condition = link->network->dhcp_use_sip;
break;
+ case SD_DHCP_LEASE_LPR_SERVERS:
+ servers = link->network->lpr;
+ lease_condition = true;
+ break;
+
default:
assert_not_reached("Uknown DHCP lease info item");
}
@@ -238,6 +243,11 @@ int dhcp4_server_configure(Link *link) {
link->network->dhcp_server_smtp,
link->network->n_dhcp_server_smtp,
},
+ [SD_DHCP_LEASE_LPR_SERVERS] = {
+ true,
+ link->network->dhcp_server_lpr,
+ link->network->n_dhcp_server_lpr,
+ },
};
assert_cc(ELEMENTSOF(configs) == _SD_DHCP_LEASE_INFO_MAX);
@@ -454,3 +464,23 @@ int config_parse_dhcp_server_smtp_servers(
&n->dhcp_server_smtp, &n->n_dhcp_server_smtp);
}
+
+int config_parse_dhcp_server_lpr_servers(
+ 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 *n = data;
+
+ return config_parse_dhcp_lease_server_list(unit, filename, line,
+ lvalue, rvalue,
+ &n->dhcp_server_lpr, &n->n_dhcp_server_lpr);
+
+}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
index 9da475dd3f..898e9acd52 100644
--- a/src/network/networkd-dhcp-server.h
+++ b/src/network/networkd-dhcp-server.h
@@ -14,3 +14,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_pop3_servers);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_smtp_servers);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_lpr_servers);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 7672b33128..e261473f6f 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -3951,9 +3951,9 @@ static void link_save_dns(FILE *f, struct in_addr_data *dns, unsigned n_dns, boo
}
int link_save(Link *link) {
+ const char *admin_state, *oper_state, *carrier_state, *address_state;
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *admin_state, *oper_state, *carrier_state, *address_state;
Address *a;
Route *route;
Iterator i;
@@ -4112,6 +4112,12 @@ int link_save(Link *link) {
space = false;
fputstrv(f, link->network->smtp, NULL, &space);
+ fputc('\n', f);
+
+ fputs("LPR_SERVERS=", f);
+ space = false;
+ fputstrv(f, link->network->lpr, NULL, &space);
+
if (link->dhcp_lease) {
const struct in_addr *addresses;
@@ -4130,6 +4136,15 @@ int link_save(Link *link) {
space = true;
}
+ if (link->dhcp_lease) {
+ const struct in_addr *addresses;
+
+ r = sd_dhcp_lease_get_lpr_servers(link->dhcp_lease, &addresses);
+ if (r > 0)
+ if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
+ space = true;
+ }
+
if (link->network->dhcp6_use_ntp && dhcp6_lease) {
struct in6_addr *in6_addrs;
char **hosts;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 1348fcb9b3..2161f70ae1 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1490,7 +1490,7 @@ static int ordered_set_put_in4_addrv(OrderedSet *s,
static int manager_save(Manager *m) {
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = NULL,
- *smtp = NULL, *search_domains = NULL, *route_domains = NULL;
+ *smtp = NULL, *lpr = NULL, *search_domains = NULL, *route_domains = NULL;
const char *operstate_str, *carrier_state_str, *address_state_str;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
@@ -1524,8 +1524,12 @@ static int manager_save(Manager *m) {
return -ENOMEM;
smtp = ordered_set_new(&string_hash_ops);
- if (!smtp)
- return -ENOMEM;
+ if (!smtp)
+ return -ENOMEM;
+
+ lpr = ordered_set_new(&string_hash_ops);
+ if (!lpr)
+ return -ENOMEM;
search_domains = ordered_set_new(&dns_name_hash_ops);
if (!search_domains)
@@ -1618,6 +1622,14 @@ static int manager_save(Manager *m) {
} else if (r < 0 && r != -ENODATA)
return r;
+ r = sd_dhcp_lease_get_lpr_servers(link->dhcp_lease, &addresses);
+ if (r > 0) {
+ r = ordered_set_put_in4_addrv(lpr, addresses, r, in4_addr_is_non_local);
+ if (r < 0)
+ return r;
+ } else if (r < 0 && r != -ENODATA)
+ return r;
+
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
const char *domainname;
char **domains = NULL;
@@ -1671,6 +1683,7 @@ static int manager_save(Manager *m) {
ordered_set_print(f, "SIP=", sip);
ordered_set_print(f, "POP3_SERVERS=", pop3);
ordered_set_print(f, "SMTP_SERVERS=", smtp);
+ ordered_set_print(f, "LPR_SERVERS=", lpr);
ordered_set_print(f, "DOMAINS=", search_domains);
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 9597176b1c..c246dc5cc1 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -212,6 +212,7 @@ DHCPServer.EmitSIP, config_parse_bool,
DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0
DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_servers, 0, 0
DHCPServer.SMTPServers, config_parse_dhcp_server_smtp_servers, 0, 0
+DHCPServer.LPRServers, config_parse_dhcp_server_lpr_servers, 0, 0
DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router)
DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone)
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 240f6689dd..a99f679318 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -155,6 +155,9 @@ struct Network {
struct in_addr *dhcp_server_smtp;
unsigned n_dhcp_server_smtp;
+ struct in_addr *dhcp_server_lpr;
+ unsigned n_dhcp_server_lpr;
+
bool dhcp_server_emit_router;
bool dhcp_server_emit_timezone;
char *dhcp_server_timezone;
@@ -312,6 +315,7 @@ struct Network {
char **sip;
char **pop3;
char **smtp;
+ char **lpr;
char **bind_carrier;
};
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index 3d1d3bd684..5471e74592 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -43,6 +43,7 @@ static const char* const dhcp_lease_info_table[_SD_DHCP_LEASE_INFO_MAX] = {
[SD_DHCP_LEASE_SIP_SERVERS] = "SIP servers",
[SD_DHCP_LEASE_POP3_SERVERS] = "POP3 servers",
[SD_DHCP_LEASE_SMTP_SERVERS] = "SMTP servers",
+ [SD_DHCP_LEASE_LPR_SERVERS] = "LPR servers",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 147ea1b639..1cd18202f4 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -278,6 +278,7 @@ EmitSIP=
SIP=
POP3Servers=
SMTPServers=
+LPRServers=
EmitRouter=
MaxLeaseTimeSec=
DefaultLeaseTimeSec=