Merge pull request #10201 from yuwata/fix-10196

sd-netlink: add destroy_callback to sd_netlink_call_async() and fix memleaks in networkd
This commit is contained in:
Lennart Poettering 2018-10-12 11:36:08 +02:00 committed by GitHub
commit 2aab8a1e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 350 additions and 234 deletions

View File

@ -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, s, LOOPBACK_SETUP_TIMEOUT_USEC, NULL);
r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, LOOPBACK_SETUP_TIMEOUT_USEC, NULL);
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, s, USEC_INFINITY, NULL);
r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, USEC_INFINITY, NULL);
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, s, USEC_INFINITY, NULL);
r = sd_netlink_call_async(rtnl, req, generic_handler, NULL, s, USEC_INFINITY, NULL);
if (r < 0)
return r;

View File

@ -23,6 +23,7 @@ struct reply_callback {
usec_t timeout;
uint64_t serial;
unsigned prioq_idx;
sd_netlink_destroy_t destroy_callback;
};
struct match_callback {

View File

@ -21,17 +21,23 @@ static int sd_netlink_new(sd_netlink **ret) {
assert_return(ret, -EINVAL);
rtnl = new0(sd_netlink, 1);
rtnl = new(sd_netlink, 1);
if (!rtnl)
return -ENOMEM;
rtnl->n_ref = REFCNT_INIT;
rtnl->fd = -1;
rtnl->sockaddr.nl.nl_family = AF_NETLINK;
rtnl->original_pid = getpid_cached();
rtnl->protocol = -1;
*rtnl = (sd_netlink) {
.n_ref = REFCNT_INIT,
.fd = -1,
.sockaddr.nl.nl_family = AF_NETLINK,
.original_pid = getpid_cached(),
.protocol = -1,
LIST_HEAD_INIT(rtnl->match_callbacks);
/* Change notification responses have sequence 0, so we must
* start our request sequence numbers at 1, or we may confuse our
* responses with notifications from the kernel */
.serial = 1,
};
/* We guarantee that the read buffer has at least space for
* a message header */
@ -39,11 +45,6 @@ static int sd_netlink_new(sd_netlink **ret) {
sizeof(struct nlmsghdr), sizeof(uint8_t)))
return -ENOMEM;
/* Change notification responses have sequence 0, so we must
* start our request sequence numbers at 1, or we may confuse our
* responses with notifications from the kernel */
rtnl->serial = 1;
*ret = TAKE_PTR(rtnl);
return 0;
@ -147,6 +148,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;
unsigned i;
@ -162,7 +164,12 @@ static sd_netlink *netlink_free(sd_netlink *rtnl) {
free(rtnl->rbuffer);
hashmap_free_free(rtnl->reply_callbacks);
while ((c = hashmap_steal_first(rtnl->reply_callbacks))) {
if (c->destroy_callback)
c->destroy_callback(c->userdata);
free(c);
}
hashmap_free(rtnl->reply_callbacks);
prioq_free(rtnl->reply_callbacks_prioq);
sd_event_source_unref(rtnl->io_event_source);
@ -298,6 +305,9 @@ static int process_timeout(sd_netlink *rtnl) {
if (r < 0)
log_debug_errno(r, "sd-netlink: timedout callback failed: %m");
if (c->destroy_callback)
c->destroy_callback(c->userdata);
free(c);
return 1;
@ -331,6 +341,9 @@ static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
if (r < 0)
log_debug_errno(r, "sd-netlink: callback failed: %m");
if (c->destroy_callback)
c->destroy_callback(c->userdata);
return 1;
}
@ -493,13 +506,15 @@ static int timeout_compare(const void *a, const void *b) {
return CMP(x->timeout, y->timeout);
}
int sd_netlink_call_async(sd_netlink *nl,
sd_netlink_message *m,
sd_netlink_message_handler_t callback,
void *userdata,
uint64_t usec,
uint32_t *serial) {
struct reply_callback *c;
int sd_netlink_call_async(
sd_netlink *nl,
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;
uint32_t s;
int r, k;
@ -518,33 +533,31 @@ int sd_netlink_call_async(sd_netlink *nl,
return r;
}
c = new0(struct reply_callback, 1);
c = new(struct reply_callback, 1);
if (!c)
return -ENOMEM;
c->callback = callback;
c->userdata = userdata;
c->timeout = calc_elapse(usec);
*c = (struct reply_callback) {
.callback = callback,
.userdata = userdata,
.timeout = calc_elapse(usec),
.destroy_callback = destroy_callback,
};
k = sd_netlink_send(nl, m, &s);
if (k < 0) {
free(c);
if (k < 0)
return k;
}
c->serial = s;
r = hashmap_put(nl->reply_callbacks, &c->serial, c);
if (r < 0) {
free(c);
if (r < 0)
return r;
}
if (c->timeout != 0) {
r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx);
if (r > 0) {
c->timeout = 0;
sd_netlink_call_async_cancel(nl, c->serial);
if (r < 0) {
(void) hashmap_remove(nl->reply_callbacks, &c->serial);
return r;
}
}
@ -552,6 +565,8 @@ int sd_netlink_call_async(sd_netlink *nl,
if (serial)
*serial = s;
TAKE_PTR(c);
return k;
}
@ -570,6 +585,9 @@ int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial) {
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;
}
@ -827,13 +845,15 @@ int sd_netlink_add_match(sd_netlink *rtnl,
assert_return(callback, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
c = new0(struct match_callback, 1);
c = new(struct match_callback, 1);
if (!c)
return -ENOMEM;
c->callback = callback;
c->type = type;
c->userdata = userdata;
*c = (struct match_callback) {
.callback = callback,
.type = type,
.userdata = userdata,
};
switch (type) {
case RTM_NEWLINK:

View File

@ -5,6 +5,7 @@
#include "sd-netlink.h"
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "missing.h"
@ -177,8 +178,9 @@ static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
assert_se(rtnl);
assert_se(m);
assert_se(userdata);
log_info("got link info about %s", ifname);
log_info("%s: got link info about %s", __func__, ifname);
free(ifname);
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
@ -199,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, ifname, 0, NULL) >= 0);
assert_se(sd_netlink_call_async(rtnl, m, link_handler, NULL, ifname, 0, NULL) >= 0);
assert_se(sd_event_default(&event) >= 0);
@ -212,6 +214,122 @@ static void test_event_loop(int ifindex) {
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
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;
char *ifname;
ifname = strdup("lo");
assert_se(ifname);
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, &serial) >= 0);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &r) >= 0);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
struct test_async_object {
unsigned n_ref;
char *ifname;
};
static struct test_async_object *test_async_object_free(struct test_async_object *t) {
assert(t);
free(t->ifname);
return mfree(t);
}
DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref);
static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
struct test_async_object *t = userdata;
const char *data;
assert_se(rtnl);
assert_se(m);
assert_se(userdata);
log_info("%s: got link info about %s", __func__, t->ifname);
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
assert_se(streq(data, "lo"));
return 1;
}
static void test_async_object_destroy(void *userdata) {
struct test_async_object *t = userdata;
assert(userdata);
log_info("%s: n_ref=%u", __func__, t->n_ref);
test_async_object_unref(t);
}
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;
char *ifname;
assert_se(t = new(struct test_async_object, 1));
assert_se(ifname = strdup("lo"));
*t = (struct test_async_object) {
.n_ref = 1,
.ifname = ifname,
};
assert_se(sd_netlink_open(&rtnl) >= 0);
/* 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(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &r) == 1);
assert_se(t->n_ref == 1);
assert_se(!sd_netlink_message_unref(m));
/* destroy callback is called when asynchronous call is cancelled */
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(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(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(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
assert_se(t->n_ref == 1);
}
static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int *counter = userdata;
int r;
@ -227,27 +345,6 @@ static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
return 1;
}
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;
char *ifname;
ifname = strdup("lo");
assert_se(ifname);
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, ifname, 0, &serial) >= 0);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &r) >= 0);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
static void test_pipe(int ifindex) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
@ -259,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, &counter, 0, NULL) >= 0);
assert_se(sd_netlink_call_async(rtnl, m1, pipe_handler, NULL, &counter, 0, NULL) >= 0);
counter++;
assert_se(sd_netlink_call_async(rtnl, m2, pipe_handler, &counter, 0, NULL) >= 0);
assert_se(sd_netlink_call_async(rtnl, m2, pipe_handler, NULL, &counter, 0, NULL) >= 0);
while (counter > 0) {
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
@ -366,31 +463,25 @@ int main(void) {
uint16_t type;
test_match();
test_multiple();
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(rtnl);
test_route(rtnl);
test_message(rtnl);
test_container(rtnl);
if_loopback = (int) if_nametoindex("lo");
assert_se(if_loopback > 0);
test_async(if_loopback);
test_async_destroy_callback(if_loopback);
test_pipe(if_loopback);
test_event_loop(if_loopback);
test_link_configure(rtnl, if_loopback);
test_get_addresses(rtnl);
test_message_link_bridge(rtnl);
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);

View File

@ -10,7 +10,7 @@
/* callback for brige netdev's parameter set */
static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(netdev_unrefp) NetDev *netdev = userdata;
NetDev *netdev = userdata;
int r;
assert(netdev);
@ -129,7 +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, 0, NULL);
r = sd_netlink_call_async(netdev->manager->rtnl, req, netdev_bridge_set_handler,
netdev_netlink_destroy_callback, netdev, 0, NULL);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");

