diff options
author | andre <andre@FreeBSD.org> | 2006-09-28 18:02:46 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2006-09-28 18:02:46 +0000 |
commit | 5eae8ee0ac0d71104053a951c861a1d656250a3f (patch) | |
tree | aab2aebc6b768d1b92e9fb1ebf178208ce201920 /sys/netinet/tcp_output.c | |
parent | b09219dff2053b3bc306fe8d2389cb38d1e84280 (diff) | |
download | FreeBSD-src-5eae8ee0ac0d71104053a951c861a1d656250a3f.zip FreeBSD-src-5eae8ee0ac0d71104053a951c861a1d656250a3f.tar.gz |
When tcp_output() receives an error upon sending a packet it reverts parts
of its internal state to ignore the failed send and try again a bit later.
If the error is EPERM the packet got blocked by the local firewall and the
revert may cause the session to get stuck and retry indefinitely. This way
we treat it like a packet loss and let the retransmit timer and timeouts
do their work over time.
The correct behavior is to drop a connection that gets an EPERM error.
However this _may_ introduce some POLA problems and a two commit approach
was chosen.
Discussed with: glebius
PR: kern/25986
PR: kern/102653
Diffstat (limited to 'sys/netinet/tcp_output.c')
-rw-r--r-- | sys/netinet/tcp_output.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 0ea53e2..6833e7e 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1137,9 +1137,18 @@ timer: /* * We know that the packet was lost, so back out the * sequence number advance, if any. + * + * If the error is EPERM the packet got blocked by the + * local firewall. Normally we should terminate the + * connection but the blocking may have been spurious + * due to a firewall reconfiguration cycle. So we treat + * it like a packet loss and let the retransmit timer and + * timeouts do their work over time. + * XXX: It is a POLA question whether calling tcp_drop right + * away would be the really correct behavior instead. */ - if ((tp->t_flags & TF_FORCEDATA) == 0 || - !callout_active(tp->tt_persist)) { + if (error != EPERM && ((tp->t_flags & TF_FORCEDATA) == 0 || + !callout_active(tp->tt_persist))) { /* * No need to check for TH_FIN here because * the TF_SENTFIN flag handles that case. @@ -1155,6 +1164,10 @@ timer: tp->snd_nxt -= len; } } + if (error == EPERM) { + tp->t_softerror = error; + return (error); + } out: SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */ |