[PATCH 4/4] lib/socket: randomize the generated local port
Thomas Haller
thaller at redhat.com
Wed Apr 9 03:08:53 PDT 2014
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 <thaller at redhat.com>
---
lib/socket.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/lib/socket.c b/lib/socket.c
index cf0dba1..7584749 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -62,16 +62,37 @@ 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) {
+ /* 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 = time(NULL);
+ } 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 8 ports 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;
--
1.9.0
More information about the libnl
mailing list