diff --git a/include/netlink/cache.h b/include/netlink/cache.h index abeeccbd..070b936d 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -146,6 +146,10 @@ struct nl_cache_mngr; 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..54e587d9 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -148,6 +148,33 @@ 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_sock *sk_blocking = nl_socket_alloc(); + int err; + + if (!sk_blocking) { + return -NLE_NOMEM; + } + if ((err = nl_connect(sk_blocking, protocol)) < 0) { + nl_socket_free(sk_blocking); + return err; + } + return nl_cache_mngr_alloc_ex(sk, sk_blocking, protocol, flags, result); +} + +/** + * Allocate new cache manager, with custom callback on refill socket + * @arg sk Netlink socket or NULL to auto allocate + * @arg sk_blocking 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 sk_blocking passes to the cache manager + */ +int nl_cache_mngr_alloc_ex(struct nl_sock *sk, struct nl_sock *sk_blocking, int protocol, int flags, + struct nl_cache_mngr **result) { struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; @@ -156,10 +183,18 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, if (flags & NL_ALLOCATED_SOCK) BUG(); + if(!sk_blocking) { + BUG(); + } + mngr = calloc(1, sizeof(*mngr)); - if (!mngr) + if (!mngr) { + // No manager yet, to free it in case of error + nl_socket_free(sk_blocking); return -NLE_NOMEM; + } + mngr->cm_sync_sock = sk_blocking; if (!sk) { if (!(sk = nl_socket_alloc())) goto errout; @@ -185,14 +220,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 +227,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; diff --git a/libnl-3.sym b/libnl-3.sym index bac4fcda..0196387c 100644 --- a/libnl-3.sym +++ b/libnl-3.sym @@ -79,6 +79,7 @@ global: nl_cache_mngr_add; nl_cache_mngr_add_cache; nl_cache_mngr_alloc; + nl_cache_mngr_alloc_ex; nl_cache_mngr_data_ready; nl_cache_mngr_free; nl_cache_mngr_get_fd;