[libnetfilter_conntrack] conntrack: add synproxy support

Message ID 20180314141417.2942-1-pablo@netfilter.org
State Accepted
Delegated to: Pablo Neira
Headers show
Series
  • [libnetfilter_conntrack] conntrack: add synproxy support
Related show

Commit Message

Pablo Neira Ayuso March 14, 2018, 2:14 p.m.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/internal/object.h                          |  6 +++
 .../libnetfilter_conntrack.h                       |  3 ++
 .../linux_nfnetlink_conntrack.h                    | 10 ++++
 src/conntrack/build.c                              | 20 ++++++++
 src/conntrack/build_mnl.c                          | 17 +++++++
 src/conntrack/copy.c                               | 21 +++++++++
 src/conntrack/getter.c                             | 18 ++++++++
 src/conntrack/parse.c                              | 28 +++++++++++
 src/conntrack/parse_mnl.c                          | 54 ++++++++++++++++++++++
 src/conntrack/setter.c                             | 21 +++++++++
 10 files changed, 198 insertions(+)

Patch

diff --git a/include/internal/object.h b/include/internal/object.h
index bb14dc8584d0..3f6904f16d8b 100644
--- a/include/internal/object.h
+++ b/include/internal/object.h
@@ -189,6 +189,12 @@  struct nf_conntrack {
 		uint64_t	stop;
 	} timestamp;
 
+	struct {
+		uint32_t	isn;
+		uint32_t	its;
+		uint32_t	tsoff;
+	} synproxy;
+
 	void *helper_info;
 	size_t helper_info_len;
 
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index b8d458c239ca..c5c6b615a3bf 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -141,6 +141,9 @@  enum nf_conntrack_attr {
 	ATTR_REPL_ZONE,				/* u16 bits */
 	ATTR_SNAT_IPV6,				/* u128 bits */
 	ATTR_DNAT_IPV6,				/* u128 bits */
+	ATTR_SYNPROXY_ISN,			/* u32 bits */
+	ATTR_SYNPROXY_ITS,			/* u32 bits */
+	ATTR_SYNPROXY_TSOFF,			/* u32 bits */
 	ATTR_MAX
 };
 
diff --git a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
index f1f50b725c5d..aa45723138db 100644
--- a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
+++ b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
@@ -57,6 +57,7 @@  enum ctattr_type {
 	CTA_MARK_MASK,
 	CTA_LABELS,
 	CTA_LABELS_MASK,
+	CTA_SYNPROXY,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -190,6 +191,15 @@  enum ctattr_natseq {
 };
 #define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1)
 
+enum ctattr_synproxy {
+	CTA_SYNPROXY_UNSPEC,
+	CTA_SYNPROXY_ISN,
+	CTA_SYNPROXY_ITS,
+	CTA_SYNPROXY_TSOFF,
+	__CTA_SYNPROXY_MAX,
+};
+#define CTA_SYNPROXY_MAX (__CTA_SYNPROXY_MAX - 1)
+
 enum ctattr_expect {
 	CTA_EXPECT_UNSPEC,
 	CTA_EXPECT_MASTER,
diff --git a/src/conntrack/build.c b/src/conntrack/build.c
index cf282e63c003..d13289094e02 100644
--- a/src/conntrack/build.c
+++ b/src/conntrack/build.c
@@ -459,6 +459,21 @@  static void __build_labels(struct nfnlhdr *req,
 	}
 }
 
+static void __build_synproxy(struct nfnlhdr *req, size_t size,
+			     const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_SYNPROXY);
+	nfnl_addattr32(&req->nlh, size, CTA_SYNPROXY_ISN,
+		       htonl(ct->synproxy.isn));
+	nfnl_addattr32(&req->nlh, size, CTA_SYNPROXY_ITS,
+		       htonl(ct->synproxy.its));
+	nfnl_addattr32(&req->nlh, size, CTA_SYNPROXY_TSOFF,
+		       htonl(ct->synproxy.tsoff));
+	nfnl_nest_end(&req->nlh, nest);
+}
+
 int __build_conntrack(struct nfnl_subsys_handle *ssh,
 		      struct nfnlhdr *req,
 		      size_t size,
@@ -594,5 +609,10 @@  int __build_conntrack(struct nfnl_subsys_handle *ssh,
 	if (test_bit(ATTR_CONNLABELS, ct->head.set))
 		__build_labels(req, size, ct);
 
+	if (test_bit(ATTR_SYNPROXY_ISN, ct->head.set) &&
+	    test_bit(ATTR_SYNPROXY_ITS, ct->head.set) &&
+	    test_bit(ATTR_SYNPROXY_TSOFF, ct->head.set))
+		__build_synproxy(req, size, ct);
+
 	return 0;
 }
diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c
index 2118bf37f89b..d9ad268cb890 100644
--- a/src/conntrack/build_mnl.c
+++ b/src/conntrack/build_mnl.c
@@ -438,6 +438,18 @@  nfct_build_labels(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	}
 }
 
