aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2008-02-07 20:54:56 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-07 20:54:56 -0500
commitb2155e7f70b3f058efe94c0c459db023b05057bd (patch)
treef943ae3b694856365be1c9aa7f6a28a9414da873 /net
parentdf922075f2a55b1ae71a6fe589c1cc1b91381f4f (diff)
[NETFILTER]: nf_conntrack: TCP conntrack reopening fix
TCP connection tracking in netfilter did not handle TCP reopening properly: active close was taken into account for one side only and not for any side, which is fixed now. The patch includes more comments to explain the logic how the different cases are handled. The bug was discovered by Jeff Chua. 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>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 3e0cccae5636..202d7fa09483 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -125,7 +125,7 @@ enum tcp_bit_set {
125 * CLOSE_WAIT: ACK seen (after FIN) 125 * CLOSE_WAIT: ACK seen (after FIN)
126 * LAST_ACK: FIN seen (after FIN) 126 * LAST_ACK: FIN seen (after FIN)
127 * TIME_WAIT: last ACK seen 127 * TIME_WAIT: last ACK seen
128 * CLOSE: closed connection 128 * CLOSE: closed connection (RST)
129 * 129 *
130 * LISTEN state is not used. 130 * LISTEN state is not used.
131 * 131 *
@@ -824,7 +824,21 @@ static int tcp_packet(struct nf_conn *ct,
824 case TCP_CONNTRACK_SYN_SENT: 824 case TCP_CONNTRACK_SYN_SENT:
825 if (old_state < TCP_CONNTRACK_TIME_WAIT) 825 if (old_state < TCP_CONNTRACK_TIME_WAIT)
826 break; 826 break;
827 if ((ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_CLOSE_INIT) 827 /* RFC 1122: "When a connection is closed actively,
828 * it MUST linger in TIME-WAIT state for a time 2xMSL
829 * (Maximum Segment Lifetime). However, it MAY accept
830 * a new SYN from the remote TCP to reopen the connection
831 * directly from TIME-WAIT state, if..."
832 * We ignore the conditions because we are in the
833 * TIME-WAIT state anyway.
834 *
835 * Handle aborted connections: we and the server
836 * think there is an existing connection but the client
837 * aborts it and starts a new one.
838 */
839 if (((ct->proto.tcp.seen[dir].flags
840 | ct->proto.tcp.seen[!dir].flags)
841 & IP_CT_TCP_FLAG_CLOSE_INIT)
828 || (ct->proto.tcp.last_dir == dir 842 || (ct->proto.tcp.last_dir == dir
829 && ct->proto.tcp.last_index == TCP_RST_SET)) { 843 && ct->proto.tcp.last_index == TCP_RST_SET)) {
830 /* Attempt to reopen a closed/aborted connection. 844 /* Attempt to reopen a closed/aborted connection.
@@ -838,15 +852,22 @@ static int tcp_packet(struct nf_conn *ct,
838 case TCP_CONNTRACK_IGNORE: 852 case TCP_CONNTRACK_IGNORE:
839 /* Ignored packets: 853 /* Ignored packets:
840 * 854 *
855 * Our connection entry may be out of sync, so ignore
856 * packets which may signal the real connection between
857 * the client and the server.
858 *
841 * a) SYN in ORIGINAL 859 * a) SYN in ORIGINAL
842 * b) SYN/ACK in REPLY 860 * b) SYN/ACK in REPLY
843 * c) ACK in reply direction after initial SYN in original. 861 * c) ACK in reply direction after initial SYN in original.
862 *
863 * If the ignored packet is invalid, the receiver will send
864 * a RST we'll catch below.
844 */ 865 */
845 if (index == TCP_SYNACK_SET 866 if (index == TCP_SYNACK_SET
846 && ct->proto.tcp.last_index == TCP_SYN_SET 867 && ct->proto.tcp.last_index == TCP_SYN_SET
847 && ct->proto.tcp.last_dir != dir 868 && ct->proto.tcp.last_dir != dir
848 && ntohl(th->ack_seq) == ct->proto.tcp.last_end) { 869 && ntohl(th->ack_seq) == ct->proto.tcp.last_end) {
849 /* This SYN/ACK acknowledges a SYN that we earlier 870 /* b) This SYN/ACK acknowledges a SYN that we earlier
850 * ignored as invalid. This means that the client and 871 * ignored as invalid. This means that the client and
851 * the server are both in sync, while the firewall is 872 * the server are both in sync, while the firewall is
852 * not. We kill this session and block the SYN/ACK so 873 * not. We kill this session and block the SYN/ACK so
@@ -870,7 +891,7 @@ static int tcp_packet(struct nf_conn *ct,
870 write_unlock_bh(&tcp_lock); 891 write_unlock_bh(&tcp_lock);
871 if (LOG_INVALID(IPPROTO_TCP)) 892 if (LOG_INVALID(IPPROTO_TCP))
872 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 893 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
873 "nf_ct_tcp: invalid packed ignored "); 894 "nf_ct_tcp: invalid packet ignored ");
874 return NF_ACCEPT; 895 return NF_ACCEPT;
875 case TCP_CONNTRACK_MAX: 896 case TCP_CONNTRACK_MAX:
876 /* Invalid packet */ 897 /* Invalid packet */
@@ -924,8 +945,7 @@ static int tcp_packet(struct nf_conn *ct,
924 945
925 ct->proto.tcp.state = new_state; 946 ct->proto.tcp.state = new_state;
926 if (old_state != new_state 947 if (old_state != new_state
927 && (new_state == TCP_CONNTRACK_FIN_WAIT 948 && new_state == TCP_CONNTRACK_CLOSE)
928 || new_state == TCP_CONNTRACK_CLOSE))
929 ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; 949 ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
930 timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans 950 timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans
931 && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans 951 && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans