*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(
+ address_hash_ops_detach,
+ Address,
+ address_hash_func,
+ address_compare_func,
+ address_detach);
+
+DEFINE_HASH_OPS(
+ address_hash_ops,
+ Address,
+ address_hash_func,
+ address_compare_func);
+
+DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ address_section_hash_ops,
+ ConfigSection,
+ config_section_hash_func,
+ config_section_compare_func,
+ Address,
+ address_detach);
+
int address_new(Address **ret) {
- _cleanup_(address_freep) Address *address = NULL;
+ _cleanup_(address_unrefp) Address *address = NULL;
address = new(Address, 1);
if (!address)
return -ENOMEM;
*address = (Address) {
+ .n_ref = 1,
.family = AF_UNSPEC,
.scope = RT_SCOPE_UNIVERSE,
.lifetime_valid_usec = USEC_INFINITY,
int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
_cleanup_(config_section_freep) ConfigSection *n = NULL;
- _cleanup_(address_freep) Address *address = NULL;
+ _cleanup_(address_unrefp) Address *address = NULL;
int r;
assert(network);
/* This will be adjusted in address_section_verify(). */
address->duplicate_address_detection = _ADDRESS_FAMILY_INVALID;
- r = ordered_hashmap_ensure_put(&network->addresses_by_section, &config_section_hash_ops, address->section, address);
+ r = ordered_hashmap_ensure_put(&network->addresses_by_section, &address_section_hash_ops, address->section, address);
if (r < 0)
return r;
return 0;
}
-Address *address_free(Address *address) {
- if (!address)
- return NULL;
+static Address* address_detach_impl(Address *address) {
+ assert(address);
+ assert(!address->link || !address->network);
if (address->network) {
assert(address->section);
if (address->network->dhcp_server_address == address)
address->network->dhcp_server_address = NULL;
+
+ address->network = NULL;
+ return address;
}
- if (address->link)
+ if (address->link) {
set_remove(address->link->addresses, address);
+ address->link = NULL;
+ return address;
+ }
+
+ return NULL;
+}
+
+static void address_detach(Address *address) {
+ assert(address);
+
+ address_unref(address_detach_impl(address));
+}
+
+static Address* address_free(Address *address) {
+ if (!address)
+ return NULL;
+
+ address_detach_impl(address);
+
config_section_free(address->section);
free(address->label);
free(address->netlabel);
return mfree(address);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(Address, address, address_free);
+
static bool address_lifetime_is_valid(const Address *a) {
assert(a);
}
}
-DEFINE_HASH_OPS(
- address_hash_ops,
- Address,
- address_hash_func,
- address_compare_func);
-
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
- address_hash_ops_free,
- Address,
- address_hash_func,
- address_compare_func,
- address_free);
-
static bool address_can_update(const Address *la, const Address *na) {
assert(la);
assert(la->link);
}
int address_dup(const Address *src, Address **ret) {
- _cleanup_(address_freep) Address *dest = NULL;
+ _cleanup_(address_unrefp) Address *dest = NULL;
int r;
assert(src);
if (!dest)
return -ENOMEM;
- /* clear all pointers */
+ /* clear the reference counter and all pointers */
+ dest->n_ref = 1;
dest->network = NULL;
dest->section = NULL;
dest->link = NULL;
}
}
-static int address_add(Link *link, Address *address) {
+static int address_attach(Link *link, Address *address) {
int r;
assert(link);
assert(address);
+ assert(!address->link);
- r = set_ensure_put(&link->addresses, &address_hash_ops_free, address);
+ r = set_ensure_put(&link->addresses, &address_hash_ops_detach, address);
if (r < 0)
return r;
if (r == 0)
return -EEXIST;
address->link = link;
+ address_ref(address);
return 0;
}
ipv4acd_detach(link, address);
- address_free(address);
+ address_detach(address);
link_update_operstate(link, /* also_update_master = */ true);
link_check_ready(link);
* arbitrary prefixlen will be returned. */
if (family == AF_INET6 || prefixlen != 0) {
- _cleanup_(address_freep) Address *tmp = NULL;
+ _cleanup_(address_unrefp) Address *tmp = NULL;
/* In this case, we can use address_get(). */
return r;
for (sd_netlink_message *addr = reply; addr; addr = sd_netlink_message_next(addr)) {
- _cleanup_(address_freep) Address *a = NULL;
+ _cleanup_(address_unrefp) Address *a = NULL;
unsigned char flags, prefixlen;
struct in6_addr address;
int ifindex;
}
static int address_acquire(Link *link, const Address *original, Address **ret) {
- _cleanup_(address_freep) Address *na = NULL;
+ _cleanup_(address_unrefp) Address *na = NULL;
union in_addr_union in_addr;
int r;
address_netlink_handler_t netlink_handler,
Request **ret) {
- _cleanup_(address_freep) Address *tmp = NULL;
+ _cleanup_(address_unrefp) Address *tmp = NULL;
Address *existing = NULL;
int r;
log_address_debug(tmp, "Requesting", link);
r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS,
tmp,
- address_free,
+ address_unref,
address_hash_func,
address_compare_func,
address_process_request,
}
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
- _cleanup_(address_freep) Address *tmp = NULL;
+ _cleanup_(address_unrefp) Address *tmp = NULL;
struct ifa_cacheinfo cinfo;
Link *link;
uint16_t type;
if (!address) {
/* If we did not know the address, then save it. */
- r = address_add(link, tmp);
+ r = address_attach(link, tmp);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to save received address %s, ignoring: %m",
IN_ADDR_PREFIX_TO_STRING(tmp->family, &tmp->in_addr, tmp->prefixlen));
return 0;
}
- address = TAKE_PTR(tmp);
+ address = tmp;
is_new = true;
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
union in_addr_union u;
int r;
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
union in_addr_union buffer;
unsigned char prefixlen;
int r, f;
if (streq(section, "Network")) {
if (isempty(rvalue)) {
/* If an empty string specified in [Network] section, clear previously assigned addresses. */
- network->addresses_by_section = ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
+ network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
return 0;
}
void *data,
void *userdata) {
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
Network *network = userdata;
int r;
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
usec_t k;
int r;
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
if (address_section_verify(address) < 0) {
/* Drop invalid [Address] sections or Address= settings in [Network].
- * Note that address_free() will drop the address from addresses_by_section. */
- address_free(address);
+ * Note that address_detach() will drop the address from addresses_by_section. */
+ address_detach(address);
continue;
}
IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen),
address->section->line,
dup->section->line, dup->section->line);
- /* address_free() will drop the address from addresses_by_section. */
- address_free(dup);
+
+ /* address_detach() will drop the address from addresses_by_section. */
+ address_detach(dup);
}
- /* Use address_hash_ops, instead of address_hash_ops_free. Otherwise, the Address objects
- * will be freed. */
+ /* Use address_hash_ops, instead of address_hash_ops_detach. Otherwise, the Address objects
+ * will be detached. */
r = set_ensure_put(&addresses, &address_hash_ops, address);
if (r < 0)
return log_oom();
void *userdata) {
Network *network = userdata;
- _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
+ _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);