]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: make link_get_address() provide matching address with peer
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 30 Jul 2024 15:59:28 +0000 (00:59 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 30 Jul 2024 20:36:14 +0000 (05:36 +0900)
As all callers do not care if the address has peer address.
This also drops prefixlen argument as it is always zero.

Fixes a bug introduced by 42f8b6a80878e688b821adfb315c0a1f0a7076ce.
Fixes #31950.

src/network/netdev/l2tp-tunnel.c
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-ndisc.c
src/network/networkd-route-util.c
src/network/networkd-route.c

index 8b9406bb08112a883bbd3dd9eff679a7b18576a7..4f9e7189d17411813668fa818db5b176e5374bf8 100644 (file)
@@ -306,9 +306,9 @@ static int l2tp_get_local_address(NetDev *netdev, union in_addr_union *ret) {
 
                 if (!a) {
                         if (link)
-                                r = link_get_address(link, t->family, &t->local, 0, &a);
+                                r = link_get_address(link, t->family, &t->local, &a);
                         else
-                                r = manager_get_address(netdev->manager, t->family, &t->local, 0, &a);
+                                r = manager_get_address(netdev->manager, t->family, &t->local, &a);
                         if (r < 0)
                                 return r;
 
index 6e55c4f0224385ef1f51385d93148415f8faf6d2..7377c22407d1fd59235158993b5f53935656bab6 100644 (file)
@@ -986,7 +986,14 @@ int address_get_harder(Link *link, const Address *in, Address **ret) {
         return 0;
 }
 
-int link_get_address(Link *link, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret) {
+int link_get_address_full(
+                Link *link,
+                int family,
+                const union in_addr_union *address,
+                const union in_addr_union *peer, /* optional, can be NULL */
+                unsigned char prefixlen,         /* optional, can be 0 */
+                Address **ret) {
+
         Address *a;
         int r;
 
@@ -994,11 +1001,11 @@ int link_get_address(Link *link, int family, const union in_addr_union *address,
         assert(IN_SET(family, AF_INET, AF_INET6));
         assert(address);
 
-        /* This find an Address object on the link which matches the given address and prefix length
-         * and does not have peer address. When the prefixlen is zero, then an Address object with an
-         * arbitrary prefixlen will be returned. */
+        /* This finds an Address object on the link which matches the given address, peer, and prefix length.
+         * If the prefixlen is zero, then an Address object with an arbitrary prefixlen will be returned.
+         * If the peer is NULL, then an Address object with an arbitrary peer will be returned. */
 
-        if (family == AF_INET6 || prefixlen != 0) {
+        if (family == AF_INET6 || (prefixlen != 0 && peer)) {
                 _cleanup_(address_unrefp) Address *tmp = NULL;
 
                 /* In this case, we can use address_get(). */
@@ -1009,6 +1016,8 @@ int link_get_address(Link *link, int family, const union in_addr_union *address,
 
                 tmp->family = family;
                 tmp->in_addr = *address;
+                if (peer)
+                        tmp->in_addr_peer = *peer;
                 tmp->prefixlen = prefixlen;
 
                 r = address_get(link, tmp, &a);
@@ -1018,7 +1027,7 @@ int link_get_address(Link *link, int family, const union in_addr_union *address,
                 if (family == AF_INET6) {
                         /* IPv6 addresses are managed without peer address and prefix length. Hence, we need
                          * to check them explicitly. */
-                        if (in_addr_is_set(family, &a->in_addr_peer))
+                        if (peer && !in_addr_equal(family, &a->in_addr_peer, peer))
                                 return -ENOENT;
                         if (prefixlen != 0 && a->prefixlen != prefixlen)
                                 return -ENOENT;
@@ -1037,7 +1046,10 @@ int link_get_address(Link *link, int family, const union in_addr_union *address,
                 if (!in_addr_equal(family, &a->in_addr, address))
                         continue;
 
-                if (in_addr_is_set(family, &a->in_addr_peer))
+                if (peer && !in_addr_equal(family, &a->in_addr_peer, peer))
+                        continue;
+
+                if (prefixlen != 0 && a->prefixlen != prefixlen)
                         continue;
 
                 if (ret)
@@ -1049,7 +1061,14 @@ int link_get_address(Link *link, int family, const union in_addr_union *address,
         return -ENOENT;
 }
 
-int manager_get_address(Manager *manager, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret) {
+int manager_get_address_full(
+                Manager *manager,
+                int family,
+                const union in_addr_union *address,
+                const union in_addr_union *peer,
+                unsigned char prefixlen,
+                Address **ret) {
+
         Link *link;
 
         assert(manager);
@@ -1060,26 +1079,13 @@ int manager_get_address(Manager *manager, int family, const union in_addr_union
                 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
                         continue;
 
-                if (link_get_address(link, family, address, prefixlen, ret) >= 0)
+                if (link_get_address_full(link, family, address, peer, prefixlen, ret) >= 0)
                         return 0;
         }
 
         return -ENOENT;
 }
 
-bool manager_has_address(Manager *manager, int family, const union in_addr_union *address) {
-        Address *a;
-
-        assert(manager);
-        assert(IN_SET(family, AF_INET, AF_INET6));
-        assert(address);
-
-        if (manager_get_address(manager, family, address, 0, &a) < 0)
-                return false;
-
-        return address_is_ready(a);
-}
-
 const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) {
         assert(buf);
         assert(l > 4);
index 8e8d04f81731e489b7798234a07d1521fa45b38c..fcad445e174f04e7af3d804871a3e080bf2105a0 100644 (file)
@@ -115,13 +115,31 @@ int link_drop_foreign_addresses(Link *link);
 int link_drop_ipv6ll_addresses(Link *link);
 void link_foreignize_addresses(Link *link);
 bool link_address_is_dynamic(const Link *link, const Address *address);
-int link_get_address(Link *link, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret);
-static inline int link_get_ipv6_address(Link *link, const struct in6_addr *address, unsigned char prefixlen, Address **ret) {
+
+int link_get_address_full(
+                Link *link,
+                int family,
+                const union in_addr_union *address,
+                const union in_addr_union *peer, /* optional, can be NULL */
+                unsigned char prefixlen,         /* optional, can be 0 */
+                Address **ret);
+static inline int link_get_address(Link *link, int family, const union in_addr_union *address, Address **ret) {
+        return link_get_address_full(link, family, address, NULL, 0, ret);
+}
+static inline int link_get_ipv6_address(Link *link, const struct in6_addr *address, Address **ret) {
         assert(address);
-        return link_get_address(link, AF_INET6, &(union in_addr_union) { .in6 = *address }, prefixlen, ret);
+        return link_get_address(link, AF_INET6, &(union in_addr_union) { .in6 = *address }, ret);
+}
+int manager_get_address_full(
+                Manager *manager,
+                int family,
+                const union in_addr_union *address,
+                const union in_addr_union *peer,
+                unsigned char prefixlen,
+                Address **ret);
+static inline int manager_get_address(Manager *manager, int family, const union in_addr_union *address, Address **ret) {
+        return manager_get_address_full(manager, family, address, NULL, 0, ret);
 }
-int manager_get_address(Manager *manager, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret);
-bool manager_has_address(Manager *manager, int family, const union in_addr_union *address);
 
 int link_request_address(
                 Link *link,
index 521a64253c4a263f8f5e075a56025fe9c62030bb..481014bba99d61b228401253acfc95ab8ea6df96 100644 (file)
@@ -1382,7 +1382,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
 
-        if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
+        if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
                 if (DEBUG_LOGGING)
                         log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route",
                                        IN6_ADDR_TO_STRING(&gateway));
index b7e07f46623213c36e591c4acf5cbc15c9fd2bf0..8d63b9b058aba869c4ae1059acc914b3a942ce5d 100644 (file)
@@ -259,7 +259,7 @@ int link_address_is_reachable(
                 return 0;
         }
 
-        r = link_get_address(link, route->family, &route->prefsrc, 0, &a);
+        r = link_get_address(link, route->family, &route->prefsrc, &a);
         if (r < 0)
                 return r;
 
@@ -312,7 +312,7 @@ int manager_address_is_reachable(
         if (r < 0)
                 return r;
 
-        r = link_get_address(link, found->family, &found->prefsrc, 0, &a);
+        r = link_get_address(link, found->family, &found->prefsrc, &a);
         if (r < 0)
                 return r;
 
index d596fd81e63cc73dd0d87298b29aba008d005e9d..9b6be2f2bfa49ef3f55fbd550d22a345cd84cdb0 100644 (file)
@@ -790,8 +790,6 @@ static int route_requeue_request(Request *req, Link *link, const Route *route) {
 }
 
 static int route_is_ready_to_configure(const Route *route, Link *link) {
-        int r;
-
         assert(route);
         assert(link);
 
@@ -799,9 +797,13 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
                 return false;
 
         if (in_addr_is_set(route->family, &route->prefsrc) > 0) {
-                r = manager_has_address(link->manager, route->family, &route->prefsrc);
-                if (r <= 0)
-                        return r;
+                Address *a;
+
+                if (manager_get_address(link->manager, route->family, &route->prefsrc, &a) < 0)
+                        return false;
+
+                if (!address_is_ready(a))
+                        return false;
         }
 
         return route_nexthops_is_ready_to_configure(route, link->manager);