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

Commit 7fe1de44 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Reapply "netfilter: conntrack: allow sctp hearbeat after connection re-use"



This reverts commit 35452319 as it
causes merge conflicts with 5.4.258.  It will be added back after the
merge.

Change-Id: I8ea66985ba95de649890adacc26670d01cee6d52
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 8a59cb30
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ struct ip_ct_sctp {
	enum sctp_conntrack state;

	__be32 vtag[IP_CT_DIR_MAX];
	u8 last_dir;
	u8 flags;
};

#endif /* _NF_CONNTRACK_SCTP_H */
+35 −4
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
	[SCTP_CONNTRACK_HEARTBEAT_SENT]		= 30 SECS,
};

#define	SCTP_FLAG_HEARTBEAT_VTAG_FAILED	1

#define sNO SCTP_CONNTRACK_NONE
#define	sCL SCTP_CONNTRACK_CLOSED
#define	sCW SCTP_CONNTRACK_COOKIE_WAIT
@@ -358,6 +360,7 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
	u_int32_t offset, count;
	unsigned int *timeouts;
	unsigned long map[256 / sizeof(unsigned long)] = { 0 };
	bool ignore = false;

	if (sctp_error(skb, dataoff, state))
		return -NF_ACCEPT;
@@ -423,15 +426,39 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
			/* (D) vtag must be same as init_vtag as found in INIT_ACK */
			if (sh->vtag != ct->proto.sctp.vtag[dir])
				goto out_unlock;
		} else if (sch->type == SCTP_CID_HEARTBEAT ||
			   sch->type == SCTP_CID_HEARTBEAT_ACK) {
		} else if (sch->type == SCTP_CID_HEARTBEAT) {
			if (ct->proto.sctp.vtag[dir] == 0) {
				pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir);
				ct->proto.sctp.vtag[dir] = sh->vtag;
			} else if (sh->vtag != ct->proto.sctp.vtag[dir]) {
				if (test_bit(SCTP_CID_DATA, map) || ignore)
					goto out_unlock;

				ct->proto.sctp.flags |= SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
				ct->proto.sctp.last_dir = dir;
				ignore = true;
				continue;
			} else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) {
				ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
			}
		} else if (sch->type == SCTP_CID_HEARTBEAT_ACK) {
			if (ct->proto.sctp.vtag[dir] == 0) {
				pr_debug("Setting vtag %x for dir %d\n",
					 sh->vtag, dir);
				ct->proto.sctp.vtag[dir] = sh->vtag;
			} else if (sh->vtag != ct->proto.sctp.vtag[dir]) {
				pr_debug("Verification tag check failed\n");
				if (test_bit(SCTP_CID_DATA, map) || ignore)
					goto out_unlock;

				if ((ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) == 0 ||
				    ct->proto.sctp.last_dir == dir)
					goto out_unlock;

				ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
				ct->proto.sctp.vtag[dir] = sh->vtag;
				ct->proto.sctp.vtag[!dir] = 0;
			} else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) {
				ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
			}
		}

@@ -470,6 +497,10 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
	}
	spin_unlock_bh(&ct->lock);

	/* allow but do not refresh timeout */
	if (ignore)
		return NF_ACCEPT;

	timeouts = nf_ct_timeout_lookup(ct);
	if (!timeouts)
		timeouts = nf_sctp_pernet(nf_ct_net(ct))->timeouts;