<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>
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");
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;
}
- return radv_emit_dns(link);
+ return 0;
}
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;