From 8541db8f5932898fe7b08625f718b8cfcd149b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 2 Apr 2020 15:42:31 +0200 Subject: [PATCH 1/5] sd-dhcp-lease: add a meta-getter to simplify querying of server lists --- src/libsystemd-network/sd-dhcp-lease.c | 99 ++++++++++++++------------ src/systemd/sd-dhcp-lease.h | 10 +++ 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 1b7b6e1068..5154af2304 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -96,59 +96,70 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { return 0; } +int sd_dhcp_lease_get_servers( + sd_dhcp_lease *lease, + sd_dhcp_lease_info what, + const struct in_addr **addr) { + + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + switch (what) { + case SD_DHCP_LEASE_DNS_SERVERS: + if (lease->dns_size <= 0) + return -ENODATA; + + *addr = lease->dns; + return (int) lease->dns_size; + + case SD_DHCP_LEASE_NTP_SERVERS: + if (lease->ntp_size <= 0) + return -ENODATA; + + *addr = lease->ntp; + return (int) lease->ntp_size; + + case SD_DHCP_LEASE_SIP_SERVERS: + if (lease->sip_size <= 0) + return -ENODATA; + + *addr = lease->sip; + return (int) lease->sip_size; + + case SD_DHCP_LEASE_POP3_SERVERS: + if (lease->pop3_server_size <= 0) + return -ENODATA; + + *addr = lease->pop3_server; + return (int) lease->pop3_server_size; + + case SD_DHCP_LEASE_SMTP_SERVERS: + if (lease->smtp_server_size <= 0) + return -ENODATA; + + *addr = lease->smtp_server; + return (int) lease->smtp_server_size; + + default: + log_debug("Uknown DHCP lease info item %d.", what); + return -ENXIO; + } +} + int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->dns_size <= 0) - return -ENODATA; - - *addr = lease->dns; - return (int) lease->dns_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS_SERVERS, addr); } - int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->ntp_size <= 0) - return -ENODATA; - - *addr = lease->ntp; - return (int) lease->ntp_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP_SERVERS, addr); } - int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->sip_size <= 0) - return -ENODATA; - - *addr = lease->sip; - return (int) lease->sip_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP_SERVERS, addr); } - 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; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3_SERVERS, addr); } - int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->smtp_server_size <= 0) - return -ENODATA; - - *addr = lease->smtp_server; - return (int) lease->smtp_server_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP_SERVERS, addr); } int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h index 1ed5bf27a3..70544e13f1 100644 --- a/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/sd-dhcp-lease.h @@ -33,6 +33,15 @@ typedef struct sd_dhcp_route sd_dhcp_route; sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); +typedef enum sd_dhcp_lease_info { + SD_DHCP_LEASE_DNS_SERVERS = 0, + SD_DHCP_LEASE_NTP_SERVERS, + SD_DHCP_LEASE_SIP_SERVERS, + SD_DHCP_LEASE_POP3_SERVERS, + SD_DHCP_LEASE_SMTP_SERVERS, + _SD_DHCP_LEASE_INFO_MAX, +} sd_dhcp_lease_info; + int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); @@ -42,6 +51,7 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_info what, const struct in_addr **addr); 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); From c8407baf30be465f667e5ea9ef7702860041a16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 2 Apr 2020 16:16:31 +0200 Subject: [PATCH 2/5] sd-dhcp-server: add a meta-setter to simplify setting of server lists --- src/libsystemd-network/sd-dhcp-server.c | 187 +++++++++--------------- src/systemd/sd-dhcp-server.h | 10 +- 2 files changed, 77 insertions(+), 120 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index ee4a7249c2..a4dcddd95d 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1123,132 +1123,81 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { return 1; } +int sd_dhcp_server_set_servers( + sd_dhcp_server *server, + sd_dhcp_lease_info what, + const struct in_addr addresses[], + unsigned n_addresses) { + + assert_return(server, -EINVAL); + assert_return(addresses || n_addresses == 0, -EINVAL); + + struct in_addr **a; + unsigned *n_a; + + switch (what) { + case SD_DHCP_LEASE_DNS_SERVERS: + a = &server->dns; + n_a = &server->n_dns; + break; + + case SD_DHCP_LEASE_NTP_SERVERS: + a = &server->ntp; + n_a = &server->n_ntp; + break; + + case SD_DHCP_LEASE_SIP_SERVERS: + a = &server->sip; + n_a = &server->n_sip; + break; + + case SD_DHCP_LEASE_POP3_SERVERS: + a = &server->pop3_server; + n_a = &server->n_pop3_server; + break; + + case SD_DHCP_LEASE_SMTP_SERVERS: + a = &server->smtp_server; + n_a = &server->n_smtp_server; + break; + + default: + log_debug("Uknown DHCP lease info item %d.", what); + return -ENXIO; + } + + if (*n_a == n_addresses && + memcmp(*a, addresses, sizeof(struct in_addr) * n_addresses) == 0) + return 0; + + struct in_addr *c = NULL; + + if (n_addresses > 0) { + c = newdup(struct in_addr, addresses, n_addresses); + if (!c) + return -ENOMEM; + } + + free(*a); + *a = c; + *n_a = n_addresses; + return 1; +} + int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) { - assert_return(server, -EINVAL); - assert_return(dns || n <= 0, -EINVAL); - - if (server->n_dns == n && - memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0) - return 0; - - if (n <= 0) { - server->dns = mfree(server->dns); - server->n_dns = 0; - } else { - struct in_addr *c; - - c = newdup(struct in_addr, dns, n); - if (!c) - return -ENOMEM; - - free(server->dns); - server->dns = c; - server->n_dns = n; - } - - return 1; + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_DNS_SERVERS, dns, n); } - int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) { - assert_return(server, -EINVAL); - assert_return(ntp || n <= 0, -EINVAL); - - if (server->n_ntp == n && - memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0) - return 0; - - if (n <= 0) { - server->ntp = mfree(server->ntp); - server->n_ntp = 0; - } else { - struct in_addr *c; - - c = newdup(struct in_addr, ntp, n); - if (!c) - return -ENOMEM; - - free(server->ntp); - server->ntp = c; - server->n_ntp = n; - } - - return 1; + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_NTP_SERVERS, ntp, n); } - int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n) { - assert_return(server, -EINVAL); - assert_return(sip || n <= 0, -EINVAL); - - if (server->n_sip == n && - memcmp(server->sip, sip, sizeof(struct in_addr) * n) == 0) - return 0; - - if (n <= 0) { - server->sip = mfree(server->sip); - server->n_sip = 0; - } else { - struct in_addr *c; - - c = newdup(struct in_addr, sip, n); - if (!c) - return -ENOMEM; - - free(server->sip); - server->sip = c; - server->n_sip = n; - } - - return 1; + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SIP_SERVERS, sip, n); } - -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_pop3_server(sd_dhcp_server *server, const struct in_addr pop3[], unsigned n) { + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_POP3_SERVERS, pop3, n); } - -int sd_dhcp_server_set_smtp_server(sd_dhcp_server *server, const struct in_addr smtp_server[], unsigned n) { - assert_return(server, -EINVAL); - assert_return(smtp_server || n <= 0, -EINVAL); - - if (server->n_smtp_server == n && - memcmp(server->smtp_server, smtp_server, sizeof(struct in_addr) * n) == 0) - return 0; - - if (n <= 0) { - server->smtp_server = mfree(server->smtp_server); - server->n_smtp_server = 0; - } else { - struct in_addr *c; - - c = newdup(struct in_addr, smtp_server, n); - if (!c) - return -ENOMEM; - - free_and_replace(server->smtp_server, c); - server->n_smtp_server = n; - } - - return 1; +int sd_dhcp_server_set_smtp_server(sd_dhcp_server *server, const struct in_addr smtp[], unsigned n) { + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SMTP_SERVERS, smtp, n); } int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) { diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 5f04034b82..4c7938ca70 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -21,6 +21,7 @@ #include #include +#include "sd-dhcp-lease.h" #include "sd-dhcp-option.h" #include "sd-event.h" @@ -47,12 +48,19 @@ int sd_dhcp_server_stop(sd_dhcp_server *server); int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size); int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); +int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled); + +int sd_dhcp_server_set_servers( + sd_dhcp_server *server, + sd_dhcp_lease_info what, + const struct in_addr addresses[], + unsigned n_addresses); + 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_smtp_server(sd_dhcp_server *server, const struct in_addr smtp_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); int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v); From ddc026f303d7c6bab1801d54f7f323de67b1ad5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 2 Apr 2020 17:33:38 +0200 Subject: [PATCH 3/5] network: define string lookup table for the DHCP info bits --- src/network/networkd-util.c | 17 +++++++++++++---- src/network/networkd-util.h | 5 +++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index deba995372..3d1d3bd684 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -8,14 +8,14 @@ #include "string-util.h" #include "util.h" -static const char * const address_family_table[_ADDRESS_FAMILY_MAX] = { +static const char* const address_family_table[_ADDRESS_FAMILY_MAX] = { [ADDRESS_FAMILY_NO] = "no", [ADDRESS_FAMILY_YES] = "yes", [ADDRESS_FAMILY_IPV4] = "ipv4", [ADDRESS_FAMILY_IPV6] = "ipv6", }; -static const char * const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = { +static const char* const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = { [ADDRESS_FAMILY_NO] = "no", [ADDRESS_FAMILY_YES] = "yes", [ADDRESS_FAMILY_IPV4] = "ipv4", @@ -24,25 +24,34 @@ static const char * const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback", }; -static const char * const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = { +static const char* const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = { [ADDRESS_FAMILY_YES] = "both", [ADDRESS_FAMILY_IPV4] = "ipv4", [ADDRESS_FAMILY_IPV6] = "ipv6", }; -static const char * const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = { +static const char* const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = { [ADDRESS_FAMILY_NO] = "none", [ADDRESS_FAMILY_YES] = "both", [ADDRESS_FAMILY_IPV4] = "ipv4", [ADDRESS_FAMILY_IPV6] = "ipv6", }; +static const char* const dhcp_lease_info_table[_SD_DHCP_LEASE_INFO_MAX] = { + [SD_DHCP_LEASE_DNS_SERVERS] = "DNS servers", + [SD_DHCP_LEASE_NTP_SERVERS] = "NTP servers", + [SD_DHCP_LEASE_SIP_SERVERS] = "SIP servers", + [SD_DHCP_LEASE_POP3_SERVERS] = "POP3 servers", + [SD_DHCP_LEASE_SMTP_SERVERS] = "SMTP servers", +}; + DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES); DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES); DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily); DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily); DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family, AddressFamily, "Failed to parse option"); +DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_info, sd_dhcp_lease_info); int config_parse_address_family_with_kernel( const char* unit, diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index 28dd9d3fe5..48411b0cf5 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "sd-dhcp-lease.h" + #include "conf-parser.h" #include "hash-funcs.h" #include "macro.h" @@ -38,6 +40,9 @@ AddressFamily routing_policy_rule_address_family_from_string(const char *s) _pur const char *duplicate_address_detection_address_family_to_string(AddressFamily b) _const_; AddressFamily duplicate_address_detection_address_family_from_string(const char *s) _pure_; +const char *dhcp_lease_info_to_string(sd_dhcp_lease_info info) _const_; +sd_dhcp_lease_info dhcp_lease_info_from_string(const char *s) _pure_; + int kernel_route_expiration_supported(void); int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s); From c1997a5bf7db4ee862e3c07653e5ac9295484ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 2 Apr 2020 11:59:47 +0200 Subject: [PATCH 4/5] network: add helper to extract server lists This code is repeable enough to define a common implementation. --- src/network/networkd-dhcp-server.c | 247 +++++++---------------------- 1 file changed, 60 insertions(+), 187 deletions(-) diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index bbaa10f5ab..f27f7247f4 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -458,6 +458,51 @@ int dhcp4_server_configure(Link *link) { return 0; } +static int config_parse_dhcp_lease_server_list( + const char *unit, + const char *filename, + unsigned line, + const char *lvalue, + const char *rvalue, + struct in_addr **addresses, + unsigned *n_addresses) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (const char *p = rvalue;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + int r; + + 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 %s= address '%s', ignoring: %m", lvalue, w); + continue; + } + + struct in_addr *m = reallocarray(*addresses, *n_addresses + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[(*n_addresses)++] = a.in; + *addresses = m; + } +} + int config_parse_dhcp_server_dns( const char *unit, const char *filename, @@ -471,45 +516,10 @@ int config_parse_dhcp_server_dns( 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) - break; - - r = in_addr_from_string(AF_INET, w, &a); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse DNS server address '%s', ignoring assignment: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_dns++] = a.in; - n->dhcp_server_dns = m; - } - - return 0; + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_dns, &n->n_dhcp_server_dns); } int config_parse_dhcp_server_ntp( @@ -525,43 +535,10 @@ int config_parse_dhcp_server_ntp( 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 NTP server address '%s', ignoring: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_ntp++] = a.in; - n->dhcp_server_ntp = m; - } + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_ntp, &n->n_dhcp_server_ntp); } int config_parse_dhcp_server_sip( @@ -577,45 +554,10 @@ int config_parse_dhcp_server_sip( 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 SIP server address '%s', ignoring: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_sip, n->n_dhcp_server_sip + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_sip++] = a.in; - n->dhcp_server_sip = m; - } - - return 0; + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_sip, &n->n_dhcp_server_sip); } int config_parse_dhcp_server_pop3_servers( @@ -631,45 +573,10 @@ int config_parse_dhcp_server_pop3_servers( 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; - } - - return 0; + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_pop3, &n->n_dhcp_server_pop3); } int config_parse_dhcp_server_smtp_servers( @@ -685,43 +592,9 @@ int config_parse_dhcp_server_smtp_servers( void *userdata) { Network *n = data; - const char *p = rvalue; - int r; - assert(filename); - assert(lvalue); - assert(rvalue); + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_smtp, &n->n_dhcp_server_smtp); - 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 SMTP server address '%s', ignoring: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_smtp, n->n_dhcp_server_smtp + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_smtp++] = a.in; - n->dhcp_server_smtp = m; - } - - return 0; } From 24e6f45842d04288025205206801f92e7ec85ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 2 Apr 2020 12:32:32 +0200 Subject: [PATCH 5/5] network: use a loop for repetitive operation This should hopefully help us avoid c&p mistakes. And there are plans to add more settings like this, which should then be rather straightforward. There is a slight functional change: the code got uplink handling wrong and run manager_find_uplink() repeatedly. That part is fixed. --- src/network/networkd-dhcp-server.c | 348 +++++++++-------------------- 1 file changed, 102 insertions(+), 246 deletions(-) diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index f27f7247f4..ce2244a8fe 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -45,11 +45,6 @@ static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { size_t n_addresses = 0, n_allocated = 0; unsigned i; - log_link_debug(link, "Copying DNS server information from link"); - - if (!link->network) - return 0; - for (i = 0; i < link->network->n_dns; i++) { struct in_addr ia; @@ -91,17 +86,53 @@ static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { return sd_dhcp_server_set_dns(s, addresses, n_addresses); } -static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { +static int link_push_uplink_to_dhcp_server( + Link *link, + sd_dhcp_lease_info what, + sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; - char **a; + bool lease_condition; + char **servers; if (!link->network) return 0; - log_link_debug(link, "Copying NTP server information from link"); + log_link_debug(link, "Copying %s from link", dhcp_lease_info_to_string(what)); - STRV_FOREACH(a, link->network->ntp) { + switch (what) { + case SD_DHCP_LEASE_DNS_SERVERS: + /* DNS servers are stored as parsed data, so special handling is required. + * TODO: check if DNS servers should be stored unparsed too. */ + return link_push_uplink_dns_to_dhcp_server(link, s); + + case SD_DHCP_LEASE_NTP_SERVERS: + servers = link->network->ntp; + lease_condition = link->network->dhcp_use_ntp; + break; + + case SD_DHCP_LEASE_POP3_SERVERS: + servers = link->network->pop3; + lease_condition = true; + break; + + case SD_DHCP_LEASE_SMTP_SERVERS: + servers = link->network->smtp; + lease_condition = true; + break; + + case SD_DHCP_LEASE_SIP_SERVERS: + servers = link->network->sip; + lease_condition = link->network->dhcp_use_sip; + break; + + default: + assert_not_reached("Uknown DHCP lease info item"); + } + + char **a; + STRV_FOREACH(a, servers) { union in_addr_union ia; /* Only look for IPv4 addresses */ @@ -118,173 +149,24 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { addresses[n_addresses++] = ia.in; } - if (link->network->dhcp_use_ntp && link->dhcp_lease) { - const struct in_addr *da = NULL; - int j, n; + if (lease_condition && link->dhcp_lease) { + const struct in_addr *da; - n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); + size_t n = sd_dhcp_lease_get_servers(link->dhcp_lease, what, &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]; + for (unsigned i = 0; i < n; i++) + if (in4_addr_is_non_local(&da[i])) + addresses[n_addresses++] = da[i]; } } if (n_addresses <= 0) return 0; - 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_smtp_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 SMTP server information from link"); - - STRV_FOREACH(a, link->network->smtp) { - 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_smtp_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_smtp_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; - char **a; - - if (!link->network) - return 0; - - log_link_debug(link, "Copying SIP server information from link"); - - STRV_FOREACH(a, link->network->sip) { - 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->network->dhcp_use_sip && link->dhcp_lease) { - const struct in_addr *da = NULL; - int j, n; - - n = sd_dhcp_lease_get_sip(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_sip(s, addresses, n_addresses); + return sd_dhcp_server_set_servers(s, what, addresses, n_addresses); } int dhcp4_server_configure(Link *link) { @@ -326,89 +208,63 @@ int dhcp4_server_configure(Link *link) { return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m"); } - if (link->network->dhcp_server_emit_dns) { - if (link->network->n_dhcp_server_dns > 0) - r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); - else { - uplink = manager_find_uplink(link->manager, link); - acquired_uplink = true; + const struct { + bool condition; + const struct in_addr *servers; + unsigned n_servers; + } configs[] = { + [SD_DHCP_LEASE_DNS_SERVERS] = { + link->network->dhcp_server_emit_dns, + link->network->dhcp_server_dns, + link->network->n_dhcp_server_dns, + }, + [SD_DHCP_LEASE_NTP_SERVERS] = { + link->network->dhcp_server_emit_ntp, + link->network->dhcp_server_ntp, + link->network->n_dhcp_server_ntp, + }, + [SD_DHCP_LEASE_SIP_SERVERS] = { + link->network->dhcp_server_emit_sip, + link->network->dhcp_server_sip, + link->network->n_dhcp_server_sip, + }, + [SD_DHCP_LEASE_POP3_SERVERS] = { + true, + link->network->dhcp_server_pop3, + link->network->n_dhcp_server_pop3, + }, + [SD_DHCP_LEASE_SMTP_SERVERS] = { + true, + link->network->dhcp_server_smtp, + link->network->n_dhcp_server_smtp, + }, + }; + assert_cc(ELEMENTSOF(configs) == _SD_DHCP_LEASE_INFO_MAX); - if (!uplink) { - log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server); + for (unsigned n = 0; n < ELEMENTSOF(configs); n++) + if (configs[n].condition) { + if (configs[n].n_servers > 0) + r = sd_dhcp_server_set_servers(link->dhcp_server, n, + configs[n].servers, configs[n].n_servers); + else { + if (!acquired_uplink) { + uplink = manager_find_uplink(link->manager, link); + acquired_uplink = true; + } + + if (!uplink) { + log_link_debug(link, + "Not emitting %s on link, couldn't find suitable uplink.", + dhcp_lease_info_to_string(n)); + r = 0; + } else + r = link_push_uplink_to_dhcp_server(uplink, n, link->dhcp_server); + } + if (r < 0) + log_link_warning_errno(link, r, + "Failed to set %s for DHCP server, ignoring: %m", + dhcp_lease_info_to_string(n)); } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); - } - - if (link->network->dhcp_server_emit_ntp) { - if (link->network->n_dhcp_server_ntp > 0) - r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); - else { - if (!acquired_uplink) - uplink = manager_find_uplink(link->manager, link); - - if (!uplink) { - log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server); - - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); - } - - if (link->network->dhcp_server_emit_sip) { - if (link->network->n_dhcp_server_sip > 0) - r = sd_dhcp_server_set_sip(link->dhcp_server, link->network->dhcp_server_sip, link->network->n_dhcp_server_sip); - else { - if (!acquired_uplink) - uplink = manager_find_uplink(link->manager, link); - - if (!uplink) { - log_link_debug(link, "Not emitting sip server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_sip_to_dhcp_server(uplink, link->dhcp_server); - - } - if (r < 0) - 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"); - - if (link->network->n_dhcp_server_smtp > 0) - r = sd_dhcp_server_set_smtp_server(link->dhcp_server, link->network->dhcp_server_smtp, link->network->n_dhcp_server_smtp); - else { - if (!acquired_uplink) - uplink = manager_find_uplink(link->manager, link); - - if (!uplink) { - log_link_debug(link, "Not emitting SMTP server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_smtp_to_dhcp_server(uplink, link->dhcp_server); - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to SMTP 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)