aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_conntrack_tcp.h4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c40
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c40
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
32struct ip_ct_tcp_state { 35struct 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. */
51int ip_ct_tcp_be_liberal __read_mostly = 0; 51int 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. */
58int ip_ct_tcp_loose __read_mostly = 3; 55int 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. */
61int nf_ct_tcp_be_liberal __read_mostly = 0; 61int 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. */
68int nf_ct_tcp_loose __read_mostly = 3; 65int 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;