summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/expression.h1
-rw-r--r--include/rule.h16
-rw-r--r--src/netlink.c55
-rw-r--r--src/segtree.c5
4 files changed, 56 insertions, 21 deletions
diff --git a/include/expression.h b/include/expression.h
index 68a36e8a..828dbaee 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -256,6 +256,7 @@ struct expr {
uint64_t expiration;
const char *comment;
struct stmt *stmt;
+ uint32_t elem_flags;
};
struct {
/* EXPR_UNARY */
diff --git a/include/rule.h b/include/rule.h
index ddad6d40..a25e99bd 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -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 */
diff --git a/src/netlink.c b/src/netlink.c
index a3453b96..9649a2f1 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -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;
diff --git a/src/segtree.c b/src/segtree.c
index f5353621..34a00161 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -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);
}