+static void nfct_build_synproxy(struct nlmsghdr *nlh,
+				const struct nf_conntrack *ct)
+{
+	struct nlattr *nest;
+
+	nest = mnl_attr_nest_start(nlh, CTA_SYNPROXY);
+	mnl_attr_put_u32(nlh, CTA_SYNPROXY_ISN, htonl(ct->synproxy.isn));
+	mnl_attr_put_u32(nlh, CTA_SYNPROXY_ITS, htonl(ct->synproxy.its));
+	mnl_attr_put_u32(nlh, CTA_SYNPROXY_TSOFF, htonl(ct->synproxy.tsoff));
+	mnl_attr_nest_end(nlh, nest);
+}
+
 int
 nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 {
@@ -579,5 +591,10 @@  nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	if (test_bit(ATTR_CONNLABELS, ct->head.set))
 		nfct_build_labels(nlh, ct);
 
+	if (test_bit(ATTR_SYNPROXY_ISN, ct->head.set) &&
+	    test_bit(ATTR_SYNPROXY_ITS, ct->head.set) &&
+	    test_bit(ATTR_SYNPROXY_TSOFF, ct->head.set))
+		nfct_build_synproxy(nlh, ct);
+
 	return 0;
 }
diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c
index e6e4f7a69bda..eca202e627bb 100644
--- a/src/conntrack/copy.c
+++ b/src/conntrack/copy.c
@@ -498,6 +498,24 @@  static void copy_attr_connlabels_mask(struct nf_conntrack *dest,
 	dest->connlabels_mask = do_copy_attr_connlabels(dest->connlabels_mask, orig->connlabels_mask);
 }
 
+static void copy_attr_synproxy_its(struct nf_conntrack *dest,
+				   const struct nf_conntrack *orig)
+{
+	dest->synproxy.its = orig->synproxy.its;
+}
+
+static void copy_attr_synproxy_isn(struct nf_conntrack *dest,
+				   const struct nf_conntrack *orig)
+{
+	dest->synproxy.isn = orig->synproxy.isn;
+}
+
+static void copy_attr_synproxy_tsoff(struct nf_conntrack *dest,
+				     const struct nf_conntrack *orig)
+{
+	dest->synproxy.tsoff = orig->synproxy.tsoff;
+}
+
 const copy_attr copy_attr_array[ATTR_MAX] = {
 	[ATTR_ORIG_IPV4_SRC]		= copy_attr_orig_ipv4_src,
 	[ATTR_ORIG_IPV4_DST] 		= copy_attr_orig_ipv4_dst,
@@ -571,6 +589,9 @@  const copy_attr copy_attr_array[ATTR_MAX] = {
 	[ATTR_CONNLABELS_MASK]		= copy_attr_connlabels_mask,
 	[ATTR_SNAT_IPV6]		= copy_attr_snat_ipv6,
 	[ATTR_DNAT_IPV6]		= copy_attr_dnat_ipv6,
+	[ATTR_SYNPROXY_ITS]		= copy_attr_synproxy_its,
+	[ATTR_SYNPROXY_ISN]		= copy_attr_synproxy_isn,
+	[ATTR_SYNPROXY_TSOFF]		= copy_attr_synproxy_tsoff,
 };
 
 /* this is used by nfct_copy() with the NFCT_CP_OVERRIDE flag set. */
diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c
index e818a05b752f..d1f9a5ac27ad 100644
--- a/src/conntrack/getter.c
+++ b/src/conntrack/getter.c
@@ -369,6 +369,21 @@  static const void *get_attr_connlabels_mask(const struct nf_conntrack *ct)
 	return ct->connlabels_mask;
 }
 
