]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: Tweak link-local addresses relevancy
authorGeorge Tsiamasiotis <gtsiam@windowslive.com>
Tue, 17 Jun 2025 12:30:41 +0000 (15:30 +0300)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 25 Jun 2025 17:17:42 +0000 (18:17 +0100)
We now consider link-local addresses routable when we have configured
unicast link-local dns servers. This allows creating the DNS scope, even
when the interface doesn't get a routable address.

(cherry picked from commit c60d2a626b88aec24e6f029f799b6631c1aaeee2)
(cherry picked from commit bd9a51fc67faead42dcaac819f5c432741b4a32a)

src/resolve/resolved-link.c
src/resolve/resolved-link.h

index bb43a73de42dcf65afb92f0029e8562361264aff..ccb10bf6fe632b84a1630c8c1aafa2892d192f76 100644 (file)
@@ -665,14 +665,35 @@ int link_update(Link *l) {
         return 0;
 }
 
+static bool link_has_link_local_dns(Link *l, int family) {
+
+        /* Check if the link has a link-local dns server for the specified family */
+
+        LIST_FOREACH(servers, s, l->dns_servers)
+                if ((family == AF_UNSPEC || s->family == family) &&
+                    in_addr_is_link_local(s->family, &s->address))
+                        return true;
+
+        return false;
+}
+
 bool link_relevant(Link *l, int family, bool local_multicast) {
+        bool allow_link_local;
+
         assert(l);
 
-        /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
-         * beat, can do multicast and has at least one link-local (or better) IP address.
-         *
-         * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
-         * least one routable address. */
+        /*
+         * A link is relevant if:
+         * - it isn't a loopback device
+         * - has a link beat
+         * - for multicast traffic:
+         *   - can do multicast
+         *   - has at least one link-local (or better) IP address.
+         * - for non-multicast traffic:
+         *   - has at least one address that must be:
+         *     - At least link-local, if using a link-local dns server to this interface.
+         *     - Better than link-local.
+         */
 
         if ((l->flags & (IFF_LOOPBACK | IFF_DORMANT)) != 0)
                 return false;
@@ -691,8 +712,11 @@ bool link_relevant(Link *l, int family, bool local_multicast) {
             !IN_SET(l->networkd_operstate, LINK_OPERSTATE_DEGRADED_CARRIER, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_ROUTABLE))
                 return false;
 
+        allow_link_local = local_multicast || link_has_link_local_dns(l, family);
+
         LIST_FOREACH(addresses, a, l->addresses)
-                if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
+                if ((family == AF_UNSPEC || a->family == family) &&
+                    link_address_relevant(a, allow_link_local))
                         return true;
 
         return false;
@@ -1142,13 +1166,13 @@ int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
         return 0;
 }
 
-bool link_address_relevant(LinkAddress *a, bool local_multicast) {
+bool link_address_relevant(LinkAddress *a, bool allow_link_local) {
         assert(a);
 
         if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
                 return false;
 
-        if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
+        if (a->scope >= (allow_link_local ? RT_SCOPE_HOST : RT_SCOPE_LINK))
                 return false;
 
         return true;
index 0695a6ff838b9c0fcf5e0663efbc9398260baa31..e2cb2a26e1532b0bb7e93c7e7f6436f28d5783c1 100644 (file)
@@ -119,7 +119,7 @@ int link_address_new(Link *l,
                 const union in_addr_union *in_addr_broadcast);
 LinkAddress *link_address_free(LinkAddress *a);
 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m);
-bool link_address_relevant(LinkAddress *l, bool local_multicast);
+bool link_address_relevant(LinkAddress *l, bool allow_link_local);
 void link_address_add_rrs(LinkAddress *a, bool force_remove);
 
 bool link_negative_trust_anchor_lookup(Link *l, const char *name);