From eaa75b7c7d3e6a4df1a2e7591ae295acfae3f73e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 24 Aug 2015 17:57:16 +0200 Subject: socket: fix assertion in nl_connect() when all ports are already in use When generating a port fails a few times (because they are already in used outside of libnl's knowledge), we would back off generating a local port and instead let kernel decide. There was however a bug in nl_connect() that caused an assertion: BUG at file position socket.c:147:_nl_socket_used_ports_release_all app: socket.c:147: _nl_socket_used_ports_release_all: Assertion `0' failed. Fixes: 96e1e5bdc2e803700055395cc3c428fa2525d1ca --- include/netlink-private/socket.h | 2 +- lib/nl.c | 4 ++-- lib/socket.c | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/netlink-private/socket.h b/include/netlink-private/socket.h index 86a440c..9ceecfd 100644 --- a/include/netlink-private/socket.h +++ b/include/netlink-private/socket.h @@ -19,7 +19,7 @@ extern "C" { #endif int _nl_socket_is_local_port_unspecified (struct nl_sock *sk); -uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk); +uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other); void _nl_socket_used_ports_release_all(const uint32_t *used_ports); void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port); diff --git a/lib/nl.c b/lib/nl.c index 737ebaa..c93b6a5 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -137,11 +137,11 @@ int nl_connect(struct nl_sock *sk, int protocol) if (ntries++ > 5) { /* try only a few times. We hit this only if many ports are already in * use but allocated *outside* libnl/generate_local_port(). */ - nl_socket_set_local_port (sk, 0); + _nl_socket_set_local_port_no_release (sk, 0); break; } - port = _nl_socket_generate_local_port_no_release(sk); + port = _nl_socket_set_local_port_no_release(sk, 1); if (port == 0) break; diff --git a/lib/socket.c b/lib/socket.c index 55bdc96..109c416 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -333,14 +333,17 @@ int _nl_socket_is_local_port_unspecified(struct nl_sock *sk) return (sk->s_local.nl_pid == 0); } -uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk) +uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other) { uint32_t port; /* reset the port to generate_local_port(), but do not release * the previously generated port. */ - port = generate_local_port(); + if (generate_other) + port = generate_local_port(); + else + port = 0; sk->s_local.nl_pid = port; if (port == 0) { /* failed to find an unsed port. Restore the socket to have an -- cgit v0.12