Skip to content

Commit ee43050

Browse files
authored
Merge pull request systemd#4692 from poettering/networkd-dhcp
Various networkd/DHCP fixes.
2 parents 6d9e45e + ef8b008 commit ee43050

File tree

15 files changed

+286
-125
lines changed

15 files changed

+286
-125
lines changed

man/nss-resolve.xml

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,13 @@
6363
hostnames via DNS.</para>
6464

6565
<para>To activate the NSS module, add <literal>resolve</literal> to the line starting with
66-
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
67-
68-
<para>It is recommended to place <literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>'
69-
<literal>hosts:</literal> line (but after the <literal>files</literal> or <literal>mymachines</literal> entries),
70-
replacing the <literal>dns</literal> entry if it exists, to ensure DNS queries are always routed via
71-
<citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
72-
73-
<para>Note that <command>nss-resolve</command> will chain-load <command>nss-dns</command> if
74-
<filename>systemd-resolved.service</filename> is not running, ensuring that basic DNS resolution continues to work
75-
if the service is down.</para>
66+
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>. Specifcally, it is recommended to place
67+
<literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>' <literal>hosts:</literal> line (but
68+
after the <literal>files</literal> or <literal>mymachines</literal> entries), right before the
69+
<literal>dns</literal> entry if it exists, followed by <literal>[!UNAVAIL=return]</literal>, to ensure DNS queries
70+
are always routed via
71+
<citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry> if it is
72+
running, but are routed to <command>nss-dns</command> if this service is not available.</para>
7673
</refsect1>
7774

7875
<refsect1>
@@ -94,9 +91,6 @@ ethers: db files
9491
rpc: db files
9592

9693
netgroup: nis</programlisting>
97-
98-
<para>This keeps the <command>dns</command> module as a fallback for cases where the <command>nss-resolve</command>
99-
module is not installed.</para>
10094
</refsect1>
10195

10296
<refsect1>

src/basic/in-addr-util.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,9 @@
3131
#include "util.h"
3232

3333
bool in4_addr_is_null(const struct in_addr *a) {
34-
return a->s_addr == 0;
35-
}
34+
assert(a);
3635

37-
bool in6_addr_is_null(const struct in6_addr *a) {
38-
return
39-
a->s6_addr32[0] == 0 &&
40-
a->s6_addr32[1] == 0 &&
41-
a->s6_addr32[2] == 0 &&
42-
a->s6_addr32[3] == 0;
36+
return a->s_addr == 0;
4337
}
4438

4539
int in_addr_is_null(int family, const union in_addr_union *u) {
@@ -49,29 +43,41 @@ int in_addr_is_null(int family, const union in_addr_union *u) {
4943
return in4_addr_is_null(&u->in);
5044

5145
if (family == AF_INET6)
52-
return in6_addr_is_null(&u->in6);
46+
return IN6_IS_ADDR_UNSPECIFIED(&u->in6);
5347

5448
return -EAFNOSUPPORT;
5549
}
5650

51+
bool in4_addr_is_link_local(const struct in_addr *a) {
52+
assert(a);
53+
54+
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
55+
}
56+
5757
int in_addr_is_link_local(int family, const union in_addr_union *u) {
5858
assert(u);
5959

6060
if (family == AF_INET)
61-
return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
61+
return in4_addr_is_link_local(&u->in);
6262

6363
if (family == AF_INET6)
6464
return IN6_IS_ADDR_LINKLOCAL(&u->in6);
6565

6666
return -EAFNOSUPPORT;
6767
}
6868

69+
bool in4_addr_is_localhost(const struct in_addr *a) {
70+
assert(a);
71+
72+
/* All of 127.x.x.x is localhost. */
73+
return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
74+
}
75+
6976
int in_addr_is_localhost(int family, const union in_addr_union *u) {
7077
assert(u);
7178

7279
if (family == AF_INET)
73-
/* All of 127.x.x.x is localhost. */
74-
return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
80+
return in4_addr_is_localhost(&u->in);
7581

7682
if (family == AF_INET6)
7783
return IN6_IS_ADDR_LOOPBACK(&u->in6);
@@ -277,15 +283,14 @@ int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifin
277283
}
278284

279285
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
280-
286+
union in_addr_union buffer;
281287
assert(s);
282-
assert(ret);
283288

284289
if (!IN_SET(family, AF_INET, AF_INET6))
285290
return -EAFNOSUPPORT;
286291

287292
errno = 0;
288-
if (inet_pton(family, s, ret) <= 0)
293+
if (inet_pton(family, s, ret ?: &buffer) <= 0)
289294
return errno > 0 ? -errno : -EINVAL;
290295

291296
return 0;
@@ -295,18 +300,18 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
295300
int r;
296301

297302
assert(s);
298-
assert(family);
299-
assert(ret);
300303

301304
r = in_addr_from_string(AF_INET, s, ret);
302305
if (r >= 0) {
303-
*family = AF_INET;
306+
if (family)
307+
*family = AF_INET;
304308
return 0;
305309
}
306310

307311
r = in_addr_from_string(AF_INET6, s, ret);
308312
if (r >= 0) {
309-
*family = AF_INET6;
313+
if (family)
314+
*family = AF_INET6;
310315
return 0;
311316
}
312317

src/basic/in-addr-util.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ struct in_addr_data {
3737
};
3838

3939
bool in4_addr_is_null(const struct in_addr *a);
40-
bool in6_addr_is_null(const struct in6_addr *a);
41-
4240
int in_addr_is_null(int family, const union in_addr_union *u);
41+
42+
bool in4_addr_is_link_local(const struct in_addr *a);
4343
int in_addr_is_link_local(int family, const union in_addr_union *u);
44+
45+
bool in4_addr_is_localhost(const struct in_addr *a);
4446
int in_addr_is_localhost(int family, const union in_addr_union *u);
47+
4548
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
4649
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
4750
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);

