From deaf962ebd7c6b9d8a161d9378a710031e4f1dd6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Nov 2016 00:03:50 +0100 Subject: 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 --- src/netlink.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'src/netlink.c') 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; -- cgit v1.2.3