}
}
-DEFINE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
bool address_equal(Address *a1, Address *a2) {
if (a1 == a2)
link_update_operstate(address->link, true);
link_check_ready(address->link);
- if (!ready &&
- address_is_ready(address) &&
- address->family == AF_INET6 &&
- in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
- in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
+ if (!ready && address_is_ready(address)) {
+ if (address->callback) {
+ r = address->callback(address);
+ if (r < 0)
+ return r;
+ }
- r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
- if (r < 0)
- return r;
+ if (address->family == AF_INET6 &&
+ in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&address->link->ipv6ll_address) > 0) {
+
+ r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
+ if (r < 0)
+ return r;
+ }
}
return 0;
return -ENOENT;
}
+static bool address_exists_internal(Set *addresses, int family, const union in_addr_union *in_addr) {
+ Address *address;
+ Iterator i;
+
+ SET_FOREACH(address, addresses, i) {
+ if (address->family != family)
+ continue;
+ if (in_addr_equal(address->family, &address->in_addr, in_addr))
+ return true;
+ }
+
+ return false;
+}
+
+bool address_exists(Link *link, int family, const union in_addr_union *in_addr) {
+ assert(link);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+ assert(in_addr);
+
+ if (address_exists_internal(link->addresses, family, in_addr))
+ return true;
+ if (address_exists_internal(link->addresses_foreign, family, in_addr))
+ return true;
+ return false;
+}
+
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
Address *address,
Link *link,
link_netlink_message_handler_t callback,
- bool update) {
+ bool update,
+ Address **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ Address *a;
int r;
assert(address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *str = NULL;
+
+ (void) in_addr_to_string(address->family, &address->in_addr, &str);
+ log_link_debug(link, "%s address: %s", update ? "Updating" : "Configuring", strna(str));
+ }
+
if (update)
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
link->ifindex, address->family);
link_ref(link);
if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
- r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL);
+ r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a);
else
- r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
+ r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a);
if (r < 0) {
address_release(address);
return log_link_error_errno(link, r, "Could not add address: %m");
log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
}
+ if (ret)
+ *ret = a;
+
return 1;
}