]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
segtree: Introduce flag for half-open range elements
authorPhil Sutter <phil@nwl.cc>
Wed, 19 Jul 2017 13:05:27 +0000 (15:05 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 19 Jul 2017 17:24:38 +0000 (19:24 +0200)
This flag is required by userspace only, so can live within userdata.
It's sole purpose is for 'nft monitor' to detect half-open ranges (which
are comprised of a single element only).

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/expression.h
include/rule.h
src/netlink.c
src/segtree.c

index 68a36e8af792aa84b1ba014ba63168b5753f9c5c..828dbaee633831045489fc97322c3fe3dbf3a288 100644 (file)
@@ -256,6 +256,7 @@ struct expr {
                        uint64_t                expiration;
                        const char              *comment;
                        struct stmt             *stmt;
+                       uint32_t                elem_flags;
                };
                struct {
                        /* EXPR_UNARY */
index ddad6d40470e4b07aae01f8164a7a4399ed68fa3..a25e99bdf4cfd07497efba49e3428f759f02caf2 100644 (file)
@@ -506,4 +506,20 @@ enum udata_set_type {
 };
 #define UDATA_SET_MAX (__UDATA_SET_MAX - 1)
 
+enum udata_set_elem_type {
+       UDATA_SET_ELEM_COMMENT,
+       UDATA_SET_ELEM_FLAGS,
+       __UDATA_SET_ELEM_MAX,
+};
+#define UDATA_SET_ELEM_MAX (__UDATA_SET_ELEM_MAX - 1)
+
+/**
+ * enum udata_set_elem_flags - meaning of bits in UDATA_SET_ELEM_FLAGS
+ *
+ * @SET_ELEM_F_INTERVAL_OPEN:  set element denotes a half-open range
+ */
+enum udata_set_elem_flags {
+       SET_ELEM_F_INTERVAL_OPEN        = 0x1,
+};
+
 #endif /* NFTABLES_RULE_H */
index a3453b96a053aaaab0ad6f799bd1d33497bee99a..9649a2f12bdb1eace83ea82e20454c5062b6917d 100644 (file)
@@ -204,7 +204,7 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
        const struct expr *elem, *key, *data;
        struct nftnl_set_elem *nlse;
        struct nft_data_linearize nld;
-       struct nftnl_udata_buf *udbuf;
+       struct nftnl_udata_buf *udbuf = NULL;
 
        nlse = nftnl_set_elem_alloc();
        if (nlse == NULL)
@@ -225,13 +225,22 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
        if (elem->timeout)
                nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_TIMEOUT,
                                       elem->timeout);
-       if (elem->comment) {
+       if (elem->comment || expr->elem_flags) {
                udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
                if (!udbuf)
                        memory_allocation_error();
-               if (!nftnl_udata_put_strz(udbuf, UDATA_TYPE_COMMENT,
+       }
+       if (elem->comment) {
+               if (!nftnl_udata_put_strz(udbuf, UDATA_SET_ELEM_COMMENT,
                                          elem->comment))
                        memory_allocation_error();
+       }
+       if (expr->elem_flags) {
+               if (!nftnl_udata_put_u32(udbuf, UDATA_SET_ELEM_FLAGS,
+                                        expr->elem_flags))
+                       memory_allocation_error();
+       }
+       if (udbuf) {
                nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_USERDATA,
                                   nftnl_udata_buf_data(udbuf),
                                   nftnl_udata_buf_len(udbuf));
@@ -1577,18 +1586,22 @@ static struct expr *netlink_parse_concat_elem(const struct datatype *dtype,
        return concat;
 }
 
-static int parse_udata_cb(const struct nftnl_udata *attr, void *data)
+static int set_elem_parse_udata_cb(const struct nftnl_udata *attr, void *data)
 {
+       const struct nftnl_udata **tb = data;
        unsigned char *value = nftnl_udata_get(attr);
        uint8_t type = nftnl_udata_type(attr);
        uint8_t len = nftnl_udata_len(attr);
-       const struct nftnl_udata **tb = data;
 
        switch (type) {
-       case UDATA_TYPE_COMMENT:
+       case UDATA_SET_ELEM_COMMENT:
                if (value[len - 1] != '\0')
                        return -1;
                break;
+       case UDATA_SET_ELEM_FLAGS:
+               if (len != sizeof(uint32_t))
+                       return -1;
+               break;
        default:
                return 0;
        }
@@ -1596,17 +1609,22 @@ static int parse_udata_cb(const struct nftnl_udata *attr, void *data)
        return 0;
 }
 
-static char *udata_get_comment(const void *data, uint32_t data_len)
+static void set_elem_parse_udata(struct nftnl_set_elem *nlse,
+                                struct expr *expr)
 {
-       const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
-
-       if (nftnl_udata_parse(data, data_len, parse_udata_cb, tb) < 0)
-               return NULL;
+       const struct nftnl_udata *ud[UDATA_SET_ELEM_MAX + 1] = {};
+       const void *data;
+       uint32_t len;
 
-       if (!tb[UDATA_TYPE_COMMENT])
-               return NULL;
+       data = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_USERDATA, &len);
+       if (nftnl_udata_parse(data, len, set_elem_parse_udata_cb, ud))
+               return;
 
-       return xstrdup(nftnl_udata_get(tb[UDATA_TYPE_COMMENT]));
+       if (ud[UDATA_SET_ELEM_COMMENT])
+               expr->comment =
+                       xstrdup(nftnl_udata_get(ud[UDATA_SET_ELEM_COMMENT]));
+       if (ud[UDATA_SET_ELEM_FLAGS])
+               expr->elem_flags = nftnl_udata_get_u32(ud[UDATA_SET_ELEM_FLAGS]);
 }
 
 static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
@@ -1640,13 +1658,8 @@ static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
                expr->timeout    = nftnl_set_elem_get_u64(nlse, NFTNL_SET_ELEM_TIMEOUT);
        if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPIRATION))
                expr->expiration = nftnl_set_elem_get_u64(nlse, NFTNL_SET_ELEM_EXPIRATION);
-       if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_USERDATA)) {
-               const void *data;
-               uint32_t len;
-
-               data = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_USERDATA, &len);
-               expr->comment = udata_get_comment(data, len);
-       }
+       if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_USERDATA))
+               set_elem_parse_udata(nlse, expr);
        if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPR)) {
                const struct nftnl_expr *nle;
 
index f53536210018d082d0213a11d00d4ffee55e7364..34a001613eabac2ef57ebb5793bea689e44b661c 100644 (file)
@@ -37,6 +37,7 @@ struct seg_tree {
 
 enum elementary_interval_flags {
        EI_F_INTERVAL_END       = 0x1,
+       EI_F_INTERVAL_OPEN      = 0x2,
 };
 
 /**
@@ -512,6 +513,8 @@ static void segtree_linearize(struct list_head *list, const struct set *set,
                mpz_bitmask(q, tree->keylen);
                nei = ei_alloc(p, q, NULL, EI_F_INTERVAL_END);
                list_add_tail(&nei->list, list);
+       } else {
+               prev->flags |= EI_F_INTERVAL_OPEN;
        }
 
        mpz_clear(p);
@@ -538,6 +541,8 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
 
        if (ei->flags & EI_F_INTERVAL_END)
                expr->flags |= EXPR_F_INTERVAL_END;
+       if (ei->flags & EI_F_INTERVAL_OPEN)
+               expr->elem_flags |= SET_ELEM_F_INTERVAL_OPEN;
 
        compound_expr_add(set, expr);
 }