diff options
author | silby <silby@FreeBSD.org> | 2004-04-20 06:45:10 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2004-04-20 06:45:10 +0000 |
commit | f0d28bbf0ce3355eba4fe72ddbc426e96aa81ec4 (patch) | |
tree | 30e6864619ec93c2c823170c08d90db8c0fc7ef6 /sys | |
parent | 743d110741f9521e52a1d3b69c448e46fb50d830 (diff) | |
download | FreeBSD-src-f0d28bbf0ce3355eba4fe72ddbc426e96aa81ec4.zip FreeBSD-src-f0d28bbf0ce3355eba4fe72ddbc426e96aa81ec4.tar.gz |
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in_pcb.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 934311b..6ebfbb3 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -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; |