#include "rtnl-util.h"
static int sd_rtnl_new(sd_rtnl **ret) {
- sd_rtnl *rtnl;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
assert_return(ret, -EINVAL);
/* We guarantee that wqueue always has space for at least
* one entry */
rtnl->wqueue = new(sd_rtnl_message*, 1);
- if (!rtnl->wqueue) {
- free(rtnl);
+ if (!rtnl->wqueue)
return -ENOMEM;
- }
*ret = rtnl;
+ rtnl = NULL;
+
return 0;
}
return rtnl->original_pid != getpid();
}
-int sd_rtnl_open(uint32_t groups, sd_rtnl **ret) {
- _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
+int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) {
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
socklen_t addrlen;
int r;
}
sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) {
+ assert_return(rtnl, NULL);
+ assert_return(!rtnl_pid_changed(rtnl), NULL);
+
if (rtnl)
assert_se(REFCNT_INC(rtnl->n_ref) >= 2);
}
sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) {
+ if (!rtnl)
+ return NULL;
- if (rtnl && REFCNT_DEC(rtnl->n_ref) <= 0) {
+ assert_return(!rtnl_pid_changed(rtnl), NULL);
+
+ if (REFCNT_DEC(rtnl->n_ref) <= 0) {
struct match_callback *f;
unsigned i;
hashmap_free_free(rtnl->reply_callbacks);
prioq_free(rtnl->reply_callbacks_prioq);
+ sd_event_source_unref(rtnl->io_event_source);
+ sd_event_source_unref(rtnl->time_event_source);
+ sd_event_source_unref(rtnl->exit_event_source);
+ sd_event_unref(rtnl->event);
+
while ((f = rtnl->match_callbacks)) {
LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f);
free(f);
}
- if (rtnl->fd >= 0)
- close_nointr_nofail(rtnl->fd);
-
+ safe_close(rtnl->fd);
free(rtnl);
}
return NULL;
}
+static void rtnl_seal_message(sd_rtnl *rtnl, sd_rtnl_message *m) {
+ assert(rtnl);
+ assert(!rtnl_pid_changed(rtnl));
+ assert(m);
+ assert(m->hdr);
+
+ m->hdr->nlmsg_seq = rtnl->serial++;
+
+ rtnl_message_seal(m);
+
+ return;
+}
+
int sd_rtnl_send(sd_rtnl *nl,
sd_rtnl_message *message,
uint32_t *serial) {
assert_return(nl, -EINVAL);
assert_return(!rtnl_pid_changed(nl), -ECHILD);
assert_return(message, -EINVAL);
+ assert_return(!message->sealed, -EPERM);
- r = message_seal(nl, message);
- if (r < 0)
- return r;
+ rtnl_seal_message(nl, message);
if (nl->wqueue_size <= 0) {
/* send directly */
}
if (serial)
- *serial = message_get_serial(message);
+ *serial = rtnl_message_get_serial(message);
return 1;
}
/* Try to read a new message */
r = socket_read_message(rtnl, &z);
- if (r < 0)
+ if (r <= 0)
return r;
- if (r == 0)
- return 0;
*message = z;
}
static int process_timeout(sd_rtnl *rtnl) {
- _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
struct reply_callback *c;
usec_t n;
int r;
if (c->timeout > n)
return 0;
- r = message_new_synthetic_error(-ETIMEDOUT, c->serial, &m);
+ r = rtnl_message_new_synthetic_error(-ETIMEDOUT, c->serial, &m);
if (r < 0)
return r;
assert(rtnl);
assert(m);
- serial = message_get_serial(m);
+ if (sd_rtnl_message_is_broadcast(m))
+ return 0;
+
+ serial = rtnl_message_get_serial(m);
c = hashmap_remove(rtnl->reply_callbacks, &serial);
if (!c)
return 0;
}
static int process_running(sd_rtnl *rtnl, sd_rtnl_message **ret) {
- _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
int r;
assert(rtnl);
for (;;) {
usec_t left;
- _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *incoming = NULL;
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *incoming = NULL;
if (!room) {
sd_rtnl_message **q;
if (r < 0)
return r;
if (incoming) {
- uint32_t received_serial = message_get_serial(incoming);
+ uint32_t received_serial = rtnl_message_get_serial(incoming);
if (received_serial == serial) {
r = sd_rtnl_message_get_errno(incoming);
return r;
}
- r = sd_event_add_io(rtnl->event, rtnl->fd, 0, io_callback, rtnl, &rtnl->io_event_source);
+ r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl);
if (r < 0)
goto fail;
if (r < 0)
goto fail;
- r = sd_event_add_monotonic(rtnl->event, 0, 0, time_callback, rtnl, &rtnl->time_event_source);
+ r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl);
if (r < 0)
goto fail;
if (r < 0)
goto fail;
- r = sd_event_add_exit(rtnl->event, exit_callback, rtnl, &rtnl->exit_event_source);
+ r = sd_event_add_exit(rtnl->event, &rtnl->exit_event_source, exit_callback, rtnl);
if (r < 0)
goto fail;
assert_return(rtnl, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
- assert_return(message_type_is_link(type) || message_type_is_addr(type) || message_type_is_route(type), -ENOTSUP);
+ assert_return(rtnl_message_type_is_link(type) ||
+ rtnl_message_type_is_addr(type) ||
+ rtnl_message_type_is_route(type), -ENOTSUP);
c = new0(struct match_callback, 1);
if (!c)