Networking Forums

Networking Forums > Computer Networking > Linux Networking > Linux free port allocation algorithm

Reply
Thread Tools Display Modes

Linux free port allocation algorithm

 
 
kreide@gmail.com
Guest
Posts: n/a

 
      01-05-2008, 10:14 AM
There seems to have been a change in the Linux free port allocation
algorithm somewhere between kernel 2.6.9 and 2.6.17.

When a socket is allocated (with the bind() system call) with
sin_port = 0 in 2.6.9 it seems that free ports are handed out
sequentially, while 2.6.17 will hand them out in random order.

Unfortunately this breaks a program I use, which depends on being able
to allocate a port, free it and then allocate it again shortly
thereafter; if ports are handed out randomly and there are several
programs on the machine doing the same thing the allocation will fail
fairly often (this is the birthday paradox).

Does anyone know when the algorithm was changed? Is there a way to
restore the old behavior in newer kernels?

Thanks!
 
Reply With Quote
 
 
 
 
Unruh
Guest
Posts: n/a

 
      01-05-2008, 06:51 PM
(E-Mail Removed) writes:

>There seems to have been a change in the Linux free port allocation
>algorithm somewhere between kernel 2.6.9 and 2.6.17.


>When a socket is allocated (with the bind() system call) with
>sin_port = 0 in 2.6.9 it seems that free ports are handed out
>sequentially, while 2.6.17 will hand them out in random order.


>Unfortunately this breaks a program I use, which depends on being able


Well, then that program should be changed. It has a bug in it.

>to allocate a port, free it and then allocate it again shortly
>thereafter; if ports are handed out randomly and there are several
>programs on the machine doing the same thing the allocation will fail
>fairly often (this is the birthday paradox).


Have you found such failures or are you just guessing?


>Does anyone know when the algorithm was changed? Is there a way to
>restore the old behavior in newer kernels?


 
Reply With Quote
 
kreide@gmail.com
Guest
Posts: n/a

 
      01-05-2008, 08:22 PM
> >Unfortunately this breaks a program I use, which depends on being able
> Well, then that program should be changed. It has a bug in it.


I agree, however, I do not have the option of changing the program in
question, thus unless I can find a way to preserve the old behavior on
newer kernels I am stuck with 2.6.9.

> >programs on the machine doing the same thing the allocation will fail
> >fairly often (this is the birthday paradox).

> Have you found such failures or are you just guessing?


Yes, unfortunately this does happen in practice, which is why I am
trying to find a solution.
 
Reply With Quote
 
David Schwartz
Guest
Posts: n/a

 
      01-06-2008, 02:43 AM
On Jan 5, 1:22 pm, kre...@gmail.com wrote:

> Yes, unfortunately this does happen in practice, which is why I am
> trying to find a solution.


Preload a library that changes the 'bind' wrapper so that a 'bind'
with a port of zero uses a port that you select using whatever
algorithm you like. Google for 'LD_PRELOAD' for more information.

DS
 
Reply With Quote
 
kreide@gmail.com
Guest
Posts: n/a

 
      01-07-2008, 08:27 AM
> Preload a library that changes the 'bind' wrapper so that a 'bind'

Actually that is a great idea, and what is even better it turned out
to work great in practice. Thank you for the help!
 
Reply With Quote
 
Chris Davies
Guest
Posts: n/a

 
      01-07-2008, 09:13 AM
On Jan 5, 1:22 pm, kre...@gmail.com wrote:
> Yes, unfortunately this does happen in practice, which is why I am
> trying to find a solution.


David Schwartz <(E-Mail Removed)> wrote:
> Preload a library that changes the 'bind' wrapper so that a 'bind'
> with a port of zero uses a port that you select using whatever
> algorithm you like.


Alternatively, change your program (since that's the one with the
incorrect expectation) to give bind() a specific port number.

Chris
 
Reply With Quote
 
Pascal Hambourg
Guest
Posts: n/a

 
      01-07-2008, 09:45 AM
Hello,

(E-Mail Removed) a écrit :
> There seems to have been a change in the Linux free port allocation
> algorithm somewhere between kernel 2.6.9 and 2.6.17.
>
> When a socket is allocated (with the bind() system call) with
> sin_port = 0 in 2.6.9 it seems that free ports are handed out
> sequentially, while 2.6.17 will hand them out in random order.


[cut description of application with broken behaviour]

> Does anyone know when the algorithm was changed?


2.6.11 :
[TCP]: Efficient port randomization