View File

@ -18,9 +18,10 @@
/* callback for geneve netdev's created without a backing Link */
static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(netdev_unrefp) NetDev *netdev = userdata;
NetDev *netdev = userdata;
int r;
assert(netdev);
assert(netdev->state != _NETDEV_STATE_INVALID);
r = sd_netlink_message_get_errno(m);
@ -135,12 +136,12 @@ 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, 0, NULL);
r = sd_netlink_call_async(netdev->manager->rtnl, m, geneve_netdev_create_handler,
netdev_netlink_destroy_callback, netdev, 0, NULL);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
netdev_ref(netdev);
netdev->state = NETDEV_STATE_CREATING;
log_netdev_debug(netdev, "Creating");

View File

@ -99,25 +99,13 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
static void netdev_cancel_callbacks(NetDev *netdev) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
static void netdev_callbacks_clear(NetDev *netdev) {
netdev_join_callback *callback;
if (!netdev || !netdev->manager)
if (!netdev)
return;
rtnl_message_new_synthetic_error(netdev->manager->rtnl, -ENODEV, 0, &m);
while ((callback = netdev->callbacks)) {
if (m) {
assert(callback->link);
assert(callback->callback);
assert(netdev->manager);
assert(netdev->manager->rtnl);
callback->callback(netdev->manager->rtnl, m, callback->link);
}
LIST_REMOVE(callbacks, netdev->callbacks, callback);
link_unref(callback->link);
free(callback);
@ -127,7 +115,7 @@ static void netdev_cancel_callbacks(NetDev *netdev) {
static NetDev *netdev_free(NetDev *netdev) {
assert(netdev);
netdev_cancel_callbacks(netdev);
netdev_callbacks_clear(netdev);
if (netdev->ifname && netdev->manager)
hashmap_remove(netdev->manager->netdevs, netdev->ifname);
@ -161,6 +149,14 @@ static NetDev *netdev_free(NetDev *netdev) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free);
void netdev_netlink_destroy_callback(void *userdata) {
NetDev *netdev = userdata;
assert(userdata);
netdev_unref(netdev);
}
void netdev_drop(NetDev *netdev) {
if (!netdev || netdev->state == NETDEV_STATE_LINGER)
return;
@ -169,7 +165,7 @@ void netdev_drop(NetDev *netdev) {
log_netdev_debug(netdev, "netdev removed");
netdev_cancel_callbacks(netdev);
netdev_callbacks_clear(netdev);
netdev_unref(netdev);
@ -197,7 +193,7 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
static int netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED;
netdev_cancel_callbacks(netdev);
netdev_callbacks_clear(netdev);
return 0;
}
@ -229,7 +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, 0, NULL);
r = sd_netlink_call_async(netdev->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
@ -274,9 +271,10 @@ static int netdev_enter_ready(NetDev *netdev) {
/* callback for netdev's created without a backing Link */
static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(netdev_unrefp) NetDev *netdev = userdata;
NetDev *netdev = userdata;
int r;
assert(netdev);
assert(netdev->state != _NETDEV_STATE_INVALID);
r = sd_netlink_message_get_errno(m);
@ -294,7 +292,7 @@ static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *
return 1;
}
int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) {
static int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) {
int r;
assert(netdev);
@ -321,8 +319,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
return log_oom();
cb->callback = callback;
cb->link = link;
link_ref(link);
cb->link = link_ref(link);
LIST_PREPEND(callbacks, netdev->callbacks, cb);
@ -537,13 +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, 0, NULL);
r = sd_netlink_call_async(netdev->manager->rtnl, m, callback,
link_netlink_destroy_callback, link, 0, NULL);
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, 0, NULL);
r = sd_netlink_call_async(netdev->manager->rtnl, m, netdev_create_handler,
netdev_netlink_destroy_callback, netdev, 0, NULL);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");

View File

@ -150,12 +150,11 @@ void netdev_drop(NetDev *netdev);
NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev);
void netdev_netlink_destroy_callback(void *userdata);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback);
int netdev_get_mac(const char *ifname, struct ether_addr **ret);
int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t cb);

