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

Commit c8e2078c authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller
Browse files

[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling



This patch let userspace programs set the IP_CT_TCP_BE_LIBERAL flag to
force the pickup of established connections.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5c8ce7c9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -30,6 +30,11 @@ enum tcp_conntrack {
/* Be liberal in window checking */
#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08

struct nf_ct_tcp_flags {
	u_int8_t flags;
	u_int8_t mask;
};

#ifdef __KERNEL__

struct ip_ct_tcp_state {
+4 −0
Original line number Diff line number Diff line
@@ -83,6 +83,10 @@ enum ctattr_protoinfo {
enum ctattr_protoinfo_tcp {
	CTA_PROTOINFO_TCP_UNSPEC,
	CTA_PROTOINFO_TCP_STATE,
	CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
	CTA_PROTOINFO_TCP_WSCALE_REPLY,
	CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
	CTA_PROTOINFO_TCP_FLAGS_REPLY,
	__CTA_PROTOINFO_TCP_MAX
};
#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
+44 −1
Original line number Diff line number Diff line
@@ -1101,11 +1101,26 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
			 const struct nf_conn *ct)
{
	struct nfattr *nest_parms;
	struct nf_ct_tcp_flags tmp = {};

	read_lock_bh(&tcp_lock);
	nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
		&ct->proto.tcp.state);

	NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
		&ct->proto.tcp.seen[0].td_scale);

	NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
		&ct->proto.tcp.seen[1].td_scale);

	tmp.flags = ct->proto.tcp.seen[0].flags;
	NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
		sizeof(struct nf_ct_tcp_flags), &tmp);

	tmp.flags = ct->proto.tcp.seen[1].flags;
	NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
		sizeof(struct nf_ct_tcp_flags), &tmp);
	read_unlock_bh(&tcp_lock);

	NFA_NEST_END(skb, nest_parms);
@@ -1119,6 +1134,10 @@ nfattr_failure:

static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
	[CTA_PROTOINFO_TCP_STATE-1]	      = sizeof(u_int8_t),
	[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] = sizeof(u_int8_t),
	[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]    = sizeof(u_int8_t),
	[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]  = sizeof(struct nf_ct_tcp_flags),
	[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]     = sizeof(struct nf_ct_tcp_flags)
};

static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
@@ -1142,6 +1161,30 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
	write_lock_bh(&tcp_lock);
	ct->proto.tcp.state =
		*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);

	if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]) {
		struct nf_ct_tcp_flags *attr =
			NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]);
		ct->proto.tcp.seen[0].flags &= ~attr->mask;
		ct->proto.tcp.seen[0].flags |= attr->flags & attr->mask;
	}

	if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]) {
		struct nf_ct_tcp_flags *attr =
			NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]);
		ct->proto.tcp.seen[1].flags &= ~attr->mask;
		ct->proto.tcp.seen[1].flags |= attr->flags & attr->mask;
	}

	if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] &&
	    tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1] &&
	    ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
	    ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
		ct->proto.tcp.seen[0].td_scale = *(u_int8_t *)
			NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]);
		ct->proto.tcp.seen[1].td_scale = *(u_int8_t *)
			NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]);
	}
	write_unlock_bh(&tcp_lock);

	return 0;