From 2edc7ccd872c60f4a71218e34e737655d6e50efa Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 13 Mar 2018 18:44:11 +0100 Subject: conntrack: add synproxy support Signed-off-by: Pablo Neira Ayuso --- 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 ++++++++++++++++++ 7 files changed, 179 insertions(+) (limited to 'src/conntrack') diff --git a/src/conntrack/build.c b/src/conntrack/build.c index cf282e6..d132890 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 2118bf3..d9ad268 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 e6e4f7a..eca202e 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 e818a05..d1f9a5a 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 b52454b..8c1d813 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 56a575e..94a0de7 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 75ab09e..7b96936 100644 --- a/src/conntrack/setter.c +++ b/src/conntrack/setter.c @@ -467,6 +467,24 @@ set_attr_connlabels_mask(struct nf_conntrack *ct, const void *value, size_t len) ct->connlabels_mask = (void *) value; } +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) {} @@ -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, }; -- cgit v1.2.3