summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-06-13 16:38:33 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-06-24 11:50:00 +0200
commitaae836a7aa628af4d4d5dd97d0eefa898e8f5245 (patch)
tree0a5999838de7e19bba5c2bfb7172fec8d70c2da5 /src/netlink_delinearize.c
parentf171d1cf8a6530fe0ac204d4a6520fe0e2a70da4 (diff)
src: use libnftables
This patch migrates nft to use the libnftables library, that is used by the iptables over nftables compat utility as well. Most of the conversion was pretty straight forward. Some small significant changes happened in the handling of set element and immediate data abstraction that libnl provides. libnftables is a bit more granular since it splits the struct nfnl_nft_data into three attributes: verdict, chain and plain data (used in maps). I have added a new file src/mnl.c that contains the low level netlink communication that now resides in nftables source tree instead of the library. This should help to implement the batching support using libmnl in follow up patches. I also spent some significant amount of time running my tests to make sure that we don't increase the number of bugs that we already have (I plan to provide a list of those that I have detected and diagnosed, so anyone else can help us to fix them). As a side effect, this change should also prepare the ground for JSON and XML support anytime soon. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c190
1 files changed, 116 insertions, 74 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 50672b98..c24e105c 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -8,6 +9,9 @@
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*/
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
#include <limits.h>
#include <linux/netfilter/nf_tables.h>
#include <netlink.h>
@@ -69,14 +73,22 @@ static struct expr *netlink_get_register(struct netlink_parse_ctx *ctx,
static void netlink_parse_immediate(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
- const struct nfnl_nft_data *data = nfnl_nft_immediate_get_data(nle);
- enum nft_registers dreg = nfnl_nft_immediate_get_dreg(nle);
+ struct nft_data_delinearize nld;
+ enum nft_registers dreg;
struct stmt *stmt;
struct expr *expr;
- expr = netlink_alloc_data(loc, data, dreg);
+ if (nft_rule_expr_is_set(nle, NFT_EXPR_IMM_VERDICT))
+ nld.verdict = nft_rule_expr_get_u32(nle, NFT_EXPR_IMM_VERDICT);
+ else if (nft_rule_expr_is_set(nle, NFT_EXPR_IMM_DATA)) {
+ nld.value = nft_rule_expr_get(nle, NFT_EXPR_IMM_DATA, &nld.len);
+ }
+
+ dreg = nft_rule_expr_get_u32(nle, NFT_EXPR_IMM_DREG);
+
+ expr = netlink_alloc_data(loc, &nld, dreg);
if (dreg == NFT_REG_VERDICT) {
stmt = verdict_stmt_alloc(loc, expr);
list_add_tail(&stmt->list, &ctx->rule->stmts);
@@ -84,9 +96,9 @@ static void netlink_parse_immediate(struct netlink_parse_ctx *ctx,
netlink_set_register(ctx, dreg, expr);
}
-static enum ops netlink_parse_cmp_op(const struct nfnl_nft_expr *nle)
+static enum ops netlink_parse_cmp_op(const struct nft_rule_expr *nle)
{
- switch (nfnl_nft_cmp_get_op(nle)) {
+ switch (nft_rule_expr_get_u8(nle, NFT_EXPR_CMP_OP)) {
case NFT_CMP_EQ:
return OP_EQ;
case NFT_CMP_NEQ:
@@ -106,21 +118,23 @@ static enum ops netlink_parse_cmp_op(const struct nfnl_nft_expr *nle)
static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
- const struct nfnl_nft_data *data = nfnl_nft_cmp_get_data(nle);
+ struct nft_data_delinearize nld;
struct expr *expr, *left, *right;
struct stmt *stmt;
enum ops op;
- left = netlink_get_register(ctx, loc, nfnl_nft_cmp_get_sreg(nle));
+ nld.value = nft_rule_expr_get(nle, NFT_EXPR_CMP_DATA, &nld.len);
+ left = netlink_get_register(ctx, loc,
+ nft_rule_expr_get_u8(nle, NFT_EXPR_CMP_SREG));
if (left == NULL)
return netlink_error(ctx, loc,
"Relational expression has no left "
"hand side");
op = netlink_parse_cmp_op(nle);
- right = netlink_alloc_value(loc, data);
+ right = netlink_alloc_value(loc, &nld);
// FIXME
if (left->len && left->dtype && left->dtype->type != TYPE_STRING &&
@@ -135,28 +149,30 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct stmt *stmt;
struct expr *expr, *left, *right;
struct set *set;
enum nft_registers dreg;
- left = netlink_get_register(ctx, loc, nfnl_nft_lookup_get_sreg(nle));
+ left = netlink_get_register(ctx, loc,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_LOOKUP_SREG));
if (left == NULL)
return netlink_error(ctx, loc,
"Lookup expression has no left hand side");
- set = set_lookup(ctx->table, nfnl_nft_lookup_get_set(nle));
+ set = set_lookup(ctx->table,
+ nft_rule_expr_get_str(nle, NFT_EXPR_LOOKUP_SET));
if (set == NULL)
return netlink_error(ctx, loc,
"Unknown set '%s' in lookup expression",
- nfnl_nft_lookup_get_set(nle));
+ nft_rule_expr_get_str(nle, NFT_EXPR_LOOKUP_SET));
right = set_ref_expr_alloc(loc, set);
- if (nfnl_nft_lookup_test_dreg(nle)) {
- dreg = nfnl_nft_lookup_get_dreg(nle);
+ if (nft_rule_expr_is_set(nle, NFT_EXPR_LOOKUP_DREG)) {
+ dreg = nft_rule_expr_get_u32(nle, NFT_EXPR_LOOKUP_DREG);
expr = map_expr_alloc(loc, left, right);
if (dreg != NFT_REG_VERDICT)
return netlink_set_register(ctx, dreg, expr);
@@ -170,12 +186,14 @@ static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,
static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr, *left, *mask, *xor, *or;
mpz_t m, x, o;
+ struct nft_data_delinearize nld;
- left = netlink_get_register(ctx, loc, nfnl_nft_bitwise_get_sreg(nle));
+ left = netlink_get_register(ctx, loc,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_BITWISE_SREG));
if (left == NULL)
return netlink_error(ctx, loc,
"Bitwise expression has no left "
@@ -183,10 +201,14 @@ static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
expr = left;
- mask = netlink_alloc_value(loc, nfnl_nft_bitwise_get_mask(nle));
+ nld.value = nft_rule_expr_get(nle, NFT_EXPR_BITWISE_MASK, &nld.len);
+
+ mask = netlink_alloc_value(loc, &nld);
mpz_init_set(m, mask->value);
- xor = netlink_alloc_value(loc, nfnl_nft_bitwise_get_xor(nle));
+ nld.value = nft_rule_expr_get(nle, NFT_EXPR_BITWISE_XOR, &nld.len);
+
+ xor = netlink_alloc_value(loc, &nld);
mpz_init_set(x, xor->value);
mpz_init_set_ui(o, 0);
@@ -215,7 +237,10 @@ static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
expr_free(xor);
if (mpz_cmp_ui(o, 0)) {
- or = netlink_alloc_value(loc, nfnl_nft_bitwise_get_xor(nle));
+ nld.value = nft_rule_expr_get(nle, NFT_EXPR_BITWISE_XOR,
+ &nld.len);
+
+ or = netlink_alloc_value(loc, &nld);
mpz_set(or->value, o);
expr = binop_expr_alloc(loc, OP_OR, expr, or);
expr->len = left->len;
@@ -225,23 +250,26 @@ static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
mpz_clear(x);
mpz_clear(o);
- netlink_set_register(ctx, nfnl_nft_bitwise_get_dreg(nle), expr);
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_BITWISE_DREG),
+ expr);
}
static void netlink_parse_byteorder(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr, *arg;
enum ops op;
- arg = netlink_get_register(ctx, loc, nfnl_nft_byteorder_get_sreg(nle));
+ arg = netlink_get_register(ctx, loc,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_BYTEORDER_SREG));
if (arg == NULL)
return netlink_error(ctx, loc,
"Byteorder expression has no left "
"hand side");
- switch (nfnl_nft_byteorder_get_op(nle)) {
+ switch (nft_rule_expr_get_u32(nle, NFT_EXPR_BYTEORDER_OP)) {
case NFT_BYTEORDER_NTOH:
op = OP_NTOH;
break;
@@ -250,106 +278,120 @@ static void netlink_parse_byteorder(struct netlink_parse_ctx *ctx,
break;
default:
BUG("invalid byteorder operation %u\n",
- nfnl_nft_byteorder_get_op(nle));
+ nft_rule_expr_get_u32(nle, NFT_EXPR_BYTEORDER_OP));
}
expr = unary_expr_alloc(loc, op, arg);
expr->len = arg->len;
- netlink_set_register(ctx, nfnl_nft_byteorder_get_dreg(nle), expr);
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_BYTEORDER_DREG),
+ expr);
}
static void netlink_parse_payload(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr;
expr = payload_expr_alloc(loc, NULL, 0);
- payload_init_raw(expr, nfnl_nft_payload_get_base(nle) + 1,
- nfnl_nft_payload_get_offset(nle) * BITS_PER_BYTE,
- nfnl_nft_payload_get_len(nle) * BITS_PER_BYTE);
+ payload_init_raw(expr, nft_rule_expr_get_u32(nle, NFT_EXPR_PAYLOAD_BASE) + 1,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_PAYLOAD_OFFSET) * BITS_PER_BYTE,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_PAYLOAD_LEN) * BITS_PER_BYTE);
- netlink_set_register(ctx, nfnl_nft_payload_get_dreg(nle), expr);
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_PAYLOAD_DREG),
+ expr);
}
static void netlink_parse_exthdr(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr;
expr = exthdr_expr_alloc(loc, NULL, 0);
- exthdr_init_raw(expr, nfnl_nft_exthdr_get_type(nle),
- nfnl_nft_exthdr_get_offset(nle) * BITS_PER_BYTE,
- nfnl_nft_exthdr_get_len(nle) * BITS_PER_BYTE);
+ exthdr_init_raw(expr, nft_rule_expr_get_u8(nle, NFT_EXPR_EXTHDR_TYPE),
+ nft_rule_expr_get_u32(nle, NFT_EXPR_EXTHDR_OFFSET) * BITS_PER_BYTE,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_EXTHDR_LEN) * BITS_PER_BYTE);
- netlink_set_register(ctx, nfnl_nft_exthdr_get_dreg(nle), expr);
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_EXTHDR_DREG),
+ expr);
}
static void netlink_parse_meta(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr;
- expr = meta_expr_alloc(loc, nfnl_nft_meta_get_key(nle));
- netlink_set_register(ctx, nfnl_nft_meta_get_dreg(nle), expr);
+ expr = meta_expr_alloc(loc,
+ nft_rule_expr_get_u8(nle, NFT_EXPR_META_KEY));
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u8(nle, NFT_EXPR_META_DREG),
+ expr);
}
static void netlink_parse_ct(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct expr *expr;
- expr = ct_expr_alloc(loc, nfnl_nft_ct_get_key(nle));
- netlink_set_register(ctx, nfnl_nft_ct_get_dreg(nle), expr);
+ expr = ct_expr_alloc(loc, nft_rule_expr_get_u32(nle, NFT_EXPR_CT_KEY));
+ netlink_set_register(ctx,
+ nft_rule_expr_get_u32(nle, NFT_EXPR_CT_DREG),
+ expr);
}
static void netlink_parse_counter(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct stmt *stmt;
stmt = counter_stmt_alloc(loc);
- stmt->counter.packets = nfnl_nft_counter_get_packets(nle);
- stmt->counter.bytes = nfnl_nft_counter_get_bytes(nle);
+ stmt->counter.packets =
+ nft_rule_expr_get_u64(nle, NFT_EXPR_CTR_PACKETS);
+ stmt->counter.bytes =
+ nft_rule_expr_get_u64(nle, NFT_EXPR_CTR_BYTES);
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
static void netlink_parse_log(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct stmt *stmt;
const char *prefix;
stmt = log_stmt_alloc(loc);
- prefix = nfnl_nft_log_get_prefix(nle);
+ prefix = nft_rule_expr_get_str(nle, NFT_EXPR_LOG_PREFIX);
if (prefix != NULL)
stmt->log.prefix = xstrdup(prefix);
- stmt->log.group = nfnl_nft_log_get_group(nle);
- stmt->log.snaplen = nfnl_nft_log_get_snaplen(nle);
- stmt->log.qthreshold = nfnl_nft_log_get_qthreshold(nle);
+ stmt->log.group = nft_rule_expr_get_u32(nle, NFT_EXPR_LOG_GROUP);
+ stmt->log.snaplen = nft_rule_expr_get_u32(nle, NFT_EXPR_LOG_SNAPLEN);
+ stmt->log.qthreshold =
+ nft_rule_expr_get_u32(nle, NFT_EXPR_LOG_QTHRESHOLD);
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
static void netlink_parse_limit(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct stmt *stmt;
stmt = limit_stmt_alloc(loc);
- stmt->limit.rate = nfnl_nft_limit_get_rate(nle);
- stmt->limit.depth = nfnl_nft_limit_get_depth(nle);
+ stmt->limit.rate = nft_rule_expr_get_u32(nle, NFT_EXPR_LIMIT_RATE);
+ stmt->limit.depth = nft_rule_expr_get_u32(nle, NFT_EXPR_LIMIT_DEPTH);
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
static void netlink_parse_reject(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *expr)
+ const struct nft_rule_expr *expr)
{
struct stmt *stmt;
@@ -359,16 +401,16 @@ static void netlink_parse_reject(struct netlink_parse_ctx *ctx,
static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle)
+ const struct nft_rule_expr *nle)
{
struct stmt *stmt;
struct expr *addr, *proto;
enum nft_registers reg1, reg2;
stmt = nat_stmt_alloc(loc);
- stmt->nat.type = nfnl_nft_nat_get_type(nle);
+ stmt->nat.type = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_TYPE);
- reg1 = nfnl_nft_nat_get_sreg_addr_min(nle);
+ reg1 = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_REG_ADDR_MIN);
if (reg1) {
addr = netlink_get_register(ctx, loc, reg1);
if (addr == NULL)
@@ -380,7 +422,7 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
stmt->nat.addr = addr;
}
- reg2 = nfnl_nft_nat_get_sreg_addr_max(nle);
+ reg2 = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_REG_ADDR_MAX);
if (reg2 && reg2 != reg1) {
addr = netlink_get_register(ctx, loc, reg2);
if (addr == NULL)
@@ -394,7 +436,7 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
stmt->nat.addr = addr;
}
- reg1 = nfnl_nft_nat_get_sreg_proto_min(nle);
+ reg1 = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_REG_PROTO_MIN);
if (reg1) {
proto = netlink_get_register(ctx, loc, reg1);
if (proto == NULL)
@@ -406,7 +448,7 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
stmt->nat.proto = proto;
}
- reg2 = nfnl_nft_nat_get_sreg_proto_max(nle);
+ reg2 = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_REG_PROTO_MAX);
if (reg2 && reg2 != reg1) {
proto = netlink_get_register(ctx, loc, reg2);
if (proto == NULL)
@@ -427,7 +469,7 @@ static const struct {
const char *name;
void (*parse)(struct netlink_parse_ctx *ctx,
const struct location *loc,
- const struct nfnl_nft_expr *nle);
+ const struct nft_rule_expr *nle);
} netlink_parsers[] = {
{ .name = "immediate", .parse = netlink_parse_immediate },
{ .name = "cmp", .parse = netlink_parse_cmp },
@@ -450,25 +492,26 @@ static const struct input_descriptor indesc_netlink = {
.type = INDESC_NETLINK,
};
-static void netlink_parse_expr(struct nl_object *obj, void *arg)
+static int netlink_parse_expr(struct nft_rule_expr *nle, void *arg)
{
- const struct nfnl_nft_expr *nle = (struct nfnl_nft_expr *)obj;
- const char *type = nfnl_nft_expr_get_type(nle);
+ const char *type = nft_rule_expr_get_str(nle, NFT_RULE_EXPR_ATTR_NAME);
struct netlink_parse_ctx *ctx = arg;
struct location loc;
unsigned int i;
memset(&loc, 0, sizeof(loc));
loc.indesc = &indesc_netlink;
- loc.nl_obj = obj;
+ loc.nle = nle;
for (i = 0; i < array_size(netlink_parsers); i++) {
if (strcmp(type, netlink_parsers[i].name))
continue;
- return netlink_parsers[i].parse(ctx, &loc, nle);
+ netlink_parsers[i].parse(ctx, &loc, nle);
+ return 0;
}
netlink_error(ctx, &loc, "unknown expression type '%s'", type);
+ return 0;
}
struct rule_pp_ctx {
@@ -697,9 +740,8 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r
}
struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
- const struct nl_object *obj)
+ const struct nft_rule *nlr)
{
- const struct nfnl_nft_rule *nlr = (const struct nfnl_nft_rule *)obj;
struct netlink_parse_ctx _ctx, *pctx = &_ctx;
struct handle h;
@@ -707,15 +749,15 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
_ctx.msgs = ctx->msgs;
memset(&h, 0, sizeof(h));
- h.family = nfnl_nft_rule_get_family(nlr);
- h.table = xstrdup(nfnl_nft_rule_get_table(nlr));
- h.chain = xstrdup(nfnl_nft_rule_get_chain(nlr));
- h.handle = nfnl_nft_rule_get_handle(nlr);
+ h.family = nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY);
+ h.table = xstrdup(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_TABLE));
+ h.chain = xstrdup(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_CHAIN));
+ h.handle = nft_rule_attr_get_u64(nlr, NFT_RULE_ATTR_HANDLE);
pctx->rule = rule_alloc(&internal_location, &h);
pctx->table = table_lookup(&h);
assert(pctx->table != NULL);
- nfnl_nft_rule_foreach_expr(nlr, netlink_parse_expr, pctx);
+ nft_rule_expr_foreach((struct nft_rule *)nlr, netlink_parse_expr, pctx);
rule_parse_postprocess(pctx, pctx->rule);
return pctx->rule;