X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-rtnl%2Fsd-rtnl.c;h=2ab9d90aa790d4f76360d6adc45111d2b6a6fe1b;hb=0a827d105de9d3d502f22e77fb3ff83da479c2e7;hp=04fcb3d002703f7ffacac96797d7a2befcc41bab;hpb=3815f36f05f8bc06904777b1eb7f1d22b78bcced;p=elogind.git diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 04fcb3d00..2ab9d90aa 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -31,7 +31,7 @@ #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); @@ -52,12 +52,12 @@ static int sd_rtnl_new(sd_rtnl **ret) { /* 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; } @@ -70,8 +70,8 @@ static bool rtnl_pid_changed(sd_rtnl *rtnl) { 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; @@ -104,6 +104,9 @@ int sd_rtnl_open(uint32_t groups, sd_rtnl **ret) { } 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); @@ -111,8 +114,12 @@ sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) { } 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; @@ -127,20 +134,36 @@ sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) { 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) { @@ -149,10 +172,9 @@ int sd_rtnl_send(sd_rtnl *nl, assert_return(nl, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); assert_return(message, -EINVAL); + assert_return(!message->sealed, -EPERM); - r = rtnl_message_seal(nl, message); - if (r < 0) - return r; + rtnl_seal_message(nl, message); if (nl->wqueue_size <= 0) { /* send directly */ @@ -205,10 +227,8 @@ static int dispatch_rqueue(sd_rtnl *rtnl, sd_rtnl_message **message) { /* 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; @@ -241,7 +261,7 @@ static int dispatch_wqueue(sd_rtnl *rtnl) { } 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; @@ -277,6 +297,9 @@ static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) { assert(rtnl); assert(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) @@ -315,7 +338,7 @@ static int process_match(sd_rtnl *rtnl, sd_rtnl_message *m) { } 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); @@ -557,7 +580,7 @@ int sd_rtnl_call(sd_rtnl *nl, 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; @@ -774,7 +797,7 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { 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; @@ -786,7 +809,7 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { 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; @@ -794,7 +817,7 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { 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;