diff --git a/include/netlink/cache.h b/include/netlink/cache.h index abeeccbd..955f9799 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -140,12 +140,16 @@ 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 */ 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/include/nl-aux-core/nl-core.h b/include/nl-aux-core/nl-core.h index 5198296f..f75df5cc 100644 --- a/include/nl-aux-core/nl-core.h +++ b/include/nl-aux-core/nl-core.h @@ -44,6 +44,12 @@ void nl_socket_free(struct nl_sock *); _NL_AUTO_DEFINE_FCN_TYPED0(struct nl_sock *, _nl_auto_nl_socket_fcn, nl_socket_free); +struct nl_cache_mngr; +void nl_cache_mngr_free(struct nl_cache_mngr *mngr); +#define _nl_auto_nl_cache_mngr _nl_auto(_nl_auto_nl_cache_mngr_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_cache_mngr *, _nl_auto_nl_cache_mngr_fcn, + nl_cache_mngr_free); + struct nl_addr *nl_addr_build(int, const void *, size_t); static inline struct nl_addr *_nl_addr_build(int family, const void *buf) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 7b2a9bd3..8d8e2625 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -37,6 +37,8 @@ #include "nl-priv-dynamic-core/cache-api.h" #include "nl-aux-core/nl-core.h" +#define NL_ALLOCATED_SYNC_SOCK 4 + /** @cond SKIP */ struct nl_cache_mngr { @@ -149,62 +151,75 @@ 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) { - struct nl_cache_mngr *mngr; - int err = -NLE_NOMEM; + 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) +{ + _nl_auto_nl_cache_mngr struct nl_cache_mngr *mngr = NULL; + int err; /* Catch abuse of flags */ if (flags & NL_ALLOCATED_SOCK) BUG(); + flags = flags & NL_AUTO_PROVIDE; mngr = calloc(1, sizeof(*mngr)); if (!mngr) return -NLE_NOMEM; + mngr->cm_flags = flags; + if (!sk) { if (!(sk = nl_socket_alloc())) - goto errout; + return -NLE_NOMEM; + mngr->cm_flags |= NL_ALLOCATED_SOCK; + } + mngr->cm_sock = sk; - flags |= NL_ALLOCATED_SOCK; + if(!sync_sk) { + if (!(sync_sk = nl_socket_alloc())) + return -NLE_NOMEM; + mngr->cm_flags |= NL_ALLOCATED_SYNC_SOCK; } + mngr->cm_sync_sock = sync_sk; - mngr->cm_sock = sk; mngr->cm_nassocs = NASSOC_INIT; mngr->cm_protocol = protocol; - mngr->cm_flags = flags; mngr->cm_assocs = calloc(mngr->cm_nassocs, sizeof(struct nl_cache_assoc)); if (!mngr->cm_assocs) - goto errout; + return -NLE_NOMEM; /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_sock); if ((err = nl_connect(mngr->cm_sock, protocol)) < 0) - goto errout; + return err; if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0) - goto errout; + return err; - /* 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; + return err; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); - *result = mngr; + *result = _nl_steal_pointer(&mngr); return 0; - -errout_free_sync_sock: - nl_socket_free(mngr->cm_sync_sock); -errout: - nl_cache_mngr_free(mngr); - return err; } /** @@ -622,14 +637,15 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) if (mngr->cm_sock) nl_close(mngr->cm_sock); - if (mngr->cm_sync_sock) { + if (mngr->cm_sync_sock) nl_close(mngr->cm_sync_sock); - nl_socket_free(mngr->cm_sync_sock); - } if (mngr->cm_flags & NL_ALLOCATED_SOCK) nl_socket_free(mngr->cm_sock); + if (mngr->cm_flags & NL_ALLOCATED_SYNC_SOCK) + nl_socket_free(mngr->cm_sync_sock); + for (i = 0; i < mngr->cm_nassocs; i++) { if (mngr->cm_assocs[i].ca_cache) { nl_cache_mngt_unprovide(mngr->cm_assocs[i].ca_cache); 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;