Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- 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(+) 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, }; -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html