*ret_all = address_state_from_scope(MIN(ipv4_scope, ipv6_scope));
}
-static void address_hash_func(const Address *a, struct siphash *state);
-static int address_compare_func(const Address *a1, const Address *a2);
static void address_detach(Address *address);
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
return 0;
}
-static void address_hash_func(const Address *a, struct siphash *state) {
+void address_hash_func(const Address *a, struct siphash *state) {
assert(a);
siphash24_compress_typesafe(a->family, state);
}
}
-static int address_compare_func(const Address *a1, const Address *a2) {
+int address_compare_func(const Address *a1, const Address *a2) {
int r;
r = CMP(a1->family, a2->family);
LinkAddressState *ret_ipv6,
LinkAddressState *ret_all);
+void address_hash_func(const Address *a, struct siphash *state);
+int address_compare_func(const Address *a1, const Address *a2);
extern const struct hash_ops address_hash_ops;
bool address_can_update(const Address *existing, const Address *requesting);
assert(address);
return link_get_address(link, AF_INET6, &(union in_addr_union) { .in6 = *address }, prefixlen, ret);
}
-static inline int link_get_ipv4_address(Link *link, const struct in_addr *address, unsigned char prefixlen, Address **ret) {
- assert(address);
- return link_get_address(link, AF_INET, &(union in_addr_union) { .in = *address }, prefixlen, 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);
#include "networkd-link.h"
#include "networkd-manager.h"
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+DEFINE_PRIVATE_HASH_OPS_FULL(
ipv4acd_hash_ops,
- void, trivial_hash_func, trivial_compare_func,
- sd_ipv4acd, sd_ipv4acd_unref);
+ Address,
+ address_hash_func,
+ address_compare_func,
+ address_unref,
+ sd_ipv4acd,
+ sd_ipv4acd_unref);
bool link_ipv4acd_supported(Link *link) {
assert(link);
if (address->family != AF_INET)
return true;
- acd = hashmap_get(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in));
+ acd = hashmap_get(link->ipv4acd_by_address, address);
if (!acd)
return true;
static void on_acd(sd_ipv4acd *acd, int event, void *userdata) {
Link *link = ASSERT_PTR(userdata);
Address *address = NULL;
- struct in_addr a;
int r;
assert(acd);
- r = sd_ipv4acd_get_address(acd, &a);
- if (r < 0) {
- log_link_warning_errno(link, r, "Failed to get address from IPv4ACD: %m");
- link_enter_failed(link);
- }
+ void *val, *key;
+ HASHMAP_FOREACH_KEY(val, key, link->ipv4acd_by_address)
+ if (val == acd) {
+ (void) address_get(link, key, &address);
+ break;
+ }
- (void) link_get_ipv4_address(link, &a, 0, &address);
+ if (!address)
+ return;
switch (event) {
case SD_IPV4ACD_EVENT_STOP:
- if (!address)
- break;
-
if (address->source == NETWORK_CONFIG_SOURCE_STATIC) {
r = static_ipv4acd_address_remove(link, address, /* on_conflict = */ false);
if (r < 0)
break;
case SD_IPV4ACD_EVENT_BIND:
- log_link_debug(link, "Successfully claimed address %s", IN4_ADDR_TO_STRING(&a));
+ log_link_debug(link, "Successfully claimed address %s", IN4_ADDR_TO_STRING(&address->in_addr.in));
break;
case SD_IPV4ACD_EVENT_CONFLICT:
- if (!address)
- break;
-
- log_link_warning(link, "Dropping address %s, as an address conflict was detected.", IN4_ADDR_TO_STRING(&a));
+ log_link_warning(link, "Dropping address %s, as an address conflict was detected.", IN4_ADDR_TO_STRING(&address->in_addr.in));
if (address->source == NETWORK_CONFIG_SOURCE_STATIC)
r = static_ipv4acd_address_remove(link, address, /* on_conflict = */ true);
int ipv4acd_configure(Link *link, const Address *address) {
_cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
+ _cleanup_(address_unrefp) Address *a = NULL;
sd_ipv4acd *existing;
int r;
if (address->family != AF_INET)
return 0;
- existing = hashmap_get(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in));
+ existing = hashmap_get(link->ipv4acd_by_address, address);
if (!address_ipv4acd_enabled(link, address))
return sd_ipv4acd_stop(existing);
log_link_debug(link, "Configuring IPv4ACD for address %s.", IN4_ADDR_TO_STRING(&address->in_addr.in));
+ r = address_new(&a);
+ if (r < 0)
+ return r;
+
+ a->family = AF_INET;
+ a->in_addr = address->in_addr;
+ a->in_addr_peer = address->in_addr_peer;
+ a->prefixlen = address->prefixlen;
+
r = sd_ipv4acd_new(&acd);
if (r < 0)
return r;
if (r < 0)
return r;
- r = hashmap_ensure_put(&link->ipv4acd_by_address, &ipv4acd_hash_ops, IN4_ADDR_TO_PTR(&address->in_addr.in), acd);
+ r = ipv4acd_start_one(link, acd);
if (r < 0)
return r;
- return ipv4acd_start_one(link, TAKE_PTR(acd));
+ r = hashmap_ensure_put(&link->ipv4acd_by_address, &ipv4acd_hash_ops, a, acd);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(a);
+ TAKE_PTR(acd);
+ return 0;
}
void ipv4acd_detach(Link *link, const Address *address) {
if (address->family != AF_INET)
return;
- sd_ipv4acd_unref(hashmap_remove(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in)));
+ Address *a;
+ sd_ipv4acd_unref(hashmap_remove2(link->ipv4acd_by_address, address, (void**) &a));
+ address_unref(a);
}
int ipv4acd_update_mac(Link *link) {