summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2020-08-20 18:21:37 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2020-08-26 18:52:28 +0200
commit913979f882d13360cba11fd4402d193d74b0396a (patch)
tree57a4d6846407b1457332cdcd113965a0c7644b9f /src
parentcf456cdf82b9ee64c53a23cc64cf231d58bce452 (diff)
src: add expression handler hashtable
netlink_parsers is actually small, but update this code to use a hashtable instead since more expressions may come in the future. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/libnftables.c2
-rw-r--r--src/netlink_delinearize.c46
2 files changed, 38 insertions, 10 deletions
diff --git a/src/libnftables.c b/src/libnftables.c
index 668e3fc4..fce52ad4 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -88,10 +88,12 @@ static void nft_init(struct nft_ctx *ctx)
realm_table_rt_init(ctx);
devgroup_table_init(ctx);
ct_label_table_init(ctx);
+ expr_handler_init();
}
static void nft_exit(struct nft_ctx *ctx)
{
+ expr_handler_exit();
ct_label_table_exit(ctx);
realm_table_rt_exit(ctx);
devgroup_table_exit(ctx);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 9e3ed53d..43d7ff82 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -27,6 +27,7 @@
#include <erec.h>
#include <sys/socket.h>
#include <libnftnl/udata.h>
+#include <cache.h>
#include <xt.h>
static int netlink_parse_expr(const struct nftnl_expr *nle,
@@ -1627,12 +1628,14 @@ static void netlink_parse_objref(struct netlink_parse_ctx *ctx,
ctx->stmt = stmt;
}
-static const struct {
+struct expr_handler {
const char *name;
void (*parse)(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle);
-} netlink_parsers[] = {
+};
+
+static const struct expr_handler netlink_parsers[] = {
{ .name = "immediate", .parse = netlink_parse_immediate },
{ .name = "cmp", .parse = netlink_parse_cmp },
{ .name = "lookup", .parse = netlink_parse_lookup },
@@ -1673,25 +1676,48 @@ static const struct {
{ .name = "synproxy", .parse = netlink_parse_synproxy },
};
+static const struct expr_handler **expr_handle_ht;
+
+#define NFT_EXPR_HSIZE 4096
+
+void expr_handler_init(void)
+{
+ unsigned int i;
+ uint32_t hash;
+
+ expr_handle_ht = calloc(NFT_EXPR_HSIZE, sizeof(expr_handle_ht));
+ if (!expr_handle_ht)
+ memory_allocation_error();
+
+ for (i = 0; i < array_size(netlink_parsers); i++) {
+ hash = djb_hash(netlink_parsers[i].name) % NFT_EXPR_HSIZE;
+ assert(expr_handle_ht[hash] == NULL);
+ expr_handle_ht[hash] = &netlink_parsers[i];
+ }
+}
+
+void expr_handler_exit(void)
+{
+ xfree(expr_handle_ht);
+}
+
static int netlink_parse_expr(const struct nftnl_expr *nle,
struct netlink_parse_ctx *ctx)
{
const char *type = nftnl_expr_get_str(nle, NFTNL_EXPR_NAME);
struct location loc;
- unsigned int i;
+ uint32_t hash;
memset(&loc, 0, sizeof(loc));
loc.indesc = &indesc_netlink;
loc.nle = nle;
- for (i = 0; i < array_size(netlink_parsers); i++) {
- if (strcmp(type, netlink_parsers[i].name))
- continue;
- netlink_parsers[i].parse(ctx, &loc, nle);
- return 0;
- }
+ hash = djb_hash(type) % NFT_EXPR_HSIZE;
+ if (expr_handle_ht[hash])
+ expr_handle_ht[hash]->parse(ctx, &loc, nle);
+ else
+ netlink_error(ctx, &loc, "unknown expression type '%s'", type);
- netlink_error(ctx, &loc, "unknown expression type '%s'", type);
return 0;
}