sd-netlink: rename variables, arguments, and functions

Most changes are 'rtnl' -> 'nl' where the function is not only for rtnl.
This commit is contained in:
Yu Watanabe
2021-08-29 17:14:03 +09:00
parent 0c45a60f8e
commit 409856d328
10 changed files with 301 additions and 307 deletions
+15 -12
View File
@@ -10,11 +10,11 @@
#include "prioq.h"
#include "time-util.h"
#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
#define NETLINK_DEFAULT_TIMEOUT_USEC ((usec_t) (25 * USEC_PER_SEC))
#define RTNL_RQUEUE_MAX 64*1024
#define NETLINK_RQUEUE_MAX 64*1024
#define RTNL_CONTAINER_DEPTH 32
#define NETLINK_CONTAINER_DEPTH 32
struct reply_callback {
sd_netlink_message_handler_t callback;
@@ -118,7 +118,7 @@ struct sd_netlink_message {
int protocol;
struct nlmsghdr *hdr;
struct netlink_container containers[RTNL_CONTAINER_DEPTH];
struct netlink_container containers[NETLINK_CONTAINER_DEPTH];
unsigned n_containers; /* number of containers */
bool sealed:1;
bool broadcast:1;
@@ -126,10 +126,16 @@ struct sd_netlink_message {
sd_netlink_message *next; /* next in a chain of multi-part messages */
};
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type);
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret);
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type);
int message_new_empty(sd_netlink *nl, sd_netlink_message **ret);
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret);
uint32_t message_get_serial(sd_netlink_message *m);
void message_seal(sd_netlink_message *m);
int netlink_open_family(sd_netlink **ret, int family);
bool netlink_pid_changed(sd_netlink *nl);
int netlink_rqueue_make_room(sd_netlink *nl);
int netlink_rqueue_partial_make_room(sd_netlink *nl);
int socket_open(int family);
int socket_bind(sd_netlink *nl);
@@ -139,9 +145,6 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount);
int socket_read_message(sd_netlink *nl);
int rtnl_rqueue_make_room(sd_netlink *rtnl);
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
/* Make sure callbacks don't destroy the rtnl connection */
#define NETLINK_DONT_DESTROY(rtnl) \
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
/* Make sure callbacks don't destroy the netlink connection */
#define NETLINK_DONT_DESTROY(nl) \
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl)
+38 -21
View File
@@ -20,15 +20,13 @@
#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)
@@ -36,7 +34,7 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
*m = (sd_netlink_message) {
.n_ref = 1,
.protocol = rtnl->protocol,
.protocol = nl->protocol,
.sealed = false,
};
@@ -45,22 +43,22 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
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;
@@ -82,6 +80,25 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
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);
@@ -538,7 +555,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
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) {
@@ -585,7 +602,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
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)
@@ -628,7 +645,7 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
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)
@@ -673,7 +690,7 @@ static int netlink_message_read_internal(
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;
@@ -1008,7 +1025,7 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
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,
@@ -1079,7 +1096,7 @@ static int netlink_container_parse(sd_netlink_message *m,
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;
@@ -1104,7 +1121,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
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,
@@ -1195,7 +1212,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id
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)
@@ -1231,7 +1248,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
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);
@@ -1291,7 +1308,7 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
/* 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);
@@ -1332,7 +1349,7 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
return 0;
}
void rtnl_message_seal(sd_netlink_message *m) {
void message_seal(sd_netlink_message *m) {
assert(m);
assert(!m->sealed);
+30 -30
View File
@@ -238,7 +238,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
if (n == -ENOBUFS)
return log_debug_errno(n, "rtnl: kernel receive buffer overrun");
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
if (IN_SET(n, -EAGAIN, -EINTR))
return 0;
if (n < 0)
@@ -246,7 +246,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
if (sender.nl.nl_pid != 0) {
/* not from the kernel, ignore */
log_debug("rtnl: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
log_debug("sd-netlink: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
if (peek) {
/* drop the message */
@@ -276,7 +276,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
* If nothing useful was received 0 is returned.
* On failure, a negative error code is returned.
*/
int socket_read_message(sd_netlink *rtnl) {
int socket_read_message(sd_netlink *nl) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
bool multi_part = false, done = false;
size_t len, allocated;
@@ -285,25 +285,25 @@ int socket_read_message(sd_netlink *rtnl) {
unsigned i = 0;
int r;
assert(rtnl);
assert(rtnl->rbuffer);
assert(nl);
assert(nl->rbuffer);
/* read nothing, just get the pending message size */
r = socket_recv_message(rtnl->fd, &iov, NULL, true);
r = socket_recv_message(nl->fd, &iov, NULL, true);
if (r <= 0)
return r;
else
len = (size_t) r;
/* make room for the pending message */
if (!greedy_realloc((void **)&rtnl->rbuffer, len, sizeof(uint8_t)))
if (!greedy_realloc((void**) &nl->rbuffer, len, sizeof(uint8_t)))
return -ENOMEM;
allocated = MALLOC_SIZEOF_SAFE(rtnl->rbuffer);
iov = IOVEC_MAKE(rtnl->rbuffer, allocated);
allocated = MALLOC_SIZEOF_SAFE(nl->rbuffer);
iov = IOVEC_MAKE(nl->rbuffer, allocated);
/* read the pending message */
r = socket_recv_message(rtnl->fd, &iov, &group, false);
r = socket_recv_message(nl->fd, &iov, &group, false);
if (r <= 0)
return r;
else
@@ -313,22 +313,22 @@ int socket_read_message(sd_netlink *rtnl) {
/* message did not fit in read buffer */
return -EIO;
if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
if (NLMSG_OK(nl->rbuffer, len) && nl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
multi_part = true;
for (i = 0; i < rtnl->rqueue_partial_size; i++)
if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
rtnl->rbuffer->nlmsg_seq) {
first = rtnl->rqueue_partial[i];
for (i = 0; i < nl->rqueue_partial_size; i++)
if (message_get_serial(nl->rqueue_partial[i]) ==
nl->rbuffer->nlmsg_seq) {
first = nl->rqueue_partial[i];
break;
}
}
for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
for (struct nlmsghdr *new_msg = nl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
const NLType *nl_type;
if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
if (!group && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
/* not broadcast and not for us */
continue;
@@ -346,7 +346,7 @@ int socket_read_message(sd_netlink *rtnl) {
}
/* check that we support this message type */
r = type_system_root_get_type(rtnl, &nl_type, new_msg->nlmsg_type);
r = type_system_root_get_type(nl, &nl_type, new_msg->nlmsg_type);
if (r < 0) {
if (r == -EOPNOTSUPP)
log_debug("sd-netlink: ignored message with unknown type: %i",
@@ -361,7 +361,7 @@ int socket_read_message(sd_netlink *rtnl) {
continue;
}
r = message_new_empty(rtnl, &m);
r = message_new_empty(nl, &m);
if (r < 0)
return r;
@@ -372,7 +372,7 @@ int socket_read_message(sd_netlink *rtnl) {
return -ENOMEM;
/* seal and parse the top-level message */
r = sd_netlink_message_rewind(m, rtnl);
r = sd_netlink_message_rewind(m, nl);
if (r < 0)
return r;
@@ -390,31 +390,31 @@ int socket_read_message(sd_netlink *rtnl) {
if (!multi_part || done) {
/* we got a complete message, push it on the read queue */
r = rtnl_rqueue_make_room(rtnl);
r = netlink_rqueue_make_room(nl);
if (r < 0)
return r;
rtnl->rqueue[rtnl->rqueue_size++] = TAKE_PTR(first);
nl->rqueue[nl->rqueue_size++] = TAKE_PTR(first);
if (multi_part && (i < rtnl->rqueue_partial_size)) {
if (multi_part && (i < nl->rqueue_partial_size)) {
/* remove the message form the partial read queue */
memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1));
rtnl->rqueue_partial_size--;
memmove(nl->rqueue_partial + i, nl->rqueue_partial + i + 1,
sizeof(sd_netlink_message*) * (nl->rqueue_partial_size - i - 1));
nl->rqueue_partial_size--;
}
return 1;
} else {
/* we only got a partial multi-part message, push it on the
partial read queue */
if (i < rtnl->rqueue_partial_size)
rtnl->rqueue_partial[i] = TAKE_PTR(first);
if (i < nl->rqueue_partial_size)
nl->rqueue_partial[i] = TAKE_PTR(first);
else {
r = rtnl_rqueue_partial_make_room(rtnl);
r = netlink_rqueue_partial_make_room(nl);
if (r < 0)
return r;
rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = TAKE_PTR(first);
nl->rqueue_partial[nl->rqueue_partial_size++] = TAKE_PTR(first);
}
return 0;
-19
View File
@@ -400,25 +400,6 @@ int rtnl_get_link_info(sd_netlink **rtnl, int ifindex, unsigned short *ret_iftyp
return 0;
}
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret) {
struct nlmsgerr *err;
int r;
assert(error <= 0);
r = message_new(rtnl, ret, NLMSG_ERROR);
if (r < 0)
return r;
rtnl_message_seal(*ret);
(*ret)->hdr->nlmsg_seq = serial;
err = NLMSG_DATA((*ret)->hdr);
err->error = error;
return 0;
}
int rtnl_log_parse_error(int r) {
return log_error_errno(r, "Failed to parse netlink message: %m");
}
-4
View File
@@ -29,10 +29,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
uint32_t rtnl_message_get_serial(sd_netlink_message *m);
void rtnl_message_seal(sd_netlink_message *m);
static inline bool rtnl_message_type_is_neigh(uint16_t type) {
return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH);
}
+3 -5
View File
@@ -13,9 +13,7 @@
#include "format-util.h"
#include "netlink-internal.h"
#include "netlink-types.h"
#include "netlink-util.h"
#include "socket-util.h"
#include "util.h"
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t type, uint16_t flags) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
@@ -66,7 +64,7 @@ static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int famil
return 0;
}
static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
static int nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -85,11 +83,11 @@ static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int
}
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret) {
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
}
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret) {
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
}
int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret,
+5 -5
View File
@@ -271,13 +271,13 @@ int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret,
}
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
uint16_t nhmsg_type, int nh_family,
uint16_t nlmsg_type, int nh_family,
unsigned char nh_protocol) {
struct nhmsg *nhm;
int r;
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
switch(nhmsg_type) {
assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL);
switch(nlmsg_type) {
case RTM_DELNEXTHOP:
assert_return(nh_family == AF_UNSPEC, -EINVAL);
_fallthrough_;
@@ -292,11 +292,11 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
}
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nhmsg_type);
r = message_new(rtnl, ret, nlmsg_type);
if (r < 0)
return r;
if (nhmsg_type == RTM_NEWNEXTHOP)
if (nlmsg_type == RTM_NEWNEXTHOP)
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
nhm = NLMSG_DATA((*ret)->hdr);
+196 -198
View File
@@ -11,25 +11,23 @@
#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,
@@ -61,60 +59,48 @@ static int sd_netlink_new(sd_netlink **ret) {
.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;
@@ -122,8 +108,8 @@ int sd_netlink_open_fd(sd_netlink **ret, int fd) {
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)
@@ -133,14 +119,14 @@ int sd_netlink_open_fd(sd_netlink **ret, int fd) {
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;
}
@@ -165,91 +151,102 @@ int sd_netlink_open(sd_netlink **ret) {
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);
return fd_inc_rcvbuf(rtnl->fd, size);
/* 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();
}
static sd_netlink *netlink_free(sd_netlink *rtnl) {
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(nl->fd, size);
}
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;
}
@@ -264,7 +261,7 @@ int sd_netlink_sendv(
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);
@@ -277,9 +274,9 @@ int sd_netlink_sendv(
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);
@@ -292,45 +289,45 @@ int sd_netlink_sendv(
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)
@@ -338,23 +335,23 @@ static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
}
/* 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;
@@ -362,17 +359,17 @@ static int process_timeout(sd_netlink *rtnl) {
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 ? "'" : "",
@@ -385,23 +382,23 @@ static int process_timeout(sd_netlink *rtnl) {
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;
}
@@ -414,7 +411,7 @@ static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
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 ? "'" : "",
@@ -427,26 +424,26 @@ static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
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 ? "'" : "",
@@ -459,28 +456,28 @@ static int process_match(sd_netlink *rtnl, sd_netlink_message *m) {
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;
}
@@ -500,17 +497,17 @@ 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;
}
@@ -520,18 +517,18 @@ static usec_t calc_elapse(uint64_t usec) {
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;
@@ -545,14 +542,14 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, usec_t timeout_usec) {
/* 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;
@@ -561,12 +558,12 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, usec_t timeout_usec) {
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) {
@@ -597,7 +594,7 @@ int sd_netlink_call_async(
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;
@@ -647,7 +644,7 @@ int sd_netlink_call_async(
}
int sd_netlink_read(
sd_netlink *rtnl,
sd_netlink *nl,
uint32_t serial,
uint64_t usec,
sd_netlink_message **ret) {
@@ -655,29 +652,29 @@ int sd_netlink_read(
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)
@@ -697,7 +694,7 @@ int sd_netlink_read(
return 1;
}
r = socket_read_message(rtnl);
r = socket_read_message(nl);
if (r < 0)
return r;
if (r > 0)
@@ -715,7 +712,7 @@ int sd_netlink_read(
} else
left = USEC_INFINITY;
r = rtnl_poll(rtnl, true, left);
r = netlink_poll(nl, true, left);
if (r < 0)
return r;
if (r == 0)
@@ -724,7 +721,7 @@ int sd_netlink_read(
}
int sd_netlink_call(
sd_netlink *rtnl,
sd_netlink *nl,
sd_netlink_message *message,
uint64_t usec,
sd_netlink_message **ret) {
@@ -732,37 +729,37 @@ int sd_netlink_call(
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;
@@ -774,12 +771,12 @@ int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) {
}
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;
@@ -787,12 +784,12 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd
}
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;
@@ -800,100 +797,100 @@ static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
}
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;
}
@@ -906,12 +903,13 @@ int sd_netlink_add_match(
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)
+4 -3
View File
@@ -9,6 +9,7 @@
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "netlink-internal.h"
#include "netlink-util.h"
#include "socket-util.h"
#include "stdio-util.h"
@@ -502,7 +503,7 @@ static void test_message(sd_netlink *rtnl) {
log_debug("/* %s */", __func__);
assert_se(rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
assert_se(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
}
@@ -528,7 +529,7 @@ static void test_array(void) {
}
assert_se(sd_netlink_message_close_container(m) >= 0);
rtnl_message_seal(m);
message_seal(m);
assert_se(sd_netlink_message_rewind(m, genl) >= 0);
assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
@@ -569,7 +570,7 @@ static void test_strv(sd_netlink *rtnl) {
assert_se(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, names_in) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
rtnl_message_seal(m);
message_seal(m);
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
assert_se(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out) >= 0);
+10 -10
View File
@@ -50,12 +50,11 @@ typedef enum sd_genl_family_t {
} sd_genl_family_t;
/* callback */
typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata);
typedef _sd_destroy_t sd_netlink_destroy_t;
/* bus */
int sd_netlink_new_from_netlink(sd_netlink **nl, int fd);
int sd_netlink_new_from_fd(sd_netlink **nl, int fd);
int sd_netlink_open(sd_netlink **nl);
int sd_netlink_open_fd(sd_netlink **nl, int fd);
int sd_netlink_inc_rcvbuf(sd_netlink *nl, const size_t size);
@@ -85,6 +84,7 @@ int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t ma
int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
int sd_netlink_detach_event(sd_netlink *nl);
/* message */
int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data);
int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type);
@@ -181,12 +181,12 @@ int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type);
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol);
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int nh_family, unsigned char nh_protocol);
int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family);
int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol);
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int nda_family);
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family);
@@ -223,7 +223,7 @@ int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle);
int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex);
/* nfnl */
int sd_nfnl_socket_open(sd_netlink **nl);
int sd_nfnl_socket_open(sd_netlink **ret);
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret);
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret);
int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
@@ -249,13 +249,13 @@ int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m,
int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m);
/* genl */
int sd_genl_socket_open(sd_netlink **nl);
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret);
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret);
int sd_genl_socket_open(sd_netlink **ret);
int sd_genl_message_new(sd_netlink *genl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret);
int sd_genl_message_get_family(sd_netlink *genl, sd_netlink_message *m, sd_genl_family_t *ret);
/* slot */
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl);
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *slot);
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *slot);
sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot);
void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot);