aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2005-12-01 17:28:58 -0500
committerDavid S. Miller <davem@davemloft.net>2005-12-01 17:28:58 -0500
commit73f306024c15bd12e59677d6eaf43ecced614f04 (patch)
tree88d89bf7d54d51df8bd229ed9384e42f4064245a
parent5666c0947ede0432ba5148570aa66ffb9febff5b (diff)
[NETFILTER]: Ignore ACKs ACKs on half open connections in TCP conntrack
Mounting NFS file systems after a (warm) reboot could take a long time if firewalling and connection tracking was enabled. The reason is that the NFS clients tends to use the same ports (800 and counting down). Now on reboot, the server would still have a TCB for an existing TCP connection client:800 -> server:2049. The client sends a SYN from port 800 to server:2049, which elicits an ACK from the server. The firewall on the client drops the ACK because (from its point of view) the connection is still in half-open state, and it expects to see a SYNACK. The client will eventually time out after several minutes. The following patch corrects this, by accepting ACKs on half open connections as well. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c29
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c29
2 files changed, 40 insertions, 18 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 625981676776..aeb7353d4777 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -272,9 +272,9 @@ static const enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
272 * sCL -> sCL 272 * sCL -> sCL
273 */ 273 */
274/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ 274/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
275/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV }, 275/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
276/* 276/*
277 * sSS -> sIV Might be a half-open connection. 277 * sSS -> sIG Might be a half-open connection.
278 * sSR -> sSR Might answer late resent SYN. 278 * sSR -> sSR Might answer late resent SYN.
279 * sES -> sES :-) 279 * sES -> sES :-)
280 * sFW -> sCW Normal close request answered by ACK. 280 * sFW -> sCW Normal close request answered by ACK.
@@ -917,8 +917,12 @@ static int tcp_packet(struct ip_conntrack *conntrack,
917 917
918 switch (new_state) { 918 switch (new_state) {
919 case TCP_CONNTRACK_IGNORE: 919 case TCP_CONNTRACK_IGNORE:
920 /* Either SYN in ORIGINAL 920 /* Ignored packets:
921 * or SYN/ACK in REPLY. */ 921 *
922 * a) SYN in ORIGINAL
923 * b) SYN/ACK in REPLY
924 * c) ACK in reply direction after initial SYN in original.
925 */
922 if (index == TCP_SYNACK_SET 926 if (index == TCP_SYNACK_SET
923 && conntrack->proto.tcp.last_index == TCP_SYN_SET 927 && conntrack->proto.tcp.last_index == TCP_SYN_SET
924 && conntrack->proto.tcp.last_dir != dir 928 && conntrack->proto.tcp.last_dir != dir
@@ -985,13 +989,20 @@ static int tcp_packet(struct ip_conntrack *conntrack,
985 } 989 }
986 case TCP_CONNTRACK_CLOSE: 990 case TCP_CONNTRACK_CLOSE:
987 if (index == TCP_RST_SET 991 if (index == TCP_RST_SET
988 && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) 992 && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
989 && conntrack->proto.tcp.last_index == TCP_SYN_SET 993 && conntrack->proto.tcp.last_index == TCP_SYN_SET)
994 || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
995 && conntrack->proto.tcp.last_index == TCP_ACK_SET))
990 && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { 996 && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
991 /* RST sent to invalid SYN we had let trough 997 /* RST sent to invalid SYN or ACK we had let trough
992 * SYN was in window then, tear down connection. 998 * at a) and c) above:
999 *
1000 * a) SYN was in window then
1001 * c) we hold a half-open connection.
1002 *
1003 * Delete our connection entry.
993 * We skip window checking, because packet might ACK 1004 * We skip window checking, because packet might ACK
994 * segments we ignored in the SYN. */ 1005 * segments we ignored. */
995 goto in_window; 1006 goto in_window;
996 } 1007 }
997 /* Just fall trough */ 1008 /* Just fall trough */
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 5a6fcf349bdf..6035633d8225 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -280,9 +280,9 @@ static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
280 * sCL -> sCL 280 * sCL -> sCL
281 */ 281 */
282/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ 282/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
283/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV }, 283/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
284/* 284/*
285 * sSS -> sIV Might be a half-open connection. 285 * sSS -> sIG Might be a half-open connection.
286 * sSR -> sSR Might answer late resent SYN. 286 * sSR -> sSR Might answer late resent SYN.
287 * sES -> sES :-) 287 * sES -> sES :-)
288 * sFW -> sCW Normal close request answered by ACK. 288 * sFW -> sCW Normal close request answered by ACK.
@@ -912,8 +912,12 @@ static int tcp_packet(struct nf_conn *conntrack,
912 912
913 switch (new_state) { 913 switch (new_state) {
914 case TCP_CONNTRACK_IGNORE: 914 case TCP_CONNTRACK_IGNORE:
915 /* Either SYN in ORIGINAL 915 /* Ignored packets:
916 * or SYN/ACK in REPLY. */ 916 *
917 * a) SYN in ORIGINAL
918 * b) SYN/ACK in REPLY
919 * c) ACK in reply direction after initial SYN in original.
920 */
917 if (index == TCP_SYNACK_SET 921 if (index == TCP_SYNACK_SET
918 && conntrack->proto.tcp.last_index == TCP_SYN_SET 922 && conntrack->proto.tcp.last_index == TCP_SYN_SET
919 && conntrack->proto.tcp.last_dir != dir 923 && conntrack->proto.tcp.last_dir != dir
@@ -979,13 +983,20 @@ static int tcp_packet(struct nf_conn *conntrack,
979 } 983 }
980 case TCP_CONNTRACK_CLOSE: 984 case TCP_CONNTRACK_CLOSE:
981 if (index == TCP_RST_SET 985 if (index == TCP_RST_SET
982 && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) 986 && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
983 && conntrack->proto.tcp.last_index == TCP_SYN_SET 987 && conntrack->proto.tcp.last_index == TCP_SYN_SET)
988 || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
989 && conntrack->proto.tcp.last_index == TCP_ACK_SET))
984 && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { 990 && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
985 /* RST sent to invalid SYN we had let trough 991 /* RST sent to invalid SYN or ACK we had let trough
986 * SYN was in window then, tear down connection. 992 * at a) and c) above:
993 *
994 * a) SYN was in window then
995 * c) we hold a half-open connection.
996 *
997 * Delete our connection entry.
987 * We skip window checking, because packet might ACK 998 * We skip window checking, because packet might ACK
988 * segments we ignored in the SYN. */ 999 * segments we ignored. */
989 goto in_window; 1000 goto in_window;
990 } 1001 }
991 /* Just fall trough */ 1002 /* Just fall trough */