summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya A. Evenbach <ievenbach@aurora.tech>2024-04-23 04:50:36 -0700
committerThomas Haller <thaller@redhat.com>2024-05-06 11:59:00 +0200
commit1dbdc30a6b9f96355aadf69899f124480aa4d374 (patch)
tree12d4d24e2d09168dcb027924b424982450a34548
parent18b74e08383b40f116902a2b9ebb93c8599a923f (diff)
downloadlibnl-1dbdc30a6b9f96355aadf69899f124480aa4d374.tar.gz
cache: 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.
-rw-r--r--include/netlink/cache.h9
-rw-r--r--lib/cache_mngr.c51
-rw-r--r--libnl-3.sym5
3 files changed, 50 insertions, 15 deletions
diff --git a/include/netlink/cache.h b/include/netlink/cache.h
index abeeccbd..faa61a78 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 7b2a9bd3..22696d5b 100644
--- a/lib/cache_mngr.c
+++ b/lib/cache_mngr.c
@@ -149,16 +149,45 @@ found:
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 bac4fcda..613529c2 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;