--- ./tcp-window-tracking/linux-2.4.patch.orig Thu May 27 09:49:45 2004 +++ ./tcp-window-tracking/linux-2.4.patch Sun Feb 6 15:32:51 2005 @@ -240,7 +240,8 @@ +#include #include - +- ++#include #include #include +#include @@ -369,8 +370,7 @@ #define sLI TCP_CONNTRACK_LISTEN #define sIV TCP_CONNTRACK_MAX +#define sIG TCP_CONNTRACK_IGNORE - --static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = { ++ +/* What TCP flags are set from RST/SYN/FIN/ACK. */ +enum tcp_bit_set { + TCP_SYN_SET, @@ -380,7 +380,8 @@ + TCP_RST_SET, + TCP_NONE_SET, +}; -+ + +-static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = { +/* + * The TCP state transition table needs a few words... + * @@ -532,9 +533,9 @@ + * sCL -> sCL + */ +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -+/*ack*/ { sIV, sIV, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV }, ++/*ack*/ { sIV, sIG, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV }, +/* -+ * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet. ++ * sSS -> sIG Might be a half-open connection + * sSR -> sIV Simultaneous open. + * sES -> sES :-) + * sFW -> sCW Normal close request answered by ACK. @@ -549,7 +550,7 @@ } }; -@@ -145,13 +335,433 @@ +@@ -145,13 +335,435 @@ return sprintf(buffer, "%s ", tcp_conntrack_names[state]); } @@ -604,12 +605,7 @@ +static void tcp_options(struct iphdr *iph, size_t len, + struct tcphdr *tcph, + struct ip_ct_tcp_state *state) - { -- if (tcph->rst) return 3; -- else if (tcph->syn) return 0; -- else if (tcph->fin) return 1; -- else if (tcph->ack) return 2; -- else return 4; ++{ + unsigned char *ptr; + int length = (tcph->doff*4) - sizeof(struct tcphdr); + @@ -764,8 +760,10 @@ + sender->td_maxwin = (win == 0 ? 1 : win); + sender->td_maxend = end + sender->td_maxwin; + } -+ } else if (state->state == TCP_CONNTRACK_SYN_SENT -+ && dir == IP_CT_DIR_ORIGINAL ++ } else if (((state->state == TCP_CONNTRACK_SYN_SENT ++ && dir == IP_CT_DIR_ORIGINAL) ++ || (state->state == TCP_CONNTRACK_SYN_RECV ++ && dir == IP_CT_DIR_REPLY)) + && after(end, sender->td_end)) { + /* + * RFC 793: "if a TCP is reinitialized ... then it need @@ -876,7 +874,7 @@ + "ip_conntrack_tcp: IGNORED: Out of window data; %s\n", + before(end, sender->td_maxend + 1) ? + after(seq, sender->td_end - receiver->td_maxwin - 1) ? -+ before(ack, receiver->td_end + 1) ? ++ before(sack, receiver->td_end + 1) ? + after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG" + : "ACK is under the lower bound (possibly overly delayed ACK)" + : "ACK is over the upper bound (ACKed data has never seen yet)" @@ -935,7 +933,12 @@ + +/* table of valid flag combinations - ECE and CWR are always valid */ +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = -+{ + { +- if (tcph->rst) return 3; +- else if (tcph->syn) return 0; +- else if (tcph->fin) return 1; +- else if (tcph->ack) return 2; +- else return 4; + [TH_SYN] = 1, + [TH_SYN|TH_ACK] = 1, + [TH_RST] = 1, @@ -989,7 +992,7 @@ } /* Returns verdict for packet, or -1 for invalid. */ -@@ -159,60 +769,132 @@ +@@ -159,60 +771,138 @@ struct iphdr *iph, size_t len, enum ip_conntrack_info ctinfo) { @@ -1028,7 +1031,9 @@ + + switch (new_state) { + case TCP_CONNTRACK_IGNORE: -+ /* Either SYN in ORIGINAL, or SYN/ACK in REPLY direction. */ ++ /* Either SYN in ORIGINAL, ++ * or SYN/ACK in REPLY ++ * or ACK in REPLY direction (half-open connection). */ + if (index == TCP_SYNACK_SET + && conntrack->proto.tcp.stored_seq == TCP_SYN_SET + && conntrack->proto.tcp.last_dir != dir @@ -1055,7 +1060,7 @@ + WRITE_UNLOCK(&tcp_lock); + if (NET_RATELIMIT(ip_ct_tcp_log_invalid)) + nf_log_ip((char *)iph, len, -+ "ip_conntrack_tcp: INVALID: invalid SYN (ignored) "); ++ "ip_conntrack_tcp: INVALID: invalid packet ignored "); + return NF_ACCEPT; + case TCP_CONNTRACK_MAX: + /* Invalid packet */ @@ -1082,10 +1087,14 @@ + break; + case TCP_CONNTRACK_CLOSE: + if (index == TCP_RST_SET -+ && conntrack->proto.tcp.stored_seq <= TCP_SYNACK_SET -+ && conntrack->proto.tcp.last_dir != dir -+ && after(ntohl(tcph->ack_seq), conntrack->proto.tcp.last_seq)) { -+ /* Ignore RST closing down invalid SYN we had let trough. */ ++ && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) ++ && conntrack->proto.tcp.stored_seq <= TCP_SYNACK_SET) ++ || (!test_bit(IPS_ASSURED_BIT, &conntrack->status) ++ && conntrack->proto.tcp.stored_seq == TCP_ACK_SET)) ++ && after(ntohl(tcph->ack_seq), ++ conntrack->proto.tcp.last_seq)) { ++ /* Ignore RST closing down invalid SYN or ACK ++ we had let trough. */ + WRITE_UNLOCK(&tcp_lock); + if (NET_RATELIMIT(ip_ct_tcp_log_invalid)) + nf_log_ip((char *)iph, len,