diff options
-rw-r--r-- | include/linux/netfilter/nf_conntrack_tcp.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 40 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 40 |
3 files changed, 33 insertions, 51 deletions
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h index 2f4e98b90cc0..007af4c2770b 100644 --- a/include/linux/netfilter/nf_conntrack_tcp.h +++ b/include/linux/netfilter/nf_conntrack_tcp.h | |||
@@ -27,6 +27,9 @@ enum tcp_conntrack { | |||
27 | /* This sender sent FIN first */ | 27 | /* This sender sent FIN first */ |
28 | #define IP_CT_TCP_FLAG_CLOSE_INIT 0x04 | 28 | #define IP_CT_TCP_FLAG_CLOSE_INIT 0x04 |
29 | 29 | ||
30 | /* Be liberal in window checking */ | ||
31 | #define IP_CT_TCP_FLAG_BE_LIBERAL 0x08 | ||
32 | |||
30 | #ifdef __KERNEL__ | 33 | #ifdef __KERNEL__ |
31 | 34 | ||
32 | struct ip_ct_tcp_state { | 35 | struct ip_ct_tcp_state { |
@@ -34,7 +37,6 @@ struct ip_ct_tcp_state { | |||
34 | u_int32_t td_maxend; /* max of ack + max(win, 1) */ | 37 | u_int32_t td_maxend; /* max of ack + max(win, 1) */ |
35 | u_int32_t td_maxwin; /* max(win) */ | 38 | u_int32_t td_maxwin; /* max(win) */ |
36 | u_int8_t td_scale; /* window scale factor */ | 39 | u_int8_t td_scale; /* window scale factor */ |
37 | u_int8_t loose; /* used when connection picked up from the middle */ | ||
38 | u_int8_t flags; /* per direction options */ | 40 | u_int8_t flags; /* per direction options */ |
39 | }; | 41 | }; |
40 | 42 | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 06e4e8a6dd9f..c34f48fe5478 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c | |||
@@ -50,12 +50,9 @@ static DEFINE_RWLOCK(tcp_lock); | |||
50 | If it's non-zero, we mark only out of window RST segments as INVALID. */ | 50 | If it's non-zero, we mark only out of window RST segments as INVALID. */ |
51 | int ip_ct_tcp_be_liberal __read_mostly = 0; | 51 | int ip_ct_tcp_be_liberal __read_mostly = 0; |
52 | 52 | ||
53 | /* When connection is picked up from the middle, how many packets are required | 53 | /* If it is set to zero, we disable picking up already established |
54 | to pass in each direction when we assume we are in sync - if any side uses | ||
55 | window scaling, we lost the game. | ||
56 | If it is set to zero, we disable picking up already established | ||
57 | connections. */ | 54 | connections. */ |
58 | int ip_ct_tcp_loose __read_mostly = 3; | 55 | int ip_ct_tcp_loose __read_mostly = 1; |
59 | 56 | ||
60 | /* Max number of the retransmitted packets without receiving an (acceptable) | 57 | /* Max number of the retransmitted packets without receiving an (acceptable) |
61 | ACK from the destination. If this number is reached, a shorter timer | 58 | ACK from the destination. If this number is reached, a shorter timer |
@@ -694,11 +691,10 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
694 | before(sack, receiver->td_end + 1), | 691 | before(sack, receiver->td_end + 1), |
695 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); | 692 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); |
696 | 693 | ||
697 | if (sender->loose || receiver->loose || | 694 | if (before(seq, sender->td_maxend + 1) && |
698 | (before(seq, sender->td_maxend + 1) && | 695 | after(end, sender->td_end - receiver->td_maxwin - 1) && |
699 | after(end, sender->td_end - receiver->td_maxwin - 1) && | 696 | before(sack, receiver->td_end + 1) && |
700 | before(sack, receiver->td_end + 1) && | 697 | after(ack, receiver->td_end - MAXACKWINDOW(sender))) { |
701 | after(ack, receiver->td_end - MAXACKWINDOW(sender)))) { | ||
702 | /* | 698 | /* |
703 | * Take into account window scaling (RFC 1323). | 699 | * Take into account window scaling (RFC 1323). |
704 | */ | 700 | */ |
@@ -743,15 +739,13 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
743 | state->retrans = 0; | 739 | state->retrans = 0; |
744 | } | 740 | } |
745 | } | 741 | } |
746 | /* | ||
747 | * Close the window of disabled window tracking :-) | ||
748 | */ | ||
749 | if (sender->loose) | ||
750 | sender->loose--; | ||
751 | |||
752 | res = 1; | 742 | res = 1; |
753 | } else { | 743 | } else { |
754 | if (LOG_INVALID(IPPROTO_TCP)) | 744 | res = 0; |
745 | if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL || | ||
746 | ip_ct_tcp_be_liberal) | ||
747 | res = 1; | ||
748 | if (!res && LOG_INVALID(IPPROTO_TCP)) | ||
755 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | 749 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
756 | "ip_ct_tcp: %s ", | 750 | "ip_ct_tcp: %s ", |
757 | before(seq, sender->td_maxend + 1) ? | 751 | before(seq, sender->td_maxend + 1) ? |
@@ -762,8 +756,6 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
762 | : "ACK is over the upper bound (ACKed data not seen yet)" | 756 | : "ACK is over the upper bound (ACKed data not seen yet)" |
763 | : "SEQ is under the lower bound (already ACKed data retransmitted)" | 757 | : "SEQ is under the lower bound (already ACKed data retransmitted)" |
764 | : "SEQ is over the upper bound (over the window of the receiver)"); | 758 | : "SEQ is over the upper bound (over the window of the receiver)"); |
765 | |||
766 | res = ip_ct_tcp_be_liberal; | ||
767 | } | 759 | } |
768 | 760 | ||
769 | DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " | 761 | DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " |
@@ -1105,8 +1097,6 @@ static int tcp_new(struct ip_conntrack *conntrack, | |||
1105 | 1097 | ||
1106 | tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]); | 1098 | tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]); |
1107 | conntrack->proto.tcp.seen[1].flags = 0; | 1099 | conntrack->proto.tcp.seen[1].flags = 0; |
1108 | conntrack->proto.tcp.seen[0].loose = | ||
1109 | conntrack->proto.tcp.seen[1].loose = 0; | ||
1110 | } else if (ip_ct_tcp_loose == 0) { | 1100 | } else if (ip_ct_tcp_loose == 0) { |
1111 | /* Don't try to pick up connections. */ | 1101 | /* Don't try to pick up connections. */ |
1112 | return 0; | 1102 | return 0; |
@@ -1127,11 +1117,11 @@ static int tcp_new(struct ip_conntrack *conntrack, | |||
1127 | conntrack->proto.tcp.seen[0].td_maxwin; | 1117 | conntrack->proto.tcp.seen[0].td_maxwin; |
1128 | conntrack->proto.tcp.seen[0].td_scale = 0; | 1118 | conntrack->proto.tcp.seen[0].td_scale = 0; |
1129 | 1119 | ||
1130 | /* We assume SACK. Should we assume window scaling too? */ | 1120 | /* We assume SACK and liberal window checking to handle |
1121 | * window scaling */ | ||
1131 | conntrack->proto.tcp.seen[0].flags = | 1122 | conntrack->proto.tcp.seen[0].flags = |
1132 | conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM; | 1123 | conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | |
1133 | conntrack->proto.tcp.seen[0].loose = | 1124 | IP_CT_TCP_FLAG_BE_LIBERAL; |
1134 | conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose; | ||
1135 | } | 1125 | } |
1136 | 1126 | ||
1137 | conntrack->proto.tcp.seen[1].td_end = 0; | 1127 | conntrack->proto.tcp.seen[1].td_end = 0; |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 626b0011dd89..6fccdcf43e08 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -60,12 +60,9 @@ static DEFINE_RWLOCK(tcp_lock); | |||
60 | If it's non-zero, we mark only out of window RST segments as INVALID. */ | 60 | If it's non-zero, we mark only out of window RST segments as INVALID. */ |
61 | int nf_ct_tcp_be_liberal __read_mostly = 0; | 61 | int nf_ct_tcp_be_liberal __read_mostly = 0; |
62 | 62 | ||
63 | /* When connection is picked up from the middle, how many packets are required | 63 | /* If it is set to zero, we disable picking up already established |
64 | to pass in each direction when we assume we are in sync - if any side uses | ||
65 | window scaling, we lost the game. | ||
66 | If it is set to zero, we disable picking up already established | ||
67 | connections. */ | 64 | connections. */ |
68 | int nf_ct_tcp_loose __read_mostly = 3; | 65 | int nf_ct_tcp_loose __read_mostly = 1; |
69 | 66 | ||
70 | /* Max number of the retransmitted packets without receiving an (acceptable) | 67 | /* Max number of the retransmitted packets without receiving an (acceptable) |
71 | ACK from the destination. If this number is reached, a shorter timer | 68 | ACK from the destination. If this number is reached, a shorter timer |
@@ -650,11 +647,10 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
650 | before(sack, receiver->td_end + 1), | 647 | before(sack, receiver->td_end + 1), |
651 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); | 648 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); |
652 | 649 | ||
653 | if (sender->loose || receiver->loose || | 650 | if (before(seq, sender->td_maxend + 1) && |
654 | (before(seq, sender->td_maxend + 1) && | 651 | after(end, sender->td_end - receiver->td_maxwin - 1) && |
655 | after(end, sender->td_end - receiver->td_maxwin - 1) && | 652 | before(sack, receiver->td_end + 1) && |
656 | before(sack, receiver->td_end + 1) && | 653 | after(ack, receiver->td_end - MAXACKWINDOW(sender))) { |
657 | after(ack, receiver->td_end - MAXACKWINDOW(sender)))) { | ||
658 | /* | 654 | /* |
659 | * Take into account window scaling (RFC 1323). | 655 | * Take into account window scaling (RFC 1323). |
660 | */ | 656 | */ |
@@ -699,15 +695,13 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
699 | state->retrans = 0; | 695 | state->retrans = 0; |
700 | } | 696 | } |
701 | } | 697 | } |
702 | /* | ||
703 | * Close the window of disabled window tracking :-) | ||
704 | */ | ||
705 | if (sender->loose) | ||
706 | sender->loose--; | ||
707 | |||
708 | res = 1; | 698 | res = 1; |
709 | } else { | 699 | } else { |
710 | if (LOG_INVALID(IPPROTO_TCP)) | 700 | res = 0; |
701 | if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL || | ||
702 | nf_ct_tcp_be_liberal) | ||
703 | res = 1; | ||
704 | if (!res && LOG_INVALID(IPPROTO_TCP)) | ||
711 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 705 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
712 | "nf_ct_tcp: %s ", | 706 | "nf_ct_tcp: %s ", |
713 | before(seq, sender->td_maxend + 1) ? | 707 | before(seq, sender->td_maxend + 1) ? |
@@ -718,8 +712,6 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
718 | : "ACK is over the upper bound (ACKed data not seen yet)" | 712 | : "ACK is over the upper bound (ACKed data not seen yet)" |
719 | : "SEQ is under the lower bound (already ACKed data retransmitted)" | 713 | : "SEQ is under the lower bound (already ACKed data retransmitted)" |
720 | : "SEQ is over the upper bound (over the window of the receiver)"); | 714 | : "SEQ is over the upper bound (over the window of the receiver)"); |
721 | |||
722 | res = nf_ct_tcp_be_liberal; | ||
723 | } | 715 | } |
724 | 716 | ||
725 | DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " | 717 | DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " |
@@ -1063,8 +1055,6 @@ static int tcp_new(struct nf_conn *conntrack, | |||
1063 | 1055 | ||
1064 | tcp_options(skb, dataoff, th, &conntrack->proto.tcp.seen[0]); | 1056 | tcp_options(skb, dataoff, th, &conntrack->proto.tcp.seen[0]); |
1065 | conntrack->proto.tcp.seen[1].flags = 0; | 1057 | conntrack->proto.tcp.seen[1].flags = 0; |
1066 | conntrack->proto.tcp.seen[0].loose = | ||
1067 | conntrack->proto.tcp.seen[1].loose = 0; | ||
1068 | } else if (nf_ct_tcp_loose == 0) { | 1058 | } else if (nf_ct_tcp_loose == 0) { |
1069 | /* Don't try to pick up connections. */ | 1059 | /* Don't try to pick up connections. */ |
1070 | return 0; | 1060 | return 0; |
@@ -1085,11 +1075,11 @@ static int tcp_new(struct nf_conn *conntrack, | |||
1085 | conntrack->proto.tcp.seen[0].td_maxwin; | 1075 | conntrack->proto.tcp.seen[0].td_maxwin; |
1086 | conntrack->proto.tcp.seen[0].td_scale = 0; | 1076 | conntrack->proto.tcp.seen[0].td_scale = 0; |
1087 | 1077 | ||
1088 | /* We assume SACK. Should we assume window scaling too? */ | 1078 | /* We assume SACK and liberal window checking to handle |
1079 | * window scaling */ | ||
1089 | conntrack->proto.tcp.seen[0].flags = | 1080 | conntrack->proto.tcp.seen[0].flags = |
1090 | conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM; | 1081 | conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | |
1091 | conntrack->proto.tcp.seen[0].loose = | 1082 | IP_CT_TCP_FLAG_BE_LIBERAL; |
1092 | conntrack->proto.tcp.seen[1].loose = nf_ct_tcp_loose; | ||
1093 | } | 1083 | } |
1094 | 1084 | ||
1095 | conntrack->proto.tcp.seen[1].td_end = 0; | 1085 | conntrack->proto.tcp.seen[1].td_end = 0; |