network: DHCP - add support to emit and receive SMTP server information

This commit is contained in:
Susant Sahani 2020-03-23 10:40:49 +01:00
parent 2c649ca1c9
commit f6269fe7bb
9 changed files with 182 additions and 15 deletions

View file

@ -1910,6 +1910,16 @@
<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>

View 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;
}

View 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);

View 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;

View 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);

View 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)

View 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);

View 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;
};

View file

@ -269,6 +269,7 @@ NTP=
EmitSIP=
SIP=
POP3Servers=
SMTPServers=
EmitRouter=
MaxLeaseTimeSec=
DefaultLeaseTimeSec=