inpcb: retire suppresion of randomization of ephemeral ports
The suppresion was added in5f311da2cc
with no explanation in the commit message of the exact problem that was fixed. In the BSDCan 2006 talk [1], slides 12 to 14, we can find that it seems that there was some problem with the TIME_WAIT state not properly being handled on the remote side (also FreeBSD!), and this switching off the suppression had hidden the problem. The rationale of the change was that other stacks may also be buggy wrt the TIME_WAIT. I did not find the actual problem in TIME_WAIT that the suppression has hidden, neither a commit that would fix it. However, since that time we started to handle SYNs with RFC5961 instead of RFC793, see3220a2121c
. We also now have the tcp-testsuite [2], that has full coverage of all possible scenarios of receiving SYN in TIME_WAIT. This effectively reverts5f311da2cc
and6ee79c59d2
. [1] https://www.bsdcan.org/2006/papers/ImprovingTCPIP.pdf [2] https://github.com/freebsd-net/tcp-testsuite Reviewed by: rscheff Discussed with: rscheff, rrs, tuexen Differential revision: https://reviews.freebsd.org/D37042
This commit is contained in:
parent
65a58d6390
commit
19acc50667
@ -453,21 +453,6 @@ In scenarios such as benchmarking, this behavior may be undesirable.
|
|||||||
In these cases,
|
In these cases,
|
||||||
.Va net.inet.ip.portrange.randomized
|
.Va net.inet.ip.portrange.randomized
|
||||||
can be used to toggle randomization off.
|
can be used to toggle randomization off.
|
||||||
If more than
|
|
||||||
.Va net.inet.ip.portrange.randomcps
|
|
||||||
ports have been allocated in the last second, then return to sequential
|
|
||||||
port allocation.
|
|
||||||
Return to random allocation only once the current port allocation rate
|
|
||||||
drops below
|
|
||||||
.Va net.inet.ip.portrange.randomcps
|
|
||||||
for at least
|
|
||||||
.Va net.inet.ip.portrange.randomtime
|
|
||||||
seconds.
|
|
||||||
The default values for
|
|
||||||
.Va net.inet.ip.portrange.randomcps
|
|
||||||
and
|
|
||||||
.Va net.inet.ip.portrange.randomtime
|
|
||||||
are 10 port allocations per second and 45 seconds correspondingly.
|
|
||||||
.Ss "Multicast Options"
|
.Ss "Multicast Options"
|
||||||
.Tn IP
|
.Tn IP
|
||||||
multicasting is supported only on
|
multicasting is supported only on
|
||||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/mbuf.h>
|
#include <sys/mbuf.h>
|
||||||
#include <sys/callout.h>
|
|
||||||
#include <sys/eventhandler.h>
|
#include <sys/eventhandler.h>
|
||||||
#include <sys/domain.h>
|
#include <sys/domain.h>
|
||||||
#include <sys/protosw.h>
|
#include <sys/protosw.h>
|
||||||
@ -117,8 +116,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define INPCBLBGROUP_SIZMAX 256
|
#define INPCBLBGROUP_SIZMAX 256
|
||||||
#define INP_FREED 0x00000200 /* See in_pcb.h. */
|
#define INP_FREED 0x00000200 /* See in_pcb.h. */
|
||||||
|
|
||||||
static struct callout ipport_tick_callout;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These configure the range of local port addresses assigned to
|
* These configure the range of local port addresses assigned to
|
||||||
* "unspecified" outgoing connections/packets/whatever.
|
* "unspecified" outgoing connections/packets/whatever.
|
||||||
@ -138,15 +135,8 @@ VNET_DEFINE(int, ipport_hilastauto) = IPPORT_HILASTAUTO; /* 65535 */
|
|||||||
VNET_DEFINE(int, ipport_reservedhigh) = IPPORT_RESERVED - 1; /* 1023 */
|
VNET_DEFINE(int, ipport_reservedhigh) = IPPORT_RESERVED - 1; /* 1023 */
|
||||||
VNET_DEFINE(int, ipport_reservedlow);
|
VNET_DEFINE(int, ipport_reservedlow);
|
||||||
|
|
||||||
/* Variables dealing with random ephemeral port allocation. */
|
/* Enable random ephemeral port allocation by default. */
|
||||||
VNET_DEFINE(int, ipport_randomized) = 1; /* user controlled via sysctl */
|
VNET_DEFINE(int, ipport_randomized) = 1;
|
||||||
VNET_DEFINE(int, ipport_randomcps) = 10; /* user controlled via sysctl */
|
|
||||||
VNET_DEFINE(int, ipport_randomtime) = 45; /* user controlled via sysctl */
|
|
||||||
VNET_DEFINE(int, ipport_stoprandom); /* toggled by ipport_tick */
|
|
||||||
VNET_DEFINE(int, ipport_tcpallocs);
|
|
||||||
VNET_DEFINE_STATIC(int, ipport_tcplastcount);
|
|
||||||
|
|
||||||
#define V_ipport_tcplastcount VNET(ipport_tcplastcount)
|
|
||||||
|
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
static struct inpcb *in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo,
|
static struct inpcb *in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo,
|
||||||
@ -214,15 +204,6 @@ SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedlow,
|
|||||||
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomized,
|
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomized,
|
||||||
CTLFLAG_VNET | CTLFLAG_RW,
|
CTLFLAG_VNET | CTLFLAG_RW,
|
||||||
&VNET_NAME(ipport_randomized), 0, "Enable random port allocation");
|
&VNET_NAME(ipport_randomized), 0, "Enable random port allocation");
|
||||||
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomcps,
|
|
||||||
CTLFLAG_VNET | CTLFLAG_RW,
|
|
||||||
&VNET_NAME(ipport_randomcps), 0, "Maximum number of random port "
|
|
||||||
"allocations before switching to a sequential one");
|
|
||||||
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime,
|
|
||||||
CTLFLAG_VNET | CTLFLAG_RW,
|
|
||||||
&VNET_NAME(ipport_randomtime), 0,
|
|
||||||
"Minimum time to keep sequential port "
|
|
||||||
"allocation before switching to a random one");
|
|
||||||
|
|
||||||
#ifdef RATELIMIT
|
#ifdef RATELIMIT
|
||||||
counter_u64_t rate_limit_new;
|
counter_u64_t rate_limit_new;
|
||||||
@ -730,7 +711,7 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
|
|||||||
struct inpcbinfo *pcbinfo;
|
struct inpcbinfo *pcbinfo;
|
||||||
struct inpcb *tmpinp;
|
struct inpcb *tmpinp;
|
||||||
unsigned short *lastport;
|
unsigned short *lastport;
|
||||||
int count, dorandom, error;
|
int count, error;
|
||||||
u_short aux, first, last, lport;
|
u_short aux, first, last, lport;
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
struct in_addr laddr, faddr;
|
struct in_addr laddr, faddr;
|
||||||
@ -764,27 +745,7 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
|
|||||||
last = V_ipport_lastauto;
|
last = V_ipport_lastauto;
|
||||||
lastport = &pcbinfo->ipi_lastport;
|
lastport = &pcbinfo->ipi_lastport;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* For UDP(-Lite), use random port allocation as long as the user
|
|
||||||
* allows it. For TCP (and as of yet unknown) connections,
|
|
||||||
* use random port allocation only if the user allows it AND
|
|
||||||
* ipport_tick() allows it.
|
|
||||||
*/
|
|
||||||
if (V_ipport_randomized &&
|
|
||||||
(!V_ipport_stoprandom || pcbinfo == &V_udbinfo ||
|
|
||||||
pcbinfo == &V_ulitecbinfo))
|
|
||||||
dorandom = 1;
|
|
||||||
else
|
|
||||||
dorandom = 0;
|
|
||||||
/*
|
|
||||||
* It makes no sense to do random port allocation if
|
|
||||||
* we have the only port available.
|
|
||||||
*/
|
|
||||||
if (first == last)
|
|
||||||
dorandom = 0;
|
|
||||||
/* Make sure to not include UDP(-Lite) packets in the count. */
|
|
||||||
if (pcbinfo != &V_udbinfo && pcbinfo != &V_ulitecbinfo)
|
|
||||||
V_ipport_tcpallocs++;
|
|
||||||
/*
|
/*
|
||||||
* Instead of having two loops further down counting up or down
|
* Instead of having two loops further down counting up or down
|
||||||
* make sure that first is always <= last and go with only one
|
* make sure that first is always <= last and go with only one
|
||||||
@ -818,7 +779,7 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
|
|||||||
tmpinp = NULL;
|
tmpinp = NULL;
|
||||||
lport = *lportp;
|
lport = *lportp;
|
||||||
|
|
||||||
if (dorandom)
|
if (V_ipport_randomized)
|
||||||
*lastport = first + (arc4random() % (last - first));
|
*lastport = first + (arc4random() % (last - first));
|
||||||
|
|
||||||
count = last - first;
|
count = last - first;
|
||||||
@ -2597,58 +2558,6 @@ in_pcbsosetlabel(struct socket *so)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ipport_tick runs once per second, determining if random port allocation
|
|
||||||
* should be continued. If more than ipport_randomcps ports have been
|
|
||||||
* allocated in the last second, then we return to sequential port
|
|
||||||
* allocation. We return to random allocation only once we drop below
|
|
||||||
* ipport_randomcps for at least ipport_randomtime seconds.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ipport_tick(void *xtp)
|
|
||||||
{
|
|
||||||
VNET_ITERATOR_DECL(vnet_iter);
|
|
||||||
|
|
||||||
VNET_LIST_RLOCK_NOSLEEP();
|
|
||||||
VNET_FOREACH(vnet_iter) {
|
|
||||||
CURVNET_SET(vnet_iter); /* XXX appease INVARIANTS here */
|
|
||||||
if (V_ipport_tcpallocs - V_ipport_tcplastcount <=
|
|
||||||
V_ipport_randomcps) {
|
|
||||||
if (V_ipport_stoprandom > 0)
|
|
||||||
V_ipport_stoprandom--;
|
|
||||||
} else
|
|
||||||
V_ipport_stoprandom = V_ipport_randomtime;
|
|
||||||
V_ipport_tcplastcount = V_ipport_tcpallocs;
|
|
||||||
CURVNET_RESTORE();
|
|
||||||
}
|
|
||||||
VNET_LIST_RUNLOCK_NOSLEEP();
|
|
||||||
callout_reset(&ipport_tick_callout, hz, ipport_tick, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ip_fini(void *xtp)
|
|
||||||
{
|
|
||||||
|
|
||||||
callout_stop(&ipport_tick_callout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The ipport_callout should start running at about the time we attach the
|
|
||||||
* inet or inet6 domains.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ipport_tick_init(const void *unused __unused)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Start ipport_tick. */
|
|
||||||
callout_init(&ipport_tick_callout, 1);
|
|
||||||
callout_reset(&ipport_tick_callout, 1, ipport_tick, NULL);
|
|
||||||
EVENTHANDLER_REGISTER(shutdown_pre_sync, ip_fini, NULL,
|
|
||||||
SHUTDOWN_PRI_DEFAULT);
|
|
||||||
}
|
|
||||||
SYSINIT(ipport_tick_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
|
|
||||||
ipport_tick_init, NULL);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
inp_wlock(struct inpcb *inp)
|
inp_wlock(struct inpcb *inp)
|
||||||
{
|
{
|
||||||
|
@ -714,10 +714,6 @@ VNET_DECLARE(int, ipport_lastauto);
|
|||||||
VNET_DECLARE(int, ipport_hifirstauto);
|
VNET_DECLARE(int, ipport_hifirstauto);
|
||||||
VNET_DECLARE(int, ipport_hilastauto);
|
VNET_DECLARE(int, ipport_hilastauto);
|
||||||
VNET_DECLARE(int, ipport_randomized);
|
VNET_DECLARE(int, ipport_randomized);
|
||||||
VNET_DECLARE(int, ipport_randomcps);
|
|
||||||
VNET_DECLARE(int, ipport_randomtime);
|
|
||||||
VNET_DECLARE(int, ipport_stoprandom);
|
|
||||||
VNET_DECLARE(int, ipport_tcpallocs);
|
|
||||||
|
|
||||||
#define V_ipport_reservedhigh VNET(ipport_reservedhigh)
|
#define V_ipport_reservedhigh VNET(ipport_reservedhigh)
|
||||||
#define V_ipport_reservedlow VNET(ipport_reservedlow)
|
#define V_ipport_reservedlow VNET(ipport_reservedlow)
|
||||||
@ -728,10 +724,6 @@ VNET_DECLARE(int, ipport_tcpallocs);
|
|||||||
#define V_ipport_hifirstauto VNET(ipport_hifirstauto)
|
#define V_ipport_hifirstauto VNET(ipport_hifirstauto)
|
||||||
#define V_ipport_hilastauto VNET(ipport_hilastauto)
|
#define V_ipport_hilastauto VNET(ipport_hilastauto)
|
||||||
#define V_ipport_randomized VNET(ipport_randomized)
|
#define V_ipport_randomized VNET(ipport_randomized)
|
||||||
#define V_ipport_randomcps VNET(ipport_randomcps)
|
|
||||||
#define V_ipport_randomtime VNET(ipport_randomtime)
|
|
||||||
#define V_ipport_stoprandom VNET(ipport_stoprandom)
|
|
||||||
#define V_ipport_tcpallocs VNET(ipport_tcpallocs)
|
|
||||||
|
|
||||||
void in_pcbinfo_init(struct inpcbinfo *, struct inpcbstorage *,
|
void in_pcbinfo_init(struct inpcbinfo *, struct inpcbstorage *,
|
||||||
u_int, u_int);
|
u_int, u_int);
|
||||||
|
Loading…
Reference in New Issue
Block a user