mirror of
https://github.com/systemd/systemd.git
synced 2025-03-11 20:58:27 +03:00
Merge pull request #4692 from poettering/networkd-dhcp
Various networkd/DHCP fixes.
This commit is contained in:
commit
ee43050b40
@ -63,16 +63,13 @@
|
||||
hostnames via DNS.</para>
|
||||
|
||||
<para>To activate the NSS module, add <literal>resolve</literal> to the line starting with
|
||||
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
|
||||
|
||||
<para>It is recommended to place <literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>'
|
||||
<literal>hosts:</literal> line (but after the <literal>files</literal> or <literal>mymachines</literal> entries),
|
||||
replacing the <literal>dns</literal> entry if it exists, to ensure DNS queries are always routed via
|
||||
<citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>Note that <command>nss-resolve</command> will chain-load <command>nss-dns</command> if
|
||||
<filename>systemd-resolved.service</filename> is not running, ensuring that basic DNS resolution continues to work
|
||||
if the service is down.</para>
|
||||
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>. Specifcally, it is recommended to place
|
||||
<literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>' <literal>hosts:</literal> line (but
|
||||
after the <literal>files</literal> or <literal>mymachines</literal> entries), right before the
|
||||
<literal>dns</literal> entry if it exists, followed by <literal>[!UNAVAIL=return]</literal>, to ensure DNS queries
|
||||
are always routed via
|
||||
<citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry> if it is
|
||||
running, but are routed to <command>nss-dns</command> if this service is not available.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -94,9 +91,6 @@ ethers: db files
|
||||
rpc: db files
|
||||
|
||||
netgroup: nis</programlisting>
|
||||
|
||||
<para>This keeps the <command>dns</command> module as a fallback for cases where the <command>nss-resolve</command>
|
||||
module is not installed.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -31,15 +31,9 @@
|
||||
#include "util.h"
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a) {
|
||||
return a->s_addr == 0;
|
||||
}
|
||||
assert(a);
|
||||
|
||||
bool in6_addr_is_null(const struct in6_addr *a) {
|
||||
return
|
||||
a->s6_addr32[0] == 0 &&
|
||||
a->s6_addr32[1] == 0 &&
|
||||
a->s6_addr32[2] == 0 &&
|
||||
a->s6_addr32[3] == 0;
|
||||
return a->s_addr == 0;
|
||||
}
|
||||
|
||||
int in_addr_is_null(int family, const union in_addr_union *u) {
|
||||
@ -49,16 +43,22 @@ int in_addr_is_null(int family, const union in_addr_union *u) {
|
||||
return in4_addr_is_null(&u->in);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return in6_addr_is_null(&u->in6);
|
||||
return IN6_IS_ADDR_UNSPECIFIED(&u->in6);
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
bool in4_addr_is_link_local(const struct in_addr *a) {
|
||||
assert(a);
|
||||
|
||||
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
|
||||
}
|
||||
|
||||
int in_addr_is_link_local(int family, const union in_addr_union *u) {
|
||||
assert(u);
|
||||
|
||||
if (family == AF_INET)
|
||||
return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
|
||||
return in4_addr_is_link_local(&u->in);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return IN6_IS_ADDR_LINKLOCAL(&u->in6);
|
||||
@ -66,12 +66,18 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
bool in4_addr_is_localhost(const struct in_addr *a) {
|
||||
assert(a);
|
||||
|
||||
/* All of 127.x.x.x is localhost. */
|
||||
return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
|
||||
}
|
||||
|
||||
int in_addr_is_localhost(int family, const union in_addr_union *u) {
|
||||
assert(u);
|
||||
|
||||
if (family == AF_INET)
|
||||
/* All of 127.x.x.x is localhost. */
|
||||
return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
|
||||
return in4_addr_is_localhost(&u->in);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return IN6_IS_ADDR_LOOPBACK(&u->in6);
|
||||
@ -277,15 +283,14 @@ fallback:
|
||||
}
|
||||
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
|
||||
|
||||
union in_addr_union buffer;
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
if (!IN_SET(family, AF_INET, AF_INET6))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
errno = 0;
|
||||
if (inet_pton(family, s, ret) <= 0)
|
||||
if (inet_pton(family, s, ret ?: &buffer) <= 0)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
return 0;
|
||||
@ -295,18 +300,18 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(family);
|
||||
assert(ret);
|
||||
|
||||
r = in_addr_from_string(AF_INET, s, ret);
|
||||
if (r >= 0) {
|
||||
*family = AF_INET;
|
||||
if (family)
|
||||
*family = AF_INET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_from_string(AF_INET6, s, ret);
|
||||
if (r >= 0) {
|
||||
*family = AF_INET6;
|
||||
if (family)
|
||||
*family = AF_INET6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,14 @@ struct in_addr_data {
|
||||
};
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a);
|
||||
bool in6_addr_is_null(const struct in6_addr *a);
|
||||
|
||||
int in_addr_is_null(int family, const union in_addr_union *u);
|
||||
|
||||
bool in4_addr_is_link_local(const struct in_addr *a);
|
||||
int in_addr_is_link_local(int family, const union in_addr_union *u);
|
||||
|
||||
bool in4_addr_is_localhost(const struct in_addr *a);
|
||||
int in_addr_is_localhost(int family, const union in_addr_union *u);
|
||||
|
||||
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
|
||||
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
|
||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||
|
@ -91,7 +91,7 @@ _public_ int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *r
|
||||
assert_return(rt, -EINVAL);
|
||||
assert_return(ret_addr, -EINVAL);
|
||||
|
||||
if (in6_addr_is_null(&rt->address))
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&rt->address))
|
||||
return -ENODATA;
|
||||
|
||||
*ret_addr = rt->address;
|
||||
|
@ -386,45 +386,23 @@ int sd_dhcp_client_set_hostname(
|
||||
sd_dhcp_client *client,
|
||||
const char *hostname) {
|
||||
|
||||
char *new_hostname = NULL;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
|
||||
/* Refuse hostnames that neither qualify as DNS nor as Linux hosntames */
|
||||
if (hostname &&
|
||||
!(hostname_is_valid(hostname, false) || dns_name_is_valid(hostname) > 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (streq_ptr(client->hostname, hostname))
|
||||
return 0;
|
||||
|
||||
if (hostname) {
|
||||
new_hostname = strdup(hostname);
|
||||
if (!new_hostname)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(client->hostname);
|
||||
client->hostname = new_hostname;
|
||||
|
||||
return 0;
|
||||
return free_and_strdup(&client->hostname, hostname);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_vendor_class_identifier(
|
||||
sd_dhcp_client *client,
|
||||
const char *vci) {
|
||||
|
||||
char *new_vci = NULL;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
new_vci = strdup(vci);
|
||||
if (!new_vci)
|
||||
return -ENOMEM;
|
||||
|
||||
free(client->vendor_class_identifier);
|
||||
|
||||
client->vendor_class_identifier = new_vci;
|
||||
|
||||
return 0;
|
||||
return free_and_strdup(&client->vendor_class_identifier, vci);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_port(
|
||||
|
@ -383,6 +383,23 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void filter_bogus_addresses(struct in_addr *addresses, size_t *n) {
|
||||
size_t i, j;
|
||||
|
||||
/* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
|
||||
|
||||
for (i = 0, j = 0; i < *n; i ++) {
|
||||
|
||||
if (in4_addr_is_null(addresses+i) ||
|
||||
in4_addr_is_localhost(addresses+i))
|
||||
continue;
|
||||
|
||||
addresses[j++] = addresses[i];
|
||||
}
|
||||
|
||||
*n = j;
|
||||
}
|
||||
|
||||
static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
|
||||
assert(option);
|
||||
assert(ret);
|
||||
@ -404,6 +421,8 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
|
||||
if (!addresses)
|
||||
return -ENOMEM;
|
||||
|
||||
filter_bogus_addresses(addresses, &n_addresses);
|
||||
|
||||
free(*ret);
|
||||
*ret = addresses;
|
||||
*n_ret = n_addresses;
|
||||
|
@ -536,6 +536,28 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
|
||||
return;
|
||||
}
|
||||
|
||||
static int dhcp4_set_hostname(Link *link) {
|
||||
_cleanup_free_ char *hostname = NULL;
|
||||
const char *hn;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->network->dhcp_send_hostname)
|
||||
hn = NULL;
|
||||
else if (link->network->dhcp_hostname)
|
||||
hn = link->network->dhcp_hostname;
|
||||
else {
|
||||
r = gethostname_strict(&hostname);
|
||||
if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
|
||||
return r;
|
||||
|
||||
hn = hostname;
|
||||
}
|
||||
|
||||
return sd_dhcp_client_set_hostname(link->dhcp_client, hn);
|
||||
}
|
||||
|
||||
int dhcp4_configure(Link *link) {
|
||||
int r;
|
||||
|
||||
@ -605,25 +627,9 @@ int dhcp4_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network->dhcp_send_hostname) {
|
||||
_cleanup_free_ char *hostname = NULL;
|
||||
const char *hn = NULL;
|
||||
|
||||
if (!link->network->dhcp_hostname) {
|
||||
hostname = gethostname_malloc();
|
||||
if (!hostname)
|
||||
return -ENOMEM;
|
||||
|
||||
hn = hostname;
|
||||
} else
|
||||
hn = link->network->dhcp_hostname;
|
||||
|
||||
if (!is_localhost(hn)) {
|
||||
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
r = dhcp4_set_hostname(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network->dhcp_vendor_class_identifier) {
|
||||
r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
|
||||
|
@ -851,21 +851,27 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
static int link_push_uplink_dns_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;
|
||||
unsigned i;
|
||||
|
||||
log_debug("Copying DNS server information from %s", link->ifname);
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(a, link->network->dns) {
|
||||
for (i = 0; i < link->network->n_dns; i++) {
|
||||
struct in_addr ia;
|
||||
|
||||
/* Only look for IPv4 addresses */
|
||||
if (inet_pton(AF_INET, *a, &ia) <= 0)
|
||||
if (link->network->dns[i].family != AF_INET)
|
||||
continue;
|
||||
|
||||
ia = link->network->dns[i].address.in;
|
||||
|
||||
/* Never propagate obviously borked data */
|
||||
if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
|
||||
@ -874,8 +880,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_dns &&
|
||||
link->dhcp_lease) {
|
||||
if (link->network->dhcp_use_dns && link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
|
||||
@ -896,7 +901,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
return sd_dhcp_server_set_dns(s, addresses, n_addresses);
|
||||
}
|
||||
|
||||
static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
static int link_push_uplink_ntp_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;
|
||||
@ -913,14 +918,17 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
if (inet_pton(AF_INET, *a, &ia) <= 0)
|
||||
continue;
|
||||
|
||||
/* Never propagate obviously borked data */
|
||||
if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
|
||||
return log_oom();
|
||||
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_ntp &&
|
||||
link->dhcp_lease) {
|
||||
if (link->network->dhcp_use_ntp && link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
|
||||
@ -1034,7 +1042,7 @@ static int link_enter_set_addresses(Link *link) {
|
||||
log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
|
||||
r = 0;
|
||||
} else
|
||||
r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
|
||||
r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
|
||||
}
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
|
||||
@ -1053,7 +1061,7 @@ static int link_enter_set_addresses(Link *link) {
|
||||
log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
|
||||
r = 0;
|
||||
} else
|
||||
r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
|
||||
r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
|
||||
|
||||
}
|
||||
if (r < 0)
|
||||
@ -3235,7 +3243,7 @@ int link_save(Link *link) {
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
fchmod(fileno(f), 0644);
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
@ -3248,6 +3256,7 @@ int link_save(Link *link) {
|
||||
sd_dhcp6_lease *dhcp6_lease = NULL;
|
||||
const char *dhcp_domainname = NULL;
|
||||
char **dhcp6_domains = NULL;
|
||||
unsigned j;
|
||||
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
|
||||
@ -3259,7 +3268,22 @@ int link_save(Link *link) {
|
||||
|
||||
fputs("DNS=", f);
|
||||
space = false;
|
||||
fputstrv(f, link->network->dns, NULL, &space);
|
||||
|
||||
for (j = 0; j < link->network->n_dns; j++) {
|
||||
_cleanup_free_ char *b = NULL;
|
||||
|
||||
r = in_addr_to_string(link->network->dns[j].family,
|
||||
&link->network->dns[j].address, &b);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to format address, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(b, f);
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_dns &&
|
||||
link->dhcp_lease) {
|
||||
|
@ -774,11 +774,48 @@ static int manager_connect_rtnl(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) {
|
||||
static int ordered_set_put_in_addr_data(OrderedSet *s, const struct in_addr_data *address) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
r = in_addr_to_string(address->family, &address->address, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_consume(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in_addr_datav(OrderedSet *s, const struct in_addr_data *addresses, unsigned n) {
|
||||
int r, c = 0;
|
||||
unsigned i;
|
||||
|
||||
assert(s);
|
||||
assert(addresses || n == 0);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
r = ordered_set_put_in_addr_data(s, addresses+i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
|
||||
if (r < 0)
|
||||
@ -791,14 +828,15 @@ static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) {
|
||||
int r, i, c = 0;
|
||||
static int ordered_set_put_in4_addrv(OrderedSet *s, const struct in_addr *addresses, unsigned n) {
|
||||
int r, c = 0;
|
||||
unsigned i;
|
||||
|
||||
assert(s);
|
||||
assert(n <= 0 || addresses);
|
||||
assert(n == 0 || addresses);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
r = ordered_set_put_in_addr(s, addresses+i);
|
||||
r = ordered_set_put_in4_addr(s, addresses+i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -865,7 +903,7 @@ static int manager_save(Manager *m) {
|
||||
continue;
|
||||
|
||||
/* First add the static configured entries */
|
||||
r = ordered_set_put_strdupv(dns, link->network->dns);
|
||||
r = ordered_set_put_in_addr_datav(dns, link->network->dns, link->network->n_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -890,7 +928,7 @@ static int manager_save(Manager *m) {
|
||||
|
||||
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in_addrv(dns, addresses, r);
|
||||
r = ordered_set_put_in4_addrv(dns, addresses, r);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
@ -902,7 +940,7 @@ static int manager_save(Manager *m) {
|
||||
|
||||
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in_addrv(ntp, addresses, r);
|
||||
r = ordered_set_put_in4_addrv(ntp, addresses, r);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
@ -934,7 +972,7 @@ static int manager_save(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fchmod(fileno(f), 0644);
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
|
@ -54,7 +54,7 @@ Network.LLMNR, config_parse_resolve_support,
|
||||
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
|
||||
Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
|
||||
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
|
||||
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
|
||||
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
|
||||
Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
|
||||
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
|
||||
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
|
||||
|
@ -244,7 +244,7 @@ void network_free(Network *network) {
|
||||
free(network->mac);
|
||||
|
||||
strv_free(network->ntp);
|
||||
strv_free(network->dns);
|
||||
free(network->dns);
|
||||
strv_free(network->search_domains);
|
||||
strv_free(network->route_domains);
|
||||
strv_free(network->bind_carrier);
|
||||
@ -396,7 +396,7 @@ int network_apply(Network *network, Link *link) {
|
||||
route->protocol = RTPROT_STATIC;
|
||||
}
|
||||
|
||||
if (!strv_isempty(network->dns) ||
|
||||
if (network->n_dns > 0 ||
|
||||
!strv_isempty(network->ntp) ||
|
||||
!strv_isempty(network->search_domains) ||
|
||||
!strv_isempty(network->route_domains))
|
||||
@ -909,13 +909,14 @@ int config_parse_dhcp_server_dns(
|
||||
struct in_addr a, *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;
|
||||
break;
|
||||
|
||||
if (inet_pton(AF_INET, w, &a) <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
|
||||
@ -929,6 +930,8 @@ int config_parse_dhcp_server_dns(
|
||||
m[n->n_dhcp_server_dns++] = a;
|
||||
n->dhcp_server_dns = m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_ntp(
|
||||
@ -956,11 +959,12 @@ int config_parse_dhcp_server_ntp(
|
||||
struct in_addr a, *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;
|
||||
|
||||
@ -1000,29 +1004,35 @@ int config_parse_dns(
|
||||
for (;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
union in_addr_union a;
|
||||
struct in_addr_data *m;
|
||||
int family;
|
||||
|
||||
r = extract_first_word(&rvalue, &w, NULL, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r == 0)
|
||||
break;
|
||||
r = extract_first_word(&rvalue, &w, NULL, 0);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = in_addr_from_string_auto(w, &family, &a);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse dns server address, ignoring: %s", w);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse dns server address, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_consume(&n->dns, w);
|
||||
if (r < 0)
|
||||
m = realloc(n->dns, (n->n_dns + 1) * sizeof(struct in_addr_data));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
m[n->n_dns++] = (struct in_addr_data) {
|
||||
.family = family,
|
||||
.address = a,
|
||||
};
|
||||
|
||||
n->dns = m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1084,6 +1094,59 @@ int config_parse_dnssec_negative_trust_anchors(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ntp(
|
||||
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) {
|
||||
|
||||
char ***l = data;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*l = strv_free(*l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
|
||||
r = extract_first_word(&rvalue, &w, NULL, 0);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract NTP server name, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = dns_name_is_valid_or_address(w);
|
||||
if (r <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name or IP address, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_push(l, w);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_route_table(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -112,19 +112,19 @@ struct Network {
|
||||
DCHPClientIdentifier dhcp_client_identifier;
|
||||
char *dhcp_vendor_class_identifier;
|
||||
char *dhcp_hostname;
|
||||
bool dhcp_use_dns;
|
||||
bool dhcp_use_ntp;
|
||||
bool dhcp_use_mtu;
|
||||
bool dhcp_use_hostname;
|
||||
DHCPUseDomains dhcp_use_domains;
|
||||
bool dhcp_send_hostname;
|
||||
bool dhcp_broadcast;
|
||||
bool dhcp_critical;
|
||||
bool dhcp_use_routes;
|
||||
bool dhcp_use_timezone;
|
||||
unsigned dhcp_route_metric;
|
||||
uint32_t dhcp_route_table;
|
||||
uint32_t dhcp_client_port;
|
||||
bool dhcp_send_hostname;
|
||||
bool dhcp_broadcast;
|
||||
bool dhcp_critical;
|
||||
bool dhcp_use_dns;
|
||||
bool dhcp_use_ntp;
|
||||
bool dhcp_use_mtu;
|
||||
bool dhcp_use_routes;
|
||||
bool dhcp_use_timezone;
|
||||
bool dhcp_use_hostname;
|
||||
DHCPUseDomains dhcp_use_domains;
|
||||
|
||||
/* DHCP Server Support */
|
||||
bool dhcp_server;
|
||||
@ -194,7 +194,10 @@ struct Network {
|
||||
Hashmap *routes_by_section;
|
||||
Hashmap *fdb_entries_by_section;
|
||||
|
||||
char **search_domains, **route_domains, **dns, **ntp, **bind_carrier;
|
||||
struct in_addr_data *dns;
|
||||
unsigned n_dns;
|
||||
|
||||
char **search_domains, **route_domains, **ntp, **bind_carrier;
|
||||
|
||||
ResolveSupport llmnr;
|
||||
ResolveSupport mdns;
|
||||
@ -233,6 +236,7 @@ int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *fil
|
||||
int config_parse_dhcp_use_domains(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);
|
||||
int config_parse_lldp_mode(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);
|
||||
int config_parse_dhcp_route_table(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);
|
||||
int config_parse_ntp(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);
|
||||
|
||||
/* Legacy IPv4LL support */
|
||||
int config_parse_ipv4ll(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);
|
||||
|
@ -1324,3 +1324,15 @@ int dns_name_apply_idna(const char *name, char **ret) {
|
||||
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
int dns_name_is_valid_or_address(const char *name) {
|
||||
/* Returns > 0 if the specified name is either a valid IP address formatted as string or a valid DNS name */
|
||||
|
||||
if (isempty(name))
|
||||
return 0;
|
||||
|
||||
if (in_addr_from_string_auto(name, NULL, NULL) >= 0)
|
||||
return 1;
|
||||
|
||||
return dns_name_is_valid(name);
|
||||
}
|
||||
|
@ -107,3 +107,5 @@ int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
|
||||
int dns_name_common_suffix(const char *a, const char *b, const char **ret);
|
||||
|
||||
int dns_name_apply_idna(const char *name, char **ret);
|
||||
|
||||
int dns_name_is_valid_or_address(const char *name);
|
||||
|
@ -627,6 +627,18 @@ static void test_dns_name_apply_idna(void) {
|
||||
test_dns_name_apply_idna_one("föö.bär.", "xn--f-1gaa.xn--br-via");
|
||||
}
|
||||
|
||||
static void test_dns_name_is_valid_or_address(void) {
|
||||
assert_se(dns_name_is_valid_or_address(NULL) == 0);
|
||||
assert_se(dns_name_is_valid_or_address("") == 0);
|
||||
assert_se(dns_name_is_valid_or_address("foobar") > 0);
|
||||
assert_se(dns_name_is_valid_or_address("foobar.com") > 0);
|
||||
assert_se(dns_name_is_valid_or_address("foobar..com") == 0);
|
||||
assert_se(dns_name_is_valid_or_address("foobar.com.") > 0);
|
||||
assert_se(dns_name_is_valid_or_address("127.0.0.1") > 0);
|
||||
assert_se(dns_name_is_valid_or_address("::") > 0);
|
||||
assert_se(dns_name_is_valid_or_address("::1") > 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
test_dns_label_unescape();
|
||||
@ -654,6 +666,7 @@ int main(int argc, char *argv[]) {
|
||||
test_dns_name_compare_func();
|
||||
test_dns_name_common_suffix();
|
||||
test_dns_name_apply_idna();
|
||||
test_dns_name_is_valid_or_address();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user