View File

@ -112,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");

View File

@ -18,7 +18,6 @@ typedef struct NetworkConfigSection NetworkConfigSection;
struct AddressLabel {
Network *network;
Link *link;
NetworkConfigSection *section;
unsigned char prefixlen;

View File

@ -453,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");
@ -631,7 +632,8 @@ int address_configure(
if (r < 0)
return r;
r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0) {
address_release(address);
return log_error_errno(r, "Could not send rtnetlink message: %m");

View File

@ -195,10 +195,13 @@ 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, 0, NULL);
r = sd_netlink_call_async(rtnl, req, set_brvlan_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}

View File

@ -17,7 +17,7 @@
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
@ -302,7 +302,7 @@ static int dhcp_lease_lost(Link *link) {
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);

View File

@ -100,18 +100,17 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
return sd_radv_start(radv);
}
static int dhcp6_route_remove_cb(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_debug_errno(l, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m");
log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m");
l = link_unref(l);
return 0;
return 1;
}
int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
@ -152,7 +151,7 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
route_update(route, NULL, 0, NULL, NULL, 0, 0,
RTN_UNREACHABLE);
r = route_remove(route, link, dhcp6_route_remove_cb);
r = route_remove(route, link, dhcp6_route_remove_handler);
if (r < 0) {
(void) in_addr_to_string(AF_INET6,
&pd_prefix, &buf);
@ -163,7 +162,6 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
continue;
}
link = link_ref(link);
log_link_debug(link, "Removing unreachable route %s/%u",
strnull(buf), pd_prefix_len);
@ -249,18 +247,17 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
return 0;
}
static int dhcp6_route_add_cb(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_debug_errno(l, r, "Received error when adding unreachable route for DHCPv6 delegated subnet: %m");
log_link_debug_errno(link, r, "Received error when adding unreachable route for DHCPv6 delegated subnet: %m");
l = link_unref(l);
return 0;
return 1;
}
@ -314,7 +311,7 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
route_update(route, NULL, 0, NULL, NULL, 0, 0,
RTN_UNREACHABLE);
r = route_configure(route, link, dhcp6_route_add_cb);
r = route_configure(route, link, dhcp6_route_handler);
if (r < 0) {
log_link_warning_errno(link, r, "Cannot configure unreachable route for delegated subnet %s/%u: %m",
strnull(buf),
@ -322,7 +319,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
route_free(route);
continue;
}
link = link_ref(link);
route_free(route);
@ -412,7 +408,7 @@ int dhcp6_request_prefix_delegation(Link *link) {
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);

View File

@ -134,10 +134,13 @@ 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, 0, NULL);
r = sd_netlink_call_async(rtnl, req, set_fdb_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}

