From 284e8fd0d7bb18ca5fc1ff9dcd8a9cf10d33f16a Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 27 Mar 2020 21:12:07 +0100 Subject: [PATCH] DHCP: Add support to emit and retrieve POP3 server --- man/systemd.network.xml | 10 ++ src/network/networkd-dhcp-server.c | 117 ++++++++++++++++++ src/network/networkd-dhcp-server.h | 1 + src/network/networkd-link.c | 15 +++ src/network/networkd-manager.c | 28 +++-- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.h | 4 + .../fuzz-network-parser/directives.network | 1 + 8 files changed, 168 insertions(+), 9 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 5457e668dd..4b2e8b8614 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/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 2ec742b5e3..83caef6fc0 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 c90d48ec00..a388f6b81c 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 f38cc9f3cf..376596bf57 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 804f33d6cb..656f52b440 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 fd996327a5..25730b58f7 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 f747ccaf10..58b310f59e 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/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 4418fc0149..01cc490c96 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=