Skip to content

Commit 284e8fd

Browse files
committed
DHCP: Add support to emit and retrieve POP3 server
1 parent f678ac7 commit 284e8fd

File tree

8 files changed

+168
-9
lines changed

8 files changed

+168
-9
lines changed

man/systemd.network.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@
13861386
read via <function>sd_network_link_get_sip_servers()</function> function.</para>
13871387
</listitem>
13881388
</varlistentry>
1389+
13891390
<varlistentry>
13901391
<term><varname>UseMTU=</varname></term>
13911392
<listitem>
@@ -1903,6 +1904,15 @@
19031904
<varname>DNS=</varname>.</para></listitem>
19041905
</varlistentry>
19051906

1907+
<varlistentry>
1908+
<term><varname>POP3Servers=</varname></term>
1909+
1910+
<listitem><para>Similar to the <varname>DNS=</varname> settings described above, these
1911+
settings configure whether and what POP3 server information shall be emitted as part of
1912+
the DHCP lease. The same syntax, propagation semantics and defaults apply as for
1913+
<varname>DNS=</varname>.</para></listitem>
1914+
</varlistentry>
1915+
19061916
<varlistentry>
19071917
<term><varname>EmitRouter=</varname></term>
19081918

src/network/networkd-dhcp-server.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,55 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
140140
return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
141141
}
142142

143+
static int link_push_uplink_pop3_to_dhcp_server(Link *link, sd_dhcp_server *s) {
144+
_cleanup_free_ struct in_addr *addresses = NULL;
145+
size_t n_addresses = 0, n_allocated = 0;
146+
char **a;
147+
148+
if (!link->network)
149+
return 0;
150+
151+
log_link_debug(link, "Copying POP3 server information from link");
152+
153+
STRV_FOREACH(a, link->network->pop3) {
154+
union in_addr_union ia;
155+
156+
/* Only look for IPv4 addresses */
157+
if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
158+
continue;
159+
160+
/* Never propagate obviously borked data */
161+
if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
162+
continue;
163+
164+
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
165+
return log_oom();
166+
167+
addresses[n_addresses++] = ia.in;
168+
}
169+
170+
if (link->dhcp_lease) {
171+
const struct in_addr *da = NULL;
172+
int j, n;
173+
174+
n = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &da);
175+
if (n > 0) {
176+
177+
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
178+
return log_oom();
179+
180+
for (j = 0; j < n; j++)
181+
if (in4_addr_is_non_local(&da[j]))
182+
addresses[n_addresses++] = da[j];
183+
}
184+
}
185+
186+
if (n_addresses <= 0)
187+
return 0;
188+
189+
return sd_dhcp_server_set_pop3_server(s, addresses, n_addresses);
190+
}
191+
143192
static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
144193
_cleanup_free_ struct in_addr *addresses = NULL;
145194
size_t n_addresses = 0, n_allocated = 0;
@@ -281,6 +330,22 @@ int dhcp4_server_configure(Link *link) {
281330
log_link_warning_errno(link, r, "Failed to set SIP server for DHCP server, ignoring: %m");
282331
}
283332

333+
if (link->network->n_dhcp_server_pop3 > 0)
334+
r = sd_dhcp_server_set_pop3_server(link->dhcp_server, link->network->dhcp_server_pop3, link->network->n_dhcp_server_pop3);
335+
else {
336+
if (!acquired_uplink)
337+
uplink = manager_find_uplink(link->manager, link);
338+
339+
if (!uplink) {
340+
log_link_debug(link, "Not emitting POP3 server information on link, couldn't find suitable uplink.");
341+
r = 0;
342+
} else
343+
r = link_push_uplink_pop3_to_dhcp_server(uplink, link->dhcp_server);
344+
345+
}
346+
if (r < 0)
347+
log_link_warning_errno(link, r, "Failed to set POP3 server for DHCP server, ignoring: %m");
348+
284349
r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
285350
if (r < 0)
286351
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(
486551
n->dhcp_server_sip = m;
487552
}
488553
}
554+
555+
int config_parse_dhcp_server_pop3_servers(
556+
const char *unit,
557+
const char *filename,
558+
unsigned line,
559+
const char *section,
560+
unsigned section_line,
561+
const char *lvalue,
562+
int ltype,
563+
const char *rvalue,
564+
void *data,
565+
void *userdata) {
566+
567+
Network *n = data;
568+
const char *p = rvalue;
569+
int r;
570+
571+
assert(filename);
572+
assert(lvalue);
573+
assert(rvalue);
574+
575+
for (;;) {
576+
_cleanup_free_ char *w = NULL;
577+
union in_addr_union a;
578+
struct in_addr *m;
579+
580+
r = extract_first_word(&p, &w, NULL, 0);
581+
if (r == -ENOMEM)
582+
return log_oom();
583+
if (r < 0) {
584+
log_syntax(unit, LOG_ERR, filename, line, r,
585+
"Failed to extract word, ignoring: %s", rvalue);
586+
return 0;
587+
}
588+
if (r == 0)
589+
return 0;
590+
591+
r = in_addr_from_string(AF_INET, w, &a);
592+
if (r < 0) {
593+
log_syntax(unit, LOG_ERR, filename, line, r,
594+
"Failed to parse POP3 server address '%s', ignoring: %m", w);
595+
continue;
596+
}
597+
598+
m = reallocarray(n->dhcp_server_pop3, n->n_dhcp_server_pop3 + 1, sizeof(struct in_addr));
599+
if (!m)
600+
return log_oom();
601+
602+
m[n->n_dhcp_server_pop3++] = a.in;
603+
n->dhcp_server_pop3 = m;
604+
}
605+
}