View File

@ -52,7 +52,7 @@ static int ipv4ll_address_lost(Link *link) {
}
static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
@ -73,7 +73,7 @@ static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *u
}
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);

View File

@ -173,10 +173,13 @@ 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, 0, NULL);
r = sd_netlink_call_async(rtnl, req, set_ipv6_proxy_ndp_address_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}

View File

@ -407,6 +407,8 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
return 0;
}
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;
@ -549,6 +551,7 @@ static Link *link_free(Link *link) {
if (link->manager) {
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
set_remove(link->manager->links_requesting_uuid, link);
link_clean(link);
}
free(link->ifname);
@ -573,6 +576,14 @@ static Link *link_free(Link *link) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(Link, link, link_free);
void link_netlink_destroy_callback(void *userdata) {
Link *link = userdata;
assert(userdata);
link_unref(link);
}
int link_get(Manager *m, int ifindex, Link **ret) {
Link *link;
@ -796,9 +807,10 @@ static int link_set_routing_policy_rule(Link *link) {
}
static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
assert(link->route_messages > 0);
assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
@ -855,7 +867,7 @@ static int link_enter_set_routes(Link *link) {
}
int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(m);
@ -873,7 +885,7 @@ int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use
}
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(rtnl);
@ -904,7 +916,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
}
static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(rtnl);
@ -1204,7 +1216,7 @@ static int link_enter_set_addresses(Link *link) {
}
int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(m);
@ -1248,25 +1260,26 @@ static int link_set_proxy_arp(Link *link) {
}
static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
log_link_debug(link, "Set link");
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_error_errno(link, r, "Could not join netdev: %m");
link_enter_failed(link);
return 1;
}
return 0;
return 1;
}
static int link_configure_after_setting_mtu(Link *link);
static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(m);
@ -1327,19 +1340,19 @@ 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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link->setting_mtu = true;
link_ref(link);
link->setting_mtu = true;
return 0;
}
static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(m);
@ -1398,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1473,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1525,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1725,7 +1741,7 @@ bool link_has_carrier(Link *link) {
}
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
@ -1735,8 +1751,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
r = sd_netlink_message_get_errno(m);
if (r < 0)
/* we warn but don't fail the link, as it may be
brought up later */
/* we warn but don't fail the link, as it may be brought up later */
log_link_warning_errno(link, r, "Could not bring up interface: %m");
return 1;
@ -1818,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1843,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1932,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, m, link_set_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -1952,7 +1970,7 @@ static int link_set_can(Link *link) {
}
static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
@ -1964,10 +1982,8 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
if (r < 0)
log_link_warning_errno(link, r, "Could not bring down interface: %m");
if (streq_ptr(link->kind, "can")) {
link_ref(link);
if (streq_ptr(link->kind, "can"))
link_set_can(link);
}
return 1;
}
@ -1991,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@ -2296,7 +2313,7 @@ static int link_joined(Link *link) {
}
static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(link);
@ -3005,9 +3022,7 @@ static int link_configure_duid(Link *link) {
return 0;
}
static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
static int link_initialized_and_synced(Link *link) {
Network *network;
int r;
@ -3073,6 +3088,11 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
return 1;
}
static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
(void) link_initialized_and_synced(userdata);
return 1;
}
int link_initialized(Link *link, sd_device *device) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@ -3102,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_and_synced, link, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, link_initialized_handler,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return r;
@ -3349,10 +3369,7 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
if (r < 0)
goto failed;
} else {
/* we are calling a callback directly, so must take a ref */
link_ref(link);
r = link_initialized_and_synced(m->rtnl, NULL, link);
r = link_initialized_and_synced(link);
if (r < 0)
goto failed;
}
@ -3478,7 +3495,6 @@ int link_update(Link *link, sd_netlink_message *m) {
assert(m);
if (link->state == LINK_STATE_LINGER) {
link_ref(link);
log_link_info(link, "Link readded");
link_set_state(link, LINK_STATE_ENSLAVING);
@ -4003,8 +4019,7 @@ void link_clean(Link *link) {
assert(link);
assert(link->manager);
set_remove(link->manager->dirty_links, link);
link_unref(link);
link_unref(set_remove(link->manager->dirty_links, link));
}
static const char* const link_state_table[_LINK_STATE_MAX] = {

View File

@ -130,6 +130,8 @@ int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
Link *link_unref(Link *link);
Link *link_ref(Link *link);
void link_netlink_destroy_callback(void *userdata);
int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
@ -180,8 +182,6 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
int link_send_changed(Link *link, const char *property, ...) _sentinel_;
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
/* Macros which append INTERFACE= to the message */
#define log_link_full(link, level, error, ...) \

View File

@ -1239,16 +1239,15 @@ Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
return hashmap_get(m->dhcp6_prefixes, addr);
}
static int dhcp6_route_add_callback(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_debug_errno(l, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
l = link_unref(l);
log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
return 0;
}
@ -1267,33 +1266,30 @@ int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
if (r < 0)
return r;
r = route_configure(route, link, dhcp6_route_add_callback);
r = route_configure(route, link, dhcp6_route_add_handler);
if (r < 0)
return r;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
link = link_ref(link);
return hashmap_put(m->dhcp6_prefixes, addr, link);
}
static int dhcp6_route_remove_callback(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_debug_errno(l, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
l = link_unref(l);
return 0;
return 1;
}
int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
Link *l;
int r;
Route *route;
@ -1313,15 +1309,13 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
if (r < 0)
return r;
r = route_remove(route, l, dhcp6_route_remove_callback);
r = route_remove(route, l, dhcp6_route_remove_handler);
if (r < 0)
return r;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
l = link_ref(l);
return 0;
}
@ -1440,6 +1434,9 @@ void manager_free(Manager *m) {
free(m->state_file);
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
while ((network = m->networks))
network_free(network);
@ -1456,8 +1453,9 @@ void manager_free(Manager *m) {
link_unref(link);
}
hashmap_free(m->links);
set_free_with_destructor(m->dirty_links, link_unref);
hashmap_free(m->links);
set_free(m->links_requesting_uuid);
set_free(m->duids_requesting_uuid);
@ -1474,8 +1472,6 @@ void manager_free(Manager *m) {
set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
sd_event_unref(m->event);
sd_resolve_unref(m->resolve);

View File

@ -94,7 +94,6 @@ int manager_request_product_uuid(Manager *m, Link *link);
Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);

View File

@ -16,8 +16,8 @@
#define NDISC_RDNSS_MAX 64U
#define NDISC_PREFIX_LFT_MIN 7200U
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
@ -126,7 +126,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->lifetime = time_now + lifetime * USEC_PER_SEC;
route->mtu = mtu;
r = route_configure(route, link, ndisc_netlink_handler);
r = route_configure(route, link, ndisc_route_handler);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set default route: %m");
link_enter_failed(link);
@ -224,7 +224,7 @@ static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *
if (address->cinfo.ifa_valid == 0)
return;
r = address_configure(address, link, ndisc_netlink_handler, true);
r = address_configure(address, link, ndisc_route_handler, true);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
link_enter_failed(link);
@ -282,7 +282,7 @@ static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt)
return;
}
r = route_configure(route, link, ndisc_netlink_handler);
r = route_configure(route, link, ndisc_route_handler);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set prefix route: %m");
link_enter_failed(link);
@ -354,7 +354,7 @@ static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
return;
}
r = route_configure(route, link, ndisc_netlink_handler);
r = route_configure(route, link, ndisc_route_handler);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set additional route: %m");
link_enter_failed(link);

