summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_output.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2006-09-28 18:02:46 +0000
committerandre <andre@FreeBSD.org>2006-09-28 18:02:46 +0000
commit5eae8ee0ac0d71104053a951c861a1d656250a3f (patch)
treeaab2aebc6b768d1b92e9fb1ebf178208ce201920 /sys/netinet/tcp_output.c
parentb09219dff2053b3bc306fe8d2389cb38d1e84280 (diff)
downloadFreeBSD-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.c17
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. */
OpenPOWER on IntegriCloud