From 5425c00c57de8fa9e5dd904bd9f7ed77ccc2a1f0 Mon Sep 17 00:00:00 2001 From: "Ilya A. Evenbach" Date: Tue, 23 Apr 2024 04:50:36 -0700 Subject: [PATCH] Allow to allocate cache manager with custom refill socket Cache managers use two sockets: one for cache refill operation, and another one for notifications. In order to simulate NETLINK events by reading data from files, we need to be able to overwrite callbacks for both sockets. This new function allows us to set up refill socket any way we want. It does have requirement that the refill socket be blocking. --- include/netlink/cache.h | 9 ++++++-- lib/cache_mngr.c | 51 ++++++++++++++++++++++++++++++----------- libnl-3.sym | 5 ++++ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index abeeccbd8..faa61a784 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -140,12 +140,17 @@ extern struct nl_cache * __nl_cache_mngt_require(const char *); struct nl_cache_mngr; -#define NL_AUTO_PROVIDE 1 -#define NL_ALLOCATED_SOCK 2 /* For internal use only, do not use */ +#define NL_AUTO_PROVIDE 1 +#define NL_ALLOCATED_SOCK 2 /* For internal use only, do not use */ +#define NL_ALLOCATED_SYNC_SOCK 4 /* For internal use only, do not use */ extern int nl_cache_mngr_alloc(struct nl_sock *, int, int, struct nl_cache_mngr **); +extern int nl_cache_mngr_alloc_ex(struct nl_sock *, + struct nl_sock *, + int, int, + struct nl_cache_mngr **); extern int nl_cache_mngr_add(struct nl_cache_mngr *, const char *, change_func_t, diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 7b2a9bd3e..22696d5b2 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -148,17 +148,46 @@ static int event_input(struct nl_msg *msg, void *arg) */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr **result) +{ + return nl_cache_mngr_alloc_ex(sk, NULL, protocol, flags, result); +} + +/** + * Allocate new cache manager, with custom callback on refill socket + * @arg sk Netlink socket or NULL to auto allocate + * @arg sync_sk Blocking Netlink socket for cache refills + * @arg protocol Netlink protocol this manager is used for + * @arg flags Flags (\c NL_AUTO_PROVIDE) + * @arg result Result pointer + * + * Same as \f nl_cache_mngr_alloc, but sets custom refill socket + * Note: ownership of the sync_sk passes to the cache manager + */ +int nl_cache_mngr_alloc_ex(struct nl_sock *sk, struct nl_sock *sync_sk, int protocol, int flags, + struct nl_cache_mngr **result) { struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; /* Catch abuse of flags */ - if (flags & NL_ALLOCATED_SOCK) + if (flags & (NL_ALLOCATED_SOCK|NL_ALLOCATED_SYNC_SOCK)) BUG(); mngr = calloc(1, sizeof(*mngr)); - if (!mngr) + if (!mngr) { return -NLE_NOMEM; + } + + if(!sync_sk) { + if (!(sync_sk = nl_socket_alloc())) + goto errout; + + flags |= NL_ALLOCATED_SOCK; + } + /* have to assign before calling nl_connect, so that it gets freed in case + * of an nl_socket_allock error for sk + */ + mngr->cm_sync_sock = sync_sk; if (!sk) { if (!(sk = nl_socket_alloc())) @@ -176,6 +205,10 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, if (!mngr->cm_assocs) goto errout; + if ((err = nl_connect(sync_sk, protocol)) < 0) { + goto errout; + } + /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_sock); @@ -185,14 +218,6 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0) goto errout; - /* Create and allocate socket for sync cache fills */ - mngr->cm_sync_sock = nl_socket_alloc(); - if (!mngr->cm_sync_sock) { - err = -NLE_NOMEM; - goto errout; - } - if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0) - goto errout_free_sync_sock; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); @@ -200,8 +225,6 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, *result = mngr; return 0; -errout_free_sync_sock: - nl_socket_free(mngr->cm_sync_sock); errout: nl_cache_mngr_free(mngr); return err; @@ -624,9 +647,11 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) if (mngr->cm_sync_sock) { nl_close(mngr->cm_sync_sock); - nl_socket_free(mngr->cm_sync_sock); } + if (mngr->cm_flags & NL_ALLOCATED_SYNC_SOCK) + nl_socket_free(mngr->cm_sync_sock); + if (mngr->cm_flags & NL_ALLOCATED_SOCK) nl_socket_free(mngr->cm_sock); diff --git a/libnl-3.sym b/libnl-3.sym index bac4fcdab..613529c2c 100644 --- a/libnl-3.sym +++ b/libnl-3.sym @@ -372,3 +372,8 @@ global: libnl_3_6 { } libnl_3_5; + +libnl_3_10 { +global: + nl_cache_mngr_alloc_ex; +} libnl_3_6;