summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-07-30 17:59:28 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-07-30 22:36:14 +0200
commit56f91e2d0b218d09ee41981b24d2b53aabf599b7 (patch)
treeca463a8d2bdebb978f211507a8cdd0d57d21b559 /src
parentnetwork/ipv4acd: manage ACD engines with Address object (diff)
downloadsystemd-56f91e2d0b218d09ee41981b24d2b53aabf599b7.tar.xz
systemd-56f91e2d0b218d09ee41981b24d2b53aabf599b7.zip
network: make link_get_address() provide matching address with peer
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.
Diffstat (limited to 'src')
-rw-r--r--src/network/netdev/l2tp-tunnel.c4
-rw-r--r--src/network/networkd-address.c50
-rw-r--r--src/network/networkd-address.h28
-rw-r--r--src/network/networkd-ndisc.c2
-rw-r--r--src/network/networkd-route-util.c4
-rw-r--r--src/network/networkd-route.c12
6 files changed, 63 insertions, 37 deletions
diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c
index 8b9406bb08..4f9e7189d1 100644
--- a/src/network/netdev/l2tp-tunnel.c
+++ b/src/network/netdev/l2tp-tunnel.c
@@ -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;
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 6e55c4f022..7377c22407 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -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);
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 8e8d04f817..fcad445e17 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -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,
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 521a64253c..481014bba9 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -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));
diff --git a/src/network/networkd-route-util.c b/src/network/networkd-route-util.c
index b7e07f4662..8d63b9b058 100644
--- a/src/network/networkd-route-util.c
+++ b/src/network/networkd-route-util.c
@@ -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;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index d596fd81e6..9b6be2f2bf 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -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);