]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd/sd-netlink/sd-netlink.c
libpasswdqc: add missing `#include "dlfcn-util.h"`
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / sd-netlink.c
index 132f63e57decbd021e48037ccfce2d3829cedc2d..b347ee6339530bf7b9de9738eccb9b289439f3f5 100644 (file)
@@ -45,13 +45,13 @@ static int netlink_new(sd_netlink **ret) {
                  * while the socket sticks around we might get confused by replies from earlier runs coming
                  * in late — which is pretty likely if we'd start our sequence numbers always from 1. Hence,
                  * let's start with a value based on the system clock. This should make collisions much less
-                 * likely (though still theoretically possible). We use a 32 bit µs counter starting at boot
+                 * likely (though still theoretically possible). We use a 32 bit μs counter starting at boot
                  * for this (and explicitly exclude the zero, see above). This counter will wrap around after
                  * a bit more than 1h, but that's hopefully OK as the kernel shouldn't take that long to
                  * reply to our requests.
                  *
                  * We only pick the initial start value this way. For each message we simply increase the
-                 * sequence number by 1. This means we could enqueue 1 netlink message per µs without risking
+                 * sequence number by 1. This means we could enqueue 1 netlink message per μs without risking
                  * collisions, which should be OK.
                  *
                  * Note this means the serials will be in the range 1…UINT32_MAX here.
@@ -176,7 +176,7 @@ static int dispatch_rqueue(sd_netlink *nl, sd_netlink_message **ret) {
         assert(nl);
         assert(ret);
 
-        if (ordered_set_size(nl->rqueue) <= 0) {
+        if (ordered_set_isempty(nl->rqueue)) {
                 /* Try to read a new message */
                 r = socket_read_message(nl);
                 if (r == -ENOBUFS) /* FIXME: ignore buffer overruns for now */
@@ -215,7 +215,6 @@ static int process_timeout(sd_netlink *nl) {
                 return r;
 
         assert_se(prioq_pop(nl->reply_callbacks_prioq) == c);
-        c->timeout = 0;
         hashmap_remove(nl->reply_callbacks, UINT32_TO_PTR(c->serial));
 
         slot = container_of(c, sd_netlink_slot, reply_callback);
@@ -248,10 +247,8 @@ static int process_reply(sd_netlink *nl, sd_netlink_message *m) {
         if (!c)
                 return 0;
 
-        if (c->timeout != 0) {
+        if (c->timeout != USEC_INFINITY)
                 prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx);
-                c->timeout = 0;
-        }
 
         r = sd_netlink_message_get_type(m, &type);
         if (r < 0)
@@ -380,12 +377,28 @@ int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret) {
         return r;
 }
 
-static usec_t calc_elapse(uint64_t usec) {
-        if (usec == UINT64_MAX)
-                return 0;
+static usec_t timespan_to_timestamp(usec_t usec) {
+        static bool default_timeout_set = false;
+        static usec_t default_timeout;
+        int r;
+
+        if (usec == 0) {
+                if (!default_timeout_set) {
+                        const char *e;
+
+                        default_timeout_set = true;
+                        default_timeout = NETLINK_DEFAULT_TIMEOUT_USEC;
 
-        if (usec == 0)
-                usec = NETLINK_DEFAULT_TIMEOUT_USEC;
+                        e = secure_getenv("SYSTEMD_NETLINK_DEFAULT_TIMEOUT");
+                        if (e) {
+                                r = parse_sec(e, &default_timeout);
+                                if (r < 0)
+                                        log_debug_errno(r, "sd-netlink: Failed to parse $SYSTEMD_NETLINK_DEFAULT_TIMEOUT environment variable, ignoring: %m");
+                        }
+                }
+
+                usec = default_timeout;
+        }
 
         return usec_add(now(CLOCK_MONOTONIC), usec);
 }
@@ -430,11 +443,11 @@ int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
         assert_return(nl, -EINVAL);
         assert_return(!netlink_pid_changed(nl), -ECHILD);
 
-        if (ordered_set_size(nl->rqueue) > 0)
+        if (!ordered_set_isempty(nl->rqueue))
                 return 0;
 
         r = netlink_poll(nl, false, timeout_usec);
-        if (r < 0 && ERRNO_IS_TRANSIENT(r)) /* Convert EINTR to "something happened" and give user a chance to run some code before calling back into us */
+        if (ERRNO_IS_NEG_TRANSIENT(r)) /* Convert EINTR to "something happened" and give user a chance to run some code before calling back into us */
                 return 1;
         return r;
 }
@@ -442,13 +455,13 @@ int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
 static int timeout_compare(const void *a, const void *b) {
         const struct reply_callback *x = a, *y = b;
 
-        if (x->timeout != 0 && y->timeout == 0)
-                return -1;
+        return CMP(x->timeout, y->timeout);
+}
 
-        if (x->timeout == 0 && y->timeout != 0)
-                return 1;
+size_t netlink_get_reply_callback_count(sd_netlink *nl) {
+        assert(nl);
 
-        return CMP(x->timeout, y->timeout);
+        return hashmap_size(nl->reply_callbacks);
 }
 
 int sd_netlink_call_async(
@@ -470,7 +483,7 @@ int sd_netlink_call_async(
         assert_return(!netlink_pid_changed(nl), -ECHILD);
 
         if (hashmap_size(nl->reply_callbacks) >= REPLY_CALLBACKS_MAX)
-                return -ERANGE;
+                return -EXFULL;
 
         r = hashmap_ensure_allocated(&nl->reply_callbacks, &trivial_hash_ops);
         if (r < 0)
@@ -487,7 +500,7 @@ int sd_netlink_call_async(
                 return r;
 
         slot->reply_callback.callback = callback;
-        slot->reply_callback.timeout = calc_elapse(usec);
+        slot->reply_callback.timeout = timespan_to_timestamp(usec);
 
         k = sd_netlink_send(nl, m, &slot->reply_callback.serial);
         if (k < 0)
@@ -497,7 +510,7 @@ int sd_netlink_call_async(
         if (r < 0)
                 return r;
 
-        if (slot->reply_callback.timeout != 0) {
+        if (slot->reply_callback.timeout != USEC_INFINITY) {
                 r = prioq_put(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
                 if (r < 0) {
                         (void) hashmap_remove(nl->reply_callbacks, UINT32_TO_PTR(slot->reply_callback.serial));
@@ -528,7 +541,7 @@ int sd_netlink_read(
         assert_return(nl, -EINVAL);
         assert_return(!netlink_pid_changed(nl), -ECHILD);
 
-        timeout = calc_elapse(usec);
+        timeout = timespan_to_timestamp(usec);
 
         for (;;) {
                 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
@@ -567,7 +580,7 @@ int sd_netlink_read(
                         /* received message, so try to process straight away */
                         continue;
 
-                if (timeout > 0) {
+                if (timeout != USEC_INFINITY) {
                         usec_t n;
 
                         n = now(CLOCK_MONOTONIC);
@@ -610,7 +623,7 @@ int sd_netlink_get_events(sd_netlink *nl) {
         assert_return(nl, -EINVAL);
         assert_return(!netlink_pid_changed(nl), -ECHILD);
 
-        return ordered_set_size(nl->rqueue) == 0 ? POLLIN : 0;
+        return ordered_set_isempty(nl->rqueue) ? POLLIN : 0;
 }
 
 int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout_usec) {
@@ -620,7 +633,7 @@ int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout_usec) {
         assert_return(timeout_usec, -EINVAL);
         assert_return(!netlink_pid_changed(nl), -ECHILD);
 
-        if (ordered_set_size(nl->rqueue) > 0) {
+        if (!ordered_set_isempty(nl->rqueue)) {
                 *timeout_usec = 0;
                 return 1;
         }
@@ -754,6 +767,12 @@ int sd_netlink_detach_event(sd_netlink *nl) {
         return 0;
 }
 
+sd_event* sd_netlink_get_event(sd_netlink *nl) {
+        assert_return(nl, NULL);
+
+        return nl->event;
+}
+
 int netlink_add_match_internal(
                 sd_netlink *nl,
                 sd_netlink_slot **ret_slot,