diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-07-30 17:59:28 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-07-30 22:36:14 +0200 |
commit | 56f91e2d0b218d09ee41981b24d2b53aabf599b7 (patch) | |
tree | ca463a8d2bdebb978f211507a8cdd0d57d21b559 /src | |
parent | network/ipv4acd: manage ACD engines with Address object (diff) | |
download | systemd-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.c | 4 | ||||
-rw-r--r-- | src/network/networkd-address.c | 50 | ||||
-rw-r--r-- | src/network/networkd-address.h | 28 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 2 | ||||
-rw-r--r-- | src/network/networkd-route-util.c | 4 | ||||
-rw-r--r-- | src/network/networkd-route.c | 12 |
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); |