network,radv: make DNS= in [IPv6PrefixDelegation] section take special value 'linklocal'

Closes #13639.
This commit is contained in:
Yu Watanabe 2020-01-31 15:52:56 +09:00
parent 2f1fc899ce
commit fd3ef936ed
3 changed files with 47 additions and 24 deletions

View File

@ -1926,15 +1926,14 @@
<term><varname>EmitDNS=</varname></term>
<term><varname>DNS=</varname></term>
<listitem><para><varname>DNS=</varname> specifies a list of recursive
DNS server IPv6 addresses that distributed via Router Advertisement
messages when <varname>EmitDNS=</varname> is true. If <varname>DNS=
</varname> is empty, DNS servers are read from the
<literal>[Network]</literal> section. If the
<literal>[Network]</literal> section does not contain any DNS servers
either, DNS servers from the uplink with the highest priority default
route are used. When <varname>EmitDNS=</varname> is false, no DNS server
information is sent in Router Advertisement messages.
<listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses
that are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is
true. <varname>DNS=</varname> also takes special value <literal>_link_local</literal>; in that
case the IPv6 link local address is distributed. If <varname>DNS=</varname> is empty, DNS
servers are read from the <literal>[Network]</literal> section. If the
<literal>[Network]</literal> section does not contain any DNS servers either, DNS servers from
the uplink with the highest priority default route are used. When <varname>EmitDNS=</varname>
is false, no DNS server information is sent in Router Advertisement messages.
<varname>EmitDNS=</varname> defaults to true.
</para></listitem>
</varlistentry>

View File

@ -1514,6 +1514,10 @@ static int link_acquire_ipv6_conf(Link *link) {
log_link_debug(link, "Starting IPv6 Router Advertisements");
r = radv_emit_dns(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure DNS or Domains in IPv6 Router Advertisement: %m");
r = sd_radv_start(link->radv);
if (r < 0 && r != -EBUSY)
return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");

View File

@ -443,20 +443,29 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
static int radv_set_dns(Link *link, Link *uplink) {
_cleanup_free_ struct in6_addr *dns = NULL;
size_t n_dns;
usec_t lifetime_usec;
size_t n_dns;
int r;
if (!link->network->router_emit_dns)
return 0;
if (link->network->router_dns) {
dns = newdup(struct in6_addr, link->network->router_dns,
link->network->n_router_dns);
struct in6_addr *p;
dns = new(struct in6_addr, link->network->n_router_dns);
if (!dns)
return -ENOMEM;
n_dns = link->network->n_router_dns;
p = dns;
for (size_t i = 0; i < link->network->n_router_dns; i++)
if (IN6_IS_ADDR_UNSPECIFIED(&link->network->router_dns[i])) {
if (!IN6_IS_ADDR_UNSPECIFIED(&link->ipv6ll_address))
*(p++) = link->ipv6ll_address;
} else
*(p++) = link->network->router_dns[i];
n_dns = p - dns;
lifetime_usec = link->network->router_dns_lifetime_usec;
goto set_dns;
@ -620,7 +629,7 @@ int radv_configure(Link *link) {
}
return radv_emit_dns(link);
return 0;
}
int config_parse_radv_dns(
@ -658,19 +667,30 @@ int config_parse_radv_dns(
if (r == 0)
break;
if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
struct in6_addr *m;
if (streq(w, "_link_local"))
a = IN_ADDR_NULL;
else {
r = in_addr_from_string(AF_INET6, w, &a);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DNS server address, ignoring: %s", w);
continue;
}
m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
if (!m)
return log_oom();
if (in_addr_is_null(AF_INET6, &a)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"DNS server address is null, ignoring: %s", w);
continue;
}
}
m[n->n_router_dns++] = a.in6;
n->router_dns = m;
struct in6_addr *m;
m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
if (!m)
return log_oom();
} else
log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse DNS server address, ignoring: %s", w);
m[n->n_router_dns++] = a.in6;
n->router_dns = m;
}
return 0;