diff options
Diffstat (limited to 'src/regs.c')
-rw-r--r-- | src/regs.c | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/src/regs.c b/src/regs.c deleted file mode 100644 index 1551aa7..0000000 --- a/src/regs.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * (C) 2012-2022 by 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 as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/* Funded through the NGI0 PET Fund established by NLnet (https://nlnet.nl) - * with support from the European Commission's Next Generation Internet - * programme. - */ - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <errno.h> -#include <assert.h> - -#include <libnftnl/regs.h> - -#include "internal.h" - -EXPORT_SYMBOL(nftnl_regs_alloc); -struct nftnl_regs *nftnl_regs_alloc(uint32_t num_regs) -{ - struct nftnl_regs *regs; - - if (num_regs < 16) - num_regs = 16; - - regs = calloc(1, sizeof(struct nftnl_regs)); - if (!regs) - return NULL; - - regs->reg = calloc(num_regs, sizeof(struct nftnl_reg)); - if (!regs->reg) { - free(regs->reg); - return NULL; - } - - regs->num_regs = num_regs; - - return regs; -} - -EXPORT_SYMBOL(nftnl_regs_free); -void nftnl_regs_free(const struct nftnl_regs *regs) -{ - xfree(regs->reg); - xfree(regs); -} - -static enum nftnl_expr_type nftnl_expr_type(const struct nftnl_expr *expr) -{ - if (!strcmp(expr->ops->name, "ct")) - return NFT_EXPR_CT; - else if (!strcmp(expr->ops->name, "exthdr")) - return NFT_EXPR_EXTHDR; - else if (!strcmp(expr->ops->name, "fib")) - return NFT_EXPR_FIB; - else if (!strcmp(expr->ops->name, "meta")) - return NFT_EXPR_META; - else if (!strcmp(expr->ops->name, "osf")) - return NFT_EXPR_OSF; - else if (!strcmp(expr->ops->name, "payload")) - return NFT_EXPR_PAYLOAD; - else if (!strcmp(expr->ops->name, "rt")) - return NFT_EXPR_RT; - else if (!strcmp(expr->ops->name, "socket")) - return NFT_EXPR_SOCKET; - else if (!strcmp(expr->ops->name, "xfrm")) - return NFT_EXPR_XFRM; - - assert(0); - return NFT_EXPR_UNSPEC; -} - -static int nftnl_expr_reg_len(const struct nftnl_expr *expr) -{ - return expr->ops->reg.len(expr); -} - -static bool nftnl_expr_reg_cmp(const struct nftnl_regs *regs, - const struct nftnl_expr *expr, int i) -{ - if (regs->reg[i].type != nftnl_expr_type(expr)) - return false; - - return expr->ops->reg.cmp(®s->reg[i], expr); -} - -static void nft_expr_reg_update(struct nftnl_regs *regs, - const struct nftnl_expr *expr, int i) -{ - return expr->ops->reg.update(®s->reg[i], expr); -} - -static int reg_space(const struct nftnl_regs *regs, int i) -{ - return sizeof(uint32_t) * regs->num_regs - sizeof(uint32_t) * i; -} - -struct nftnl_reg_ctx { - uint64_t genid; - int reg; - int evict; -}; - -static void register_track(struct nftnl_reg_ctx *ctx, - const struct nftnl_regs *regs, int i, int len) -{ - if (ctx->reg >= 0 || regs->reg[i].word || reg_space(regs, i) < len) - return; - - if (regs->reg[i].type == NFT_EXPR_UNSPEC) { - ctx->genid = regs->genid; - ctx->reg = i; - } else if (regs->reg[i].genid < ctx->genid) { - ctx->genid = regs->reg[i].genid; - ctx->evict = i; - } -} - -static void register_evict(struct nftnl_reg_ctx *ctx) -{ - if (ctx->reg < 0) { - assert(ctx->evict >= 0); - ctx->reg = ctx->evict; - } -} - -static void __register_update(struct nftnl_regs *regs, uint8_t reg, - int type, uint32_t len, uint8_t word, - uint64_t genid, const struct nftnl_expr *expr) -{ - regs->reg[reg].type = type; - regs->reg[reg].genid = genid; - regs->reg[reg].len = len; - regs->reg[reg].word = word; - nft_expr_reg_update(regs, expr, reg); -} - -static void __register_cancel(struct nftnl_regs *regs, int i) -{ - regs->reg[i].type = NFT_EXPR_UNSPEC; - regs->reg[i].word = 0; - regs->reg[i].len = 0; - regs->reg[i].genid = 0; -} - -static void register_cancel(struct nftnl_reg_ctx *ctx, struct nftnl_regs *regs, - int len) -{ - int i; - - for (i = ctx->reg; len > 0; i++, len -= sizeof(uint32_t)) { - if (regs->reg[i].type == NFT_EXPR_UNSPEC) - continue; - - __register_cancel(regs, i); - } - - while (i < regs->num_regs && regs->reg[i].word != 0) { - __register_cancel(regs, i); - i++; - } -} - -static void register_update(struct nftnl_reg_ctx *ctx, struct nftnl_regs *regs, - int type, uint32_t len, uint64_t genid, - const struct nftnl_expr *expr) -{ - register_cancel(ctx, regs, len); - __register_update(regs, ctx->reg, type, len, 0, genid, expr); -} - -static uint64_t reg_genid(struct nftnl_regs *regs) -{ - return ++regs->genid; -} - -EXPORT_SYMBOL(nftnl_reg_get); -uint32_t nftnl_reg_get(struct nftnl_regs *regs, const struct nftnl_expr *expr) -{ - struct nftnl_reg_ctx ctx = { - .reg = -1, - .evict = -1, - .genid = UINT64_MAX, - }; - enum nftnl_expr_type type; - uint64_t genid; - int i, j, len; - - type = nftnl_expr_type(expr); - len = nftnl_expr_reg_len(expr); - - for (i = 0; i < regs->num_regs; i++) { - register_track(&ctx, regs, i, len); - - if (!nftnl_expr_reg_cmp(regs, expr, i)) - continue; - - regs->reg[i].genid = reg_genid(regs); - return i + NFT_REG32_00; - } - - register_evict(&ctx); - genid = reg_genid(regs); - register_update(&ctx, regs, type, len, genid, expr); - - len -= sizeof(uint32_t); - j = 1; - for (i = ctx.reg + 1; len > 0; i++, len -= sizeof(uint32_t)) - __register_update(regs, i, type, len, j++, genid, expr); - - return ctx.reg + NFT_REG32_00; -} - -EXPORT_SYMBOL(nftnl_reg_get_scratch); -uint32_t nftnl_reg_get_scratch(struct nftnl_regs *regs, uint32_t len) -{ - struct nftnl_reg_ctx ctx = { - .reg = -1, - .evict = -1, - .genid = UINT64_MAX, - }; - int i; - - for (i = 0; i < regs->num_regs; i++) - register_track(&ctx, regs, i, len); - - register_evict(&ctx); - register_cancel(&ctx, regs, len); - - return ctx.reg + NFT_REG32_00; -} |