diff options
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r-- | src/netlink_delinearize.c | 190 |
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; |