From 1f734a8f892abcd3f81637df4a089155aca1b66a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Apr 2014 12:08:53 +0200 Subject: [PATCH] lib/socket: randomize the generated local port Instead of always trying the same order of ports when looking for an unused port, randomize the order (naively). As libnl-1 uses the same function, it is likely that two applications that are using both libraries generate the same ports. By chosing a different order how to select the local port, the chances are smaller for this to happen (however, it cannot avoid it entirely. The user and/or libnl3 still has to cope with the situation, that somebody else might already use the port). Signed-off-by: Thomas Haller --- lib/socket.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/socket.c b/lib/socket.c index c08f053..5f61b38 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -62,16 +62,39 @@ static NL_RW_LOCK(port_map_lock); static uint32_t generate_local_port(void) { - int i, n; + int i, j, n, m; + static uint16_t idx_state = 0; uint32_t pid = getpid() & 0x3FFFFF; nl_write_lock(&port_map_lock); - for (i = 0; i < 32; i++) { + if (idx_state == 0) { + uint32_t t = time(NULL); + + /* from time to time (on average each 2^15 calls), the idx_state will + * be zero again. No problem, just "seed" anew with time(). */ + idx_state = t ^ (t >> 16) ^ 0x3047; + } else + idx_state = idx_state + 20011; /* add prime number */ + + i = idx_state >> 5; + n = idx_state; + for (j = 0; j < 32; j++) { + /* walk the index somewhat randomized, with always leaving the block + * #0 as last. The reason is that libnl-1 will start at block #0, + * so just leave the first 32 ports preferably for libnl-1 owned sockets + * (this is relevant only if the applications ends up using both versions + * of the library and doesn't hurt otherwise). */ + if (j == 31) + i = 0; + else + i = (((i-1) + 7) % 31) + 1; + if (used_ports_map[i] == 0xFFFFFFFF) continue; - for (n = 0; n < 32; n++) { + for (m = 0; m < 32; m++) { + n = (n + 13) % 32; if (1UL & (used_ports_map[i] >> n)) continue;