#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
-int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
+int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
sd_netlink_message *m;
assert_return(ret, -EINVAL);
- /* Note that 'rtnl' is currently unused, if we start using it internally
- we must take care to avoid problems due to mutual references between
- buses and their queued messages. See sd-bus.
- */
+ /* Note that 'nl' is currently unused, if we start using it internally we must take care to
+ * avoid problems due to mutual references between buses and their queued messages. See sd-bus. */
m = new(sd_netlink_message, 1);
if (!m)
*m = (sd_netlink_message) {
.n_ref = 1,
- .protocol = rtnl->protocol,
+ .protocol = nl->protocol,
.sealed = false,
};
return 0;
}
-int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
+int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
const NLType *nl_type;
size_t size;
int r;
- assert_return(rtnl, -EINVAL);
+ assert_return(nl, -EINVAL);
- r = type_system_root_get_type(rtnl, &nl_type, type);
+ r = type_system_root_get_type(nl, &nl_type, type);
if (r < 0)
return r;
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
return -EINVAL;
- r = message_new_empty(rtnl, &m);
+ r = message_new_empty(nl, &m);
if (r < 0)
return r;
return 0;
}
+int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
+ struct nlmsgerr *err;
+ int r;
+
+ assert(error <= 0);
+
+ r = message_new(nl, ret, NLMSG_ERROR);
+ if (r < 0)
+ return r;
+
+ message_seal(*ret);
+ (*ret)->hdr->nlmsg_seq = serial;
+
+ err = NLMSG_DATA((*ret)->hdr);
+ err->error = error;
+
+ return 0;
+}
+
int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
/* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
- assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
+ assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
if (r < 0) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
+ assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
if (r < 0)
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
+ assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
if (r < 0)
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
- assert(m->n_containers < RTNL_CONTAINER_DEPTH);
+ assert(m->n_containers < NETLINK_CONTAINER_DEPTH);
if (!m->containers[m->n_containers].attributes)
return -ENODATA;
int r;
assert_return(m, -EINVAL);
- assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
+ assert_return(m->n_containers < NETLINK_CONTAINER_DEPTH, -EINVAL);
r = type_system_get_type(m->containers[m->n_containers].type_system,
&nl_type,
return -ENOMEM;
if (attributes[type].offset != 0)
- log_debug("rtnl: message parse - overwriting repeated attribute");
+ log_debug("sd-netlink: message parse - overwriting repeated attribute");
attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
int r;
assert_return(m, -EINVAL);
- assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
+ assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
r = type_system_get_type(m->containers[m->n_containers].type_system,
&nl_type,
int r;
assert_return(m, -EINVAL);
- assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
+ assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
r = netlink_message_read_internal(m, type_id, &container, NULL);
if (r < 0)
return 0;
}
-uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
+uint32_t message_get_serial(sd_netlink_message *m) {
assert(m);
assert(m->hdr);
/* don't allow appending to message once parsed */
if (!m->sealed)
- rtnl_message_seal(m);
+ message_seal(m);
for (unsigned i = 1; i <= m->n_containers; i++)
m->containers[i].attributes = mfree(m->containers[i].attributes);
return 0;
}
-void rtnl_message_seal(sd_netlink_message *m) {
+void message_seal(sd_netlink_message *m) {
assert(m);
assert(!m->sealed);
#include "macro.h"
#include "netlink-internal.h"
#include "netlink-slot.h"
-#include "netlink-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "string-util.h"
-#include "util.h"
/* Some really high limit, to catch programming errors */
#define REPLY_CALLBACKS_MAX UINT16_MAX
-static int sd_netlink_new(sd_netlink **ret) {
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+static int netlink_new(sd_netlink **ret) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
assert_return(ret, -EINVAL);
- rtnl = new(sd_netlink, 1);
- if (!rtnl)
+ nl = new(sd_netlink, 1);
+ if (!nl)
return -ENOMEM;
- *rtnl = (sd_netlink) {
+ *nl = (sd_netlink) {
.n_ref = 1,
.fd = -1,
.sockaddr.nl.nl_family = AF_NETLINK,
.serial = (uint32_t) (now(CLOCK_MONOTONIC) % UINT32_MAX) + 1,
};
- /* We guarantee that the read buffer has at least space for
- * a message header */
- if (!greedy_realloc((void**)&rtnl->rbuffer, sizeof(struct nlmsghdr), sizeof(uint8_t)))
+ /* We guarantee that the read buffer has at least space for a message header */
+ if (!greedy_realloc((void**) &nl->rbuffer, sizeof(struct nlmsghdr), sizeof(uint8_t)))
return -ENOMEM;
- *ret = TAKE_PTR(rtnl);
-
+ *ret = TAKE_PTR(nl);
return 0;
}
-int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+int sd_netlink_new_from_fd(sd_netlink **ret, int fd) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
socklen_t addrlen;
int r;
assert_return(ret, -EINVAL);
- r = sd_netlink_new(&rtnl);
+ r = netlink_new(&nl);
if (r < 0)
return r;
- addrlen = sizeof(rtnl->sockaddr);
+ addrlen = sizeof(nl->sockaddr);
- r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen);
+ r = getsockname(fd, &nl->sockaddr.sa, &addrlen);
if (r < 0)
return -errno;
- if (rtnl->sockaddr.nl.nl_family != AF_NETLINK)
+ if (nl->sockaddr.nl.nl_family != AF_NETLINK)
return -EINVAL;
- rtnl->fd = fd;
-
- *ret = TAKE_PTR(rtnl);
+ nl->fd = fd;
+ *ret = TAKE_PTR(nl);
return 0;
}
-static bool rtnl_pid_changed(const sd_netlink *rtnl) {
- assert(rtnl);
-
- /* We don't support people creating an rtnl connection and
- * keeping it around over a fork(). Let's complain. */
-
- return rtnl->original_pid != getpid_cached();
-}
-
int sd_netlink_open_fd(sd_netlink **ret, int fd) {
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
int r, protocol;
assert_return(ret, -EINVAL);
assert_return(fd >= 0, -EBADF);
- r = sd_netlink_new(&rtnl);
+ r = netlink_new(&nl);
if (r < 0)
return r;
if (r < 0)
return r;
- rtnl->fd = fd;
- rtnl->protocol = protocol;
+ nl->fd = fd;
+ nl->protocol = protocol;
r = setsockopt_int(fd, SOL_NETLINK, NETLINK_EXT_ACK, true);
if (r < 0)
if (r < 0)
log_debug_errno(r, "sd-netlink: Failed to enable NETLINK_GET_STRICT_CHK option, ignoring: %m");
- r = socket_bind(rtnl);
+ r = socket_bind(nl);
if (r < 0) {
- rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
- rtnl->protocol = -1;
+ nl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
+ nl->protocol = -1;
return r;
}
- *ret = TAKE_PTR(rtnl);
+ *ret = TAKE_PTR(nl);
return 0;
}
return netlink_open_family(ret, NETLINK_ROUTE);
}
-int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) {
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+bool netlink_pid_changed(sd_netlink *nl) {
+ assert(nl);
+
+ /* We don't support people creating an nl connection and
+ * keeping it around over a fork(). Let's complain. */
+
+ return nl->original_pid != getpid_cached();
+}
+
+int sd_netlink_inc_rcvbuf(sd_netlink *nl, size_t size) {
+ assert_return(nl, -EINVAL);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
- return fd_inc_rcvbuf(rtnl->fd, size);
+ return fd_inc_rcvbuf(nl->fd, size);
}
-static sd_netlink *netlink_free(sd_netlink *rtnl) {
+static sd_netlink *netlink_free(sd_netlink *nl) {
sd_netlink_slot *s;
unsigned i;
- assert(rtnl);
+ assert(nl);
- for (i = 0; i < rtnl->rqueue_size; i++)
- sd_netlink_message_unref(rtnl->rqueue[i]);
- free(rtnl->rqueue);
+ for (i = 0; i < nl->rqueue_size; i++)
+ sd_netlink_message_unref(nl->rqueue[i]);
+ free(nl->rqueue);
- for (i = 0; i < rtnl->rqueue_partial_size; i++)
- sd_netlink_message_unref(rtnl->rqueue_partial[i]);
- free(rtnl->rqueue_partial);
+ for (i = 0; i < nl->rqueue_partial_size; i++)
+ sd_netlink_message_unref(nl->rqueue_partial[i]);
+ free(nl->rqueue_partial);
- free(rtnl->rbuffer);
+ free(nl->rbuffer);
- while ((s = rtnl->slots)) {
+ while ((s = nl->slots)) {
assert(s->floating);
netlink_slot_disconnect(s, true);
}
- hashmap_free(rtnl->reply_callbacks);
- prioq_free(rtnl->reply_callbacks_prioq);
+ hashmap_free(nl->reply_callbacks);
+ prioq_free(nl->reply_callbacks_prioq);
- sd_event_source_unref(rtnl->io_event_source);
- sd_event_source_unref(rtnl->time_event_source);
- sd_event_unref(rtnl->event);
+ sd_event_source_unref(nl->io_event_source);
+ sd_event_source_unref(nl->time_event_source);
+ sd_event_unref(nl->event);
- hashmap_free(rtnl->broadcast_group_refs);
+ hashmap_free(nl->broadcast_group_refs);
- hashmap_free(rtnl->genl_family_to_nlmsg_type);
- hashmap_free(rtnl->nlmsg_type_to_genl_family);
+ hashmap_free(nl->genl_family_to_nlmsg_type);
+ hashmap_free(nl->nlmsg_type_to_genl_family);
- safe_close(rtnl->fd);
- return mfree(rtnl);
+ safe_close(nl->fd);
+ return mfree(nl);
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
-static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
+static void netlink_seal_message(sd_netlink *nl, sd_netlink_message *m) {
uint32_t picked;
- assert(rtnl);
- assert(!rtnl_pid_changed(rtnl));
+ assert(nl);
+ assert(!netlink_pid_changed(nl));
assert(m);
assert(m->hdr);
/* Avoid collisions with outstanding requests */
do {
- picked = rtnl->serial;
+ picked = nl->serial;
/* Don't use seq == 0, as that is used for broadcasts, so we would get confused by replies to
such messages */
- rtnl->serial = rtnl->serial == UINT32_MAX ? 1 : rtnl->serial + 1;
+ nl->serial = nl->serial == UINT32_MAX ? 1 : nl->serial + 1;
- } while (hashmap_contains(rtnl->reply_callbacks, UINT32_TO_PTR(picked)));
+ } while (hashmap_contains(nl->reply_callbacks, UINT32_TO_PTR(picked)));
m->hdr->nlmsg_seq = picked;
- rtnl_message_seal(m);
+ message_seal(m);
}
-int sd_netlink_send(sd_netlink *nl,
- sd_netlink_message *message,
- uint32_t *serial) {
+int sd_netlink_send(
+ sd_netlink *nl,
+ sd_netlink_message *message,
+ uint32_t *serial) {
+
int r;
assert_return(nl, -EINVAL);
- assert_return(!rtnl_pid_changed(nl), -ECHILD);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
assert_return(message, -EINVAL);
assert_return(!message->sealed, -EPERM);
- rtnl_seal_message(nl, message);
+ netlink_seal_message(nl, message);
r = socket_write_message(nl, message);
if (r < 0)
return r;
if (serial)
- *serial = rtnl_message_get_serial(message);
+ *serial = message_get_serial(message);
return 1;
}
int r;
assert_return(nl, -EINVAL);
- assert_return(!rtnl_pid_changed(nl), -ECHILD);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
assert_return(messages, -EINVAL);
assert_return(msgcount > 0, -EINVAL);
for (unsigned i = 0; i < msgcount; i++) {
assert_return(!messages[i]->sealed, -EPERM);
- rtnl_seal_message(nl, messages[i]);
+ netlink_seal_message(nl, messages[i]);
if (serials)
- serials[i] = rtnl_message_get_serial(messages[i]);
+ serials[i] = message_get_serial(messages[i]);
}
r = socket_writev_message(nl, messages, msgcount);
return r;
}
-int rtnl_rqueue_make_room(sd_netlink *rtnl) {
- assert(rtnl);
+int netlink_rqueue_make_room(sd_netlink *nl) {
+ assert(nl);
- if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX)
+ if (nl->rqueue_size >= NETLINK_RQUEUE_MAX)
return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS),
- "rtnl: exhausted the read queue size (%d)",
- RTNL_RQUEUE_MAX);
+ "sd-netlink: exhausted the read queue size (%d)",
+ NETLINK_RQUEUE_MAX);
- if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_size + 1))
+ if (!GREEDY_REALLOC(nl->rqueue, nl->rqueue_size + 1))
return -ENOMEM;
return 0;
}
-int rtnl_rqueue_partial_make_room(sd_netlink *rtnl) {
- assert(rtnl);
+int netlink_rqueue_partial_make_room(sd_netlink *nl) {
+ assert(nl);
- if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX)
+ if (nl->rqueue_partial_size >= NETLINK_RQUEUE_MAX)
return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS),
- "rtnl: exhausted the partial read queue size (%d)",
- RTNL_RQUEUE_MAX);
+ "sd-netlink: exhausted the partial read queue size (%d)",
+ NETLINK_RQUEUE_MAX);
- if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_size + 1))
+ if (!GREEDY_REALLOC(nl->rqueue_partial, nl->rqueue_partial_size + 1))
return -ENOMEM;
return 0;
}
-static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
+static int dispatch_rqueue(sd_netlink *nl, sd_netlink_message **message) {
int r;
- assert(rtnl);
+ assert(nl);
assert(message);
- if (rtnl->rqueue_size <= 0) {
+ if (nl->rqueue_size <= 0) {
/* Try to read a new message */
- r = socket_read_message(rtnl);
+ r = socket_read_message(nl);
if (r == -ENOBUFS) { /* FIXME: ignore buffer overruns for now */
- log_debug_errno(r, "Got ENOBUFS from netlink socket, ignoring.");
+ log_debug_errno(r, "sd-netlink: Got ENOBUFS from netlink socket, ignoring.");
return 1;
}
if (r <= 0)
}
/* Dispatch a queued message */
- *message = rtnl->rqueue[0];
- rtnl->rqueue_size--;
- memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size);
+ *message = nl->rqueue[0];
+ nl->rqueue_size--;
+ memmove(nl->rqueue, nl->rqueue + 1, sizeof(sd_netlink_message*) * nl->rqueue_size);
return 1;
}
-static int process_timeout(sd_netlink *rtnl) {
+static int process_timeout(sd_netlink *nl) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
struct reply_callback *c;
sd_netlink_slot *slot;
usec_t n;
int r;
- assert(rtnl);
+ assert(nl);
- c = prioq_peek(rtnl->reply_callbacks_prioq);
+ c = prioq_peek(nl->reply_callbacks_prioq);
if (!c)
return 0;
if (c->timeout > n)
return 0;
- r = rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, c->serial, &m);
+ r = message_new_synthetic_error(nl, -ETIMEDOUT, c->serial, &m);
if (r < 0)
return r;
- assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c);
+ assert_se(prioq_pop(nl->reply_callbacks_prioq) == c);
c->timeout = 0;
- hashmap_remove(rtnl->reply_callbacks, UINT32_TO_PTR(c->serial));
+ hashmap_remove(nl->reply_callbacks, UINT32_TO_PTR(c->serial));
slot = container_of(c, sd_netlink_slot, reply_callback);
- r = c->callback(rtnl, m, slot->userdata);
+ r = c->callback(nl, m, slot->userdata);
if (r < 0)
log_debug_errno(r, "sd-netlink: timedout callback %s%s%sfailed: %m",
slot->description ? "'" : "",
return 1;
}
-static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
+static int process_reply(sd_netlink *nl, sd_netlink_message *m) {
struct reply_callback *c;
sd_netlink_slot *slot;
uint32_t serial;
uint16_t type;
int r;
- assert(rtnl);
+ assert(nl);
assert(m);
- serial = rtnl_message_get_serial(m);
- c = hashmap_remove(rtnl->reply_callbacks, UINT32_TO_PTR(serial));
+ serial = message_get_serial(m);
+ c = hashmap_remove(nl->reply_callbacks, UINT32_TO_PTR(serial));
if (!c)
return 0;
if (c->timeout != 0) {
- prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx);
+ prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx);
c->timeout = 0;
}
slot = container_of(c, sd_netlink_slot, reply_callback);
- r = c->callback(rtnl, m, slot->userdata);
+ r = c->callback(nl, m, slot->userdata);
if (r < 0)
log_debug_errno(r, "sd-netlink: reply callback %s%s%sfailed: %m",
slot->description ? "'" : "",
return 1;
}
-static int process_match(sd_netlink *rtnl, sd_netlink_message *m) {
+static int process_match(sd_netlink *nl, sd_netlink_message *m) {
struct match_callback *c;
sd_netlink_slot *slot;
uint16_t type;
int r;
- assert(rtnl);
+ assert(nl);
assert(m);
r = sd_netlink_message_get_type(m, &type);
if (r < 0)
return r;
- LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) {
+ LIST_FOREACH(match_callbacks, c, nl->match_callbacks) {
if (type != c->type)
continue;
slot = container_of(c, sd_netlink_slot, match_callback);
- r = c->callback(rtnl, m, slot->userdata);
+ r = c->callback(nl, m, slot->userdata);
if (r < 0)
log_debug_errno(r, "sd-netlink: match callback %s%s%sfailed: %m",
slot->description ? "'" : "",
return 1;
}
-static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
+static int process_running(sd_netlink *nl, sd_netlink_message **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
- assert(rtnl);
+ assert(nl);
- r = process_timeout(rtnl);
+ r = process_timeout(nl);
if (r != 0)
goto null_message;
- r = dispatch_rqueue(rtnl, &m);
+ r = dispatch_rqueue(nl, &m);
if (r < 0)
return r;
if (!m)
goto null_message;
if (sd_netlink_message_is_broadcast(m)) {
- r = process_match(rtnl, m);
+ r = process_match(nl, m);
if (r != 0)
goto null_message;
} else {
- r = process_reply(rtnl, m);
+ r = process_reply(nl, m);
if (r != 0)
goto null_message;
}
return r;
}
-int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) {
- NETLINK_DONT_DESTROY(rtnl);
+int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret) {
+ NETLINK_DONT_DESTROY(nl);
int r;
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
- assert_return(!rtnl->processing, -EBUSY);
+ assert_return(nl, -EINVAL);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
+ assert_return(!nl->processing, -EBUSY);
- rtnl->processing = true;
- r = process_running(rtnl, ret);
- rtnl->processing = false;
+ nl->processing = true;
+ r = process_running(nl, ret);
+ nl->processing = false;
return r;
}
return 0;
if (usec == 0)
- usec = RTNL_DEFAULT_TIMEOUT;
+ usec = NETLINK_DEFAULT_TIMEOUT_USEC;
return usec_add(now(CLOCK_MONOTONIC), usec);
}
-static int rtnl_poll(sd_netlink *rtnl, bool need_more, usec_t timeout_usec) {
+static int netlink_poll(sd_netlink *nl, bool need_more, usec_t timeout_usec) {
usec_t m = USEC_INFINITY;
int r, e;
- assert(rtnl);
+ assert(nl);
- e = sd_netlink_get_events(rtnl);
+ e = sd_netlink_get_events(nl);
if (e < 0)
return e;
/* Caller wants to process if there is something to
* process, but doesn't care otherwise */
- r = sd_netlink_get_timeout(rtnl, &until);
+ r = sd_netlink_get_timeout(nl, &until);
if (r < 0)
return r;
m = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
}
- r = fd_wait_for_event(rtnl->fd, e, MIN(m, timeout_usec));
+ r = fd_wait_for_event(nl->fd, e, MIN(m, timeout_usec));
if (r <= 0)
return r;
int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
assert_return(nl, -EINVAL);
- assert_return(!rtnl_pid_changed(nl), -ECHILD);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
if (nl->rqueue_size > 0)
return 0;
- return rtnl_poll(nl, false, timeout_usec);
+ return netlink_poll(nl, false, timeout_usec);
}
static int timeout_compare(const void *a, const void *b) {
assert_return(nl, -EINVAL);
assert_return(m, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(!rtnl_pid_changed(nl), -ECHILD);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
if (hashmap_size(nl->reply_callbacks) >= REPLY_CALLBACKS_MAX)
return -ERANGE;
}
int sd_netlink_read(
- sd_netlink *rtnl,
+ sd_netlink *nl,
uint32_t serial,
uint64_t usec,
sd_netlink_message **ret) {
usec_t timeout;
int r;
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+ assert_return(nl, -EINVAL);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
timeout = calc_elapse(usec);
for (;;) {
usec_t left;
- for (unsigned i = 0; i < rtnl->rqueue_size; i++) {
+ for (unsigned i = 0; i < nl->rqueue_size; i++) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
uint32_t received_serial;
uint16_t type;
- received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
+ received_serial = message_get_serial(nl->rqueue[i]);
if (received_serial != serial)
continue;
- incoming = rtnl->rqueue[i];
+ incoming = nl->rqueue[i];
/* found a match, remove from rqueue and return it */
- memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1,
- sizeof(sd_netlink_message*) * (rtnl->rqueue_size - i - 1));
- rtnl->rqueue_size--;
+ memmove(nl->rqueue + i, nl->rqueue + i + 1,
+ sizeof(sd_netlink_message*) * (nl->rqueue_size - i - 1));
+ nl->rqueue_size--;
r = sd_netlink_message_get_errno(incoming);
if (r < 0)
return 1;
}
- r = socket_read_message(rtnl);
+ r = socket_read_message(nl);
if (r < 0)
return r;
if (r > 0)
} else
left = USEC_INFINITY;
- r = rtnl_poll(rtnl, true, left);
+ r = netlink_poll(nl, true, left);
if (r < 0)
return r;
if (r == 0)
}
int sd_netlink_call(
- sd_netlink *rtnl,
+ sd_netlink *nl,
sd_netlink_message *message,
uint64_t usec,
sd_netlink_message **ret) {
uint32_t serial;
int r;
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+ assert_return(nl, -EINVAL);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
assert_return(message, -EINVAL);
- r = sd_netlink_send(rtnl, message, &serial);
+ r = sd_netlink_send(nl, message, &serial);
if (r < 0)
return r;
- return sd_netlink_read(rtnl, serial, usec, ret);
+ return sd_netlink_read(nl, serial, usec, ret);
}
-int sd_netlink_get_events(sd_netlink *rtnl) {
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+int sd_netlink_get_events(sd_netlink *nl) {
+ assert_return(nl, -EINVAL);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
- return rtnl->rqueue_size == 0 ? POLLIN : 0;
+ return nl->rqueue_size == 0 ? POLLIN : 0;
}
-int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) {
+int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout_usec) {
struct reply_callback *c;
- assert_return(rtnl, -EINVAL);
+ assert_return(nl, -EINVAL);
assert_return(timeout_usec, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+ assert_return(!netlink_pid_changed(nl), -ECHILD);
- if (rtnl->rqueue_size > 0) {
+ if (nl->rqueue_size > 0) {
*timeout_usec = 0;
return 1;
}
- c = prioq_peek(rtnl->reply_callbacks_prioq);
+ c = prioq_peek(nl->reply_callbacks_prioq);
if (!c) {
*timeout_usec = UINT64_MAX;
return 0;
}
static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- sd_netlink *rtnl = userdata;
+ sd_netlink *nl = userdata;
int r;
- assert(rtnl);
+ assert(nl);
- r = sd_netlink_process(rtnl, NULL);
+ r = sd_netlink_process(nl, NULL);
if (r < 0)
return r;
}
static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
- sd_netlink *rtnl = userdata;
+ sd_netlink *nl = userdata;
int r;
- assert(rtnl);
+ assert(nl);
- r = sd_netlink_process(rtnl, NULL);
+ r = sd_netlink_process(nl, NULL);
if (r < 0)
return r;
}
static int prepare_callback(sd_event_source *s, void *userdata) {
- sd_netlink *rtnl = userdata;
+ sd_netlink *nl = userdata;
int r, e;
usec_t until;
assert(s);
- assert(rtnl);
+ assert(nl);
- e = sd_netlink_get_events(rtnl);
+ e = sd_netlink_get_events(nl);
if (e < 0)
return e;
- r = sd_event_source_set_io_events(rtnl->io_event_source, e);
+ r = sd_event_source_set_io_events(nl->io_event_source, e);
if (r < 0)
return r;
- r = sd_netlink_get_timeout(rtnl, &until);
+ r = sd_netlink_get_timeout(nl, &until);
if (r < 0)
return r;
if (r > 0) {
int j;
- j = sd_event_source_set_time(rtnl->time_event_source, until);
+ j = sd_event_source_set_time(nl->time_event_source, until);
if (j < 0)
return j;
}
- r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0);
+ r = sd_event_source_set_enabled(nl->time_event_source, r > 0);
if (r < 0)
return r;
return 1;
}
-int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int64_t priority) {
+int sd_netlink_attach_event(sd_netlink *nl, sd_event *event, int64_t priority) {
int r;
- assert_return(rtnl, -EINVAL);
- assert_return(!rtnl->event, -EBUSY);
+ assert_return(nl, -EINVAL);
+ assert_return(!nl->event, -EBUSY);
- assert(!rtnl->io_event_source);
- assert(!rtnl->time_event_source);
+ assert(!nl->io_event_source);
+ assert(!nl->time_event_source);
if (event)
- rtnl->event = sd_event_ref(event);
+ nl->event = sd_event_ref(event);
else {
- r = sd_event_default(&rtnl->event);
+ r = sd_event_default(&nl->event);
if (r < 0)
return r;
}
- r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl);
+ r = sd_event_add_io(nl->event, &nl->io_event_source, nl->fd, 0, io_callback, nl);
if (r < 0)
goto fail;
- r = sd_event_source_set_priority(rtnl->io_event_source, priority);
+ r = sd_event_source_set_priority(nl->io_event_source, priority);
if (r < 0)
goto fail;
- r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message");
+ r = sd_event_source_set_description(nl->io_event_source, "netlink-receive-message");
if (r < 0)
goto fail;
- r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback);
+ r = sd_event_source_set_prepare(nl->io_event_source, prepare_callback);
if (r < 0)
goto fail;
- r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl);
+ r = sd_event_add_time(nl->event, &nl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, nl);
if (r < 0)
goto fail;
- r = sd_event_source_set_priority(rtnl->time_event_source, priority);
+ r = sd_event_source_set_priority(nl->time_event_source, priority);
if (r < 0)
goto fail;
- r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer");
+ r = sd_event_source_set_description(nl->time_event_source, "netlink-timer");
if (r < 0)
goto fail;
return 0;
fail:
- sd_netlink_detach_event(rtnl);
+ sd_netlink_detach_event(nl);
return r;
}
-int sd_netlink_detach_event(sd_netlink *rtnl) {
- assert_return(rtnl, -EINVAL);
- assert_return(rtnl->event, -ENXIO);
+int sd_netlink_detach_event(sd_netlink *nl) {
+ assert_return(nl, -EINVAL);
+ assert_return(nl->event, -ENXIO);
- rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source);
+ nl->io_event_source = sd_event_source_unref(nl->io_event_source);
- rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source);
+ nl->time_event_source = sd_event_source_unref(nl->time_event_source);
- rtnl->event = sd_event_unref(rtnl->event);
+ nl->event = sd_event_unref(nl->event);
return 0;
}
sd_netlink_destroy_t destroy_callback,
void *userdata,
const char *description) {
+
_cleanup_free_ sd_netlink_slot *slot = NULL;
int r;
assert_return(rtnl, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
+ assert_return(!netlink_pid_changed(rtnl), -ECHILD);
r = netlink_slot_allocate(rtnl, !ret_slot, NETLINK_MATCH_CALLBACK, sizeof(struct match_callback), userdata, description, &slot);
if (r < 0)