]> granicus.if.org Git - libnl/commitdiff
socket: fix assertion in nl_connect() when all ports are already in use
authorThomas Haller <thaller@redhat.com>
Mon, 24 Aug 2015 15:57:16 +0000 (17:57 +0200)
committerThomas Haller <thaller@redhat.com>
Mon, 24 Aug 2015 16:01:42 +0000 (18:01 +0200)
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
lib/nl.c
lib/socket.c

index 86a440c5460e445b53b45f4b1be5d3348b1bf9b7..9ceecfd1b2713de55610d0879c81a9d6c7d6b5b3 100644 (file)
@@ -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);
index 737ebaa3328672bf4ea95768c547585faa9917f9..c93b6a59c74fcff0aef49351a34bbc6c9dd20d31 100644 (file)
--- 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;
 
index 55bdc962554764fe5d9443a6dd48e039d5473ef6..109c416a6c9f4601f6035078fc6cd92427a5c051 100644 (file)
@@ -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