summaryrefslogtreecommitdiffstats
path: root/src/netlink.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-11-28 00:03:50 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2017-01-03 14:21:53 +0100
commitdeaf962ebd7c6b9d8a161d9378a710031e4f1dd6 (patch)
tree8e885dfedb3eefafa29bd46edc1ebe09f5f8c41c /src/netlink.c
parentb139f738f558d6afb8c8f3e73526f578b059abd6 (diff)
src: add support for stateful object maps
You can create these maps using explicit map declarations: # nft add table filter # nft add chain filter input { type filter hook input priority 0\; } # nft add map filter badguys { type ipv4_addr : counter \; } # nft add rule filter input counter name ip saddr map @badguys # nft add counter filter badguy1 # nft add counter filter badguy2 # nft add element filter badguys { 192.168.2.3 : "badguy1" } # nft add element filter badguys { 192.168.2.4 : "badguy2" } Or through implicit map definitions: table ip filter { counter http-traffic { packets 8 bytes 672 } chain input { type filter hook input priority 0; policy accept; counter name tcp dport map { 80 : "http-traffic", 443 : "http-traffic"} } } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink.c')
-rw-r--r--src/netlink.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/netlink.c b/src/netlink.c
index 68bed201..97220f45 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -205,7 +205,8 @@ struct nftnl_set *alloc_nftnl_set(const struct handle *h)
return nls;
}
-static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *expr)
+static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
+ const struct expr *expr)
{
const struct expr *elem, *key, *data;
struct nftnl_set_elem *nlse;
@@ -243,8 +244,7 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *expr)
nftnl_udata_buf_len(udbuf));
nftnl_udata_buf_free(udbuf);
}
-
- if (data != NULL) {
+ if (set->set_flags & NFT_SET_MAP && data != NULL) {
netlink_gen_data(data, &nld);
switch (data->ops->type) {
case EXPR_VERDICT:
@@ -263,6 +263,11 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *expr)
break;
}
}
+ if (set->set_flags & NFT_SET_OBJECT) {
+ netlink_gen_data(data, &nld);
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_OBJREF,
+ nld.value, nld.len);
+ }
if (expr->flags & EXPR_F_INTERVAL_END)
nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_FLAGS,
@@ -1110,7 +1115,7 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
{
struct set *set;
const struct datatype *keytype, *datatype;
- uint32_t flags, key, data, data_len;
+ uint32_t flags, key, data, data_len, objtype = 0;
key = nftnl_set_get_u32(nls, NFTNL_SET_KEY_TYPE);
keytype = dtype_map_from_kernel(key);
@@ -1133,6 +1138,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
} else
datatype = NULL;
+ if (flags & NFT_SET_OBJECT) {
+ objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
+ datatype = &string_type;
+ }
+
set = set_alloc(&netlink_location);
set->handle.family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY);
set->handle.table = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE));
@@ -1142,6 +1152,8 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
set->keylen = nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE;
set->flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
+ set->objtype = objtype;
+
set->datatype = datatype;
if (nftnl_set_is_set(nls, NFTNL_SET_DATA_LEN)) {
data_len = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN);
@@ -1214,6 +1226,9 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx,
nftnl_set_set_u32(nls, NFTNL_SET_DATA_LEN,
set->datalen / BITS_PER_BYTE);
}
+ if (set->flags & NFT_SET_OBJECT)
+ nftnl_set_set_u32(nls, NFTNL_SET_OBJ_TYPE, set->objtype);
+
if (set->timeout)
nftnl_set_set_u64(nls, NFTNL_SET_TIMEOUT, set->timeout);
if (set->gc_int)
@@ -1357,7 +1372,7 @@ static void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
const struct expr *expr;
list_for_each_entry(expr, &set->expressions, list) {
- nlse = alloc_nftnl_setelem(expr);
+ nlse = alloc_nftnl_setelem(set, expr);
nftnl_set_elem_add(nls, nlse);
}
}
@@ -1577,10 +1592,10 @@ static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
nle = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_EXPR, NULL);
expr->stmt = netlink_parse_set_expr(set, nle);
}
-
- if (flags & NFT_SET_ELEM_INTERVAL_END) {
+ if (flags & NFT_SET_ELEM_INTERVAL_END)
expr->flags |= EXPR_F_INTERVAL_END;
- } else {
+
+ if (set->flags & NFT_SET_MAP) {
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_DATA)) {
nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_DATA,
&nld.len);
@@ -1602,6 +1617,15 @@ static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
expr = mapping_expr_alloc(&netlink_location, expr, data);
}
+ if (set->flags & NFT_SET_OBJECT) {
+ nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_OBJREF,
+ &nld.len);
+ data = netlink_alloc_value(&netlink_location, &nld);
+ data->dtype = &string_type;
+ data->byteorder = BYTEORDER_HOST_ENDIAN;
+ mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
+ expr = mapping_expr_alloc(&netlink_location, expr, data);
+ }
out:
compound_expr_add(set->init, expr);
return 0;