summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_pcb.c
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2004-04-20 06:45:10 +0000
committersilby <silby@FreeBSD.org>2004-04-20 06:45:10 +0000
commitf0d28bbf0ce3355eba4fe72ddbc426e96aa81ec4 (patch)
tree30e6864619ec93c2c823170c08d90db8c0fc7ef6 /sys/netinet/in_pcb.c
parent743d110741f9521e52a1d3b69c448e46fb50d830 (diff)
downloadFreeBSD-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/netinet/in_pcb.c')
-rw-r--r--sys/netinet/in_pcb.c34
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;
OpenPOWER on IntegriCloud