+static const void *get_attr_synproxy_isn(const struct nf_conntrack *ct)
+{
+	return &ct->synproxy.isn;
+}
+
+static const void *get_attr_synproxy_its(const struct nf_conntrack *ct)
+{
+	return &ct->synproxy.its;
+}
+
+static const void *get_attr_synproxy_tsoff(const struct nf_conntrack *ct)
+{
+	return &ct->synproxy.tsoff;
+}
+
 const get_attr get_attr_array[ATTR_MAX] = {
 	[ATTR_ORIG_IPV4_SRC]		= get_attr_orig_ipv4_src,
 	[ATTR_ORIG_IPV4_DST] 		= get_attr_orig_ipv4_dst,
@@ -442,4 +457,7 @@  const get_attr get_attr_array[ATTR_MAX] = {
 	[ATTR_CONNLABELS_MASK]		= get_attr_connlabels_mask,
 	[ATTR_SNAT_IPV6]		= get_attr_snat_ipv6,
 	[ATTR_DNAT_IPV6]		= get_attr_dnat_ipv6,
+	[ATTR_SYNPROXY_ISN]		= get_attr_synproxy_isn,
+	[ATTR_SYNPROXY_ITS]		= get_attr_synproxy_its,
+	[ATTR_SYNPROXY_TSOFF]		= get_attr_synproxy_tsoff,
 };
diff --git a/src/conntrack/parse.c b/src/conntrack/parse.c
index b52454b182de..8c1d813bc9fb 100644
--- a/src/conntrack/parse.c
+++ b/src/conntrack/parse.c
@@ -422,6 +422,31 @@  __parse_nat_seq(const struct nfattr *attr, struct nf_conntrack *ct, int dir)
 	}
 }
 
+static void __parse_synproxy(const struct nfattr *attr, struct nf_conntrack *ct)
+{
+	struct nfattr *tb[CTA_SYNPROXY_MAX];
+
+	nfnl_parse_nested(tb, CTA_SYNPROXY_MAX, attr);
+
+	if (tb[CTA_SYNPROXY_ISN - 1]) {
+		ct->synproxy.isn =
+			ntohl(*(uint32_t *)NFA_DATA(tb[CTA_SYNPROXY_ISN-1]));
+		set_bit(ATTR_SYNPROXY_ISN, ct->head.set);
+	}
+
+	if (tb[CTA_SYNPROXY_ITS - 1]) {
+		ct->synproxy.its =
+			ntohl(*(uint32_t *)NFA_DATA(tb[CTA_SYNPROXY_ITS-1]));
+		set_bit(ATTR_SYNPROXY_ITS, ct->head.set);
+	}
+
+	if (tb[CTA_SYNPROXY_TSOFF - 1]) {
+		ct->synproxy.tsoff =
+			ntohl(*(uint32_t *)NFA_DATA(tb[CTA_SYNPROXY_TSOFF-1]));
+		set_bit(ATTR_SYNPROXY_TSOFF, ct->head.set);
+	}
+}
+
 static void 
 __parse_helper(const struct nfattr *attr, struct nf_conntrack *ct)
 {
@@ -596,4 +621,7 @@  void __parse_conntrack(const struct nlmsghdr *nlh,
 
 	if (cda[CTA_LABELS-1])
 		__parse_labels(cda[CTA_LABELS-1], ct);
+
+	if (cda[CTA_SYNPROXY-1])
+		__parse_synproxy(cda[CTA_SYNPROXY-1], ct);
 }
diff --git a/src/conntrack/parse_mnl.c b/src/conntrack/parse_mnl.c
index 56a575ed8ad7..94a0de7caf31 100644
--- a/src/conntrack/parse_mnl.c
+++ b/src/conntrack/parse_mnl.c
@@ -809,6 +809,55 @@  static int nfct_parse_labels(const struct nlattr *attr, struct nf_conntrack *ct)
 	return 0;
 }
 