Provide port randomization for incoming connections using
variation of existing sequence number hash.

2.6.15 :
[TCP/DCCP]: Randomize port selection

This patch randomizes the port selected on bind() for connections
to help with possible security attacks. It should also be faster
in most cases because there is no need for a global lock.

> Is there a way to restore the old behavior in newer kernels?


I haven't found any sysctl which does that.
 
Reply With Quote
 
kreide@gmail.com
Guest
Posts: n/a

 
      01-07-2008, 04:36 PM
> Preload a library that changes the 'bind' wrapper so that a 'bind'

In case someone else is interested I am posting the source code for
the program that I came up with. It has been a while since I did low-
level C programming, but hopefully someone here can do a code review
and point out any flaws or suggest improvements.

#include <stdio.h>
#include <errno.h>

// avoid duplicate definition of bind()
#define _SYS_SOCKET_H 1
#include <netinet/in.h>

// required to get RTLD_NEXT
#ifndef __USE_GNU
#define __USE_GNU 1
#endif
#include <dlfcn.h>

#define LOW_PORT 32768
#define HIGH_PORT 60999

volatile static int next_port = LOW_PORT;

int bind(int __fd, struct sockaddr * __addr, socklen_t __len) {
static off_t (*funcptr)(int, struct sockaddr *, socklen_t) = NULL;

if (!funcptr) {
funcptr = (off_t (*)(int, struct sockaddr *, socklen_t))
dlsym(RTLD_NEXT, "bind");
}

if ( __addr->sa_family == AF_INET) {
struct sockaddr_in * __addr_in = (struct sockaddr_in *) __addr;
if (__addr_in->sin_port == 0) {
int ret;
do {
if (next_port > HIGH_PORT) next_port = LOW_PORT;
int my_port = next_port++;
__addr_in->sin_port = htons(my_port);
ret = (*funcptr)(__fd, __addr, __len);
} while (ret < 0 && errno == EADDRINUSE);
return ret;
}
}
return (*funcptr)(__fd, __addr, __len);
}
 
Reply With Quote
 
kreide@gmail.com
Guest
Posts: n/a

 
      01-07-2008, 04:51 PM
> [cut description of application with broken behavior]

Let me quickly describe why I need this; it is not as unreasonable as
one might think.

I have several server modules which are unit tested automatically; my
testing tool is integrated with the RCS (mercurial in case anyone is
curious) which checks out and tests all committed revisions. Since the
testing is somewhat time consuming and the machine has lots of spare
CPU cores many revisions are tested in parallel.

Some of the server modules are 3rd party and require a port number to
be specified when they are started; since many instances of each
server module is running on the same machine they need different port
numbers and the way I obtain these is by allocating a socket on a free
port, close the socket and give that port number to the server module.
There is of course a race condition here, but if free ports are handed
out sequentially this is not a problem in practice; if they are random
it is.

Changing the 3rd party modules is unfortunately not an option, and I
would like to avoid having to implement my own service to keep track
of allocated ports on the machine; depending on bind() behaving in a
certain way seems like the better option.
 
Reply With Quote
 
David Schwartz
Guest
Posts: n/a

 
      01-07-2008, 07:19 PM
On Jan 7, 9:51 am, kre...@gmail.com wrote:

> Some of the server modules are 3rd party and require a port number to
> be specified when they are started; since many instances of each
> server module is running on the same machine they need different port
> numbers and the way I obtain these is by allocating a socket on a free
> port, close the socket and give that port number to the server module.
> There is of course a race condition here, but if free ports are handed
> out sequentially this is not a problem in practice; if they are random
> it is.


A better solution, IMO, is to use a range of ports that is outside the
range the system assigns from. So if the system assigns from, say,
33,000 to 55,000, you assign from 60,000 up sequentially, wrapping
around if you run out.

You don't seem to have any need for system-assigned port numbers here.

DS
 
Reply With Quote
 
 
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: WEP algorithm Jack [MVP-Networking] Wireless Networks 0 01-04-2010 10:35 PM
RPC port allocation Blake Windows Networking 1 11-14-2008 07:05 PM
IAX/IAX2 Port allocation Andy Cap Network Routers 0 09-14-2007 03:07 PM
How to get first free udp port ? Jarek Linux Networking 4 09-12-2006 03:44 PM
scheduling algorithm? Choonho Son Linux Networking 1 05-19-2004 12:22 PM



1 2 3 4 5 6 7 8 9 10 11