summaryrefslogtreecommitdiffstats
path: root/src/netlink.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.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.c')
-rw-r--r--src/netlink.c846
1 files changed, 419 insertions, 427 deletions
diff --git a/src/netlink.c b/src/netlink.c
index da290d58..d835281c 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008-2012 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,59 +9,39 @@
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*/
-#include <netlink/netfilter/nfnl.h>
-#include <netlink/netfilter/netfilter.h>
-#include <netlink/netfilter/nft_table.h>
-#include <netlink/netfilter/nft_chain.h>
-#include <netlink/netfilter/nft_rule.h>
-#include <netlink/netfilter/nft_expr.h>
-#include <netlink/netfilter/nft_data.h>
-#include <netlink/netfilter/nft_setelem.h>
-#include <netlink/netfilter/nft_set.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libmnl/libmnl.h>
+
+#include <libnftables/table.h>
+#include <libnftables/chain.h>
+#include <libnftables/expr.h>
+#include <libnftables/set.h>
#include <linux/netfilter/nf_tables.h>
#include <nftables.h>
#include <netlink.h>
+#include <mnl.h>
#include <expression.h>
#include <gmputil.h>
#include <utils.h>
#include <erec.h>
-static struct nl_sock *nf_sock;
+static struct mnl_socket *nf_sock;
static void __init netlink_open_sock(void)
{
- nlmsg_set_default_size(65536);
- nf_sock = nl_socket_alloc();
+ nf_sock = mnl_socket_open(NETLINK_NETFILTER);
if (nf_sock == NULL)
memory_allocation_error();
- nfnl_connect(nf_sock);
- nl_socket_set_nonblocking(nf_sock);
+ fcntl(mnl_socket_get_fd(nf_sock), F_SETFL, O_NONBLOCK);
}
static void __exit netlink_close_sock(void)
{
- nl_socket_free(nf_sock);
-}
-
-static void netlink_set_callback(nl_recvmsg_msg_cb_t func, void *arg)
-{
- nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, func, arg);
-}
-
-void netlink_dump_object(struct nl_object *obj)
-{
-#ifdef DEBUG
- struct nl_dump_params params = {
- .dp_fd = stdout,
- .dp_type = NL_DUMP_DETAILS,
- };
-
- if (!(debug_level & DEBUG_NETLINK))
- return;
- nl_object_dump(obj, &params);
-#endif
+ mnl_socket_close(nf_sock);
}
static int netlink_io_error(struct netlink_ctx *ctx, const struct location *loc,
@@ -79,119 +60,128 @@ static int netlink_io_error(struct netlink_ctx *ctx, const struct location *loc,
return -1;
}
-struct nfnl_nft_table *alloc_nft_table(const struct handle *h)
+struct nft_table *alloc_nft_table(const struct handle *h)
{
- struct nfnl_nft_table *nlt;
+ struct nft_table *nlt;
- nlt = nfnl_nft_table_alloc();
+ nlt = nft_table_alloc();
if (nlt == NULL)
memory_allocation_error();
- nfnl_nft_table_set_family(nlt, h->family);
+
+ nft_table_attr_set_u32(nlt, NFT_TABLE_ATTR_FAMILY, h->family);
if (h->table != NULL)
- nfnl_nft_table_set_name(nlt, h->table, strlen(h->table) + 1);
+ nft_table_attr_set(nlt, NFT_TABLE_ATTR_NAME, h->table);
return nlt;
}
-struct nfnl_nft_chain *alloc_nft_chain(const struct handle *h)
+struct nft_chain *alloc_nft_chain(const struct handle *h)
{
- struct nfnl_nft_chain *nlc;
+ struct nft_chain *nlc;
- nlc = nfnl_nft_chain_alloc();
+ nlc = nft_chain_alloc();
if (nlc == NULL)
memory_allocation_error();
- nfnl_nft_chain_set_family(nlc, h->family);
- nfnl_nft_chain_set_table(nlc, h->table, strlen(h->table) + 1);
+
+ nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_FAMILY, h->family);
+ nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_TABLE, h->table);
if (h->handle != 0)
- nfnl_nft_chain_set_handle(nlc, h->handle);
+ nft_chain_attr_set_u64(nlc, NFT_CHAIN_ATTR_HANDLE, h->handle);
if (h->chain != NULL)
- nfnl_nft_chain_set_name(nlc, h->chain, strlen(h->chain) + 1);
+ nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_NAME, h->chain);
return nlc;
}
-struct nfnl_nft_rule *alloc_nft_rule(const struct handle *h)
+struct nft_rule *alloc_nft_rule(const struct handle *h)
{
- struct nfnl_nft_rule *nlr;
+ struct nft_rule *nlr;
- nlr = nfnl_nft_rule_alloc();
+ nlr = nft_rule_alloc();
if (nlr == NULL)
memory_allocation_error();
- nfnl_nft_rule_set_family(nlr, h->family);
- nfnl_nft_rule_set_table(nlr, h->table, strlen(h->table) + 1);
+
+ nft_rule_attr_set_u32(nlr, NFT_RULE_ATTR_FAMILY, h->family);
+ nft_rule_attr_set_str(nlr, NFT_RULE_ATTR_TABLE, h->table);
if (h->chain != NULL)
- nfnl_nft_rule_set_chain(nlr, h->chain, strlen(h->chain) + 1);
+ nft_rule_attr_set_str(nlr, NFT_RULE_ATTR_CHAIN, h->chain);
if (h->handle)
- nfnl_nft_rule_set_handle(nlr, h->handle);
+ nft_rule_attr_set_u64(nlr, NFT_RULE_ATTR_HANDLE, h->handle);
return nlr;
}
-struct nfnl_nft_expr *alloc_nft_expr(int (*init)(struct nfnl_nft_expr *))
+struct nft_rule_expr *alloc_nft_expr(const char *name)
{
- struct nfnl_nft_expr *nle;
+ struct nft_rule_expr *nle;
- nle = nfnl_nft_expr_alloc();
- if (nle == NULL || init(nle) != 0)
+ nle = nft_rule_expr_alloc(name);
+ if (nle == NULL)
memory_allocation_error();
return nle;
}
-struct nfnl_nft_set *alloc_nft_set(const struct handle *h)
+struct nft_set *alloc_nft_set(const struct handle *h)
{
- struct nfnl_nft_set *nls;
+ struct nft_set *nls;
- nls = nfnl_nft_set_alloc();
+ nls = nft_set_alloc();
if (nls == NULL)
memory_allocation_error();
- nfnl_nft_set_set_family(nls, h->family);
- nfnl_nft_set_set_table(nls, h->table, strlen(h->table) + 1);
+
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_FAMILY, h->family);
+ nft_set_attr_set_str(nls, NFT_SET_ATTR_TABLE, h->table);
if (h->set != NULL)
- nfnl_nft_set_set_name(nls, h->set, strlen(h->set) + 1);
+ nft_set_attr_set_str(nls, NFT_SET_ATTR_NAME, h->set);
+
return nls;
}
-static struct nfnl_nft_setelem *alloc_nft_setelem(const struct expr *expr)
+static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr)
{
- struct nfnl_nft_setelem *nlse;
+ struct nft_set_elem *nlse;
+ struct nft_data_linearize nld;
- nlse = nfnl_nft_setelem_alloc();
+ nlse = nft_set_elem_alloc();
if (nlse == NULL)
memory_allocation_error();
- if (expr->ops->type == EXPR_VALUE || expr->flags & EXPR_F_INTERVAL_END)
- nfnl_nft_setelem_set_key(nlse, netlink_gen_data(expr));
- else {
+ if (expr->ops->type == EXPR_VALUE ||
+ expr->flags & EXPR_F_INTERVAL_END) {
+ netlink_gen_data(expr, &nld);
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY,
+ &nld.value, nld.len);
+ } else {
assert(expr->ops->type == EXPR_MAPPING);
- nfnl_nft_setelem_set_key(nlse, netlink_gen_data(expr->left));
- nfnl_nft_setelem_set_data(nlse, netlink_gen_data(expr->right));
+ netlink_gen_data(expr->left, &nld);
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY,
+ &nld.value, nld.len);
+ netlink_gen_data(expr->right, &nld);
+ if (expr->right->ops->type == EXPR_VERDICT) {
+ nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT,
+ expr->right->verdict);
+ if (expr->chain != NULL) {
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_CHAIN,
+ nld.chain, strlen(nld.chain));
+ }
+ }
}
- if (expr->flags & EXPR_F_INTERVAL_END)
- nfnl_nft_setelem_set_flags(nlse, NFT_SET_ELEM_INTERVAL_END);
+ if (expr->flags & EXPR_F_INTERVAL_END) {
+ nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_FLAGS,
+ NFT_SET_ELEM_INTERVAL_END);
+ }
return nlse;
}
-struct nfnl_nft_data *alloc_nft_data(const void *data, unsigned int len)
+void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder,
+ unsigned int len, struct nft_data_linearize *data)
{
- struct nfnl_nft_data *nld;
-
assert(len > 0);
- nld = nfnl_nft_data_alloc(data, len);
- if (nld == NULL)
- memory_allocation_error();
- return nld;
+ mpz_export_data(data->value, value, byteorder, len);
+ data->len = len;
}
-struct nfnl_nft_data *netlink_gen_raw_data(const mpz_t value,
- enum byteorder byteorder,
- unsigned int len)
-{
- unsigned char data[len];
-
- mpz_export_data(data, value, byteorder, len);
- return alloc_nft_data(data, len);
-}
-
-static struct nfnl_nft_data *netlink_gen_concat_data(const struct expr *expr)
+static void netlink_gen_concat_data(const struct expr *expr,
+ struct nft_data_linearize *nld)
{
const struct expr *i;
unsigned int len, offset;
@@ -210,79 +200,75 @@ static struct nfnl_nft_data *netlink_gen_concat_data(const struct expr *expr)
i->len / BITS_PER_BYTE);
offset += i->len / BITS_PER_BYTE;
}
-
- return alloc_nft_data(data, len / BITS_PER_BYTE);
+
+ memcpy(nld->value, data, len / BITS_PER_BYTE);
+ nld->len = len;
}
}
-static struct nfnl_nft_data *netlink_gen_constant_data(const struct expr *expr)
+static void netlink_gen_constant_data(const struct expr *expr,
+ struct nft_data_linearize *data)
{
assert(expr->ops->type == EXPR_VALUE);
- return netlink_gen_raw_data(expr->value, expr->byteorder,
- div_round_up(expr->len, BITS_PER_BYTE));
+ netlink_gen_raw_data(expr->value, expr->byteorder,
+ div_round_up(expr->len, BITS_PER_BYTE), data);
}
-static struct nfnl_nft_data *netlink_gen_verdict(const struct expr *expr)
+static void netlink_gen_verdict(const struct expr *expr,
+ struct nft_data_linearize *data)
{
- struct nfnl_nft_data *verdict;
-
- verdict = nfnl_nft_verdict_alloc();
- nfnl_nft_verdict_set_verdict(verdict, expr->verdict);
+ data->verdict = expr->verdict;
switch (expr->verdict) {
case NFT_JUMP:
case NFT_GOTO:
- nfnl_nft_verdict_set_chain(verdict, expr->chain);
+ strncpy(data->chain, expr->chain, NFT_CHAIN_MAXNAMELEN);
+ data->chain[NFT_CHAIN_MAXNAMELEN-1] = '\0';
break;
}
-
- return verdict;
}
-struct nfnl_nft_data *netlink_gen_data(const struct expr *expr)
+void netlink_gen_data(const struct expr *expr, struct nft_data_linearize *data)
{
switch (expr->ops->type) {
case EXPR_VALUE:
- return netlink_gen_constant_data(expr);
+ return netlink_gen_constant_data(expr, data);
case EXPR_CONCAT:
- return netlink_gen_concat_data(expr);
+ return netlink_gen_concat_data(expr, data);
case EXPR_VERDICT:
- return netlink_gen_verdict(expr);
+ return netlink_gen_verdict(expr, data);
default:
BUG("invalid data expression type %s\n", expr->ops->name);
}
}
struct expr *netlink_alloc_value(const struct location *loc,
- const struct nfnl_nft_data *nld)
+ const struct nft_data_delinearize *nld)
{
return constant_expr_alloc(loc, &invalid_type, BYTEORDER_INVALID,
- nfnl_nft_data_get_size(nld) * BITS_PER_BYTE,
- nfnl_nft_data_get(nld));
+ nld->len * BITS_PER_BYTE, nld->value);
}
static struct expr *netlink_alloc_verdict(const struct location *loc,
- const struct nfnl_nft_data *nld)
+ const struct nft_data_delinearize *nld)
{
- unsigned int code;
char *chain;
- code = nfnl_nft_verdict_get_verdict(nld);
- switch (code) {
+ switch (nld->verdict) {
case NFT_JUMP:
case NFT_GOTO:
- chain = xstrdup(nfnl_nft_verdict_get_chain(nld));
+ chain = xstrdup(nld->chain);
break;
default:
chain = NULL;
break;
}
- return verdict_expr_alloc(loc, code, chain);
+ return verdict_expr_alloc(loc, nld->verdict, chain);
}
struct expr *netlink_alloc_data(const struct location *loc,
- const struct nfnl_nft_data *nld,
+ const struct nft_data_delinearize *nld,
enum nft_registers dreg)
{
switch (dreg) {
@@ -296,230 +282,246 @@ struct expr *netlink_alloc_data(const struct location *loc,
int netlink_add_rule(struct netlink_ctx *ctx, const struct handle *h,
const struct rule *rule, uint32_t flags)
{
- struct nfnl_nft_rule *nlr;
+ struct nft_rule *nlr;
int err;
nlr = alloc_nft_rule(&rule->handle);
err = netlink_linearize_rule(ctx, nlr, rule);
if (err == 0) {
- err = nfnl_nft_rule_add(nf_sock, nlr, flags | NLM_F_EXCL);
+ err = mnl_nft_rule_add(nf_sock, nlr, flags | NLM_F_EXCL);
if (err < 0)
netlink_io_error(ctx, &rule->location,
- "Could not add rule: %s", nl_geterror(err));
+ "Could not add rule: %s",
+ strerror(errno));
}
- nfnl_nft_rule_put(nlr);
+ nft_rule_free(nlr);
return err;
}
int netlink_delete_rule(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_rule *nlr;
+ struct nft_rule *nlr;
int err;
nlr = alloc_nft_rule(h);
- err = nfnl_nft_rule_delete(nf_sock, nlr, 0);
- nfnl_nft_rule_put(nlr);
+ err = mnl_nft_rule_delete(nf_sock, nlr, 0);
+ nft_rule_free(nlr);
if (err < 0)
netlink_io_error(ctx, loc, "Could not delete rule: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
-static void list_rule_cb(struct nl_object *obj, void *arg)
+void netlink_dump_rule(struct nft_rule *nlr)
{
- const struct nfnl_nft_rule *nlr = (struct nfnl_nft_rule *)obj;
- struct netlink_ctx *ctx = arg;
- struct rule *rule;
+#ifdef DEBUG
+ char buf[4096];
- netlink_dump_object(obj);
- if (!nfnl_nft_rule_test_family(nlr) ||
- !nfnl_nft_rule_test_table(nlr) ||
- !nfnl_nft_rule_test_chain(nlr) ||
- !nfnl_nft_rule_test_handle(nlr)) {
- netlink_io_error(ctx, NULL, "Incomplete rule received");
+ if (!(debug_level & DEBUG_NETLINK))
return;
- }
- rule = netlink_delinearize_rule(ctx, obj);
- list_add_tail(&rule->list, &ctx->list);
+ nft_rule_snprintf(buf, sizeof(buf), nlr, 0, 0);
+ fprintf(stderr, "%s\n", buf);
+#endif
}
-static int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc)
+void netlink_dump_expr(struct nft_rule_expr *nle)
{
- struct nl_cache *rule_cache;
- struct nfnl_nft_rule *nlr;
- int err;
+#ifdef DEBUG
+ char buf[4096];
- err = nfnl_nft_rule_alloc_cache(nf_sock, &rule_cache);
- if (err < 0)
- return netlink_io_error(ctx, loc,
- "Could not receive rules from kernel: %s",
- nl_geterror(err));
+ if (!(debug_level & DEBUG_NETLINK))
+ return;
- nlr = alloc_nft_rule(h);
- nl_cache_foreach_filter(rule_cache, OBJ_CAST(nlr), list_rule_cb, ctx);
- nfnl_nft_rule_put(nlr);
- nl_cache_free(rule_cache);
- return 0;
+ nft_rule_expr_snprintf(buf, sizeof(buf), nle, 0, 0);
+ fprintf(stderr, "%s\n", buf);
+#endif
}
-static int netlink_get_rule_cb(struct nl_msg *msg, void *arg)
+static int list_rule_cb(struct nft_rule *nlr, void *arg)
{
- return nl_msg_parse(msg, list_rule_cb, arg);
+ struct netlink_ctx *ctx = arg;
+ const struct handle *h = ctx->data;
+ struct rule *rule;
+
+ if ((h->family != nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY)) ||
+ strcmp(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_TABLE), h->table) != 0 ||
+ (h->chain &&
+ strcmp(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_CHAIN), h->chain) != 0))
+ return 0;
+
+ netlink_dump_rule(nlr);
+ rule = netlink_delinearize_rule(ctx, nlr);
+ list_add_tail(&rule->list, &ctx->list);
+
+ return 0;
}
-int netlink_get_rule(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc)
+static int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h,
+ const struct location *loc)
{
- struct nfnl_nft_rule *nlr;
- int err;
-
- nlr = alloc_nft_rule(h);
- netlink_set_callback(netlink_get_rule_cb, ctx);
- err = nfnl_nft_rule_query(nf_sock, nlr, 0);
- if (err == 0)
- err = nl_recvmsgs_default(nf_sock);
- nfnl_nft_rule_put(nlr);
+ struct nft_rule_list *rule_cache;
- if (err < 0)
+ rule_cache = mnl_nft_rule_dump(nf_sock, h->family);
+ if (rule_cache == NULL)
return netlink_io_error(ctx, loc,
- "Could not receive rule from kernel: %s",
- nl_geterror(err));
- return err;
+ "Could not receive rules from kernel: %s",
+ strerror(errno));
+
+ ctx->data = h;
+ nft_rule_list_foreach(rule_cache, list_rule_cb, ctx);
+ nft_rule_list_free(rule_cache);
+ return 0;
}
-static void flush_rule_cb(struct nl_object *obj, void *arg)
+static int flush_rule_cb(struct nft_rule *nlr, void *arg)
{
struct netlink_ctx *ctx = arg;
int err;
- netlink_dump_object(obj);
- err = nfnl_nft_rule_delete(nf_sock, (struct nfnl_nft_rule *)obj, 0);
- if (err < 0)
+ netlink_dump_rule(nlr);
+ err = mnl_nft_rule_delete(nf_sock, nlr, 0);
+ if (err < 0) {
netlink_io_error(ctx, NULL, "Could not delete rule: %s",
- nl_geterror(err));
+ strerror(errno));
+ return err;
+ }
+ return 0;
}
static int netlink_flush_rules(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nl_cache *rule_cache;
- struct nfnl_nft_rule *nlr;
- int err;
+ struct nft_rule_list *rule_cache;
+ struct nft_rule *nlr;
- err = nfnl_nft_rule_alloc_cache(nf_sock, &rule_cache);
- if (err < 0)
+ rule_cache = mnl_nft_rule_dump(nf_sock, h->family);
+ if (rule_cache == NULL)
return netlink_io_error(ctx, loc,
"Could not receive rules from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
nlr = alloc_nft_rule(h);
- nl_cache_foreach_filter(rule_cache, OBJ_CAST(nlr), flush_rule_cb, ctx);
- nfnl_nft_rule_put(nlr);
- nl_cache_free(rule_cache);
+ nft_rule_list_foreach(rule_cache, flush_rule_cb, ctx);
+ nft_rule_free(nlr);
+ nft_rule_list_free(rule_cache);
return 0;
}
+void netlink_dump_chain(struct nft_chain *nlc)
+{
+#ifdef DEBUG
+ char buf[4096];
+
+ if (!(debug_level & DEBUG_NETLINK))
+ return;
+
+ nft_chain_snprintf(buf, sizeof(buf), nlc, 0, 0);
+ fprintf(stderr, "%s\n", buf);
+#endif
+}
+
int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, const struct chain *chain)
{
- struct nfnl_nft_chain *nlc;
+ struct nft_chain *nlc;
int err;
nlc = alloc_nft_chain(h);
if (chain != NULL && chain->flags & CHAIN_F_BASECHAIN) {
- nfnl_nft_chain_set_hooknum(nlc, chain->hooknum);
- nfnl_nft_chain_set_priority(nlc, chain->priority);
+ nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_HOOKNUM,
+ chain->hooknum);
+ nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_PRIO,
+ chain->priority);
}
- netlink_dump_object(OBJ_CAST(nlc));
- err = nfnl_nft_chain_add(nf_sock, nlc, NLM_F_EXCL);
- nfnl_nft_chain_put(nlc);
+ netlink_dump_chain(nlc);
+ err = mnl_nft_chain_add(nf_sock, nlc, NLM_F_EXCL);
+ nft_chain_free(nlc);
if (err < 0)
netlink_io_error(ctx, loc, "Could not add chain: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
int netlink_rename_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, const char *name)
{
- struct nfnl_nft_chain *nlc;
+ struct nft_chain *nlc;
int err;
nlc = alloc_nft_chain(h);
- nfnl_nft_chain_set_name(nlc, name, strlen(name) + 1);
- netlink_dump_object(OBJ_CAST(nlc));
- err = nfnl_nft_chain_add(nf_sock, nlc, 0);
- nfnl_nft_chain_put(nlc);
+ nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_NAME, name);
+ netlink_dump_chain(nlc);
+ err = mnl_nft_chain_add(nf_sock, nlc, 0);
+ nft_chain_free(nlc);
if (err < 0)
netlink_io_error(ctx, loc, "Could not rename chain: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_chain *nlc;
+ struct nft_chain *nlc;
int err;
nlc = alloc_nft_chain(h);
- netlink_dump_object(OBJ_CAST(nlc));
- err = nfnl_nft_chain_delete(nf_sock, nlc, 0);
- nfnl_nft_chain_put(nlc);
+ netlink_dump_chain(nlc);
+ err = mnl_nft_chain_delete(nf_sock, nlc, 0);
+ nft_chain_free(nlc);
if (err < 0)
netlink_io_error(ctx, loc, "Could not delete chain: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
-static void list_chain_cb(struct nl_object *obj, void *arg)
+static int list_chain_cb(struct nft_chain *nlc, void *arg)
{
- struct nfnl_nft_chain *nlc = (struct nfnl_nft_chain *)obj;
struct netlink_ctx *ctx = arg;
+ const struct handle *h = ctx->data;
struct chain *chain;
- netlink_dump_object(obj);
- if (!nfnl_nft_chain_test_family(nlc) ||
- !nfnl_nft_chain_test_table(nlc) ||
- !nfnl_nft_chain_test_name(nlc)) {
- netlink_io_error(ctx, NULL, "Incomplete chain received");
- return;
- }
+ if ((h->family != nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY)) ||
+ strcmp(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_TABLE), h->table) != 0)
+ return 0;
- chain = chain_alloc(nfnl_nft_chain_get_name(nlc));
- chain->handle.family = nfnl_nft_chain_get_family(nlc);
- chain->handle.table = xstrdup(nfnl_nft_chain_get_table(nlc));
- chain->handle.handle = nfnl_nft_chain_get_handle(nlc);
- chain->hooknum = nfnl_nft_chain_get_hooknum(nlc);
- chain->priority = nfnl_nft_chain_get_priority(nlc);
+ chain = chain_alloc(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_NAME));
+ chain->handle.family =
+ nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY);
+ chain->handle.table =
+ xstrdup(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_NAME));
+ chain->handle.handle =
+ nft_chain_attr_get_u64(nlc, NFT_CHAIN_ATTR_HANDLE);
+ chain->hooknum =
+ nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_HOOKNUM);
+ chain->priority =
+ nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_PRIO);
list_add_tail(&chain->list, &ctx->list);
+
+ return 0;
}
int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nl_cache *chain_cache;
- struct nfnl_nft_chain *nlc;
+ struct nft_chain_list *chain_cache;
struct chain *chain;
- int err;
- err = nfnl_nft_chain_alloc_cache(nf_sock, &chain_cache);
- if (err < 0)
+ chain_cache = mnl_nft_chain_dump(nf_sock, h->family);
+ if (chain_cache == NULL)
return netlink_io_error(ctx, loc,
"Could not receive chains from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
- nlc = alloc_nft_chain(h);
- nl_cache_foreach_filter(chain_cache, OBJ_CAST(nlc), list_chain_cb, ctx);
- nfnl_nft_chain_put(nlc);
- nl_cache_free(chain_cache);
+ ctx->data = h;
+ nft_chain_list_foreach(chain_cache, list_chain_cb, ctx);
+ nft_chain_list_free(chain_cache);
/* Caller wants all existing chains */
if (h->chain == NULL)
@@ -534,32 +536,33 @@ int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h,
return netlink_io_error(ctx, NULL,
"Could not find chain `%s' in table `%s': %s",
h->chain, h->table,
- nl_geterror(NLE_OBJ_NOTFOUND));
-}
-
-static int netlink_get_chain_cb(struct nl_msg *msg, void *arg)
-{
- return nl_msg_parse(msg, list_chain_cb, arg);
+ strerror(ENOENT));
}
int netlink_get_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_chain *nlc;
+ struct nft_chain *nlc;
+ struct chain *chain;
int err;
nlc = alloc_nft_chain(h);
- netlink_set_callback(netlink_get_chain_cb, ctx);
- err = nfnl_nft_chain_query(nf_sock, nlc, 0);
- if (err == 0)
- err = nl_recvmsgs_default(nf_sock);
- netlink_set_callback(NULL, NULL);
- nfnl_nft_chain_put(nlc);
+ err = mnl_nft_chain_get(nf_sock, nlc, 0);
+
+ chain = chain_alloc(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_NAME));
+ chain->handle.family = nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY);
+ chain->handle.table = xstrdup(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_TABLE));
+ chain->handle.handle = nft_chain_attr_get_u64(nlc, NFT_CHAIN_ATTR_HANDLE);
+ chain->hooknum = nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_HOOKNUM);
+ chain->priority = nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_PRIO);
+ list_add_tail(&chain->list, &ctx->list);
+
+ nft_chain_free(nlc);
if (err < 0)
return netlink_io_error(ctx, loc,
"Could not receive chain from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
@@ -578,96 +581,97 @@ int netlink_flush_chain(struct netlink_ctx *ctx, const struct handle *h,
int netlink_add_table(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, const struct table *table)
{
- struct nfnl_nft_table *nlt;
+ struct nft_table *nlt;
int err;
nlt = alloc_nft_table(h);
- err = nfnl_nft_table_add(nf_sock, nlt, NLM_F_EXCL);
- nfnl_nft_table_put(nlt);
+ err = mnl_nft_table_add(nf_sock, nlt, NLM_F_EXCL);
+ nft_table_free(nlt);
if (err < 0)
netlink_io_error(ctx, loc, "Could not add table: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
int netlink_delete_table(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_table *nlt;
+ struct nft_table *nlt;
int err;
nlt = alloc_nft_table(h);
- err = nfnl_nft_table_delete(nf_sock, nlt, 0);
- nfnl_nft_table_put(nlt);
+ err = mnl_nft_table_delete(nf_sock, nlt, 0);
+ nft_table_free(nlt);
if (err < 0)
netlink_io_error(ctx, loc, "Could not delete table: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
-static void list_table_cb(struct nl_object *obj, void *arg)
+void netlink_dump_table(struct nft_table *nlt)
{
- struct nfnl_nft_table *nlt = (struct nfnl_nft_table *)obj;
- struct netlink_ctx *ctx = arg;
- struct table *table;
+#ifdef DEBUG
+ char buf[4096];
- netlink_dump_object(obj);
- if (!nfnl_nft_table_test_family(nlt) ||
- !nfnl_nft_table_test_name(nlt)) {
- netlink_io_error(ctx, NULL, "Incomplete table received");
+ if (!(debug_level & DEBUG_NETLINK))
return;
- }
+ nft_table_snprintf(buf, sizeof(buf), nlt, 0, 0);
+ fprintf(stderr, "%s\n", buf);
+#endif
+}
+
+static int list_table_cb(struct nft_table *nlt, void *arg)
+{
+ struct netlink_ctx *ctx = arg;
+ struct table *table;
+
+ netlink_dump_table(nlt);
table = table_alloc();
- table->handle.family = nfnl_nft_table_get_family(nlt);
- table->handle.table = xstrdup(nfnl_nft_table_get_name(nlt));
+ table->handle.family =
+ nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY);
+ table->handle.table =
+ xstrdup(nft_table_attr_get_str(nlt, NFT_TABLE_ATTR_NAME));
list_add_tail(&table->list, &ctx->list);
+
+ return 0;
}
int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nl_cache *table_cache;
- struct nfnl_nft_table *nlt;
- int err;
+ struct nft_table_list *table_cache;
+ struct nft_table *nlt;
- err = nfnl_nft_table_alloc_cache(nf_sock, &table_cache);
- if (err < 0)
+ table_cache = mnl_nft_table_dump(nf_sock, h->family);
+ if (table_cache == NULL)
return netlink_io_error(ctx, loc,
"Could not receive tables from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
nlt = alloc_nft_table(h);
- nl_cache_foreach_filter(table_cache, OBJ_CAST(nlt), list_table_cb, ctx);
- nfnl_nft_table_put(nlt);
- nl_cache_free(table_cache);
+ nft_table_list_foreach(table_cache, list_table_cb, ctx);
+ nft_table_free(nlt);
+ nft_table_list_free(table_cache);
return 0;
}
-static int netlink_get_table_cb(struct nl_msg *msg, void *arg)
-{
- return nl_msg_parse(msg, list_table_cb, arg);
-}
-
int netlink_get_table(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_table *nlt;
+ struct nft_table *nlt;
int err;
nlt = alloc_nft_table(h);
- netlink_set_callback(netlink_get_table_cb, ctx);
- err = nfnl_nft_table_query(nf_sock, nlt, 0);
- if (err == 0)
- err = nl_recvmsgs_default(nf_sock);
- nfnl_nft_table_put(nlt);
+ err = mnl_nft_table_get(nf_sock, nlt, 0);
+ nft_table_free(nlt);
if (err < 0)
return netlink_io_error(ctx, loc,
"Could not receive table from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
@@ -704,268 +708,261 @@ static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
}
}
-static void add_set_cb(struct nl_object *obj, void *arg)
+void netlink_dump_set(struct nft_set *nls)
{
- struct nfnl_nft_set *nls = (struct nfnl_nft_set *)obj;
- struct netlink_ctx *ctx = arg;
- struct set *set = ctx->set;
+#ifdef DEBUG
+ char buf[4096];
- netlink_dump_object(OBJ_CAST(nls));
- set->handle.set = xstrdup(nfnl_nft_set_get_name(nls));
-}
+ if (!(debug_level & DEBUG_NETLINK))
+ return;
-static int netlink_add_set_cb(struct nl_msg *msg, void *arg)
-{
- return nl_msg_parse(msg, add_set_cb, arg);
+ nft_set_snprintf(buf, sizeof(buf), nls, 0, 0);
+ fprintf(stderr, "%s\n", buf);
+#endif
}
int netlink_add_set(struct netlink_ctx *ctx, const struct handle *h,
struct set *set)
{
- struct nfnl_nft_set *nls;
+ struct nft_set *nls;
int err;
nls = alloc_nft_set(h);
- nfnl_nft_set_set_flags(nls, set->flags);
- nfnl_nft_set_set_keytype(nls, dtype_map_to_kernel(set->keytype));
- nfnl_nft_set_set_keylen(nls, set->keylen / BITS_PER_BYTE);
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_FLAGS, set->flags);
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_KEY_TYPE,
+ dtype_map_to_kernel(set->keytype));
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_KEY_LEN,
+ set->keylen / BITS_PER_BYTE);
if (set->flags & NFT_SET_MAP) {
- nfnl_nft_set_set_datatype(nls, dtype_map_to_kernel(set->datatype));
- nfnl_nft_set_set_datalen(nls, set->datalen / BITS_PER_BYTE);
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_TYPE,
+ dtype_map_to_kernel(set->datatype));
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN,
+ set->datalen / BITS_PER_BYTE);
}
- netlink_dump_object(OBJ_CAST(nls));
-
- ctx->set = set;
- netlink_set_callback(netlink_add_set_cb, ctx);
- err = nfnl_nft_set_add(nf_sock, nls, NLM_F_EXCL | NLM_F_ECHO);
- if (err == 0)
- err = nl_recvmsgs_default(nf_sock);
- netlink_set_callback(NULL, NULL);
- nfnl_nft_set_put(nls);
- ctx->set = NULL;
+ netlink_dump_set(nls);
+ err = mnl_nft_set_add(nf_sock, nls, NLM_F_EXCL | NLM_F_ECHO);
if (err < 0)
netlink_io_error(ctx, NULL, "Could not add set: %s",
- nl_geterror(err));
+ strerror(errno));
+
+ set->handle.set =
+ xstrdup(nft_set_attr_get_str(nls, NFT_SET_ATTR_NAME));
+ nft_set_free(nls);
+
return err;
}
int netlink_delete_set(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_set *nls;
+ struct nft_set *nls;
int err;
nls = alloc_nft_set(h);
- err = nfnl_nft_set_delete(nf_sock, nls, 0);
- nfnl_nft_set_put(nls);
+ err = mnl_nft_set_delete(nf_sock, nls, 0);
+ nft_set_free(nls);
if (err < 0)
netlink_io_error(ctx, loc, "Could not delete set: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
-static void list_set_cb(struct nl_object *obj, void *arg)
+static int list_set_cb(struct nft_set *nls, void *arg)
{
- struct nfnl_nft_set *nls = (struct nfnl_nft_set *)obj;
struct netlink_ctx *ctx = arg;
const struct datatype *keytype, *datatype;
- uint32_t flags;
+ uint32_t flags, key, data;
struct set *set;
- netlink_dump_object(obj);
- if (!nfnl_nft_set_test_family(nls) ||
- !nfnl_nft_set_test_table(nls) ||
- !nfnl_nft_set_test_name(nls) ||
- !nfnl_nft_set_test_keytype(nls) ||
- !nfnl_nft_set_test_keylen(nls)) {
- netlink_io_error(ctx, NULL, "Incomplete set received");
- return;
- }
-
- keytype = dtype_map_from_kernel(nfnl_nft_set_get_keytype(nls));
+ netlink_dump_set(nls);
+ key = nft_set_attr_get_u32(nls, NFT_SET_ATTR_KEY_TYPE);
+ keytype = dtype_map_from_kernel(key);
if (keytype == NULL) {
netlink_io_error(ctx, NULL, "Unknown data type in set key %u",
- nfnl_nft_set_get_keytype(nls));
- return;
+ key);
+ return -1;
}
- flags = nfnl_nft_set_get_flags(nls);
+ flags = nft_set_attr_get_u32(nls, NFT_SET_ATTR_FLAGS);
if (flags & NFT_SET_MAP) {
- datatype = dtype_map_from_kernel(nfnl_nft_set_get_datatype(nls));
+ data = nft_set_attr_get_u32(nls, NFT_SET_ATTR_DATA_TYPE);
+ datatype = dtype_map_from_kernel(data);
if (datatype == NULL) {
netlink_io_error(ctx, NULL, "Unknown data type in set key %u",
- nfnl_nft_set_get_datatype(nls));
- return;
+ data);
+ return -1;
}
} else
datatype = NULL;
set = set_alloc(&internal_location);
- set->handle.family = nfnl_nft_set_get_family(nls);
- set->handle.table = xstrdup(nfnl_nft_set_get_table(nls));
- set->handle.set = xstrdup(nfnl_nft_set_get_name(nls));
+ set->handle.family = nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY);
+ set->handle.table =
+ xstrdup(nft_set_attr_get_str(nls, NFT_SET_ATTR_TABLE));
+ set->handle.set =
+ xstrdup(nft_set_attr_get_str(nls, NFT_SET_ATTR_NAME));
set->keytype = keytype;
- set->keylen = nfnl_nft_set_get_keylen(nls) * BITS_PER_BYTE;
+ set->keylen =
+ nft_set_attr_get_u32(nls, NFT_SET_ATTR_KEY_LEN) * BITS_PER_BYTE;
set->flags = flags;
set->datatype = datatype;
- set->datalen = nfnl_nft_set_get_datalen(nls) * BITS_PER_BYTE;
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_DATA_LEN)) {
+ set->datalen =
+ nft_set_attr_get_u32(nls, NFT_SET_ATTR_DATA_LEN) * BITS_PER_BYTE;
+ }
list_add_tail(&set->list, &ctx->list);
+
+ return 0;
}
int netlink_list_sets(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nl_cache *set_cache;
- int err;
+ struct nft_set_list *set_cache;
- err = nfnl_nft_set_alloc_cache(nf_sock, h->family, h->table, &set_cache);
- if (err < 0)
+ set_cache = mnl_nft_set_dump(nf_sock, h->family, h->table);
+ if (set_cache == NULL)
return netlink_io_error(ctx, loc,
"Could not receive sets from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
- nl_cache_foreach(set_cache, list_set_cb, ctx);
- nl_cache_free(set_cache);
+ nft_set_list_foreach(set_cache, list_set_cb, ctx);
+ nft_set_list_free(set_cache);
return 0;
}
-static int netlink_get_set_cb(struct nl_msg *msg, void *arg)
-{
- return nl_msg_parse(msg, list_set_cb, arg);
-}
-
int netlink_get_set(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc)
{
- struct nfnl_nft_set *nls;
+ struct nft_set *nls;
+ struct set *set;
int err;
nls = alloc_nft_set(h);
- netlink_dump_object(OBJ_CAST(nls));
- netlink_set_callback(netlink_get_set_cb, ctx);
- err = nfnl_nft_set_query(nf_sock, nls, 0);
- if (err == 0)
- err = nl_recvmsgs_default(nf_sock);
- netlink_set_callback(NULL, NULL);
-
- nfnl_nft_set_put(nls);
-
+ netlink_dump_set(nls);
+ err = mnl_nft_set_get(nf_sock, nls);
if (err < 0)
return netlink_io_error(ctx, loc,
"Could not receive set from kernel: %s",
- nl_geterror(err));
+ strerror(errno));
+
+ set = set_alloc(&internal_location);
+ set->handle.family = nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY);
+ set->handle.table =
+ xstrdup(nft_set_attr_get_str(nls, NFT_SET_ATTR_TABLE));
+ set->handle.set =
+ xstrdup(nft_set_attr_get_str(nls, NFT_SET_ATTR_NAME));
+ set->keytype =
+ dtype_map_from_kernel(nft_set_attr_get_u32(nls, NFT_SET_ATTR_KEY_TYPE));
+ set->keylen =
+ nft_set_attr_get_u32(nls, NFT_SET_ATTR_KEY_LEN) * BITS_PER_BYTE;
+ set->flags = nft_set_attr_get_u32(nls, NFT_SET_ATTR_FLAGS);
+ set->datatype =
+ dtype_map_from_kernel(nft_set_attr_get_u32(nls, NFT_SET_ATTR_DATA_TYPE));
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_DATA_LEN)) {
+ set->datalen =
+ nft_set_attr_get_u32(nls, NFT_SET_ATTR_DATA_LEN) * BITS_PER_BYTE;
+ }
+ list_add_tail(&set->list, &ctx->list);
+ nft_set_free(nls);
+
return err;
}
-static int alloc_setelem_cache(const struct expr *set, struct nl_cache **res)
+static void alloc_setelem_cache(const struct expr *set, struct nft_set *nls)
{
- struct nfnl_nft_setelem *nlse;
- struct nl_cache *elements;
+ struct nft_set_elem *nlse;
const struct expr *expr;
- int err;
- err = nl_cache_alloc_name("netfilter/nft_setelem", &elements);
- if (err < 0)
- return err;
list_for_each_entry(expr, &set->expressions, list) {
nlse = alloc_nft_setelem(expr);
- netlink_dump_object(OBJ_CAST(nlse));
- nl_cache_add(elements, OBJ_CAST(nlse));
+ nft_set_elem_add(nls, nlse);
}
- *res = elements;
- return 0;
}
int netlink_add_setelems(struct netlink_ctx *ctx, const struct handle *h,
const struct expr *expr)
{
- struct nfnl_nft_set *nls;
- struct nl_cache *elements;
+ struct nft_set *nls;
int err;
nls = alloc_nft_set(h);
- netlink_dump_object(OBJ_CAST(nls));
+ alloc_setelem_cache(expr, nls);
+ netlink_dump_set(nls);
- err = alloc_setelem_cache(expr, &elements);
- if (err < 0)
- goto out;
- err = nfnl_nft_setelem_add(nf_sock, nls, elements, 0);
- if (err < 0)
- goto out;
- err = nl_recvmsgs_default(nf_sock);
-out:
- nfnl_nft_set_put(nls);
+ err = mnl_nft_setelem_add(nf_sock, nls, 0);
+ nft_set_free(nls);
if (err < 0)
netlink_io_error(ctx, &expr->location,
"Could not add set elements: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
int netlink_delete_setelems(struct netlink_ctx *ctx, const struct handle *h,
const struct expr *expr)
{
- struct nfnl_nft_set *nls;
- struct nl_cache *elements;
+ struct nft_set *nls;
int err;
nls = alloc_nft_set(h);
- err = alloc_setelem_cache(expr, &elements);
- if (err < 0)
- goto out;
- err = nfnl_nft_setelem_delete(nf_sock, nls, elements, 0);
- if (err < 0)
- goto out;
- err = nl_recvmsgs_default(nf_sock);
-out:
- nfnl_nft_set_put(nls);
+ alloc_setelem_cache(expr, nls);
+ netlink_dump_set(nls);
+
+ err = mnl_nft_setelem_delete(nf_sock, nls, 0);
+ nft_set_free(nls);
if (err < 0)
netlink_io_error(ctx, &expr->location,
"Could not delete set elements: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}
-static void list_setelem_cb(struct nl_object *obj, void *arg)
+static int list_setelem_cb(struct nft_set_elem *nlse, void *arg)
{
- struct nfnl_nft_setelem *nlse = nl_object_priv(obj);
- struct nfnl_nft_data *nld;
+ struct nft_data_delinearize nld;
struct netlink_ctx *ctx = arg;
struct set *set = ctx->set;
struct expr *expr, *data;
- uint32_t flags;
+ uint32_t flags = 0;
- netlink_dump_object(obj);
- if (!nfnl_nft_setelem_test_key(nlse)) {
- netlink_io_error(ctx, NULL, "Incomplete set element received");
- return;
- }
+ nld.value =
+ nft_set_elem_attr_get(nlse, NFT_SET_ELEM_ATTR_KEY, &nld.len);
+ if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_FLAGS))
+ flags = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_FLAGS);
- nld = nfnl_nft_setelem_get_key(nlse);
- flags = nfnl_nft_setelem_get_flags(nlse);
-
- expr = netlink_alloc_value(&internal_location, nld);
+ expr = netlink_alloc_value(&internal_location, &nld);
expr->dtype = set->keytype;
expr->byteorder = set->keytype->byteorder;
if (expr->byteorder == BYTEORDER_HOST_ENDIAN)
mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
- if (flags & NFT_SET_ELEM_INTERVAL_END)
+ if (flags & NFT_SET_ELEM_INTERVAL_END) {
expr->flags |= EXPR_F_INTERVAL_END;
- else if (nfnl_nft_setelem_test_data(nlse)) {
- nld = nfnl_nft_setelem_get_data(nlse);
-
- data = netlink_alloc_data(&internal_location, nld,
+ } else {
+ if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_DATA)) {
+ nld.value = nft_set_elem_attr_get(nlse, NFT_SET_ELEM_ATTR_DATA,
+ &nld.len);
+ } else if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_CHAIN)) {
+ nld.chain = nft_set_elem_attr_get_str(nlse, NFT_SET_ELEM_ATTR_CHAIN);
+ nld.verdict = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT);
+ } else if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_VERDICT)) {
+ nld.verdict = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT);
+ } else
+ goto out;
+
+ data = netlink_alloc_data(&internal_location, &nld,
set->datatype->type == TYPE_VERDICT ?
NFT_REG_VERDICT : NFT_REG_1);
data->dtype = set->datatype;
expr = mapping_expr_alloc(&internal_location, expr, data);
}
-
+out:
compound_expr_add(set->init, expr);
+ return 0;
}
extern void interval_map_decompose(struct expr *set);
@@ -973,32 +970,27 @@ extern void interval_map_decompose(struct expr *set);
int netlink_get_setelems(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, struct set *set)
{
- struct nl_cache *elements;
- struct nfnl_nft_set *nls;
+ struct nft_set *nls;
int err;
nls = alloc_nft_set(h);
- netlink_dump_object(OBJ_CAST(nls));
+ netlink_dump_set(nls);
- err = nfnl_nft_setelem_alloc_cache(nf_sock, nls, &elements);
- if (err < 0)
- goto out;
- err = nl_recvmsgs_default(nf_sock);
+ err = mnl_nft_setelem_get(nf_sock, nls);
if (err < 0)
goto out;
ctx->set = set;
set->init = set_expr_alloc(loc);
- nl_cache_foreach(elements, list_setelem_cb, ctx);
- nl_cache_free(elements);
+ nft_set_elem_foreach(nls, list_setelem_cb, ctx);
+ nft_set_free(nls);
ctx->set = NULL;
if (set->flags & NFT_SET_INTERVAL)
interval_map_decompose(set->init);
out:
- nfnl_nft_set_put(nls);
if (err < 0)
netlink_io_error(ctx, loc, "Could not receive set elements: %s",
- nl_geterror(err));
+ strerror(errno));
return err;
}