Switch from using sequential to random ephemeral port allocation,

implementation taken directly from OpenBSD.

I've resisted committing this for quite some time because of concern over
TIME_WAIT recycling breakage (sequential allocation ensures that there is a
long time before ports are recycled), but recent testing has shown me that
my fears were unwarranted.
This commit is contained in:
Mike Silbersack 2004-04-20 06:45:10 +00:00
parent c1537ef063
commit 6dd946b3f7

View File

@ -377,8 +377,8 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, cred)
if (*lportp != 0)
lport = *lportp;
if (lport == 0) {
u_short first, last;
int count;
u_short first, last, old;
int count, loopcount;
if (laddr.s_addr != INADDR_ANY)
if (prison_ip(cred, 0, &laddr.s_addr))
@ -406,15 +406,27 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, cred)
* We split the two cases (up and down) so that the direction
* is not being tested on each round of the loop.
*/
loopcount = old = 0;
portloop:
if (first > last) {
/*
* counting down
*/
if (loopcount == 0) { /* only do this once */
old = first;
first -= (arc4random() % (first - last));
}
count = first - last;
*lastport = first; /* restart each time */
do {
if (count-- < 0) /* completely used? */
if (count-- < 0) { /* completely used? */
if (loopcount == 0) {
last = old;
loopcount++;
goto portloop;
}
return (EADDRNOTAVAIL);
}
--*lastport;
if (*lastport > first || *lastport < last)
*lastport = first;
@ -425,11 +437,21 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, cred)
/*
* counting up
*/
if (loopcount == 0) { /* only do this once. */
old = first;
first += (arc4random() % (last - first));
}
count = last - first;
*lastport = first; /* restart each time */
do {
if (count-- < 0) /* completely used? */
if (count-- < 0) { /* completely used? */
if (loopcount == 0) {
first = old;
loopcount++;
goto portloop;
}
return (EADDRNOTAVAIL);
}
++*lastport;
if (*lastport < first || *lastport > last)
*lastport = first;