View File

@ -439,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");
@ -448,32 +449,13 @@ int route_remove(Route *route, Link *link,
return 0;
}
static int route_expire_callback(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_warning_errno(link, r, "could not remove route: %m");
return 1;
}
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
Route *route = userdata;
int r;
assert(route);
r = route_remove(route, route->link, route_expire_callback);
r = route_remove(route, route->link, link_route_remove_handler);
if (r < 0)
log_warning_errno(r, "Could not remove route: %m");
else
@ -638,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, req, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");

View File

@ -308,7 +308,7 @@ int routing_policy_rule_add_foreign(Manager *m,
}
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(m);
@ -370,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, m, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");
@ -419,7 +420,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
}
int link_routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_(link_unrefp) Link *link = userdata;
Link *link = userdata;
int r;
assert(rtnl);
@ -538,7 +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, 0, NULL);
r = sd_netlink_call_async(link->manager->rtnl, m, callback,
link_netlink_destroy_callback, link, 0, NULL);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");

View File

@ -38,6 +38,7 @@ typedef enum {SD_GENL_ID_CTRL, SD_GENL_WIREGUARD, SD_GENL_FOU} sd_genl_family;
/* callback */
typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata);
typedef void (*sd_netlink_destroy_t)(void *userdata);
/* bus */
int sd_netlink_new_from_netlink(sd_netlink **nl, int fd);
@ -50,11 +51,12 @@ 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,
void *userdata, uint64_t usec, uint32_t *serial);
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(sd_netlink *nl, sd_netlink_message *message, uint64_t timeout,
sd_netlink_message **reply);
sd_netlink_message **reply);
int sd_netlink_get_events(sd_netlink *nl);
int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout);