Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fac42a9a authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by Patrick McHardy
Browse files

netfilter: nf_ct_tcp: fix flow recovery with TCP window tracking enabled



This patch adds the missing bits to support the recovery of TCP flows
without disabling window tracking (aka be_liberal). To ensure a
successful recovery, we have to inject the window scale factor via
ctnetlink.

This patch has been tested with a development snapshot of conntrackd
and the new clause `TCPWindowTracking' that allows to perform strict
TCP window tracking recovery across fail-overs.

With this patch, we don't update the receiver's window until it's not
initiated. We require this to perform a successful recovery. Jozsef
confirmed in a private email that this spotted a real issue since that
should not happen.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Acked-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent cca5cf91
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -585,8 +585,16 @@ static bool tcp_in_window(const struct nf_conn *ct,
			 * Let's try to use the data from the packet.
			 */
			sender->td_end = end;
			win <<= sender->td_scale;
			sender->td_maxwin = (win == 0 ? 1 : win);
			sender->td_maxend = end + sender->td_maxwin;
			/*
			 * We haven't seen traffic in the other direction yet
			 * but we have to tweak window tracking to pass III
			 * and IV until that happens.
			 */
			if (receiver->td_maxwin == 0)
				receiver->td_end = receiver->td_maxend = sack;
		}
	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
		     && dir == IP_CT_DIR_ORIGINAL)
@@ -680,7 +688,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
		/*
		 * Update receiver data.
		 */
		if (after(end, sender->td_maxend))
		if (receiver->td_maxwin != 0 && after(end, sender->td_maxend))
			receiver->td_maxwin += end - sender->td_maxend;
		if (after(sack + win, receiver->td_maxend - 1)) {
			receiver->td_maxend = sack + win;