]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: DHCP - add support to emit and receive SMTP server information
authorSusant Sahani <ssahani@vmware.com>
Mon, 23 Mar 2020 09:40:49 +0000 (10:40 +0100)
committerSusant Sahani <ssahani@vmware.com>
Sun, 29 Mar 2020 20:59:11 +0000 (22:59 +0200)
man/systemd.network.xml
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives.network

index 4b2e8b8614964a715401a285b339bbfa0576ec6a..2ead483519e7810fc9f18e6073fe2fae6b2da7d9 100644 (file)
         <listitem><para>Similar to the <varname>DNS=</varname> 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
+        <term><varname>SMTPServers=</varname></term>
+        <varname>DNS=</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>SMTPServers=</varname></term>
+
+        <listitem><para>Similar to the <varname>DNS=</varname> setting described above, this
+        setting configures whether and what SMTP server information shall be emitted as part of
+        the DHCP lease. The same syntax, propagation semantics and defaults apply as for
         <varname>DNS=</varname>.</para></listitem>
       </varlistentry>
 
index 83caef6fc0d2f28f28cbe64e35a7ac79dd16c1a1..bbaa10f5ab276e0b945144331178cbcd3be624db 100644 (file)
@@ -189,6 +189,55 @@ static int link_push_uplink_pop3_to_dhcp_server(Link *link, sd_dhcp_server *s) {
         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;
@@ -330,21 +379,36 @@ 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 (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 (!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");
 
-                }
-                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)
@@ -550,6 +614,8 @@ int config_parse_dhcp_server_sip(
                 m[n->n_dhcp_server_sip++] = a.in;
                 n->dhcp_server_sip = m;
         }
+
+        return 0;
 }
 
 int config_parse_dhcp_server_pop3_servers(
@@ -602,4 +668,60 @@ int config_parse_dhcp_server_pop3_servers(
                 m[n->n_dhcp_server_pop3++] = a.in;
                 n->dhcp_server_pop3 = m;
         }
+
+        return 0;
+}
+
+int config_parse_dhcp_server_smtp_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 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;
 }
index a388f6b81c74059bfb1f520c034be33b14cede50..9da475dd3f4e1fdbc8ec3da4c20d8e57976bd1bd 100644 (file)
@@ -13,3 +13,4 @@ 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);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_smtp_servers);
index 376596bf57bd16326b5fbf81a6a36c36697f6f1a..7672b33128cc4b7f3050f3c8844ba202024a1c1f 100644 (file)
@@ -4106,6 +4106,12 @@ int link_save(Link *link) {
                 space = false;
                 fputstrv(f, link->network->pop3, NULL, &space);
 
+                fputc('\n', f);
+
+                fputs("SMTP_SERVERS=", f);
+                space = false;
+                fputstrv(f, link->network->smtp, NULL, &space);
+
                 if (link->dhcp_lease) {
                         const struct in_addr *addresses;
 
@@ -4115,6 +4121,15 @@ int link_save(Link *link) {
                                         space = true;
                 }
 
+                if (link->dhcp_lease) {
+                        const struct in_addr *addresses;
+
+                        r = sd_dhcp_lease_get_smtp_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;
index 656f52b4402c82ebe9ff217e0a7db2da5181f51c..24e662bc0c17e3a85737a7c4ec7ecc2685a05229 100644 (file)
@@ -1489,7 +1489,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,
-                     *search_domains = NULL, *route_domains = NULL;
+                *smtp = 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;
@@ -1520,6 +1520,10 @@ static int manager_save(Manager *m) {
 
         pop3 = ordered_set_new(&string_hash_ops);
         if (!pop3)
+                return -ENOMEM;
+
+        smtp = ordered_set_new(&string_hash_ops);
+       if (!smtp)
                return -ENOMEM;
 
         search_domains = ordered_set_new(&dns_name_hash_ops);
@@ -1597,7 +1601,6 @@ 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);
@@ -1606,6 +1609,14 @@ static int manager_save(Manager *m) {
                 } else if (r < 0 && r != -ENODATA)
                         return r;
 
+                r = sd_dhcp_lease_get_smtp_server(link->dhcp_lease, &addresses);
+                if (r > 0) {
+                        r = ordered_set_put_in4_addrv(smtp, 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;
@@ -1658,6 +1669,7 @@ static int manager_save(Manager *m) {
         ordered_set_print(f, "NTP=", ntp);
         ordered_set_print(f, "SIP=", sip);
         ordered_set_print(f, "POP3_SERVERS=", pop3);
+        ordered_set_print(f, "SMTP_SERVERS=", smtp);
         ordered_set_print(f, "DOMAINS=", search_domains);
         ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
 
index 25730b58f795fb868491e34991d69d9ed765d475..04d411c4adbc9e9577256824bb345adea5c1d785 100644 (file)
@@ -208,6 +208,7 @@ DHCPServer.NTP,                              config_parse_dhcp_server_ntp,
 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.SMTPServers,                      config_parse_dhcp_server_smtp_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)
index e7ead446c7640227874263790168a09adfa426f6..0165b0b91a44d58f8392b2dfaea873ae6d83e359 100644 (file)
@@ -651,6 +651,7 @@ static Network *network_free(Network *network) {
         strv_free(network->ntp);
         free(network->dns);
         strv_free(network->sip);
+        strv_free(network->smtp);
         ordered_set_free_free(network->search_domains);
         ordered_set_free_free(network->route_domains);
         strv_free(network->bind_carrier);
index 58b310f59ea1066e7cd303ff72ba76bab1f40748..fe2878978470e5fe6e7b3f5ae0a8dc232d4ee5f1 100644 (file)
@@ -150,6 +150,9 @@ struct Network {
         struct in_addr *dhcp_server_pop3;
         unsigned n_dhcp_server_pop3;
 
+        struct in_addr *dhcp_server_smtp;
+        unsigned n_dhcp_server_smtp;
+
         bool dhcp_server_emit_router;
         bool dhcp_server_emit_timezone;
         char *dhcp_server_timezone;
@@ -300,6 +303,7 @@ struct Network {
         char **ntp;
         char **sip;
         char **pop3;
+        char **smtp;
         char **bind_carrier;
 };
 
index 01cc490c96d8f80cfb0db1b2f0bea5a55c49d387..e1af20694171d73a05d5bdebabb756b7e6f7cef9 100644 (file)
@@ -269,6 +269,7 @@ NTP=
 EmitSIP=
 SIP=
 POP3Servers=
+SMTPServers=
 EmitRouter=
 MaxLeaseTimeSec=
 DefaultLeaseTimeSec=