The function sd_radv_add_prefix() in dhcp6_pd_prefix_assign() may
return -EEXIST, and in that case the sd_radv_prefix object allocated
in dhcp6_pd_prefix_assign() will be freed when the function returns.
Hence, the key value in Manager::dhcp6_prefixes hashmap is lost.
if (r < 0 && r != -EEXIST)
return r;
if (r < 0 && r != -EEXIST)
return r;
- r = manager_dhcp6_prefix_add(link->manager, &p->opt.in6_addr, link);
+ r = manager_dhcp6_prefix_add(link->manager, prefix, link);
continue;
assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6);
continue;
assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6);
- if (assigned_link != NULL && assigned_link != link)
+ if (assigned_link && assigned_link != link)
continue;
(void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf);
continue;
(void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
-
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
_cleanup_(link_unrefp) Link *link = NULL;
uint16_t type;
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
_cleanup_(link_unrefp) Link *link = NULL;
uint16_t type;
Link *link_unref(Link *link);
Link *link_ref(Link *link);
Link *link_unref(Link *link);
Link *link_ref(Link *link);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
int link_get(Manager *m, int ifindex, Link **ret);
DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
int link_get(Manager *m, int ifindex, Link **ret);
DEFINE_PRIVATE_HASH_OPS(dhcp6_prefixes_hash_ops, struct in6_addr, dhcp6_prefixes_hash_func, dhcp6_prefixes_compare_func);
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
DEFINE_PRIVATE_HASH_OPS(dhcp6_prefixes_hash_ops, struct in6_addr, dhcp6_prefixes_hash_func, dhcp6_prefixes_compare_func);
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
+ _cleanup_free_ struct in6_addr *a = NULL;
_cleanup_free_ char *buf = NULL;
_cleanup_free_ char *buf = NULL;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
+ assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
+ if (assigned_link) {
+ assert(assigned_link == link);
+ return 0;
+ }
+
+ a = newdup(struct in6_addr, addr, 1);
+ if (!a)
+ return -ENOMEM;
+
r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &dhcp6_prefixes_hash_ops);
if (r < 0)
return r;
r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &dhcp6_prefixes_hash_ops);
if (r < 0)
return r;
- return hashmap_put(m->dhcp6_prefixes, addr, link);
+ r = hashmap_put(m->dhcp6_prefixes, a, link);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(a);
+ link_ref(link);
+ return 0;
}
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
}
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
}
static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
}
static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
+ _cleanup_free_ struct in6_addr *a = NULL;
+ _cleanup_(link_unrefp) Link *l = NULL;
_cleanup_free_ char *buf = NULL;
Route *route;
_cleanup_free_ char *buf = NULL;
Route *route;
int r;
assert_return(m, -EINVAL);
assert_return(addr, -EINVAL);
int r;
assert_return(m, -EINVAL);
assert_return(addr, -EINVAL);
- l = hashmap_remove(m->dhcp6_prefixes, addr);
+ l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
if (!l)
return -EINVAL;
(void) sd_radv_remove_prefix(l->radv, addr, 64);
if (!l)
return -EINVAL;
(void) sd_radv_remove_prefix(l->radv, addr, 64);
- r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64,
- 0, 0, 0, &route);
+ r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
assert_return(m, -EINVAL);
assert_return(link, -EINVAL);
assert_return(m, -EINVAL);
assert_return(link, -EINVAL);
- HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) {
- if (l != link)
- continue;
-
- (void) manager_dhcp6_prefix_remove(m, addr);
- }
+ HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
+ if (l == link)
+ (void) manager_dhcp6_prefix_remove(m, addr);
}
void manager_free(Manager *m) {
}
void manager_free(Manager *m) {
AddressPool *pool;
Link *link;
AddressPool *pool;
Link *link;
- while ((link = hashmap_first(m->dhcp6_prefixes)))
- manager_dhcp6_prefix_remove_all(m, link);
+ while ((a = hashmap_first_key(m->dhcp6_prefixes)))
+ (void) manager_dhcp6_prefix_remove(m, a);
hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_steal_first(m->links))) {
hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_steal_first(m->links))) {