src/libsystemd-network/ndisc-router.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ _public_ int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *r
9191
assert_return(rt, -EINVAL);
9292
assert_return(ret_addr, -EINVAL);
9393

94-
if (in6_addr_is_null(&rt->address))
94+
if (IN6_IS_ADDR_UNSPECIFIED(&rt->address))
9595
return -ENODATA;
9696

9797
*ret_addr = rt->address;

src/libsystemd-network/sd-dhcp-client.c

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -386,45 +386,23 @@ int sd_dhcp_client_set_hostname(
386386
sd_dhcp_client *client,
387387
const char *hostname) {
388388

389-
char *new_hostname = NULL;
390-
391389
assert_return(client, -EINVAL);
392390

393-
if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
391+
/* Refuse hostnames that neither qualify as DNS nor as Linux hosntames */
392+
if (hostname &&
393+
!(hostname_is_valid(hostname, false) || dns_name_is_valid(hostname) > 0))
394394
return -EINVAL;
395395

396-
if (streq_ptr(client->hostname, hostname))
397-
return 0;
398-
399-
if (hostname) {
400-
new_hostname = strdup(hostname);
401-
if (!new_hostname)
402-
return -ENOMEM;
403-
}
404-
405-
free(client->hostname);
406-
client->hostname = new_hostname;
407-
408-
return 0;
396+
return free_and_strdup(&client->hostname, hostname);
409397
}
410398

411399
int sd_dhcp_client_set_vendor_class_identifier(
412400
sd_dhcp_client *client,
413401
const char *vci) {
414402

415-
char *new_vci = NULL;
416-
417403
assert_return(client, -EINVAL);
418404

419-
new_vci = strdup(vci);
420-
if (!new_vci)
421-
return -ENOMEM;
422-
423-
free(client->vendor_class_identifier);
424-
425-
client->vendor_class_identifier = new_vci;
426-
427-
return 0;
405+
return free_and_strdup(&client->vendor_class_identifier, vci);
428406
}
429407

430408
int sd_dhcp_client_set_client_port(

src/libsystemd-network/sd-dhcp-lease.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,23 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
383383
return 0;
384384
}
385385

386+
static void filter_bogus_addresses(struct in_addr *addresses, size_t *n) {
387+
size_t i, j;
388+
389+
/* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
390+
391+
for (i = 0, j = 0; i < *n; i ++) {
392+
393+
if (in4_addr_is_null(addresses+i) ||
394+
in4_addr_is_localhost(addresses+i))
395+
continue;
396+
397+
addresses[j++] = addresses[i];
398+
}
399+
400+
*n = j;
401+
}
402+
386403
static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
387404
assert(option);
388405
assert(ret);
@@ -404,6 +421,8 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
404421
if (!addresses)
405422
return -ENOMEM;
406423

424+
filter_bogus_addresses(addresses, &n_addresses);
425+
407426
free(*ret);
408427
*ret = addresses;
409428
*n_ret = n_addresses;

src/network/networkd-dhcp4.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,28 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
536536
return;
537537
}
538538

539+
static int dhcp4_set_hostname(Link *link) {
540+
_cleanup_free_ char *hostname = NULL;
541+
const char *hn;
542+
int r;
543+
544+
assert(link);
545+
546+
if (!link->network->dhcp_send_hostname)
547+
hn = NULL;
548+
else if (link->network->dhcp_hostname)
549+
hn = link->network->dhcp_hostname;
550+
else {
551+
r = gethostname_strict(&hostname);
552+
if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
553+
return r;
554+
555+
hn = hostname;
556+
}
557+
558+
return sd_dhcp_client_set_hostname(link->dhcp_client, hn);
559+
}
560+
539561
int dhcp4_configure(Link *link) {
540562
int r;
541563

@@ -605,25 +627,9 @@ int dhcp4_configure(Link *link) {
605627
if (r < 0)
606628
return r;
607629

608-
if (link->network->dhcp_send_hostname) {
609-
_cleanup_free_ char *hostname = NULL;
610-
const char *hn = NULL;
611-
612-
if (!link->network->dhcp_hostname) {
613-
hostname = gethostname_malloc();
614-
if (!hostname)
615-
return -ENOMEM;
616-
617-
hn = hostname;
618-
} else
619-
hn = link->network->dhcp_hostname;
620-
621-
if (!is_localhost(hn)) {
622-
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
623-
if (r < 0)
624-
return r;
625-
}
626-
}
630+
r = dhcp4_set_hostname(link);
631+
if (r < 0)
632+
return r;
627633

628634
if (link->network->dhcp_vendor_class_identifier) {
629635
r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,

0 commit comments

Comments
 (0)