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;
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;
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;
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
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;
LIST_HEAD(struct match_callback, match_callbacks);
+ LIST_HEAD(sd_netlink_slot, slots);
+
pid_t original_pid;
sd_event_source *io_event_source;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#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);
--- /dev/null
+/* 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);
#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"
}
static sd_netlink *netlink_free(sd_netlink *rtnl) {
- struct reply_callback *c;
- struct match_callback *f;
+ sd_netlink_slot *s;
unsigned i;
assert(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);
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);
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;
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;
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;
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");
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;
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,
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:
return -EOPNOTSUPP;
}
- LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c);
+ LIST_PREPEND(match_callbacks, rtnl->match_callbacks, &slot->match_callback);
- c = NULL;
-
- return 0;
-}
+ if (ret_slot)
+ *ret_slot = slot;
-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;
- }
+ TAKE_PTR(slot);
return 0;
}
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);
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");
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);
_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));
/* 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));
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));
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);
}
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);
}
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");
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");
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");
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");
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");
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");
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");
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");
}
/* 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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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;
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;
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");
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");
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");
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");
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;
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");
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;
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 */
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);
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);
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