diff --git a/src/core/loopback-setup.c b/src/core/loopback-setup.c index 9380d1b09d..d0585158c5 100644 --- a/src/core/loopback-setup.c +++ b/src/core/loopback-setup.c @@ -53,7 +53,7 @@ static int start_loopback(sd_netlink *rtnl, struct state *s) { if (r < 0) return r; - r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, LOOPBACK_SETUP_TIMEOUT_USEC, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, LOOPBACK_SETUP_TIMEOUT_USEC); if (r < 0) return r; @@ -88,7 +88,7 @@ static int add_ipv4_address(sd_netlink *rtnl, struct state *s) { if (r < 0) return r; - r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, USEC_INFINITY, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, USEC_INFINITY); if (r < 0) return r; @@ -123,7 +123,7 @@ static int add_ipv6_address(sd_netlink *rtnl, struct state *s) { if (r < 0) return r; - r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, USEC_INFINITY, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, USEC_INFINITY); if (r < 0) return r; diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index d95406e7ac..9d83bda2a6 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -66,6 +66,8 @@ libsystemd_sources = files(''' sd-netlink/local-addresses.h sd-netlink/netlink-internal.h sd-netlink/netlink-message.c + sd-netlink/netlink-slot.c + sd-netlink/netlink-slot.h sd-netlink/netlink-socket.c sd-netlink/netlink-types.c sd-netlink/netlink-types.h diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h index 8b56d34220..d7fccad87e 100644 --- a/src/libsystemd/sd-netlink/netlink-internal.h +++ b/src/libsystemd/sd-netlink/netlink-internal.h @@ -19,21 +19,41 @@ struct reply_callback { sd_netlink_message_handler_t callback; - void *userdata; usec_t timeout; uint64_t serial; unsigned prioq_idx; - sd_netlink_destroy_t destroy_callback; }; struct match_callback { sd_netlink_message_handler_t callback; uint16_t type; - void *userdata; LIST_FIELDS(struct match_callback, match_callbacks); }; +typedef enum NetlinkSlotType { + NETLINK_REPLY_CALLBACK, + NETLINK_MATCH_CALLBACK, + _NETLINK_SLOT_INVALID = -1, +} NetlinkSlotType; + +struct sd_netlink_slot { + unsigned n_ref; + sd_netlink *netlink; + void *userdata; + sd_netlink_destroy_t destroy_callback; + NetlinkSlotType type:2; + + bool floating:1; + + LIST_FIELDS(sd_netlink_slot, slots); + + union { + struct reply_callback reply_callback; + struct match_callback match_callback; + }; +}; + struct sd_netlink { RefCount n_ref; @@ -69,6 +89,8 @@ struct sd_netlink { LIST_HEAD(struct match_callback, match_callbacks); + LIST_HEAD(sd_netlink_slot, slots); + pid_t original_pid; sd_event_source *io_event_source; diff --git a/src/libsystemd/sd-netlink/netlink-slot.c b/src/libsystemd/sd-netlink/netlink-slot.c new file mode 100644 index 0000000000..18fcbe8818 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-slot.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "netlink-internal.h" +#include "netlink-slot.h" + +sd_netlink_slot *netlink_slot_allocate( + sd_netlink *nl, + bool floating, + NetlinkSlotType type, + size_t extra, + sd_netlink_destroy_t destroy_callback, + void *userdata) { + + sd_netlink_slot *slot; + + assert(nl); + + slot = malloc0(offsetof(sd_netlink_slot, reply_callback) + extra); + if (!slot) + return NULL; + + slot->n_ref = 1; + slot->netlink = nl; + slot->userdata = userdata; + slot->destroy_callback = destroy_callback; + slot->type = type; + slot->floating = floating; + + if (!floating) + sd_netlink_ref(nl); + + LIST_PREPEND(slots, nl->slots, slot); + + return slot; +} + +void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) { + sd_netlink *nl; + + assert(slot); + + nl = slot->netlink; + if (!nl) + return; + + switch (slot->type) { + + case NETLINK_REPLY_CALLBACK: + (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial); + + if (slot->reply_callback.timeout != 0) + prioq_remove(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); + + break; + case NETLINK_MATCH_CALLBACK: + LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback); + + switch (slot->match_callback.type) { + case RTM_NEWLINK: + case RTM_DELLINK: + (void) socket_broadcast_group_unref(nl, RTNLGRP_LINK); + + break; + case RTM_NEWADDR: + case RTM_DELADDR: + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR); + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR); + + break; + case RTM_NEWROUTE: + case RTM_DELROUTE: + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE); + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE); + + break; + } + + break; + default: + assert_not_reached("Wut? Unknown slot type?"); + } + + slot->type = _NETLINK_SLOT_INVALID; + slot->netlink = NULL; + LIST_REMOVE(slots, nl->slots, slot); + + if (!slot->floating) + sd_netlink_unref(nl); + else if (unref) + sd_netlink_slot_unref(slot); +} + +static sd_netlink_slot* netlink_slot_free(sd_netlink_slot *slot) { + assert(slot); + + netlink_slot_disconnect(slot, false); + + if (slot->destroy_callback) + slot->destroy_callback(slot->userdata); + + return mfree(slot); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free); diff --git a/src/libsystemd/sd-netlink/netlink-slot.h b/src/libsystemd/sd-netlink/netlink-slot.h new file mode 100644 index 0000000000..d7d084a205 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-slot.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +sd_netlink_slot *netlink_slot_allocate( + sd_netlink *nl, + bool floating, + NetlinkSlotType type, + size_t extra, + sd_netlink_destroy_t destroy_callback, + void *userdata); +void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref); diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c index 6c8740097d..9484446ca1 100644 --- a/src/libsystemd/sd-netlink/sd-netlink.c +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -11,6 +11,7 @@ #include "macro.h" #include "missing.h" #include "netlink-internal.h" +#include "netlink-slot.h" #include "netlink-util.h" #include "process-util.h" #include "socket-util.h" @@ -148,8 +149,7 @@ int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) { } static sd_netlink *netlink_free(sd_netlink *rtnl) { - struct reply_callback *c; - struct match_callback *f; + sd_netlink_slot *s; unsigned i; assert(rtnl); @@ -164,10 +164,9 @@ static sd_netlink *netlink_free(sd_netlink *rtnl) { free(rtnl->rbuffer); - while ((c = hashmap_steal_first(rtnl->reply_callbacks))) { - if (c->destroy_callback) - c->destroy_callback(c->userdata); - free(c); + while ((s = rtnl->slots)) { + assert(s->floating); + netlink_slot_disconnect(s, true); } hashmap_free(rtnl->reply_callbacks); prioq_free(rtnl->reply_callbacks_prioq); @@ -176,9 +175,6 @@ static sd_netlink *netlink_free(sd_netlink *rtnl) { sd_event_source_unref(rtnl->time_event_source); sd_event_unref(rtnl->event); - while ((f = rtnl->match_callbacks)) - sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata); - hashmap_free(rtnl->broadcast_group_refs); safe_close(rtnl->fd); @@ -281,6 +277,7 @@ static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) { static int process_timeout(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; struct reply_callback *c; + sd_netlink_slot *slot; usec_t n; int r; @@ -299,22 +296,24 @@ static int process_timeout(sd_netlink *rtnl) { return r; assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c); + c->timeout = 0; hashmap_remove(rtnl->reply_callbacks, &c->serial); - r = c->callback(rtnl, m, c->userdata); + slot = container_of(c, sd_netlink_slot, reply_callback); + + r = c->callback(rtnl, m, slot->userdata); if (r < 0) log_debug_errno(r, "sd-netlink: timedout callback failed: %m"); - if (c->destroy_callback) - c->destroy_callback(c->userdata); - - free(c); + if (slot->floating) + netlink_slot_disconnect(slot, true); return 1; } static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) { - _cleanup_free_ struct reply_callback *c = NULL; + struct reply_callback *c; + sd_netlink_slot *slot; uint64_t serial; uint16_t type; int r; @@ -327,28 +326,33 @@ static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) { if (!c) return 0; - if (c->timeout != 0) + if (c->timeout != 0) { prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } r = sd_netlink_message_get_type(m, &type); if (r < 0) - return 0; + return r; if (type == NLMSG_DONE) m = NULL; - r = c->callback(rtnl, m, c->userdata); + slot = container_of(c, sd_netlink_slot, reply_callback); + + r = c->callback(rtnl, m, slot->userdata); if (r < 0) log_debug_errno(r, "sd-netlink: callback failed: %m"); - if (c->destroy_callback) - c->destroy_callback(c->userdata); + if (slot->floating) + netlink_slot_disconnect(slot, true); return 1; } static int process_match(sd_netlink *rtnl, sd_netlink_message *m) { struct match_callback *c; + sd_netlink_slot *slot; uint16_t type; int r; @@ -361,7 +365,9 @@ static int process_match(sd_netlink *rtnl, sd_netlink_message *m) { LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) { if (type == c->type) { - r = c->callback(rtnl, m, c->userdata); + slot = container_of(c, sd_netlink_slot, match_callback); + + r = c->callback(rtnl, m, slot->userdata); if (r != 0) { if (r < 0) log_debug_errno(r, "sd-netlink: match callback failed: %m"); @@ -508,13 +514,13 @@ static int timeout_compare(const void *a, const void *b) { int sd_netlink_call_async( sd_netlink *nl, + sd_netlink_slot **ret_slot, sd_netlink_message *m, sd_netlink_message_handler_t callback, sd_netlink_destroy_t destroy_callback, void *userdata, - uint64_t usec, - uint32_t *serial) { - _cleanup_free_ struct reply_callback *c = NULL; + uint64_t usec) { + _cleanup_free_ sd_netlink_slot *slot = NULL; uint32_t s; int r, k; @@ -533,65 +539,39 @@ int sd_netlink_call_async( return r; } - c = new(struct reply_callback, 1); - if (!c) + slot = netlink_slot_allocate(nl, !ret_slot, NETLINK_REPLY_CALLBACK, sizeof(struct reply_callback), destroy_callback, userdata); + if (!slot) return -ENOMEM; - *c = (struct reply_callback) { - .callback = callback, - .userdata = userdata, - .timeout = calc_elapse(usec), - .destroy_callback = destroy_callback, - }; + slot->reply_callback.callback = callback; + slot->reply_callback.timeout = calc_elapse(usec); k = sd_netlink_send(nl, m, &s); if (k < 0) return k; - c->serial = s; + slot->reply_callback.serial = s; - r = hashmap_put(nl->reply_callbacks, &c->serial, c); + r = hashmap_put(nl->reply_callbacks, &slot->reply_callback.serial, &slot->reply_callback); if (r < 0) return r; - if (c->timeout != 0) { - r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx); + if (slot->reply_callback.timeout != 0) { + r = prioq_put(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); if (r < 0) { - (void) hashmap_remove(nl->reply_callbacks, &c->serial); + (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial); return r; } } - if (serial) - *serial = s; + if (ret_slot) + *ret_slot = slot; - TAKE_PTR(c); + TAKE_PTR(slot); return k; } -int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial) { - struct reply_callback *c; - uint64_t s = serial; - - assert_return(nl, -EINVAL); - assert_return(serial != 0, -EINVAL); - assert_return(!rtnl_pid_changed(nl), -ECHILD); - - c = hashmap_remove(nl->reply_callbacks, &s); - if (!c) - return 0; - - if (c->timeout != 0) - prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx); - - if (c->destroy_callback) - c->destroy_callback(c->userdata); - - free(c); - return 1; -} - int sd_netlink_call(sd_netlink *rtnl, sd_netlink_message *message, uint64_t usec, @@ -834,26 +814,26 @@ int sd_netlink_detach_event(sd_netlink *rtnl) { return 0; } -int sd_netlink_add_match(sd_netlink *rtnl, - uint16_t type, - sd_netlink_message_handler_t callback, - void *userdata) { - _cleanup_free_ struct match_callback *c = NULL; +int sd_netlink_add_match( + sd_netlink *rtnl, + sd_netlink_slot **ret_slot, + uint16_t type, + sd_netlink_message_handler_t callback, + sd_netlink_destroy_t destroy_callback, + void *userdata) { + _cleanup_free_ sd_netlink_slot *slot = NULL; int r; assert_return(rtnl, -EINVAL); assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - c = new(struct match_callback, 1); - if (!c) + slot = netlink_slot_allocate(rtnl, !ret_slot, NETLINK_MATCH_CALLBACK, sizeof(struct match_callback), destroy_callback, userdata); + if (!slot) return -ENOMEM; - *c = (struct match_callback) { - .callback = callback, - .type = type, - .userdata = userdata, - }; + slot->match_callback.callback = callback; + slot->match_callback.type = type; switch (type) { case RTM_NEWLINK: @@ -898,64 +878,12 @@ int sd_netlink_add_match(sd_netlink *rtnl, return -EOPNOTSUPP; } - LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c); + LIST_PREPEND(match_callbacks, rtnl->match_callbacks, &slot->match_callback); - c = NULL; - - return 0; -} - -int sd_netlink_remove_match(sd_netlink *rtnl, - uint16_t type, - sd_netlink_message_handler_t callback, - void *userdata) { - struct match_callback *c; - int r; - - assert_return(rtnl, -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) - if (c->callback == callback && c->type == type && c->userdata == userdata) { - LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c); - free(c); - - switch (type) { - case RTM_NEWLINK: - case RTM_DELLINK: - r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINK); - if (r < 0) - return r; - - break; - case RTM_NEWADDR: - case RTM_DELADDR: - r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDR); - if (r < 0) - return r; - - r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDR); - if (r < 0) - return r; - - break; - case RTM_NEWROUTE: - case RTM_DELROUTE: - r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTE); - if (r < 0) - return r; - - r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTE); - if (r < 0) - return r; - break; - default: - return -EOPNOTSUPP; - } - - return 1; - } + if (ret_slot) + *ret_slot = slot; + + TAKE_PTR(slot); return 0; } diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index 710ed0d089..5fffb70119 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -201,7 +201,7 @@ static void test_event_loop(int ifindex) { assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_netlink_call_async(rtnl, m, link_handler, NULL, ifname, 0, NULL) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, ifname, 0) >= 0); assert_se(sd_event_default(&event) >= 0); @@ -217,7 +217,7 @@ static void test_event_loop(int ifindex) { static void test_async(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; - uint32_t serial; + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL; char *ifname; ifname = strdup("lo"); @@ -227,7 +227,7 @@ static void test_async(int ifindex) { assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_netlink_call_async(rtnl, m, link_handler, NULL, ifname, 0, &serial) >= 0); + assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, NULL, ifname, 0) >= 0); assert_se(sd_netlink_wait(rtnl, 0) >= 0); assert_se(sd_netlink_process(rtnl, &r) >= 0); @@ -279,7 +279,7 @@ static void test_async_destroy_callback(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; _cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL; - uint32_t serial; + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL; char *ifname; assert_se(t = new(struct test_async_object, 1)); @@ -293,7 +293,7 @@ static void test_async_destroy_callback(int ifindex) { /* destroy callback is called after processing message */ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0) >= 0); assert_se(t->n_ref == 1); assert_se(test_async_object_ref(t)); @@ -305,22 +305,22 @@ static void test_async_destroy_callback(int ifindex) { assert_se(!sd_netlink_message_unref(m)); - /* destroy callback is called when asynchronous call is cancelled */ + /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0); + assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0) >= 0); assert_se(t->n_ref == 1); assert_se(test_async_object_ref(t)); assert_se(t->n_ref == 2); - assert_se(sd_netlink_call_async_cancel(rtnl, serial) >= 0); + assert_se(!(slot = sd_netlink_slot_unref(slot))); assert_se(t->n_ref == 1); assert_se(!sd_netlink_message_unref(m)); /* destroy callback is also called by sd_netlink_unref() */ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0) >= 0); assert_se(t->n_ref == 1); assert_se(test_async_object_ref(t)); @@ -356,10 +356,10 @@ static void test_pipe(int ifindex) { assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0); counter++; - assert_se(sd_netlink_call_async(rtnl, m1, pipe_handler, NULL, &counter, 0, NULL) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0) >= 0); counter++; - assert_se(sd_netlink_call_async(rtnl, m2, pipe_handler, NULL, &counter, 0, NULL) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0) >= 0); while (counter > 0) { assert_se(sd_netlink_wait(rtnl, 0) >= 0); @@ -405,16 +405,17 @@ static void test_container(sd_netlink *rtnl) { } static void test_match(void) { + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; assert_se(sd_netlink_open(&rtnl) >= 0); - assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, link_handler, NULL) >= 0); - assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, link_handler, NULL) >= 0); + assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL) >= 0); + assert_se(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL) >= 0); + assert_se(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL) >= 0); - assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 1); - assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 1); - assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 0); + assert_se(!(s1 = sd_netlink_slot_unref(s1))); + assert_se(!(s2 = sd_netlink_slot_unref(s2))); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); } diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c index ce9f75e27b..604a5e3f55 100644 --- a/src/network/netdev/bridge.c +++ b/src/network/netdev/bridge.c @@ -129,8 +129,8 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); - r = sd_netlink_call_async(netdev->manager->rtnl, req, netdev_bridge_set_handler, - netdev_netlink_destroy_callback, netdev, 0, NULL); + r = sd_netlink_call_async(netdev->manager->rtnl, NULL, req, netdev_bridge_set_handler, + netdev_netlink_destroy_callback, netdev, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c index 9350f0257a..e7c8afd936 100644 --- a/src/network/netdev/geneve.c +++ b/src/network/netdev/geneve.c @@ -136,8 +136,8 @@ static int netdev_geneve_create(NetDev *netdev) { if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); - r = sd_netlink_call_async(netdev->manager->rtnl, m, geneve_netdev_create_handler, - netdev_netlink_destroy_callback, netdev, 0, NULL); + r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler, + netdev_netlink_destroy_callback, netdev, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 9b956ff66d..023cc922d5 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -225,8 +225,8 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m"); - r = sd_netlink_call_async(netdev->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(netdev->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); @@ -534,15 +534,15 @@ static int netdev_create(NetDev *netdev, Link *link, return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); if (link) { - r = sd_netlink_call_async(netdev->manager->rtnl, m, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); link_ref(link); } else { - r = sd_netlink_call_async(netdev->manager->rtnl, m, netdev_create_handler, - netdev_netlink_destroy_callback, netdev, 0, NULL); + r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, netdev_create_handler, + netdev_netlink_destroy_callback, netdev, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index a0c4be3ef0..6265701e3f 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -112,8 +112,8 @@ int address_label_configure( if (r < 0) return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 3ffd3fe4ab..f2fae866e2 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -453,8 +453,8 @@ int address_remove( if (r < 0) return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); @@ -632,8 +632,8 @@ int address_configure( if (r < 0) return r; - r = sd_netlink_call_async(link->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) { address_release(address); return log_error_errno(r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c index 3707347a68..32e8547037 100644 --- a/src/network/networkd-brvlan.c +++ b/src/network/networkd-brvlan.c @@ -195,8 +195,8 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); /* send message to the kernel */ - r = sd_netlink_call_async(rtnl, req, set_brvlan_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, set_brvlan_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 5112d91b90..337ff2e6ac 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -134,8 +134,8 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { } /* send message to the kernel to update its internal static MAC table. */ - r = sd_netlink_call_async(rtnl, req, set_fdb_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, set_fdb_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 1dcdbad0be..11e1b8421f 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -173,8 +173,8 @@ int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy if (r < 0) return rtnl_log_create_error(r); - r = sd_netlink_call_async(rtnl, req, set_ipv6_proxy_ndp_address_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1f3204b486..e160d75a65 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1340,8 +1340,8 @@ int link_set_mtu(Link *link, uint32_t mtu) { if (r < 0) return log_link_error_errno(link, r, "Could not append MTU: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, set_mtu_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1411,8 +1411,8 @@ static int link_set_flags(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1487,8 +1487,8 @@ static int link_set_bridge(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, link_set_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1540,8 +1540,8 @@ static int link_bond_set(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1833,8 +1833,8 @@ int link_up(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1859,8 +1859,8 @@ static int link_up_can(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1949,8 +1949,8 @@ static int link_set_can(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Failed to close netlink container: %m"); - r = sd_netlink_call_async(link->manager->rtnl, m, link_set_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -2007,8 +2007,8 @@ int link_down(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, link_down_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -3122,8 +3122,8 @@ int link_initialized(Link *link, sd_device *device) { if (r < 0) return r; - r = sd_netlink_call_async(link->manager->rtnl, req, link_initialized_handler, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, link_initialized_handler, + link_netlink_destroy_callback, link, 0); if (r < 0) return r; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index e5c929f29b..8c66986294 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -930,35 +930,35 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWROUTE, &manager_rtnl_process_route, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELROUTE, &manager_rtnl_process_route, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWRULE, &manager_rtnl_process_rule, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELRULE, &manager_rtnl_process_rule, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m); if (r < 0) return r; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f0b72c78f4..591fae6e76 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -439,8 +439,8 @@ int route_remove(Route *route, Link *link, return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); } - r = sd_netlink_call_async(link->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); @@ -620,8 +620,8 @@ int route_configure( if (r < 0) return log_error_errno(r, "Could not append RTA_METRICS attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index d7c68c680f..fe393856f8 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -370,8 +370,8 @@ int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *lin return log_error_errno(r, "Could not set destination prefix length: %m"); } - r = sd_netlink_call_async(link->manager->rtnl, m, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, m, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); @@ -539,8 +539,8 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin rule->link = link; - r = sd_netlink_call_async(link->manager->rtnl, m, callback, - link_netlink_destroy_callback, link, 0, NULL); + r = sd_netlink_call_async(link->manager->rtnl, NULL, m, callback, + link_netlink_destroy_callback, link, 0); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c index c054c2a96d..22252ef826 100644 --- a/src/network/wait-online/manager.c +++ b/src/network/wait-online/manager.c @@ -169,11 +169,11 @@ static int manager_rtnl_listen(Manager *m) { if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, on_rtnl_event, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, on_rtnl_event, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, on_rtnl_event, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, on_rtnl_event, NULL, m); if (r < 0) return r; diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c index 07da7922f1..0eaf0ca5f5 100644 --- a/src/nspawn/nspawn-expose-ports.c +++ b/src/nspawn/nspawn-expose-ports.c @@ -209,11 +209,11 @@ int expose_port_watch_rtnl( return log_error_errno(r, "Failed to create rtnl object: %m"); } - r = sd_netlink_add_match(rtnl, RTM_NEWADDR, handler, exposed); + r = sd_netlink_add_match(rtnl, NULL, RTM_NEWADDR, handler, NULL, exposed); if (r < 0) return log_error_errno(r, "Failed to subscribe to RTM_NEWADDR messages: %m"); - r = sd_netlink_add_match(rtnl, RTM_DELADDR, handler, exposed); + r = sd_netlink_add_match(rtnl, NULL, RTM_DELADDR, handler, NULL, exposed); if (r < 0) return log_error_errno(r, "Failed to subscribe to RTM_DELADDR messages: %m"); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index f99a7b3d8d..05244499c0 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -200,19 +200,19 @@ static int manager_rtnl_listen(Manager *m) { if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, manager_process_link, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, manager_process_link, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, manager_process_address, NULL, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m); + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, manager_process_address, NULL, m); if (r < 0) return r; diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index 01b33c8fc0..357a503525 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -33,6 +33,7 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_netlink sd_netlink; typedef struct sd_genl_socket sd_genl_socket; typedef struct sd_netlink_message sd_netlink_message; +typedef struct sd_netlink_slot sd_netlink_slot; typedef enum {SD_GENL_ID_CTRL, SD_GENL_WIREGUARD, SD_GENL_FOU} sd_genl_family; /* callback */ @@ -50,11 +51,9 @@ sd_netlink *sd_netlink_ref(sd_netlink *nl); sd_netlink *sd_netlink_unref(sd_netlink *nl); int sd_netlink_send(sd_netlink *nl, sd_netlink_message *message, uint32_t *serial); -int sd_netlink_call_async(sd_netlink *nl, sd_netlink_message *message, - sd_netlink_message_handler_t callback, - sd_netlink_destroy_t destoy_callback, - void *userdata, uint64_t usec, uint32_t *serial); -int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial); +int sd_netlink_call_async(sd_netlink *nl, sd_netlink_slot **ret_slot, sd_netlink_message *message, + sd_netlink_message_handler_t callback, sd_netlink_destroy_t destoy_callback, + void *userdata, uint64_t usec); int sd_netlink_call(sd_netlink *nl, sd_netlink_message *message, uint64_t timeout, sd_netlink_message **reply); @@ -63,8 +62,9 @@ int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout); int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret); int sd_netlink_wait(sd_netlink *nl, uint64_t timeout); -int sd_netlink_add_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata); -int sd_netlink_remove_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata); +int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t match, + sd_netlink_message_handler_t callback, + sd_netlink_destroy_t destroy_callback, void *userdata); int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority); int sd_netlink_detach_event(sd_netlink *nl); @@ -178,13 +178,18 @@ int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(sd_netlink_message int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type); int sd_rtnl_message_routing_policy_rule_get_rtm_type(sd_netlink_message *m, unsigned char *type); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref); - /* genl */ int sd_genl_socket_open(sd_netlink **nl); int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **m); +/* slot */ +sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl); +sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_slot, sd_netlink_slot_unref); + _SD_END_DECLARATIONS; #endif