+static int nfct_parse_synproxy_attr_cb(const struct nlattr *attr, void *data)
+{
+	int type = mnl_attr_get_type(attr);
+	const struct nlattr **tb = data;
+
+	if (mnl_attr_type_valid(attr, CTA_SYNPROXY_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_SYNPROXY_ISN:
+	case CTA_SYNPROXY_ITS:
+	case CTA_SYNPROXY_TSOFF:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+			return MNL_CB_ERROR;
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int nfct_parse_synproxy(const struct nlattr *attr,
+			       struct nf_conntrack *ct)
+{
+	struct nlattr *tb[CTA_SYNPROXY + 1] = {};
+
+	if (mnl_attr_parse_nested(attr, nfct_parse_synproxy_attr_cb, tb) < 0)
+		return -1;
+
+	if (tb[CTA_SYNPROXY_ISN]) {
+		ct->synproxy.isn =
+			ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ISN]));
+		set_bit(ATTR_SYNPROXY_ISN, ct->head.set);
+	}
+
+	if (tb[CTA_SYNPROXY_ITS]) {
+		ct->synproxy.its =
+			ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ITS]));
+		set_bit(ATTR_SYNPROXY_ITS, ct->head.set);
+	}
+
+	if (tb[CTA_SYNPROXY_TSOFF]) {
+		ct->synproxy.tsoff =
+			ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_TSOFF]));
+		set_bit(ATTR_SYNPROXY_TSOFF, ct->head.set);
+	}
+
+	return 0;
+}
+
 static int
 nfct_parse_conntrack_attr_cb(const struct nlattr *attr, void *data)
 {
@@ -977,6 +1026,11 @@  nfct_payload_parse(const void *payload, size_t payload_len,
 	}
 	/* CTA_LABELS_MASK: never sent by kernel */
 
+	if (tb[CTA_SYNPROXY]) {
+		if (nfct_parse_synproxy(tb[CTA_SYNPROXY], ct) < 0)
+			return -1;
+	}
+
 	return 0;
 }
 
diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c
index 75ab09e00b3d..7b9693690ea0 100644
--- a/src/conntrack/setter.c
+++ b/src/conntrack/setter.c
@@ -468,6 +468,24 @@  set_attr_connlabels_mask(struct nf_conntrack *ct, const void *value, size_t len)
 }
 
 static void
+set_attr_synproxy_isn(struct nf_conntrack *ct, const void *value, size_t len)
+{
+	ct->synproxy.isn = *((uint32_t *) value);
+}
+
+static void
+set_attr_synproxy_its(struct nf_conntrack *ct, const void *value, size_t len)
+{
+	ct->synproxy.its = *((uint32_t *) value);
+}
+
+static void
+set_attr_synproxy_tsoff(struct nf_conntrack *ct, const void *value, size_t len)
+{
+	ct->synproxy.tsoff = *((uint32_t *) value);
+}
+
+static void
 set_attr_do_nothing(struct nf_conntrack *ct, const void *value, size_t len) {}
 
 const set_attr set_attr_array[ATTR_MAX] = {
@@ -543,4 +561,7 @@  const set_attr set_attr_array[ATTR_MAX] = {
 	[ATTR_CONNLABELS_MASK]	= set_attr_connlabels_mask,
 	[ATTR_SNAT_IPV6]	= set_attr_snat_ipv6,
 	[ATTR_DNAT_IPV6]	= set_attr_dnat_ipv6,
+	[ATTR_SYNPROXY_ISN]	= set_attr_synproxy_isn,
+	[ATTR_SYNPROXY_ITS]	= set_attr_synproxy_its,
+	[ATTR_SYNPROXY_TSOFF]	= set_attr_synproxy_tsoff,
 };