diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 5457e668dd2..4b2e8b86149 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1386,6 +1386,7 @@
read via sd_network_link_get_sip_servers() function.
+
UseMTU=
@@ -1903,6 +1904,15 @@
DNS=.
+
+ POP3Servers=
+
+ Similar to the DNS= settings described above, these
+ settings configure whether and what POP3 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/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h
index a2d0f8bd5e7..efc79768381 100644
--- a/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/libsystemd-network/dhcp-lease-internal.h
@@ -61,6 +61,9 @@ struct sd_dhcp_lease {
struct in_addr *sip;
size_t sip_size;
+ struct in_addr *pop3_server;
+ size_t pop3_server_size;
+
struct sd_dhcp_route *static_route;
size_t static_route_size, static_route_allocated;
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index 41901894f57..468bd303dcc 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -55,8 +55,8 @@ struct sd_dhcp_server {
char *timezone;
- struct in_addr *ntp, *dns, *sip;
- unsigned n_ntp, n_dns, n_sip;
+ struct in_addr *ntp, *dns, *sip, *pop3_server;
+ unsigned n_ntp, n_dns, n_sip, n_pop3_server;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index d072f1c57a0..4a6c56ecbf5 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -129,6 +129,17 @@ int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
return (int) lease->sip_size;
}
+int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (lease->pop3_server_size <= 0)
+ return -ENODATA;
+
+ *addr = lease->pop3_server;
+ return (int) lease->pop3_server_size;
+}
+
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL);
@@ -279,6 +290,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
free(lease->dns);
free(lease->ntp);
free(lease->sip);
+ free(lease->pop3_server);
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
@@ -601,6 +613,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
break;
+ case SD_DHCP_OPTION_POP3_SERVER:
+ r = lease_parse_in_addrs(option, len, &lease->pop3_server, &lease->pop3_server_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
+ break;
+
case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0)
@@ -1037,6 +1055,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
*dns = NULL,
*ntp = NULL,
*sip = NULL,
+ *pop3_server = NULL,
*mtu = NULL,
*routes = NULL,
*domains = NULL,
@@ -1066,6 +1085,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"DNS", &dns,
"NTP", &ntp,
"SIP", &sip,
+ "POP3_SERVERS", &pop3_server,
"MTU", &mtu,
"DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname,
@@ -1178,6 +1198,14 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
lease->sip_size = r;
}
+ if (pop3_server) {
+ r = deserialize_in_addrs(&lease->pop3_server, pop3_server);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3_server);
+ else
+ lease->pop3_server_size = r;
+ }
+
if (mtu) {
r = safe_atou16(mtu, &lease->mtu);
if (r < 0)
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index a0b779bc096..89a487cf017 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -140,6 +140,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
free(server->dns);
free(server->ntp);
free(server->sip);
+ free(server->pop3_server);
hashmap_free(server->leases_by_client_id);
@@ -513,6 +514,15 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
return r;
}
+ if (server->n_pop3_server > 0) {
+ r = dhcp_option_append(
+ &packet->dhcp, req->max_optlen, &offset, 0,
+ SD_DHCP_OPTION_POP3_SERVER,
+ sizeof(struct in_addr) * server->n_pop3_server, server->pop3_server);
+ if (r < 0)
+ return r;
+ }
+
if (server->timezone) {
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
@@ -1181,6 +1191,31 @@ int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], u
return 1;
}
+int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr pop3_server[], unsigned n) {
+ assert_return(server, -EINVAL);
+ assert_return(pop3_server || n <= 0, -EINVAL);
+
+ if (server->n_pop3_server == n &&
+ memcmp(server->pop3_server, pop3_server, sizeof(struct in_addr) * n) == 0)
+ return 0;
+
+ if (n <= 0) {
+ server->pop3_server = mfree(server->pop3_server);
+ server->n_pop3_server = 0;
+ } else {
+ struct in_addr *c;
+
+ c = newdup(struct in_addr, pop3_server, n);
+ if (!c)
+ return -ENOMEM;
+
+ free_and_replace(server->pop3_server, c);
+ server->n_pop3_server = n;
+ }
+
+ return 1;
+}
+
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
assert_return(server, -EINVAL);
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 964200a55e9..a5ab5b3c364 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -256,6 +256,10 @@ _public_ int sd_network_link_get_sip_servers(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "SIP", ret);
}
+_public_ int sd_network_link_get_pop3_servers(int ifindex, char ***pop3) {
+ return network_link_get_strv(ifindex, "POP3_SERVERS", pop3);
+}
+
_public_ int sd_network_link_get_dns_default_route(int ifindex) {
char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
_cleanup_free_ char *s = NULL;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index b68798769be..cfe511c3870 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -1240,7 +1240,8 @@ static int link_status_one(
sd_hwdb *hwdb,
const LinkInfo *info) {
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL,
+ **pop3_server = NULL;
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_free_ char *t = NULL, *network = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
@@ -1267,6 +1268,7 @@ static int link_status_one(
(void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
(void) sd_network_link_get_ntp(info->ifindex, &ntp);
(void) sd_network_link_get_sip(info->ifindex, &sip);
+ (void) sd_network_link_get_pop3_servers(info->ifindex, &pop3_server);
if (info->sd_device) {
(void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link);
@@ -1827,6 +1829,9 @@ static int link_status_one(
if (r < 0)
return r;
r = dump_list(table, "SIP:", sip);
+ if (r < 0)
+ return r;
+ r = dump_list(table, "POP3 servers:", pop3_server);
if (r < 0)
return r;
r = dump_ifindexes(table, "Carrier Bound To:", carrier_bound_to);
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index 2ec742b5e32..83caef6fc0d 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -140,6 +140,55 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
}
+static int link_push_uplink_pop3_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ char **a;
+
+ if (!link->network)
+ return 0;
+
+ log_link_debug(link, "Copying POP3 server information from link");
+
+ STRV_FOREACH(a, link->network->pop3) {
+ union in_addr_union ia;
+
+ /* Only look for IPv4 addresses */
+ if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
+ continue;
+
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia.in;
+ }
+
+ if (link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int j, n;
+
+ n = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_pop3_server(s, addresses, n_addresses);
+}
+
static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
_cleanup_free_ struct in_addr *addresses = NULL;
size_t n_addresses = 0, n_allocated = 0;
@@ -281,6 +330,22 @@ int dhcp4_server_configure(Link *link) {
log_link_warning_errno(link, r, "Failed to set SIP server for DHCP server, ignoring: %m");
}
+ if (link->network->n_dhcp_server_pop3 > 0)
+ r = sd_dhcp_server_set_pop3_server(link->dhcp_server, link->network->dhcp_server_pop3, link->network->n_dhcp_server_pop3);
+ else {
+ if (!acquired_uplink)
+ uplink = manager_find_uplink(link->manager, link);
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting POP3 server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_uplink_pop3_to_dhcp_server(uplink, link->dhcp_server);
+
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set POP3 server for DHCP server, ignoring: %m");
+
r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set router emission for DHCP server: %m");
@@ -486,3 +551,55 @@ int config_parse_dhcp_server_sip(
n->dhcp_server_sip = m;
}
}
+
+int config_parse_dhcp_server_pop3_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;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+ struct in_addr *m;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = in_addr_from_string(AF_INET, w, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse POP3 server address '%s', ignoring: %m", w);
+ continue;
+ }
+
+ m = reallocarray(n->dhcp_server_pop3, n->n_dhcp_server_pop3 + 1, sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
+
+ m[n->n_dhcp_server_pop3++] = a.in;
+ n->dhcp_server_pop3 = m;
+ }
+}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
index c90d48ec002..a388f6b81c7 100644
--- a/src/network/networkd-dhcp-server.h
+++ b/src/network/networkd-dhcp-server.h
@@ -12,3 +12,4 @@ int dhcp4_server_configure(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
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);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index f38cc9f3cfd..376596bf57b 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -4100,6 +4100,21 @@ int link_save(Link *link) {
space = true;
}
+ fputc('\n', f);
+
+ fputs("POP3_SERVERS=", f);
+ space = false;
+ fputstrv(f, link->network->pop3, NULL, &space);
+
+ if (link->dhcp_lease) {
+ const struct in_addr *addresses;
+
+ r = sd_dhcp_lease_get_pop3_server(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 804f33d6cb4..656f52b4402 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1488,7 +1488,8 @@ 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, *search_domains = NULL, *route_domains = NULL;
+ _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = 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;
@@ -1496,6 +1497,7 @@ static int manager_save(Manager *m) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
+ const struct in_addr *addresses;
Link *link;
Iterator i;
int r;
@@ -1512,10 +1514,14 @@ static int manager_save(Manager *m) {
if (!ntp)
return -ENOMEM;
- sip = ordered_set_new(&string_hash_ops);
- if (!sip)
+ sip = ordered_set_new(&string_hash_ops);
+ if (!sip)
return -ENOMEM;
+ pop3 = ordered_set_new(&string_hash_ops);
+ if (!pop3)
+ return -ENOMEM;
+
search_domains = ordered_set_new(&dns_name_hash_ops);
if (!search_domains)
return -ENOMEM;
@@ -1562,8 +1568,6 @@ static int manager_save(Manager *m) {
/* Secondly, add the entries acquired via DHCP */
if (link->network->dhcp_use_dns) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
@@ -1574,8 +1578,6 @@ static int manager_save(Manager *m) {
}
if (link->network->dhcp_use_ntp) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
@@ -1586,8 +1588,6 @@ static int manager_save(Manager *m) {
}
if (link->network->dhcp_use_sip) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
@@ -1597,6 +1597,15 @@ static int manager_save(Manager *m) {
return r;
}
+
+ r = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &addresses);
+ if (r > 0) {
+ r = ordered_set_put_in4_addrv(pop3, 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;
@@ -1648,6 +1657,7 @@ static int manager_save(Manager *m) {
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
ordered_set_print(f, "SIP=", sip);
+ ordered_set_print(f, "POP3_SERVERS=", pop3);
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 fd996327a55..25730b58f79 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -207,6 +207,7 @@ DHCPServer.EmitNTP, config_parse_bool,
DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0
DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_sip)
DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0
+DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_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 f747ccaf101..58b310f59ea 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -147,6 +147,9 @@ struct Network {
struct in_addr *dhcp_server_sip;
unsigned n_dhcp_server_sip;
+ struct in_addr *dhcp_server_pop3;
+ unsigned n_dhcp_server_pop3;
+
bool dhcp_server_emit_router;
bool dhcp_server_emit_timezone;
char *dhcp_server_timezone;
@@ -296,6 +299,7 @@ struct Network {
char **ntp;
char **sip;
+ char **pop3;
char **bind_carrier;
};
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 9dd562fa43f..b8ffe78468d 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -83,6 +83,7 @@ enum {
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_POP3_SERVER = 70,
SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h
index b80d607fea6..e216c768d4a 100644
--- a/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/sd-dhcp-lease.h
@@ -45,6 +45,7 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index 55272b5164d..98db7aded56 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -50,6 +50,7 @@ int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone);
int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n);
int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n);
int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n);
+int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr pop3_server[], unsigned n);
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 1e6d3540110..ea06c9d8752 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -167,6 +167,9 @@ int sd_network_link_get_route_domains(int ifindex, char ***domains);
/* Get the sip servers for a given link. */
int sd_network_link_get_sip_servers(int ifindex, char ***sip);
+/* Get the pop3 servers for a given link. */
+int sd_network_link_get_pop3_servers(int ifindex, char ***pop3);
+
/* Get whether this link shall be used as 'default route' for DNS queries */
int sd_network_link_get_dns_default_route(int ifindex);
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 4418fc01495..01cc490c96d 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -268,6 +268,7 @@ EmitDNS=
NTP=
EmitSIP=
SIP=
+POP3Servers=
EmitRouter=
MaxLeaseTimeSec=
DefaultLeaseTimeSec=