src/network/networkd-dhcp-server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ int dhcp4_server_configure(Link *link);
1212
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
1313
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
1414
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
15+
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_pop3_servers);

src/network/networkd-link.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4100,6 +4100,21 @@ int link_save(Link *link) {
41004100
space = true;
41014101
}
41024102

4103+
fputc('\n', f);
4104+
4105+
fputs("POP3_SERVERS=", f);
4106+
space = false;
4107+
fputstrv(f, link->network->pop3, NULL, &space);
4108+
4109+
if (link->dhcp_lease) {
4110+
const struct in_addr *addresses;
4111+
4112+
r = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &addresses);
4113+
if (r > 0)
4114+
if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
4115+
space = true;
4116+
}
4117+
41034118
if (link->network->dhcp6_use_ntp && dhcp6_lease) {
41044119
struct in6_addr *in6_addrs;
41054120
char **hosts;

src/network/networkd-manager.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,14 +1488,16 @@ static int ordered_set_put_in4_addrv(OrderedSet *s,
14881488
}
14891489

14901490
static int manager_save(Manager *m) {
1491-
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
1491+
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = NULL,
1492+
*search_domains = NULL, *route_domains = NULL;
14921493
const char *operstate_str, *carrier_state_str, *address_state_str;
14931494
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
14941495
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
14951496
LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
14961497
_cleanup_free_ char *temp_path = NULL;
14971498
_cleanup_strv_free_ char **p = NULL;
14981499
_cleanup_fclose_ FILE *f = NULL;
1500+
const struct in_addr *addresses;
14991501
Link *link;
15001502
Iterator i;
15011503
int r;
@@ -1512,10 +1514,14 @@ static int manager_save(Manager *m) {
15121514
if (!ntp)
15131515
return -ENOMEM;
15141516

1515-
sip = ordered_set_new(&string_hash_ops);
1516-
if (!sip)
1517+
sip = ordered_set_new(&string_hash_ops);
1518+
if (!sip)
15171519
return -ENOMEM;
15181520

1521+
pop3 = ordered_set_new(&string_hash_ops);
1522+
if (!pop3)
1523+
return -ENOMEM;
1524+
15191525
search_domains = ordered_set_new(&dns_name_hash_ops);
15201526
if (!search_domains)
15211527
return -ENOMEM;
@@ -1562,8 +1568,6 @@ static int manager_save(Manager *m) {
15621568

15631569
/* Secondly, add the entries acquired via DHCP */
15641570
if (link->network->dhcp_use_dns) {
1565-
const struct in_addr *addresses;
1566-
15671571
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
15681572
if (r > 0) {
15691573
r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
@@ -1574,8 +1578,6 @@ static int manager_save(Manager *m) {
15741578
}
15751579

15761580
if (link->network->dhcp_use_ntp) {
1577-
const struct in_addr *addresses;
1578-
15791581
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
15801582
if (r > 0) {
15811583
r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
@@ -1586,8 +1588,6 @@ static int manager_save(Manager *m) {
15861588
}
15871589

15881590
if (link->network->dhcp_use_sip) {
1589-
const struct in_addr *addresses;
1590-
15911591
r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
15921592
if (r > 0) {
15931593
r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
@@ -1597,6 +1597,15 @@ static int manager_save(Manager *m) {
15971597
return r;
15981598
}
15991599

1600+
1601+
r = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &addresses);
1602+
if (r > 0) {
1603+
r = ordered_set_put_in4_addrv(pop3, addresses, r, in4_addr_is_non_local);
1604+
if (r < 0)
1605+
return r;
1606+
} else if (r < 0 && r != -ENODATA)
1607+
return r;
1608+
16001609
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
16011610
const char *domainname;
16021611
char **domains = NULL;
@@ -1648,6 +1657,7 @@ static int manager_save(Manager *m) {
16481657
ordered_set_print(f, "DNS=", dns);
16491658
ordered_set_print(f, "NTP=", ntp);
16501659
ordered_set_print(f, "SIP=", sip);
1660+
ordered_set_print(f, "POP3_SERVERS=", pop3);
16511661
ordered_set_print(f, "DOMAINS=", search_domains);
16521662
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
16531663

src/network/networkd-network-gperf.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ DHCPServer.EmitNTP, config_parse_bool,
207207
DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0
208208
DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_sip)
209209
DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0
210+
DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_servers, 0, 0
210211
DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router)
211212
DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone)
212213
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)

src/network/networkd-network.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ struct Network {
147147
struct in_addr *dhcp_server_sip;
148148
unsigned n_dhcp_server_sip;
149149

150+
struct in_addr *dhcp_server_pop3;
151+
unsigned n_dhcp_server_pop3;
152+
150153
bool dhcp_server_emit_router;
151154
bool dhcp_server_emit_timezone;
152155
char *dhcp_server_timezone;
@@ -296,6 +299,7 @@ struct Network {
296299

297300
char **ntp;
298301
char **sip;
302+
char **pop3;
299303
char **bind_carrier;
300304
};
301305

test/fuzz/fuzz-network-parser/directives.network

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ EmitDNS=
268268
NTP=
269269
EmitSIP=
270270
SIP=
271+
POP3Servers=
271272
EmitRouter=
272273
MaxLeaseTimeSec=
273274
DefaultLeaseTimeSec=

0 commit comments

Comments
 (0)