]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network,radv: make DNS= in [IPv6PrefixDelegation] section take special value 'linklocal'
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 31 Jan 2020 06:52:56 +0000 (15:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 4 Feb 2020 04:56:30 +0000 (13:56 +0900)
Closes #13639.

man/systemd.network.xml
src/network/networkd-link.c
src/network/networkd-radv.c

index 1492f2032a9d83746032ea6b45676959e1ee7ef6..1bff564d5917d374ee912d037aca922e75515c91 100644 (file)
         <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>
index f3744e2354ce42b29d4f124fdb2244413e06327c..cfecf76a79452765a3490c49f49be93bd6d7e6e2 100644 (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");
index d48609f985ad7a9b1498440ab02b1d0e14744e79..620939e251839214dc1ffc2bf81fd4640678ce4b 100644 (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;