Commit 290749d4 authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.4

parent 89c92f0c
#ifndef _NFT_CACHE_H_
#define _NFT_CACHE_H_
struct nft_handle;
void nft_fake_cache(struct nft_handle *h);
void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c);
void nft_rebuild_cache(struct nft_handle *h);
void nft_release_cache(struct nft_handle *h);
void flush_chain_cache(struct nft_handle *h, const char *tablename);
int flush_rule_cache(struct nft_handle *h, const char *table,
struct nftnl_chain *c);
struct nftnl_chain_list *
nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain);
struct nftnl_set_list *
nft_set_list_get(struct nft_handle *h, const char *table, const char *set);
struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h);
#endif /* _NFT_CACHE_H_ */
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "nft.h" #include "nft.h"
#include "nft-shared.h" #include "nft-shared.h"
static int nft_ipv4_add(struct nftnl_rule *r, void *data) static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
{ {
struct iptables_command_state *cs = data; struct iptables_command_state *cs = data;
struct xtables_rule_match *matchp; struct xtables_rule_match *matchp;
...@@ -77,7 +77,7 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data) ...@@ -77,7 +77,7 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO); add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) { for (matchp = cs->matches; matchp; matchp = matchp->next) {
ret = add_match(r, matchp->match->m); ret = add_match(h, r, matchp->match->m);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -261,12 +261,12 @@ static void print_fragment(unsigned int flags, unsigned int invflags, ...@@ -261,12 +261,12 @@ static void print_fragment(unsigned int flags, unsigned int invflags,
fputc(' ', stdout); fputc(' ', stdout);
} }
static void nft_ipv4_print_rule(struct nftnl_rule *r, unsigned int num, static void nft_ipv4_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int format) unsigned int num, unsigned int format)
{ {
struct iptables_command_state cs = {}; struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(r, &cs); nft_rule_to_iptables_command_state(h, r, &cs);
print_rule_details(&cs, cs.jumpto, cs.fw.ip.flags, print_rule_details(&cs, cs.jumpto, cs.fw.ip.flags,
cs.fw.ip.invflags, cs.fw.ip.proto, num, format); cs.fw.ip.invflags, cs.fw.ip.proto, num, format);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "nft.h" #include "nft.h"
#include "nft-shared.h" #include "nft-shared.h"
static int nft_ipv6_add(struct nftnl_rule *r, void *data) static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
{ {
struct iptables_command_state *cs = data; struct iptables_command_state *cs = data;
struct xtables_rule_match *matchp; struct xtables_rule_match *matchp;
...@@ -66,7 +66,7 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data) ...@@ -66,7 +66,7 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data)
add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO); add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) { for (matchp = cs->matches; matchp; matchp = matchp->next) {
ret = add_match(r, matchp->match->m); ret = add_match(h, r, matchp->match->m);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -187,12 +187,12 @@ static void nft_ipv6_parse_immediate(const char *jumpto, bool nft_goto, ...@@ -187,12 +187,12 @@ static void nft_ipv6_parse_immediate(const char *jumpto, bool nft_goto,
cs->fw6.ipv6.flags |= IP6T_F_GOTO; cs->fw6.ipv6.flags |= IP6T_F_GOTO;
} }
static void nft_ipv6_print_rule(struct nftnl_rule *r, unsigned int num, static void nft_ipv6_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int format) unsigned int num, unsigned int format)
{ {
struct iptables_command_state cs = {}; struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(r, &cs); nft_rule_to_iptables_command_state(h, r, &cs);
print_rule_details(&cs, cs.jumpto, cs.fw6.ipv6.flags, print_rule_details(&cs, cs.jumpto, cs.fw6.ipv6.flags,
cs.fw6.ipv6.invflags, cs.fw6.ipv6.proto, cs.fw6.ipv6.invflags, cs.fw6.ipv6.proto,
......
...@@ -69,7 +69,7 @@ void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base) ...@@ -69,7 +69,7 @@ void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base)
} }
/* bitwise operation is = sreg & mask ^ xor */ /* bitwise operation is = sreg & mask ^ xor */
void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor) void add_bitwise_u16(struct nftnl_rule *r, uint16_t mask, uint16_t xor)
{ {
struct nftnl_expr *expr; struct nftnl_expr *expr;
...@@ -310,7 +310,6 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -310,7 +310,6 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
struct xtables_target *target; struct xtables_target *target;
struct xt_entry_target *t; struct xt_entry_target *t;
size_t size; size_t size;
struct nft_family_ops *ops;
void *data = ctx->cs; void *data = ctx->cs;
target = xtables_find_target(targname, XTF_TRY_LOAD); target = xtables_find_target(targname, XTF_TRY_LOAD);
...@@ -327,8 +326,7 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -327,8 +326,7 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
target->t = t; target->t = t;
ops = nft_family_ops_lookup(ctx->family); ctx->h->ops->parse_target(target, data);
ops->parse_target(target, data);
} }
static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
...@@ -339,9 +337,8 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -339,9 +337,8 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
struct xtables_match *match; struct xtables_match *match;
struct xtables_rule_match **matches; struct xtables_rule_match **matches;
struct xt_entry_match *m; struct xt_entry_match *m;
struct nft_family_ops *ops;
switch (ctx->family) { switch (ctx->h->family) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
case NFPROTO_IPV6: case NFPROTO_IPV6:
case NFPROTO_BRIDGE: case NFPROTO_BRIDGE:
...@@ -349,7 +346,7 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -349,7 +346,7 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
break; break;
default: default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n", fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
ctx->family); ctx->h->family);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -365,9 +362,8 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -365,9 +362,8 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
match->m = m; match->m = m;
ops = nft_family_ops_lookup(ctx->family); if (ctx->h->ops->parse_match != NULL)
if (ops->parse_match != NULL) ctx->h->ops->parse_match(match, ctx->cs);
ops->parse_match(match, ctx->cs);
} }
void print_proto(uint16_t proto, int invert) void print_proto(uint16_t proto, int invert)
...@@ -400,7 +396,6 @@ void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv) ...@@ -400,7 +396,6 @@ void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
static void nft_meta_set_to_target(struct nft_xt_ctx *ctx) static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
{ {
const struct nft_family_ops *ops;
struct xtables_target *target; struct xtables_target *target;
struct xt_entry_target *t; struct xt_entry_target *t;
unsigned int size; unsigned int size;
...@@ -429,8 +424,7 @@ static void nft_meta_set_to_target(struct nft_xt_ctx *ctx) ...@@ -429,8 +424,7 @@ static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
target->t = t; target->t = t;
ops = nft_family_ops_lookup(ctx->family); ctx->h->ops->parse_target(target, ctx->cs);
ops->parse_target(target, ctx->cs);
} }
static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
...@@ -451,8 +445,16 @@ static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -451,8 +445,16 @@ static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
static void nft_parse_payload(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_payload(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{ {
if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
memcpy(&ctx->prev_payload, &ctx->payload,
sizeof(ctx->prev_payload));
ctx->flags |= NFT_XT_CTX_PREV_PAYLOAD;
}
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG); ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
ctx->payload.base = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_BASE);
ctx->payload.offset = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET); ctx->payload.offset = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET);
ctx->payload.len = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_LEN);
ctx->flags |= NFT_XT_CTX_PAYLOAD; ctx->flags |= NFT_XT_CTX_PAYLOAD;
} }
...@@ -474,7 +476,6 @@ static void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -474,7 +476,6 @@ static void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{ {
struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
void *data = ctx->cs; void *data = ctx->cs;
uint32_t reg; uint32_t reg;
...@@ -483,12 +484,12 @@ static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -483,12 +484,12 @@ static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
return; return;
if (ctx->flags & NFT_XT_CTX_META) { if (ctx->flags & NFT_XT_CTX_META) {
ops->parse_meta(ctx, e, data); ctx->h->ops->parse_meta(ctx, e, data);
ctx->flags &= ~NFT_XT_CTX_META; ctx->flags &= ~NFT_XT_CTX_META;
} }
/* bitwise context is interpreted from payload */ /* bitwise context is interpreted from payload */
if (ctx->flags & NFT_XT_CTX_PAYLOAD) { if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
ops->parse_payload(ctx, e, data); ctx->h->ops->parse_payload(ctx, e, data);
ctx->flags &= ~NFT_XT_CTX_PAYLOAD; ctx->flags &= ~NFT_XT_CTX_PAYLOAD;
} }
} }
...@@ -502,7 +503,6 @@ static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters ...@@ -502,7 +503,6 @@ static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters
static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{ {
const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN); const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
struct nft_family_ops *ops;
const char *jumpto = NULL; const char *jumpto = NULL;
bool nft_goto = false; bool nft_goto = false;
void *data = ctx->cs; void *data = ctx->cs;
...@@ -544,8 +544,7 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -544,8 +544,7 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
break; break;
} }
ops = nft_family_ops_lookup(ctx->family); ctx->h->ops->parse_immediate(jumpto, nft_goto, data);
ops->parse_immediate(jumpto, nft_goto, data);
} }
static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e) static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
...@@ -555,19 +554,18 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -555,19 +554,18 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
__u64 rate = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_RATE); __u64 rate = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_RATE);
struct xtables_rule_match **matches; struct xtables_rule_match **matches;
struct xtables_match *match; struct xtables_match *match;
struct nft_family_ops *ops;
struct xt_rateinfo *rinfo; struct xt_rateinfo *rinfo;
size_t size; size_t size;
switch (ctx->family) { switch (ctx->h->family) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
case NFPROTO_IPV6: case NFPROTO_IPV6:
case NFPROTO_BRIDGE: case NFPROTO_BRIDGE:
matches = &ctx->cs->matches; matches = &ctx->cs->matches;
break; break;
default: default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n", fprintf(stderr, "BUG: nft_parse_limit() unknown family %d\n",
ctx->family); ctx->h->family);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -586,20 +584,27 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -586,20 +584,27 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
rinfo->avg = XT_LIMIT_SCALE * unit / rate; rinfo->avg = XT_LIMIT_SCALE * unit / rate;
rinfo->burst = burst; rinfo->burst = burst;
ops = nft_family_ops_lookup(ctx->family); if (ctx->h->ops->parse_match != NULL)
if (ops->parse_match != NULL) ctx->h->ops->parse_match(match, ctx->cs);
ops->parse_match(match, ctx->cs); }
static void nft_parse_lookup(struct nft_xt_ctx *ctx, struct nft_handle *h,
struct nftnl_expr *e)
{
if (ctx->h->ops->parse_lookup)
ctx->h->ops->parse_lookup(ctx, e, NULL);
} }
void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, void nft_rule_to_iptables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs) struct iptables_command_state *cs)
{ {
struct nftnl_expr_iter *iter; struct nftnl_expr_iter *iter;
struct nftnl_expr *expr; struct nftnl_expr *expr;
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct nft_xt_ctx ctx = { struct nft_xt_ctx ctx = {
.cs = cs, .cs = cs,
.family = family, .h = h,
.table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE),
}; };
iter = nftnl_expr_iter_create(r); iter = nftnl_expr_iter_create(r);
...@@ -630,6 +635,8 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, ...@@ -630,6 +635,8 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
nft_parse_target(&ctx, expr); nft_parse_target(&ctx, expr);
else if (strcmp(name, "limit") == 0) else if (strcmp(name, "limit") == 0)
nft_parse_limit(&ctx, expr); nft_parse_limit(&ctx, expr);
else if (strcmp(name, "lookup") == 0)
nft_parse_lookup(&ctx, h, expr);
expr = nftnl_expr_iter_next(iter); expr = nftnl_expr_iter_next(iter);
} }
...@@ -982,19 +989,18 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data) ...@@ -982,19 +989,18 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data)
cs->target = t; cs->target = t;
} }
bool nft_ipv46_rule_find(struct nft_family_ops *ops, bool nft_ipv46_rule_find(struct nft_handle *h, struct nftnl_rule *r, void *data)
struct nftnl_rule *r, void *data)
{ {
struct iptables_command_state *cs = data, this = {}; struct iptables_command_state *cs = data, this = {};
bool ret = false; bool ret = false;
nft_rule_to_iptables_command_state(r, &this); nft_rule_to_iptables_command_state(h, r, &this);
DEBUGP("comparing with... "); DEBUGP("comparing with... ");
#ifdef DEBUG_DEL #ifdef DEBUG_DEL
nft_rule_print_save(r, NFT_RULE_APPEND, 0); nft_rule_print_save(r, NFT_RULE_APPEND, 0);
#endif #endif
if (!ops->is_same(cs, &this)) if (!h->ops->is_same(cs, &this))
goto out; goto out;
if (!compare_matches(cs->matches, this.matches)) { if (!compare_matches(cs->matches, this.matches)) {
...@@ -1014,7 +1020,7 @@ bool nft_ipv46_rule_find(struct nft_family_ops *ops, ...@@ -1014,7 +1020,7 @@ bool nft_ipv46_rule_find(struct nft_family_ops *ops,
ret = true; ret = true;
out: out:
ops->clear_cs(&this); h->ops->clear_cs(&this);
return ret; return ret;
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) #define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
struct xtables_args; struct xtables_args;
struct nft_handle;
struct xt_xlate; struct xt_xlate;
enum { enum {
...@@ -42,19 +43,22 @@ enum { ...@@ -42,19 +43,22 @@ enum {
NFT_XT_CTX_META = (1 << 1), NFT_XT_CTX_META = (1 << 1),
NFT_XT_CTX_BITWISE = (1 << 2), NFT_XT_CTX_BITWISE = (1 << 2),
NFT_XT_CTX_IMMEDIATE = (1 << 3), NFT_XT_CTX_IMMEDIATE = (1 << 3),
NFT_XT_CTX_PREV_PAYLOAD = (1 << 4),
}; };
struct nft_xt_ctx { struct nft_xt_ctx {
struct iptables_command_state *cs; struct iptables_command_state *cs;
struct nftnl_expr_iter *iter; struct nftnl_expr_iter *iter;
int family; struct nft_handle *h;
uint32_t flags; uint32_t flags;
const char *table;
uint32_t reg; uint32_t reg;
struct { struct {
uint32_t base;
uint32_t offset; uint32_t offset;
uint32_t len; uint32_t len;
} payload; } payload, prev_payload;
struct { struct {
uint32_t key; uint32_t key;
} meta; } meta;
...@@ -69,7 +73,7 @@ struct nft_xt_ctx { ...@@ -69,7 +73,7 @@ struct nft_xt_ctx {
}; };
struct nft_family_ops { struct nft_family_ops {
int (*add)(struct nftnl_rule *r, void *data); int (*add)(struct nft_handle *h, struct nftnl_rule *r, void *data);
bool (*is_same)(const void *data_a, bool (*is_same)(const void *data_a,
const void *data_b); const void *data_b);
void (*print_payload)(struct nftnl_expr *e, void (*print_payload)(struct nftnl_expr *e,
...@@ -82,6 +86,8 @@ struct nft_family_ops { ...@@ -82,6 +86,8 @@ struct nft_family_ops {
void *data); void *data);
void (*parse_cmp)(struct nft_xt_ctx *ctx, struct nftnl_expr *e, void (*parse_cmp)(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
void *data); void *data);
void (*parse_lookup)(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
void *data);
void (*parse_immediate)(const char *jumpto, bool nft_goto, void *data); void (*parse_immediate)(const char *jumpto, bool nft_goto, void *data);
void (*print_table_header)(const char *tablename); void (*print_table_header)(const char *tablename);
...@@ -89,8 +95,8 @@ struct nft_family_ops { ...@@ -89,8 +95,8 @@ struct nft_family_ops {
const char *pol, const char *pol,
const struct xt_counters *counters, bool basechain, const struct xt_counters *counters, bool basechain,
uint32_t refs, uint32_t entries); uint32_t refs, uint32_t entries);
void (*print_rule)(struct nftnl_rule *r, unsigned int num, void (*print_rule)(struct nft_handle *h, struct nftnl_rule *r,
unsigned int format); unsigned int num, unsigned int format);
void (*save_rule)(const void *data, unsigned int format); void (*save_rule)(const void *data, unsigned int format);
void (*save_counters)(const void *data); void (*save_counters)(const void *data);
void (*save_chain)(const struct nftnl_chain *c, const char *policy); void (*save_chain)(const struct nftnl_chain *c, const char *policy);
...@@ -100,10 +106,10 @@ struct nft_family_ops { ...@@ -100,10 +106,10 @@ struct nft_family_ops {
struct xtables_args *args); struct xtables_args *args);
void (*parse_match)(struct xtables_match *m, void *data); void (*parse_match)(struct xtables_match *m, void *data);
void (*parse_target)(struct xtables_target *t, void *data); void (*parse_target)(struct xtables_target *t, void *data);
void (*rule_to_cs)(const struct nftnl_rule *r, void (*rule_to_cs)(struct nft_handle *h, const struct nftnl_rule *r,
struct iptables_command_state *cs); struct iptables_command_state *cs);
void (*clear_cs)(struct iptables_command_state *cs); void (*clear_cs)(struct iptables_command_state *cs);
bool (*rule_find)(struct nft_family_ops *ops, struct nftnl_rule *r, bool (*rule_find)(struct nft_handle *h, struct nftnl_rule *r,
void *data); void *data);
int (*xlate)(const void *data, struct xt_xlate *xl); int (*xlate)(const void *data, struct xt_xlate *xl);
}; };
...@@ -111,7 +117,7 @@ struct nft_family_ops { ...@@ -111,7 +117,7 @@ struct nft_family_ops {
void add_meta(struct nftnl_rule *r, uint32_t key); void add_meta(struct nftnl_rule *r, uint32_t key);
void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base); void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base);
void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len); void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len);
void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor); void add_bitwise_u16(struct nftnl_rule *r, uint16_t mask, uint16_t xor);
void add_cmp_ptr(struct nftnl_rule *r, uint32_t op, void *data, size_t len); void add_cmp_ptr(struct nftnl_rule *r, uint32_t op, void *data, size_t len);
void add_cmp_u8(struct nftnl_rule *r, uint8_t val, uint32_t op); void add_cmp_u8(struct nftnl_rule *r, uint8_t val, uint32_t op);
void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op); void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op);
...@@ -137,7 +143,8 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface, ...@@ -137,7 +143,8 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
unsigned char *outiface_mask, uint8_t *invflags); unsigned char *outiface_mask, uint8_t *invflags);
void print_proto(uint16_t proto, int invert); void print_proto(uint16_t proto, int invert);
void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv); void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv);
void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, void nft_rule_to_iptables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs); struct iptables_command_state *cs);
void nft_clear_iptables_command_state(struct iptables_command_state *cs); void nft_clear_iptables_command_state(struct iptables_command_state *cs);
void print_header(unsigned int format, const char *chain, const char *pol, void print_header(unsigned int format, const char *chain, const char *pol,
...@@ -163,9 +170,8 @@ void save_matches_and_target(const struct iptables_command_state *cs, ...@@ -163,9 +170,8 @@ void save_matches_and_target(const struct iptables_command_state *cs,
struct nft_family_ops *nft_family_ops_lookup(int family); struct nft_family_ops *nft_family_ops_lookup(int family);
struct nft_handle;
void nft_ipv46_parse_target(struct xtables_target *t, void *data); void nft_ipv46_parse_target(struct xtables_target *t, void *data);
bool nft_ipv46_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r, bool nft_ipv46_rule_find(struct nft_handle *h, struct nftnl_rule *r,
void *data); void *data);
bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2); bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2);
...@@ -199,23 +205,6 @@ struct xtables_args { ...@@ -199,23 +205,6 @@ struct xtables_args {
unsigned long long pcnt_cnt, bcnt_cnt; unsigned long long pcnt_cnt, bcnt_cnt;
}; };
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_DELETE_NUM 0x0004U
#define CMD_REPLACE 0x0008U
#define CMD_APPEND 0x0010U
#define CMD_LIST 0x0020U
#define CMD_FLUSH 0x0040U
#define CMD_ZERO 0x0080U
#define CMD_NEW_CHAIN 0x0100U
#define CMD_DELETE_CHAIN 0x0200U
#define CMD_SET_POLICY 0x0400U
#define CMD_RENAME_CHAIN 0x0800U
#define CMD_LIST_RULES 0x1000U
#define CMD_ZERO_NUM 0x2000U
#define CMD_CHECK 0x4000U
struct nft_xt_cmd_parse { struct nft_xt_cmd_parse {
unsigned int command; unsigned int command;
unsigned int rulenum; unsigned int rulenum;
...@@ -232,19 +221,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], ...@@ -232,19 +221,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
struct nft_xt_cmd_parse *p, struct iptables_command_state *cs, struct nft_xt_cmd_parse *p, struct iptables_command_state *cs,
struct xtables_args *args); struct xtables_args *args);
struct nft_xt_restore_parse {
FILE *in;
int testing;
const char *tablename;
bool commit;
};
struct nftnl_chain_list; struct nftnl_chain_list;
struct nft_xt_restore_cb { struct nft_xt_restore_cb {
void (*table_new)(struct nft_handle *h, const char *table); void (*table_new)(struct nft_handle *h, const char *table);
struct nftnl_chain_list *(*chain_list)(struct nft_handle *h,
const char *table);
int (*chain_set)(struct nft_handle *h, const char *table, int (*chain_set)(struct nft_handle *h, const char *table,
const char *chain, const char *policy, const char *chain, const char *policy,
const struct xt_counters *counters); const struct xt_counters *counters);
...@@ -260,10 +240,16 @@ struct nft_xt_restore_cb { ...@@ -260,10 +240,16 @@ struct nft_xt_restore_cb {
int (*abort)(struct nft_handle *h); int (*abort)(struct nft_handle *h);
}; };
struct nft_xt_restore_parse {
FILE *in;
int testing;
const char *tablename;
bool commit;
const struct nft_xt_restore_cb *cb;
};
void xtables_restore_parse(struct nft_handle *h, void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_parse *p, const struct nft_xt_restore_parse *p);
struct nft_xt_restore_cb *cb,
int argc, char *argv[]);
void nft_check_xt_legacy(int family, bool is_ipt_save); void nft_check_xt_legacy(int family, bool is_ipt_save);
#endif #endif
...@@ -55,48 +55,18 @@ ...@@ -55,48 +55,18 @@
#include "nft.h" #include "nft.h"
#include "xshared.h" /* proto_to_name */ #include "xshared.h" /* proto_to_name */
#include "nft-cache.h"
#include "nft-shared.h" #include "nft-shared.h"
#include "nft-bridge.h" /* EBT_NOPROTO */ #include "nft-bridge.h" /* EBT_NOPROTO */
#include "xtables-config-parser.h"
static void *nft_fn; static void *nft_fn;
static int genid_cb(const struct nlmsghdr *nlh, void *data)
{
uint32_t *genid = data;
struct nftnl_gen *gen;
gen = nftnl_gen_alloc();
if (!gen)
return MNL_CB_ERROR;
if (nftnl_gen_nlmsg_parse(nlh, gen) < 0)
goto out;
*genid = nftnl_gen_get_u32(gen, NFTNL_GEN_ID);
nftnl_gen_free(gen);
return MNL_CB_STOP;
out:
nftnl_gen_free(gen);
return MNL_CB_ERROR;
}
static int mnl_genid_get(struct nft_handle *h, uint32_t *genid)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, 0, 0, h->seq);
return mnl_talk(h, nlh, genid_cb, genid);
}
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int (*cb)(const struct nlmsghdr *nlh, void *data), int (*cb)(const struct nlmsghdr *nlh, void *data),
void *data) void *data)
{ {
int ret; int ret;
char buf[16536]; char buf[32768];
if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
return -1; return -1;
...@@ -186,33 +156,42 @@ static void mnl_err_list_free(struct mnl_err *err) ...@@ -186,33 +156,42 @@ static void mnl_err_list_free(struct mnl_err *err)
free(err); free(err);
} }
static int nlbuffsiz; static void mnl_set_sndbuffer(struct nft_handle *h)
static void mnl_set_sndbuffer(const struct mnl_socket *nl,
struct nftnl_batch *batch)
{ {
int newbuffsiz; int newbuffsiz = nftnl_batch_iovec_len(h->batch) * BATCH_PAGE_SIZE;
if (nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz) if (newbuffsiz <= h->nlsndbuffsiz)
return; return;
newbuffsiz = nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE;
/* Rise sender buffer length to avoid hitting -EMSGSIZE */ /* Rise sender buffer length to avoid hitting -EMSGSIZE */
if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUFFORCE, if (setsockopt(mnl_socket_get_fd(h->nl), SOL_SOCKET, SO_SNDBUFFORCE,
&newbuffsiz, sizeof(socklen_t)) < 0)
return;
h->nlsndbuffsiz = newbuffsiz;
}
static void mnl_set_rcvbuffer(struct nft_handle *h, int numcmds)
{
int newbuffsiz = getpagesize() * numcmds;
if (newbuffsiz <= h->nlrcvbuffsiz)
return;
/* Rise receiver buffer length to avoid hitting -ENOBUFS */
if (setsockopt(mnl_socket_get_fd(h->nl), SOL_SOCKET, SO_RCVBUFFORCE,
&newbuffsiz, sizeof(socklen_t)) < 0) &newbuffsiz, sizeof(socklen_t)) < 0)
return; return;
nlbuffsiz = newbuffsiz; h->nlrcvbuffsiz = newbuffsiz;
} }
static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock, static ssize_t mnl_nft_socket_sendmsg(struct nft_handle *h, int numcmds)
struct nftnl_batch *batch)
{ {
static const struct sockaddr_nl snl = { static const struct sockaddr_nl snl = {
.nl_family = AF_NETLINK .nl_family = AF_NETLINK
}; };
uint32_t iov_len = nftnl_batch_iovec_len(batch); uint32_t iov_len = nftnl_batch_iovec_len(h->batch);
struct iovec iov[iov_len]; struct iovec iov[iov_len];
struct msghdr msg = { struct msghdr msg = {
.msg_name = (struct sockaddr *) &snl, .msg_name = (struct sockaddr *) &snl,
...@@ -221,16 +200,16 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock, ...@@ -221,16 +200,16 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
.msg_iovlen = iov_len, .msg_iovlen = iov_len,
}; };
mnl_set_sndbuffer(nf_sock, batch); mnl_set_sndbuffer(h);
nftnl_batch_iovec(batch, iov, iov_len); mnl_set_rcvbuffer(h, numcmds);
nftnl_batch_iovec(h->batch, iov, iov_len);
return sendmsg(mnl_socket_get_fd(nf_sock), &msg, 0); return sendmsg(mnl_socket_get_fd(h->nl), &msg, 0);
} }
static int mnl_batch_talk(const struct mnl_socket *nf_sock, static int mnl_batch_talk(struct nft_handle *h, int numcmds)
struct nftnl_batch *batch, struct list_head *err_list)
{ {
const struct mnl_socket *nl = nf_sock; const struct mnl_socket *nl = h->nl;
int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl); int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl);
char rcv_buf[MNL_SOCKET_BUFFER_SIZE]; char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
fd_set readfds; fd_set readfds;
...@@ -240,7 +219,7 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock, ...@@ -240,7 +219,7 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock,
}; };
int err = 0; int err = 0;
ret = mnl_nft_socket_sendmsg(nf_sock, batch); ret = mnl_nft_socket_sendmsg(h, numcmds);
if (ret == -1) if (ret == -1)
return -1; return -1;
...@@ -262,7 +241,8 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock, ...@@ -262,7 +241,8 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock,
ret = mnl_cb_run(rcv_buf, ret, 0, portid, NULL, NULL); ret = mnl_cb_run(rcv_buf, ret, 0, portid, NULL, NULL);
/* Continue on error, make sure we get all acknowledgments */ /* Continue on error, make sure we get all acknowledgments */
if (ret == -1) { if (ret == -1) {
mnl_err_list_node_add(err_list, errno, nlh->nlmsg_seq); mnl_err_list_node_add(&h->err_list, errno,
nlh->nlmsg_seq);
err = -1; err = -1;
} }
...@@ -291,6 +271,7 @@ enum obj_update_type { ...@@ -291,6 +271,7 @@ enum obj_update_type {
NFT_COMPAT_RULE_REPLACE, NFT_COMPAT_RULE_REPLACE,
NFT_COMPAT_RULE_DELETE, NFT_COMPAT_RULE_DELETE,
NFT_COMPAT_RULE_FLUSH, NFT_COMPAT_RULE_FLUSH,
NFT_COMPAT_SET_ADD,
}; };
enum obj_action { enum obj_action {
...@@ -308,6 +289,7 @@ struct obj_update { ...@@ -308,6 +289,7 @@ struct obj_update {
struct nftnl_table *table; struct nftnl_table *table;
struct nftnl_chain *chain; struct nftnl_chain *chain;
struct nftnl_rule *rule; struct nftnl_rule *rule;
struct nftnl_set *set;
void *ptr; void *ptr;
}; };
struct { struct {
...@@ -335,6 +317,7 @@ static int mnl_append_error(const struct nft_handle *h, ...@@ -335,6 +317,7 @@ static int mnl_append_error(const struct nft_handle *h,
[NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE", [NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE",
[NFT_COMPAT_RULE_DELETE] = "RULE_DELETE", [NFT_COMPAT_RULE_DELETE] = "RULE_DELETE",
[NFT_COMPAT_RULE_FLUSH] = "RULE_FLUSH", [NFT_COMPAT_RULE_FLUSH] = "RULE_FLUSH",
[NFT_COMPAT_SET_ADD] = "SET_ADD",
}; };
char errmsg[256]; char errmsg[256];
char tcr[128]; char tcr[128];
...@@ -371,10 +354,14 @@ static int mnl_append_error(const struct nft_handle *h, ...@@ -371,10 +354,14 @@ static int mnl_append_error(const struct nft_handle *h,
nftnl_rule_get_str(o->rule, NFTNL_RULE_CHAIN)); nftnl_rule_get_str(o->rule, NFTNL_RULE_CHAIN));
#if 0 #if 0
{ {
nft_rule_print_save(o->rule, NFT_RULE_APPEND, FMT_NOCOUNTS); nft_rule_print_save(h, o->rule, NFT_RULE_APPEND, FMT_NOCOUNTS);
} }
#endif #endif
break; break;
case NFT_COMPAT_SET_ADD:
snprintf(tcr, sizeof(tcr), "set %s",
nftnl_set_get_str(o->set, NFTNL_SET_NAME));
break;
} }
return snprintf(buf, len, "%s: %s", errmsg, tcr); return snprintf(buf, len, "%s: %s", errmsg, tcr);
...@@ -404,6 +391,13 @@ batch_table_add(struct nft_handle *h, enum obj_update_type type, ...@@ -404,6 +391,13 @@ batch_table_add(struct nft_handle *h, enum obj_update_type type,
return batch_add(h, type, t); return batch_add(h, type, t);
} }
static struct obj_update *
batch_set_add(struct nft_handle *h, enum obj_update_type type,
struct nftnl_set *s)
{
return batch_add(h, type, s);
}
static int batch_chain_add(struct nft_handle *h, enum obj_update_type type, static int batch_chain_add(struct nft_handle *h, enum obj_update_type type,
struct nftnl_chain *c) struct nftnl_chain *c)
{ {
...@@ -647,7 +641,7 @@ static int nft_table_builtin_add(struct nft_handle *h, ...@@ -647,7 +641,7 @@ static int nft_table_builtin_add(struct nft_handle *h,
if (t == NULL) if (t == NULL)
return -1; return -1;
nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name); nftnl_table_set_str(t, NFTNL_TABLE_NAME, _t->name);
ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t) ? 0 : - 1; ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t) ? 0 : - 1;
...@@ -664,12 +658,12 @@ nft_chain_builtin_alloc(const struct builtin_table *table, ...@@ -664,12 +658,12 @@ nft_chain_builtin_alloc(const struct builtin_table *table,
if (c == NULL) if (c == NULL)
return NULL; return NULL;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table->name); nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table->name);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain->name); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain->name);
nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook); nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook);
nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio); nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy); nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy);
nftnl_chain_set(c, NFTNL_CHAIN_TYPE, (char *)chain->type); nftnl_chain_set_str(c, NFTNL_CHAIN_TYPE, chain->type);
return c; return c;
} }
...@@ -688,31 +682,25 @@ static void nft_chain_builtin_add(struct nft_handle *h, ...@@ -688,31 +682,25 @@ static void nft_chain_builtin_add(struct nft_handle *h,
nftnl_chain_list_add_tail(c, h->cache->table[table->type].chains); nftnl_chain_list_add_tail(c, h->cache->table[table->type].chains);
} }
static const struct builtin_table * /* find if built-in table already exists */
__nft_table_builtin_find(const struct builtin_table *tables, const char *table) const struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{ {
int i; int i;
bool found = false; bool found = false;
for (i = 0; i < NFT_TABLE_MAX; i++) { for (i = 0; i < NFT_TABLE_MAX; i++) {
if (tables[i].name == NULL) if (h->tables[i].name == NULL)
continue; continue;
if (strcmp(tables[i].name, table) != 0) if (strcmp(h->tables[i].name, table) != 0)
continue; continue;
found = true; found = true;
break; break;
} }
return found ? &tables[i] : NULL; return found ? &h->tables[i] : NULL;
}
/* find if built-in table already exists */
const struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{
return __nft_table_builtin_find(h->tables, table);
} }
/* find if built-in chain already exists */ /* find if built-in chain already exists */
...@@ -735,15 +723,16 @@ nft_chain_builtin_find(const struct builtin_table *t, const char *chain) ...@@ -735,15 +723,16 @@ nft_chain_builtin_find(const struct builtin_table *t, const char *chain)
static void nft_chain_builtin_init(struct nft_handle *h, static void nft_chain_builtin_init(struct nft_handle *h,
const struct builtin_table *table) const struct builtin_table *table)
{ {
struct nftnl_chain_list *list = nft_chain_list_get(h, table->name); struct nftnl_chain_list *list;
struct nftnl_chain *c; struct nftnl_chain *c;
int i; int i;
if (!list)
return;
/* Initialize built-in chains if they don't exist yet */ /* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) { for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
list = nft_chain_list_get(h, table->name,
table->chains[i].name);
if (!list)
continue;
c = nftnl_chain_list_lookup_byname(list, table->chains[i].name); c = nftnl_chain_list_lookup_byname(list, table->chains[i].name);
if (c != NULL) if (c != NULL)
...@@ -782,7 +771,7 @@ static bool nft_chain_builtin(struct nftnl_chain *c) ...@@ -782,7 +771,7 @@ static bool nft_chain_builtin(struct nftnl_chain *c)
return nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM) != NULL; return nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM) != NULL;
} }
static int nft_restart(struct nft_handle *h) int nft_restart(struct nft_handle *h)
{ {
mnl_socket_close(h->nl); mnl_socket_close(h->nl);
...@@ -794,7 +783,8 @@ static int nft_restart(struct nft_handle *h) ...@@ -794,7 +783,8 @@ static int nft_restart(struct nft_handle *h)
return -1; return -1;
h->portid = mnl_socket_get_portid(h->nl); h->portid = mnl_socket_get_portid(h->nl);
nlbuffsiz = 0; h->nlsndbuffsiz = 0;
h->nlrcvbuffsiz = 0;
return 0; return 0;
} }
...@@ -820,67 +810,6 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t) ...@@ -820,67 +810,6 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t)
return 0; return 0;
} }
static int __flush_rule_cache(struct nftnl_rule *r, void *data)
{
nftnl_rule_list_del(r);
nftnl_rule_free(r);
return 0;
}
static void flush_rule_cache(struct nftnl_chain *c)
{
nftnl_rule_foreach(c, __flush_rule_cache, NULL);
}
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
{
nftnl_chain_list_del(c);
nftnl_chain_free(c);
return 0;
}
static int flush_cache(struct nft_cache *c, const struct builtin_table *tables,
const char *tablename)
{
const struct builtin_table *table;
int i;
if (tablename) {
table = __nft_table_builtin_find(tables, tablename);
if (!table || !c->table[table->type].chains)
return 0;
nftnl_chain_list_foreach(c->table[table->type].chains,
__flush_chain_cache, NULL);
return 0;
}
for (i = 0; i < NFT_TABLE_MAX; i++) {
if (tables[i].name == NULL)
continue;
if (!c->table[i].chains)
continue;
nftnl_chain_list_free(c->table[i].chains);
c->table[i].chains = NULL;
}
nftnl_table_list_free(c->tables);
c->tables = NULL;
return 1;
}
static void flush_chain_cache(struct nft_handle *h, const char *tablename)
{
if (!h->have_cache)
return;
if (flush_cache(h->cache, h->tables, tablename))
h->have_cache = false;
}
void nft_fini(struct nft_handle *h) void nft_fini(struct nft_handle *h)
{ {
flush_chain_cache(h, NULL); flush_chain_cache(h, NULL);
...@@ -1015,13 +944,163 @@ static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m) ...@@ -1015,13 +944,163 @@ static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
return 0; return 0;
} }
int add_match(struct nftnl_rule *r, struct xt_entry_match *m) static struct nftnl_set *add_anon_set(struct nft_handle *h, const char *table,
uint32_t flags, uint32_t key_type,
uint32_t key_len, uint32_t size)
{
static uint32_t set_id = 0;
struct nftnl_set *s;
s = nftnl_set_alloc();
if (!s)
return NULL;
nftnl_set_set_u32(s, NFTNL_SET_FAMILY, h->family);
nftnl_set_set_str(s, NFTNL_SET_TABLE, table);
nftnl_set_set_str(s, NFTNL_SET_NAME, "__set%d");
nftnl_set_set_u32(s, NFTNL_SET_ID, ++set_id);
nftnl_set_set_u32(s, NFTNL_SET_FLAGS,
NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | flags);
nftnl_set_set_u32(s, NFTNL_SET_KEY_TYPE, key_type);
nftnl_set_set_u32(s, NFTNL_SET_KEY_LEN, key_len);
nftnl_set_set_u32(s, NFTNL_SET_DESC_SIZE, size);
return batch_set_add(h, NFT_COMPAT_SET_ADD, s) ? s : NULL;
}
static struct nftnl_expr *
gen_payload(uint32_t base, uint32_t offset, uint32_t len, uint32_t dreg)
{
struct nftnl_expr *e = nftnl_expr_alloc("payload");
if (!e)
return NULL;
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_BASE, base);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET, offset);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_LEN, len);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_DREG, dreg);
return e;
}
static struct nftnl_expr *
gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
{
struct nftnl_expr *e = nftnl_expr_alloc("lookup");
if (!e)
return NULL;
nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SREG, sreg);
nftnl_expr_set_str(e, NFTNL_EXPR_LOOKUP_SET, set_name);
nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SET_ID, set_id);
nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_FLAGS, flags);
return e;
}
/* simplified nftables:include/netlink.h, netlink_padded_len() */
#define NETLINK_ALIGN 4
/* from nftables:include/datatype.h, TYPE_BITS */
#define CONCAT_TYPE_BITS 6
/* from nftables:include/datatype.h, enum datatypes */
#define NFT_DATATYPE_IPADDR 7
#define NFT_DATATYPE_ETHERADDR 9
static int __add_nft_among(struct nft_handle *h, const char *table,
struct nftnl_rule *r, struct nft_among_pair *pairs,
int cnt, bool dst, bool inv, bool ip)
{
uint32_t set_id, type = NFT_DATATYPE_ETHERADDR, len = ETH_ALEN;
/* { !dst, dst } */
static const int eth_addr_off[] = {
offsetof(struct ether_header, ether_shost),
offsetof(struct ether_header, ether_dhost)
};
static const int ip_addr_off[] = {
offsetof(struct iphdr, saddr),
offsetof(struct iphdr, daddr)
};
struct nftnl_expr *e;
struct nftnl_set *s;
int idx = 0;
if (ip) {
type = type << CONCAT_TYPE_BITS | NFT_DATATYPE_IPADDR;
len += sizeof(struct in_addr) + NETLINK_ALIGN - 1;
len &= ~(NETLINK_ALIGN - 1);
}
s = add_anon_set(h, table, 0, type, len, cnt);
if (!s)
return -ENOMEM;
set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);
for (idx = 0; idx < cnt; idx++) {
struct nftnl_set_elem *elem = nftnl_set_elem_alloc();
if (!elem)
return -ENOMEM;
nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY,
&pairs[idx], len);
nftnl_set_elem_add(s, elem);
}
e = gen_payload(NFT_PAYLOAD_LL_HEADER,
eth_addr_off[dst], ETH_ALEN, NFT_REG_1);
if (!e)
return -ENOMEM;
nftnl_rule_add_expr(r, e);
if (ip) {
e = gen_payload(NFT_PAYLOAD_NETWORK_HEADER, ip_addr_off[dst],
sizeof(struct in_addr), NFT_REG32_02);
if (!e)
return -ENOMEM;
nftnl_rule_add_expr(r, e);
}
e = gen_lookup(NFT_REG_1, "__set%d", set_id, inv);
if (!e)
return -ENOMEM;
nftnl_rule_add_expr(r, e);
return 0;
}
static int add_nft_among(struct nft_handle *h,
struct nftnl_rule *r, struct xt_entry_match *m)
{
struct nft_among_data *data = (struct nft_among_data *)m->data;
const char *table = nftnl_rule_get(r, NFTNL_RULE_TABLE);
if ((data->src.cnt && data->src.ip) ||
(data->dst.cnt && data->dst.ip)) {
uint16_t eth_p_ip = htons(ETH_P_IP);
add_meta(r, NFT_META_PROTOCOL);
add_cmp_ptr(r, NFT_CMP_EQ, &eth_p_ip, 2);
}
if (data->src.cnt)
__add_nft_among(h, table, r, data->pairs, data->src.cnt,
false, data->src.inv, data->src.ip);
if (data->dst.cnt)
__add_nft_among(h, table, r, data->pairs + data->src.cnt,
data->dst.cnt, true, data->dst.inv,
data->dst.ip);
return 0;
}
int add_match(struct nft_handle *h,
struct nftnl_rule *r, struct xt_entry_match *m)
{ {
struct nftnl_expr *expr; struct nftnl_expr *expr;
int ret; int ret;
if (!strcmp(m->u.user.name, "limit")) if (!strcmp(m->u.user.name, "limit"))
return add_nft_limit(r, m); return add_nft_limit(r, m);
else if (!strcmp(m->u.user.name, "among"))
return add_nft_among(h, r, m);
expr = nftnl_expr_alloc("match"); expr = nftnl_expr_alloc("match");
if (expr == NULL) if (expr == NULL)
...@@ -1234,10 +1313,10 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table, ...@@ -1234,10 +1313,10 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
return NULL; return NULL;
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, h->family); nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, h->family);
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table); nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain); nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
if (h->ops->add(r, data) < 0) if (h->ops->add(h, r, data) < 0)
goto err; goto err;
return r; return r;
...@@ -1257,9 +1336,15 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, ...@@ -1257,9 +1336,15 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
struct nftnl_rule *r; struct nftnl_rule *r;
int type; int type;
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table); /* Since ebtables user-defined chain policies are implemented as last
* rule in nftables, rule cache is required here to treat them right. */
if (h->family == NFPROTO_BRIDGE) {
c = nft_chain_find(h, table, chain);
if (c && !nft_chain_builtin(c))
nft_build_cache(h, c);
}
nft_fn = nft_rule_append; nft_fn = nft_rule_append;
...@@ -1280,7 +1365,7 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, ...@@ -1280,7 +1365,7 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
} }
if (verbose) if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE); h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
if (ref) { if (ref) {
nftnl_chain_rule_insert_at(r, ref); nftnl_chain_rule_insert_at(r, ref);
...@@ -1298,16 +1383,14 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, ...@@ -1298,16 +1383,14 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
} }
void void
nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
unsigned int format) enum nft_rule_print type, unsigned int format)
{ {
const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN); const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct iptables_command_state cs = {}; struct iptables_command_state cs = {};
struct nft_family_ops *ops; struct nft_family_ops *ops = h->ops;
ops = nft_family_ops_lookup(family); ops->rule_to_cs(h, r, &cs);
ops->rule_to_cs(r, &cs);
if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters) if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters)
ops->save_counters(&cs); ops->save_counters(&cs);
...@@ -1329,106 +1412,6 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, ...@@ -1329,106 +1412,6 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
ops->clear_cs(&cs); ops->clear_cs(&cs);
} }
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nft_handle *h = data;
const struct builtin_table *t;
struct nftnl_chain *c;
c = nftnl_chain_alloc();
if (c == NULL)
goto err;
if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
goto out;
t = nft_table_builtin_find(h,
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
if (!t)
goto out;
nftnl_chain_list_add_tail(c, h->cache->table[t->type].chains);
return MNL_CB_OK;
out:
nftnl_chain_free(c);
err:
return MNL_CB_OK;
}
static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_table *t;
struct nftnl_table_list *list = data;
t = nftnl_table_alloc();
if (t == NULL)
goto err;
if (nftnl_table_nlmsg_parse(nlh, t) < 0)
goto out;
nftnl_table_list_add_tail(t, list);
return MNL_CB_OK;
out:
nftnl_table_free(t);
err:
return MNL_CB_OK;
}
static int fetch_table_cache(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
struct nftnl_table_list *list;
int ret;
list = nftnl_table_list_alloc();
if (list == NULL)
return 0;
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
h->cache->tables = list;
return 1;
}
static int fetch_chain_cache(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
int i, ret;
fetch_table_cache(h);
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
h->cache->table[type].chains = nftnl_chain_list_alloc();
if (!h->cache->table[type].chains)
return -1;
}
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
return ret;
}
static bool nft_rule_is_policy_rule(struct nftnl_rule *r) static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
{ {
const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {}; const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
...@@ -1467,8 +1450,8 @@ static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c) ...@@ -1467,8 +1450,8 @@ static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c)
return last; return last;
} }
static void nft_bridge_chain_postprocess(struct nft_handle *h, void nft_bridge_chain_postprocess(struct nft_handle *h,
struct nftnl_chain *c) struct nftnl_chain *c)
{ {
struct nftnl_rule *last = nft_chain_last_rule(c); struct nftnl_rule *last = nft_chain_last_rule(c);
struct nftnl_expr_iter *iter; struct nftnl_expr_iter *iter;
...@@ -1509,138 +1492,6 @@ static void nft_bridge_chain_postprocess(struct nft_handle *h, ...@@ -1509,138 +1492,6 @@ static void nft_bridge_chain_postprocess(struct nft_handle *h,
out_iter: out_iter:
nftnl_expr_iter_destroy(iter); nftnl_expr_iter_destroy(iter);
} }
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_chain *c = data;
struct nftnl_rule *r;
r = nftnl_rule_alloc();
if (r == NULL)
return MNL_CB_OK;
if (nftnl_rule_nlmsg_parse(nlh, r) < 0) {
nftnl_rule_free(r);
return MNL_CB_OK;
}
nftnl_chain_rule_add_tail(r, c);
return MNL_CB_OK;
}
static int nft_rule_list_update(struct nftnl_chain *c, void *data)
{
struct nft_handle *h = data;
char buf[16536];
struct nlmsghdr *nlh;
struct nftnl_rule *rule;
int ret;
rule = nftnl_rule_alloc();
if (!rule)
return -1;
nftnl_rule_set_str(rule, NFTNL_RULE_TABLE,
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN,
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
NLM_F_DUMP, h->seq);
nftnl_rule_nlmsg_build_payload(nlh, rule);
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
nftnl_rule_free(rule);
if (h->family == NFPROTO_BRIDGE)
nft_bridge_chain_postprocess(h, c);
return 0;
}
static int fetch_rule_cache(struct nft_handle *h)
{
int i;
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
if (nftnl_chain_list_foreach(h->cache->table[type].chains,
nft_rule_list_update, h))
return -1;
}
return 0;
}
static void __nft_build_cache(struct nft_handle *h)
{
uint32_t genid_start, genid_stop;
retry:
mnl_genid_get(h, &genid_start);
fetch_chain_cache(h);
fetch_rule_cache(h);
h->have_cache = true;
mnl_genid_get(h, &genid_stop);
if (genid_start != genid_stop) {
flush_chain_cache(h, NULL);
goto retry;
}
h->nft_genid = genid_start;
}
void nft_build_cache(struct nft_handle *h)
{
if (!h->have_cache)
__nft_build_cache(h);
}
static void __nft_flush_cache(struct nft_handle *h)
{
if (!h->cache_index) {
h->cache_index++;
h->cache = &h->__cache[h->cache_index];
} else {
flush_chain_cache(h, NULL);
}
}
static void nft_rebuild_cache(struct nft_handle *h)
{
if (h->have_cache)
__nft_flush_cache(h);
__nft_build_cache(h);
}
static void nft_release_cache(struct nft_handle *h)
{
if (h->cache_index)
flush_cache(&h->__cache[0], h->tables, NULL);
}
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
const char *table)
{
const struct builtin_table *t;
t = nft_table_builtin_find(h, table);
if (!t)
return NULL;
nft_build_cache(h);
return h->cache->table[t->type].chains;
}
static const char *policy_name[NF_ACCEPT+1] = { static const char *policy_name[NF_ACCEPT+1] = {
[NF_DROP] = "DROP", [NF_DROP] = "DROP",
[NF_ACCEPT] = "ACCEPT", [NF_ACCEPT] = "ACCEPT",
...@@ -1648,12 +1499,10 @@ static const char *policy_name[NF_ACCEPT+1] = { ...@@ -1648,12 +1499,10 @@ static const char *policy_name[NF_ACCEPT+1] = {
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
{ {
struct nft_family_ops *ops = h->ops;
struct nftnl_chain_list_iter *iter; struct nftnl_chain_list_iter *iter;
struct nft_family_ops *ops;
struct nftnl_chain *c; struct nftnl_chain *c;
ops = nft_family_ops_lookup(h->family);
iter = nftnl_chain_list_iter_create(list); iter = nftnl_chain_list_iter_create(list);
if (iter == NULL) if (iter == NULL)
return 0; return 0;
...@@ -1702,7 +1551,7 @@ static int nft_chain_save_rules(struct nft_handle *h, ...@@ -1702,7 +1551,7 @@ static int nft_chain_save_rules(struct nft_handle *h,
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
while (r != NULL) { while (r != NULL) {
nft_rule_print_save(r, NFT_RULE_APPEND, format); nft_rule_print_save(h, r, NFT_RULE_APPEND, format);
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
} }
...@@ -1717,7 +1566,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) ...@@ -1717,7 +1566,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
struct nftnl_chain *c; struct nftnl_chain *c;
int ret = 0; int ret = 0;
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, NULL);
if (!list) if (!list)
return 0; return 0;
...@@ -1727,6 +1576,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) ...@@ -1727,6 +1576,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
c = nftnl_chain_list_iter_next(iter); c = nftnl_chain_list_iter_next(iter);
while (c) { while (c) {
nft_build_cache(h, c);
ret = nft_chain_save_rules(h, c, format); ret = nft_chain_save_rules(h, c, format);
if (ret != 0) if (ret != 0)
break; break;
...@@ -1747,15 +1597,16 @@ __nft_rule_flush(struct nft_handle *h, const char *table, ...@@ -1747,15 +1597,16 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
struct obj_update *obj; struct obj_update *obj;
struct nftnl_rule *r; struct nftnl_rule *r;
if (verbose) if (verbose && chain)
fprintf(stdout, "Flushing chain `%s'\n", chain); fprintf(stdout, "Flushing chain `%s'\n", chain);
r = nftnl_rule_alloc(); r = nftnl_rule_alloc();
if (r == NULL) if (r == NULL)
return; return;
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table); nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain); if (chain)
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
obj = batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r); obj = batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r);
if (!obj) { if (!obj) {
...@@ -1769,29 +1620,34 @@ __nft_rule_flush(struct nft_handle *h, const char *table, ...@@ -1769,29 +1620,34 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
bool verbose) bool verbose)
{ {
int ret = 0;
struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter; struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c; struct nftnl_chain_list *list;
struct nftnl_chain *c = NULL;
int ret = 0;
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) nft_xt_builtin_init(h, table);
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_flush; nft_fn = nft_rule_flush;
list = nft_chain_list_get(h, table); if (chain || verbose) {
if (list == NULL) { list = nft_chain_list_get(h, table, chain);
ret = 1; if (list == NULL) {
goto err; ret = 1;
goto err;
}
} }
if (chain) { if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain); c = nftnl_chain_list_lookup_byname(list, chain);
if (!c) if (!c) {
errno = ENOENT;
return 0; return 0;
}
}
if (chain || !verbose) {
__nft_rule_flush(h, table, chain, verbose, false); __nft_rule_flush(h, table, chain, verbose, false);
flush_rule_cache(c); flush_rule_cache(h, table, c);
return 1; return 1;
} }
...@@ -1803,11 +1659,10 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, ...@@ -1803,11 +1659,10 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
c = nftnl_chain_list_iter_next(iter); c = nftnl_chain_list_iter_next(iter);
while (c != NULL) { while (c != NULL) {
const char *chain_name = chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
__nft_rule_flush(h, table, chain_name, verbose, false); __nft_rule_flush(h, table, chain, verbose, false);
flush_rule_cache(c); flush_rule_cache(h, table, c);
c = nftnl_chain_list_iter_next(iter); c = nftnl_chain_list_iter_next(iter);
} }
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
...@@ -1824,9 +1679,7 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1824,9 +1679,7 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nft_fn = nft_chain_user_add; nft_fn = nft_chain_user_add;
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
if (nft_chain_exists(h, table, chain)) { if (nft_chain_exists(h, table, chain)) {
errno = EEXIST; errno = EEXIST;
...@@ -1837,14 +1690,14 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1837,14 +1690,14 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
if (c == NULL) if (c == NULL)
return 0; return 0;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table); nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
if (h->family == NFPROTO_BRIDGE) if (h->family == NFPROTO_BRIDGE)
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT); nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, chain);
if (list) if (list)
nftnl_chain_list_add(c, list); nftnl_chain_list_add(c, list);
...@@ -1871,8 +1724,8 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table ...@@ -1871,8 +1724,8 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
if (!c) if (!c)
return -1; return -1;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table); nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
created = true; created = true;
} }
...@@ -1884,7 +1737,7 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table ...@@ -1884,7 +1737,7 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, chain);
if (list) if (list)
nftnl_chain_list_add(c, list); nftnl_chain_list_add(c, list);
...@@ -1916,6 +1769,10 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data) ...@@ -1916,6 +1769,10 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
fprintf(stdout, "Deleting chain `%s'\n", fprintf(stdout, "Deleting chain `%s'\n",
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
/* This triggers required policy rule deletion. */
if (h->family == NFPROTO_BRIDGE)
nft_build_cache(h, c);
/* XXX This triggers a fast lookup from the kernel. */ /* XXX This triggers a fast lookup from the kernel. */
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
...@@ -1939,7 +1796,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, ...@@ -1939,7 +1796,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
nft_fn = nft_chain_user_del; nft_fn = nft_chain_user_del;
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, chain);
if (list == NULL) if (list == NULL)
return 0; return 0;
...@@ -1967,7 +1824,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain) ...@@ -1967,7 +1824,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{ {
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, chain);
if (list == NULL) if (list == NULL)
return NULL; return NULL;
...@@ -2003,9 +1860,7 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -2003,9 +1860,7 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
return 0; return 0;
} }
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
/* Config load changed errno. Ensure genuine info for our callers. */ /* Config load changed errno. Ensure genuine info for our callers. */
errno = 0; errno = 0;
...@@ -2023,8 +1878,8 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -2023,8 +1878,8 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
if (c == NULL) if (c == NULL)
return 0; return 0;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table); nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, newname);
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle); nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c); ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
...@@ -2033,13 +1888,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -2033,13 +1888,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
} }
static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
{
nft_build_cache(h);
return h->cache->tables;
}
bool nft_table_find(struct nft_handle *h, const char *tablename) bool nft_table_find(struct nft_handle *h, const char *tablename)
{ {
struct nftnl_table_list_iter *iter; struct nftnl_table_list_iter *iter;
...@@ -2075,8 +1923,8 @@ err: ...@@ -2075,8 +1923,8 @@ err:
} }
int nft_for_each_table(struct nft_handle *h, int nft_for_each_table(struct nft_handle *h,
int (*func)(struct nft_handle *h, const char *tablename, bool counters), int (*func)(struct nft_handle *h, const char *tablename, void *data),
bool counters) void *data)
{ {
struct nftnl_table_list *list; struct nftnl_table_list *list;
struct nftnl_table_list_iter *iter; struct nftnl_table_list_iter *iter;
...@@ -2095,7 +1943,7 @@ int nft_for_each_table(struct nft_handle *h, ...@@ -2095,7 +1943,7 @@ int nft_for_each_table(struct nft_handle *h,
const char *tablename = const char *tablename =
nftnl_table_get(t, NFTNL_TABLE_NAME); nftnl_table_get(t, NFTNL_TABLE_NAME);
func(h, tablename, counters); func(h, tablename, data);
t = nftnl_table_list_iter_next(iter); t = nftnl_table_list_iter_next(iter);
} }
...@@ -2179,8 +2027,7 @@ err_out: ...@@ -2179,8 +2027,7 @@ err_out:
void nft_table_new(struct nft_handle *h, const char *table) void nft_table_new(struct nft_handle *h, const char *table)
{ {
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) nft_xt_builtin_init(h, table);
nft_xt_builtin_init(h, table);
} }
static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r) static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
...@@ -2189,6 +2036,9 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r) ...@@ -2189,6 +2036,9 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
nftnl_rule_list_del(r); nftnl_rule_list_del(r);
if (!nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE))
nftnl_rule_set_u32(r, NFTNL_RULE_ID, ++h->rule_id);
obj = batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r); obj = batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r);
if (!obj) { if (!obj) {
nftnl_rule_free(r); nftnl_rule_free(r);
...@@ -2204,6 +2054,8 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen ...@@ -2204,6 +2054,8 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen
struct nftnl_rule_iter *iter; struct nftnl_rule_iter *iter;
bool found = false; bool found = false;
nft_build_cache(h, c);
if (rulenum >= 0) if (rulenum >= 0)
/* Delete by rule number case */ /* Delete by rule number case */
return nftnl_rule_lookup_byindex(c, rulenum); return nftnl_rule_lookup_byindex(c, rulenum);
...@@ -2214,7 +2066,7 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen ...@@ -2214,7 +2066,7 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
while (r != NULL) { while (r != NULL) {
found = h->ops->rule_find(h->ops, r, data); found = h->ops->rule_find(h, r, data);
if (found) if (found)
break; break;
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
...@@ -2242,7 +2094,7 @@ int nft_rule_check(struct nft_handle *h, const char *chain, ...@@ -2242,7 +2094,7 @@ int nft_rule_check(struct nft_handle *h, const char *chain,
goto fail_enoent; goto fail_enoent;
if (verbose) if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE); h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
return 1; return 1;
fail_enoent: fail_enoent:
...@@ -2271,7 +2123,7 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, ...@@ -2271,7 +2123,7 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
if (ret < 0) if (ret < 0)
errno = ENOMEM; errno = ENOMEM;
if (verbose) if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE); h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
} else } else
errno = ENOENT; errno = ENOENT;
...@@ -2312,7 +2164,7 @@ nft_rule_add(struct nft_handle *h, const char *chain, ...@@ -2312,7 +2164,7 @@ nft_rule_add(struct nft_handle *h, const char *chain,
} }
if (verbose) if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE); h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
return r; return r;
} }
...@@ -2323,9 +2175,7 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, ...@@ -2323,9 +2175,7 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
struct nftnl_rule *r = NULL, *new_rule; struct nftnl_rule *r = NULL, *new_rule;
struct nftnl_chain *c; struct nftnl_chain *c;
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_insert; nft_fn = nft_rule_insert;
...@@ -2423,8 +2273,8 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, ...@@ -2423,8 +2273,8 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
static int static int
__nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
int rulenum, unsigned int format, int rulenum, unsigned int format,
void (*cb)(struct nftnl_rule *r, unsigned int num, void (*cb)(struct nft_handle *h, struct nftnl_rule *r,
unsigned int format)) unsigned int num, unsigned int format))
{ {
struct nftnl_rule_iter *iter; struct nftnl_rule_iter *iter;
struct nftnl_rule *r; struct nftnl_rule *r;
...@@ -2437,7 +2287,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, ...@@ -2437,7 +2287,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
* valid chain but invalid rule number * valid chain but invalid rule number
*/ */
return 1; return 1;
cb(r, rulenum, format); cb(h, r, rulenum, format);
return 1; return 1;
} }
...@@ -2447,7 +2297,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, ...@@ -2447,7 +2297,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
while (r != NULL) { while (r != NULL) {
cb(r, ++rule_ctr, format); cb(h, r, ++rule_ctr, format);
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
} }
...@@ -2476,7 +2326,6 @@ static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c) ...@@ -2476,7 +2326,6 @@ static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c)
} }
static void __nft_print_header(struct nft_handle *h, static void __nft_print_header(struct nft_handle *h,
const struct nft_family_ops *ops,
struct nftnl_chain *c, unsigned int format) struct nftnl_chain *c, unsigned int format)
{ {
const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
...@@ -2492,31 +2341,23 @@ static void __nft_print_header(struct nft_handle *h, ...@@ -2492,31 +2341,23 @@ static void __nft_print_header(struct nft_handle *h,
if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY))
pname = policy_name[nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY)]; pname = policy_name[nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY)];
ops->print_header(format, chain_name, pname, h->ops->print_header(format, chain_name, pname,
&ctrs, basechain, refs - entries, entries); &ctrs, basechain, refs - entries, entries);
} }
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
int rulenum, unsigned int format) int rulenum, unsigned int format)
{ {
const struct nft_family_ops *ops; const struct nft_family_ops *ops = h->ops;
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter; struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c; struct nftnl_chain *c;
bool found = false; bool found = false;
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) nft_assert_table_compatible(h, table, chain);
nft_xt_builtin_init(h, table);
ops = nft_family_ops_lookup(h->family); list = nft_chain_list_get(h, table, chain);
if (!nft_is_table_compatible(h, table)) {
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
return 0;
}
list = nft_chain_list_get(h, table);
if (!list) if (!list)
return 0; return 0;
...@@ -2528,7 +2369,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, ...@@ -2528,7 +2369,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (!rulenum) { if (!rulenum) {
if (ops->print_table_header) if (ops->print_table_header)
ops->print_table_header(table); ops->print_table_header(table);
__nft_print_header(h, ops, c, format); __nft_print_header(h, c, format);
} }
__nft_rule_list(h, c, rulenum, format, ops->print_rule); __nft_rule_list(h, c, rulenum, format, ops->print_rule);
return 1; return 1;
...@@ -2546,7 +2387,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, ...@@ -2546,7 +2387,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (found) if (found)
printf("\n"); printf("\n");
__nft_print_header(h, ops, c, format); __nft_print_header(h, c, format);
__nft_rule_list(h, c, rulenum, format, ops->print_rule); __nft_rule_list(h, c, rulenum, format, ops->print_rule);
found = true; found = true;
...@@ -2557,9 +2398,10 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, ...@@ -2557,9 +2398,10 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
} }
static void static void
list_save(struct nftnl_rule *r, unsigned int num, unsigned int format) list_save(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format)
{ {
nft_rule_print_save(r, NFT_RULE_APPEND, format); nft_rule_print_save(h, r, NFT_RULE_APPEND, format);
} }
static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data) static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data)
...@@ -2612,16 +2454,10 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, ...@@ -2612,16 +2454,10 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
struct nftnl_chain *c; struct nftnl_chain *c;
int ret = 0; int ret = 0;
/* If built-in chains don't exist for this table, create them */ nft_xt_builtin_init(h, table);
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) nft_assert_table_compatible(h, table, chain);
nft_xt_builtin_init(h, table);
if (!nft_is_table_compatible(h, table)) { list = nft_chain_list_get(h, table, chain);
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
return 0;
}
list = nft_chain_list_get(h, table);
if (!list) if (!list)
return 0; return 0;
...@@ -2677,7 +2513,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, ...@@ -2677,7 +2513,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
goto error; goto error;
} }
nft_rule_to_iptables_command_state(r, &cs); nft_rule_to_iptables_command_state(h, r, &cs);
cs.counters.pcnt = cs.counters.bcnt = 0; cs.counters.pcnt = cs.counters.bcnt = 0;
...@@ -2698,6 +2534,39 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type, ...@@ -2698,6 +2534,39 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
nftnl_table_nlmsg_build_payload(nlh, table); nftnl_table_nlmsg_build_payload(nlh, table);
} }
static void nft_compat_set_batch_add(struct nft_handle *h, uint16_t type,
uint16_t flags, uint32_t seq,
struct nftnl_set *set)
{
struct nlmsghdr *nlh;
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
type, h->family, flags, seq);
nftnl_set_nlmsg_build_payload(nlh, set);
}
static void nft_compat_setelem_batch_add(struct nft_handle *h, uint16_t type,
uint16_t flags, uint32_t *seq,
struct nftnl_set *set)
{
struct nftnl_set_elems_iter *iter;
struct nlmsghdr *nlh;
iter = nftnl_set_elems_iter_create(set);
if (!iter)
return;
while (nftnl_set_elems_iter_cur(iter)) {
(*seq)++;
mnl_nft_batch_continue(h->batch);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
type, h->family, flags, *seq);
if (nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter) <= 0)
break;
}
nftnl_set_elems_iter_destroy(iter);
}
static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type, static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
uint16_t flags, uint32_t seq, uint16_t flags, uint32_t seq,
struct nftnl_chain *chain) struct nftnl_chain *chain)
...@@ -2747,6 +2616,9 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o) ...@@ -2747,6 +2616,9 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_RULE_FLUSH: case NFT_COMPAT_RULE_FLUSH:
nftnl_rule_free(o->rule); nftnl_rule_free(o->rule);
break; break;
case NFT_COMPAT_SET_ADD:
nftnl_set_free(o->set);
break;
} }
h->obj_list_num--; h->obj_list_num--;
list_del(&o->head); list_del(&o->head);
...@@ -2813,6 +2685,7 @@ static void nft_refresh_transaction(struct nft_handle *h) ...@@ -2813,6 +2685,7 @@ static void nft_refresh_transaction(struct nft_handle *h)
case NFT_COMPAT_RULE_REPLACE: case NFT_COMPAT_RULE_REPLACE:
case NFT_COMPAT_RULE_DELETE: case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH: case NFT_COMPAT_RULE_FLUSH:
case NFT_COMPAT_SET_ADD:
break; break;
} }
} }
...@@ -2903,6 +2776,13 @@ retry: ...@@ -2903,6 +2776,13 @@ retry:
nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0, nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
n->seq, n->rule); n->seq, n->rule);
break; break;
case NFT_COMPAT_SET_ADD:
nft_compat_set_batch_add(h, NFT_MSG_NEWSET,
NLM_F_CREATE, n->seq, n->set);
nft_compat_setelem_batch_add(h, NFT_MSG_NEWSETELEM,
NLM_F_CREATE, &n->seq, n->set);
seq = n->seq;
break;
} }
mnl_nft_batch_continue(h->batch); mnl_nft_batch_continue(h->batch);
...@@ -2917,7 +2797,7 @@ retry: ...@@ -2917,7 +2797,7 @@ retry:
} }
errno = 0; errno = 0;
ret = mnl_batch_talk(h->nl, h->batch, &h->err_list); ret = mnl_batch_talk(h, seq);
if (ret && errno == ERESTART) { if (ret && errno == ERESTART) {
nft_rebuild_cache(h); nft_rebuild_cache(h);
...@@ -3039,6 +2919,8 @@ int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, ...@@ -3039,6 +2919,8 @@ int ebt_set_user_chain_policy(struct nft_handle *h, const char *table,
else else
return 0; return 0;
nft_build_cache(h, c);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval); nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval);
return 1; return 1;
} }
...@@ -3065,11 +2947,15 @@ static void nft_bridge_commit_prepare(struct nft_handle *h) ...@@ -3065,11 +2947,15 @@ static void nft_bridge_commit_prepare(struct nft_handle *h)
int nft_commit(struct nft_handle *h) int nft_commit(struct nft_handle *h)
{ {
if (h->family == NFPROTO_BRIDGE)
nft_bridge_commit_prepare(h);
return nft_action(h, NFT_COMPAT_COMMIT); return nft_action(h, NFT_COMPAT_COMMIT);
} }
int nft_bridge_commit(struct nft_handle *h)
{
nft_bridge_commit_prepare(h);
return nft_commit(h);
}
int nft_abort(struct nft_handle *h) int nft_abort(struct nft_handle *h)
{ {
return nft_action(h, NFT_COMPAT_ABORT); return nft_action(h, NFT_COMPAT_ABORT);
...@@ -3204,7 +3090,7 @@ const char *nft_strerror(int err) ...@@ -3204,7 +3090,7 @@ const char *nft_strerror(int err)
{ NULL, ENOENT, "No chain/target/match by that name" }, { NULL, ENOENT, "No chain/target/match by that name" },
}; };
for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { for (i = 0; i < ARRAY_SIZE(table); i++) {
if ((!table[i].fn || table[i].fn == nft_fn) if ((!table[i].fn || table[i].fn == nft_fn)
&& table[i].err == err) && table[i].err == err)
return table[i].message; return table[i].message;
...@@ -3213,136 +3099,42 @@ const char *nft_strerror(int err) ...@@ -3213,136 +3099,42 @@ const char *nft_strerror(int err)
return strerror(err); return strerror(err);
} }
static void xtables_config_perror(uint32_t flags, const char *fmt, ...) static int recover_rule_compat(struct nftnl_rule *r)
{
va_list args;
va_start(args, fmt);
if (flags & NFT_LOAD_VERBOSE)
vfprintf(stderr, fmt, args);
va_end(args);
}
static int __nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags)
{ {
struct nftnl_table_list *table_list = NULL; struct nftnl_expr_iter *iter;
struct nftnl_chain_list *chain_list = NULL; struct nftnl_expr *e;
struct nftnl_table_list_iter *titer = NULL; uint32_t reg;
struct nftnl_chain_list_iter *citer = NULL; int ret = -1;
struct nftnl_table *table;
struct nftnl_chain *chain;
uint32_t table_family, chain_family;
bool found = false;
table_list = nftnl_table_list_alloc();
chain_list = nftnl_chain_list_alloc();
if (xtables_config_parse(filename, table_list, chain_list) < 0) {
if (errno == ENOENT) {
xtables_config_perror(flags,
"configuration file `%s' does not exists\n",
filename);
} else {
xtables_config_perror(flags,
"Fatal error parsing config file: %s\n",
strerror(errno));
}
goto err;
}
/* Stage 1) create tables */
titer = nftnl_table_list_iter_create(table_list);
while ((table = nftnl_table_list_iter_next(titer)) != NULL) {
table_family = nftnl_table_get_u32(table,
NFTNL_TABLE_FAMILY);
if (h->family != table_family)
continue;
found = true;
if (batch_table_add(h, NFT_COMPAT_TABLE_ADD, table) < 0) {
if (errno == EEXIST) {
xtables_config_perror(flags,
"table `%s' already exists, skipping\n",
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
} else {
xtables_config_perror(flags,
"table `%s' cannot be create, reason `%s'. Exitting\n",
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME),
strerror(errno));
goto err;
}
continue;
}
xtables_config_perror(flags, "table `%s' has been created\n",
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
}
nftnl_table_list_iter_destroy(titer);
nftnl_table_list_free(table_list);
if (!found)
goto err;
/* Stage 2) create chains */
citer = nftnl_chain_list_iter_create(chain_list);
while ((chain = nftnl_chain_list_iter_next(citer)) != NULL) {
chain_family = nftnl_chain_get_u32(chain,
NFTNL_CHAIN_TABLE);
if (h->family != chain_family)
continue;
if (batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, chain) < 0) {
if (errno == EEXIST) {
xtables_config_perror(flags,
"chain `%s' already exists in table `%s', skipping\n",
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
} else {
xtables_config_perror(flags,
"chain `%s' cannot be create, reason `%s'. Exitting\n",
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
strerror(errno));
goto err;
}
continue;
}
xtables_config_perror(flags,
"chain `%s' in table `%s' has been created\n",
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
}
nftnl_chain_list_iter_destroy(citer);
nftnl_chain_list_free(chain_list);
h->config_done = 1;
return 0; iter = nftnl_expr_iter_create(r);
if (!iter)
return -1;
err: next_expr:
nftnl_table_list_free(table_list); e = nftnl_expr_iter_next(iter);
nftnl_chain_list_free(chain_list); if (!e)
goto out;
if (titer != NULL) if (strcmp("meta", nftnl_expr_get_str(e, NFTNL_EXPR_NAME)) ||
nftnl_table_list_iter_destroy(titer); nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY) != NFT_META_L4PROTO)
if (citer != NULL) goto next_expr;
nftnl_chain_list_iter_destroy(citer);
h->config_done = -1; reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
return -1; e = nftnl_expr_iter_next(iter);
} if (!e)
goto out;
int nft_xtables_config_load(struct nft_handle *h, const char *filename, if (strcmp("cmp", nftnl_expr_get_str(e, NFTNL_EXPR_NAME)) ||
uint32_t flags) reg != nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG))
{ goto next_expr;
if (!h->config_done)
return __nft_xtables_config_load(h, filename, flags);
return h->config_done; add_compat(r, nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA),
nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ);
ret = 0;
out:
nftnl_expr_iter_destroy(iter);
return ret;
} }
struct chain_zero_data { struct chain_zero_data {
...@@ -3370,6 +3162,8 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data) ...@@ -3370,6 +3162,8 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
return -1; return -1;
} }
nft_build_cache(h, c);
iter = nftnl_rule_iter_create(c); iter = nftnl_rule_iter_create(c);
if (iter == NULL) if (iter == NULL)
return -1; return -1;
...@@ -3407,6 +3201,7 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data) ...@@ -3407,6 +3201,7 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
* Unset RULE_POSITION for older kernels, we want to replace * Unset RULE_POSITION for older kernels, we want to replace
* rule based on its handle only. * rule based on its handle only.
*/ */
recover_rule_compat(r);
nftnl_rule_unset(r, NFTNL_RULE_POSITION); nftnl_rule_unset(r, NFTNL_RULE_POSITION);
if (!batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r)) { if (!batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r)) {
nftnl_rule_iter_destroy(iter); nftnl_rule_iter_destroy(iter);
...@@ -3431,7 +3226,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, ...@@ -3431,7 +3226,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nftnl_chain *c; struct nftnl_chain *c;
int ret = 0; int ret = 0;
list = nft_chain_list_get(h, table); list = nft_chain_list_get(h, table, chain);
if (list == NULL) if (list == NULL)
goto err; goto err;
...@@ -3460,9 +3255,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag) ...@@ -3460,9 +3255,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag)
return NFT_CMP_EQ; return NFT_CMP_EQ;
} }
#define NFT_COMPAT_EXPR_MAX 8 static const char *supported_exprs[] = {
static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
"match", "match",
"target", "target",
"payload", "payload",
...@@ -3470,7 +3263,8 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = { ...@@ -3470,7 +3263,8 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
"cmp", "cmp",
"bitwise", "bitwise",
"counter", "counter",
"immediate" "immediate",
"lookup",
}; };
...@@ -3479,7 +3273,7 @@ static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data) ...@@ -3479,7 +3273,7 @@ static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data)
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
int i; int i;
for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) { for (i = 0; i < ARRAY_SIZE(supported_exprs); i++) {
if (strcmp(supported_exprs[i], name) == 0) if (strcmp(supported_exprs[i], name) == 0)
return 0; return 0;
} }
...@@ -3506,6 +3300,8 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) ...@@ -3506,6 +3300,8 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
enum nf_inet_hooks hook; enum nf_inet_hooks hook;
int prio; int prio;
nft_build_cache(h, c);
if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL)) if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL))
return -1; return -1;
...@@ -3533,11 +3329,12 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) ...@@ -3533,11 +3329,12 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
return 0; return 0;
} }
bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) bool nft_is_table_compatible(struct nft_handle *h,
const char *table, const char *chain)
{ {
struct nftnl_chain_list *clist; struct nftnl_chain_list *clist;
clist = nft_chain_list_get(h, tablename); clist = nft_chain_list_get(h, table, chain);
if (clist == NULL) if (clist == NULL)
return false; return false;
...@@ -3546,3 +3343,22 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) ...@@ -3546,3 +3343,22 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
return true; return true;
} }
void nft_assert_table_compatible(struct nft_handle *h,
const char *table, const char *chain)
{
const char *pfx = "", *sfx = "";
if (nft_is_table_compatible(h, table, chain))
return;
if (chain) {
pfx = "chain `";
sfx = "' in ";
} else {
chain = "";
}
xtables_error(OTHER_PROBLEM,
"%s%s%stable `%s' is incompatible, use 'nft' tool.\n",
pfx, chain, sfx, table);
}
...@@ -27,10 +27,19 @@ struct builtin_table { ...@@ -27,10 +27,19 @@ struct builtin_table {
struct builtin_chain chains[NF_INET_NUMHOOKS]; struct builtin_chain chains[NF_INET_NUMHOOKS];
}; };
enum nft_cache_level {
NFT_CL_NONE,
NFT_CL_TABLES,
NFT_CL_CHAINS,
NFT_CL_SETS,
NFT_CL_RULES
};
struct nft_cache { struct nft_cache {
struct nftnl_table_list *tables; struct nftnl_table_list *tables;
struct { struct {
struct nftnl_chain_list *chains; struct nftnl_chain_list *chains;
struct nftnl_set_list *sets;
bool initialized; bool initialized;
} table[NFT_TABLE_MAX]; } table[NFT_TABLE_MAX];
}; };
...@@ -38,6 +47,8 @@ struct nft_cache { ...@@ -38,6 +47,8 @@ struct nft_cache {
struct nft_handle { struct nft_handle {
int family; int family;
struct mnl_socket *nl; struct mnl_socket *nl;
int nlsndbuffsiz;
int nlrcvbuffsiz;
uint32_t portid; uint32_t portid;
uint32_t seq; uint32_t seq;
uint32_t nft_genid; uint32_t nft_genid;
...@@ -51,7 +62,7 @@ struct nft_handle { ...@@ -51,7 +62,7 @@ struct nft_handle {
unsigned int cache_index; unsigned int cache_index;
struct nft_cache __cache[2]; struct nft_cache __cache[2];
struct nft_cache *cache; struct nft_cache *cache;
bool have_cache; enum nft_cache_level cache_level;
bool restore; bool restore;
bool noflush; bool noflush;
int8_t config_done; int8_t config_done;
...@@ -71,7 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, ...@@ -71,7 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
void *data); void *data);
int nft_init(struct nft_handle *h, const struct builtin_table *t); int nft_init(struct nft_handle *h, const struct builtin_table *t);
void nft_fini(struct nft_handle *h); void nft_fini(struct nft_handle *h);
void nft_build_cache(struct nft_handle *h); int nft_restart(struct nft_handle *h);
/* /*
* Operations with tables. * Operations with tables.
...@@ -79,7 +90,7 @@ void nft_build_cache(struct nft_handle *h); ...@@ -79,7 +90,7 @@ void nft_build_cache(struct nft_handle *h);
struct nftnl_table; struct nftnl_table;
struct nftnl_chain_list; struct nftnl_chain_list;
int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, const char *tablename, bool counters), bool counters); int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, const char *tablename, void *data), void *data);
bool nft_table_find(struct nft_handle *h, const char *tablename); bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list); int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
int nft_table_flush(struct nft_handle *h, const char *table); int nft_table_flush(struct nft_handle *h, const char *table);
...@@ -92,8 +103,6 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c ...@@ -92,8 +103,6 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c
struct nftnl_chain; struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
const char *table);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose);
...@@ -102,6 +111,9 @@ int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *t ...@@ -102,6 +111,9 @@ int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *t
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose);
const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain); const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain);
bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain); bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain);
void nft_bridge_chain_postprocess(struct nft_handle *h,
struct nftnl_chain *c);
/* /*
* Operations with rule-set. * Operations with rule-set.
...@@ -125,7 +137,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char * ...@@ -125,7 +137,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *
*/ */
int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes); int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes);
int add_verdict(struct nftnl_rule *r, int verdict); int add_verdict(struct nftnl_rule *r, int verdict);
int add_match(struct nftnl_rule *r, struct xt_entry_match *m); int add_match(struct nft_handle *h, struct nftnl_rule *r, struct xt_entry_match *m);
int add_target(struct nftnl_rule *r, struct xt_entry_target *t); int add_target(struct nftnl_rule *r, struct xt_entry_target *t);
int add_jumpto(struct nftnl_rule *r, const char *name, int verdict); int add_jumpto(struct nftnl_rule *r, const char *name, int verdict);
int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set); int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set);
...@@ -136,8 +148,8 @@ enum nft_rule_print { ...@@ -136,8 +148,8 @@ enum nft_rule_print {
NFT_RULE_DEL, NFT_RULE_DEL,
}; };
void nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, void nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
unsigned int format); enum nft_rule_print type, unsigned int format);
uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag); uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);
...@@ -145,6 +157,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag); ...@@ -145,6 +157,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);
* global commit and abort * global commit and abort
*/ */
int nft_commit(struct nft_handle *h); int nft_commit(struct nft_handle *h);
int nft_bridge_commit(struct nft_handle *h);
int nft_abort(struct nft_handle *h); int nft_abort(struct nft_handle *h);
int nft_abort_policy_rule(struct nft_handle *h, const char *table); int nft_abort_policy_rule(struct nft_handle *h, const char *table);
...@@ -168,22 +181,6 @@ int nft_init_eb(struct nft_handle *h, const char *pname); ...@@ -168,22 +181,6 @@ int nft_init_eb(struct nft_handle *h, const char *pname);
int ebt_get_current_chain(const char *chain); int ebt_get_current_chain(const char *chain);
int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table, bool restore); int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table, bool restore);
/*
* Parse config for tables and chain helper functions
*/
#define XTABLES_CONFIG_DEFAULT "/etc/xtables.conf"
struct nftnl_table_list;
struct nftnl_chain_list;
extern int xtables_config_parse(const char *filename, struct nftnl_table_list *table_list, struct nftnl_chain_list *chain_list);
enum {
NFT_LOAD_VERBOSE = (1 << 0),
};
int nft_xtables_config_load(struct nft_handle *h, const char *filename, uint32_t flags);
/* /*
* Translation from iptables to nft * Translation from iptables to nft
*/ */
...@@ -211,7 +208,10 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain, ...@@ -211,7 +208,10 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain,
void nft_rule_to_arpt_entry(struct nftnl_rule *r, struct arpt_entry *fw); void nft_rule_to_arpt_entry(struct nftnl_rule *r, struct arpt_entry *fw);
bool nft_is_table_compatible(struct nft_handle *h, const char *name); bool nft_is_table_compatible(struct nft_handle *h,
const char *table, const char *chain);
void nft_assert_table_compatible(struct nft_handle *h,
const char *table, const char *chain);
int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, int ebt_set_user_chain_policy(struct nft_handle *h, const char *table,
const char *chain, const char *policy); const char *chain, const char *policy);
......
...@@ -38,6 +38,14 @@ while [ -n "$1" ]; do ...@@ -38,6 +38,14 @@ while [ -n "$1" ]; do
HOST=y HOST=y
shift shift
;; ;;
-l|--legacy)
LEGACY_ONLY=y
shift
;;
-n|--nft)
NFT_ONLY=y
shift
;;
*${RETURNCODE_SEPARATOR}+([0-9])) *${RETURNCODE_SEPARATOR}+([0-9]))
SINGLE+=" $1" SINGLE+=" $1"
VERBOSE=y VERBOSE=y
...@@ -98,19 +106,23 @@ do_test() { ...@@ -98,19 +106,23 @@ do_test() {
} }
echo "" echo ""
for testfile in $(find_tests);do if [ "$NFT_ONLY" != "y" ]; then
do_test "$testfile" "$XTABLES_LEGACY_MULTI" for testfile in $(find_tests);do
done do_test "$testfile" "$XTABLES_LEGACY_MULTI"
msg_info "legacy results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))" done
msg_info "legacy results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
fi
legacy_ok=$ok legacy_ok=$ok
legacy_fail=$failed legacy_fail=$failed
ok=0 ok=0
failed=0 failed=0
for testfile in $(find_tests);do if [ "$LEGACY_ONLY" != "y" ]; then
do_test "$testfile" "$XTABLES_NFT_MULTI" for testfile in $(find_tests);do
done do_test "$testfile" "$XTABLES_NFT_MULTI"
msg_info "nft results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))" done
msg_info "nft results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
fi
ok=$((legacy_ok+ok)) ok=$((legacy_ok+ok))
failed=$((legacy_fail+failed)) failed=$((legacy_fail+failed))
......
...@@ -50,13 +50,12 @@ DUMP='*filter ...@@ -50,13 +50,12 @@ DUMP='*filter
-A foo -j MARK --set-mark 12345 -A foo -j MARK --set-mark 12345
-A foo -j ACCEPT --opcode 1 -A foo -j ACCEPT --opcode 1
-A foo -j ACCEPT --proto-type 0x800 -A foo -j ACCEPT --proto-type 0x800
-A foo -j ACCEPT -i lo --opcode 1 --proto-type 0x800 -A foo -j ACCEPT -i lo --opcode 1 --proto-type 0x800'
'
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save) diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save | grep -v "^#")
# make sure dump can be restored and check it didn't change # make sure dump can be restored and check it didn't change
$XT_MULTI arptables -F $XT_MULTI arptables -F
$XT_MULTI arptables-restore <<<$DUMP $XT_MULTI arptables-restore <<<$DUMP
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save) diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save | grep -v "^#")
...@@ -11,8 +11,7 @@ set -e ...@@ -11,8 +11,7 @@ set -e
DUMP='*filter DUMP='*filter
:OUTPUT ACCEPT :OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1 -A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2 -A OUTPUT -j mangle --mangle-ip-d 10.0.0.2'
'
# note how mangle-ip-s is unset in second rule # note how mangle-ip-s is unset in second rule
...@@ -20,8 +19,7 @@ EXPECT='*filter ...@@ -20,8 +19,7 @@ EXPECT='*filter
:INPUT ACCEPT :INPUT ACCEPT
:OUTPUT ACCEPT :OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1 -A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2 -A OUTPUT -j mangle --mangle-ip-d 10.0.0.2'
'
$XT_MULTI arptables -F $XT_MULTI arptables -F
$XT_MULTI arptables-restore <<<$DUMP $XT_MULTI arptables-restore <<<$DUMP
......
...@@ -58,7 +58,6 @@ EXPECT='*filter ...@@ -58,7 +58,6 @@ EXPECT='*filter
-A INPUT -j MARK -i eth23 --set-mark 42 -A INPUT -j MARK -i eth23 --set-mark 42
-A OUTPUT -j CLASSIFY -o eth23 --set-class 23:42 -A OUTPUT -j CLASSIFY -o eth23 --set-class 23:42
-A OUTPUT -j foo -o eth23 -A OUTPUT -j foo -o eth23
-A foo -j mangle -o eth23 --mangle-ip-s 10.0.0.1 -A foo -j mangle -o eth23 --mangle-ip-s 10.0.0.1'
'
diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables-save) diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables-save | grep -v '^#')
#!/bin/sh #!/bin/sh
get_entries_count() { # (chain)
$XT_MULTI ebtables -L $1 | sed -n 's/.*entries: \([0-9]*\).*/\1/p'
}
set -x set -x
case "$XT_MULTI" in case "$XT_MULTI" in
*/xtables-nft-multi) */xtables-nft-multi)
...@@ -28,32 +32,32 @@ case "$XT_MULTI" in ...@@ -28,32 +32,32 @@ case "$XT_MULTI" in
exit 1 exit 1
fi fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0' entries=$(get_entries_count FOO)
if [ $? -ne 0 ]; then if [ $entries -ne 0 ]; then
echo "Unexpected entries count in empty unreferenced chain" echo "Unexpected entries count in empty unreferenced chain (expected 0, have $entries)"
$XT_MULTI ebtables -L $XT_MULTI ebtables -L
exit 1 exit 1
fi fi
$XT_MULTI ebtables -A FORWARD -j FOO $XT_MULTI ebtables -A FORWARD -j FOO
$XT_MULTI ebtables -L FORWARD | grep -q 'entries: 1' entries=$(get_entries_count FORWARD)
if [ $? -ne 0 ]; then if [ $entries -ne 1 ]; then
echo "Unexpected entries count in FORWARD chain" echo "Unexpected entries count in FORWARD chain (expected 1, have $entries)"
$XT_MULTI ebtables -L $XT_MULTI ebtables -L
exit 1 exit 1
fi fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0' entries=$(get_entries_count FOO)
if [ $? -ne 0 ]; then if [ $entries -ne 0 ]; then
echo "Unexpected entries count in empty referenced chain" echo "Unexpected entries count in empty referenced chain (expected 0, have $entries)"
$XT_MULTI ebtables -L $XT_MULTI ebtables -L
exit 1 exit 1
fi fi
$XT_MULTI ebtables -A FOO -j ACCEPT $XT_MULTI ebtables -A FOO -j ACCEPT
$XT_MULTI ebtables -L FOO | grep -q 'entries: 1' entries=$(get_entries_count FOO)
if [ $? -ne 0 ]; then if [ $entries -ne 1 ]; then
echo "Unexpected entries count in non-empty referenced chain" echo "Unexpected entries count in non-empty referenced chain (expected 1, have $entries)"
$XT_MULTI ebtables -L $XT_MULTI ebtables -L
exit 1 exit 1
fi fi
......
...@@ -99,7 +99,6 @@ DUMP='*filter ...@@ -99,7 +99,6 @@ DUMP='*filter
-A foo --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT -A foo --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT
-A foo --pkttype-type multicast --log-level notice --log-prefix "" -j CONTINUE -A foo --pkttype-type multicast --log-level notice --log-prefix "" -j CONTINUE
-A foo --pkttype-type multicast --limit 100/sec --limit-burst 5 -j ACCEPT -A foo --pkttype-type multicast --limit 100/sec --limit-burst 5 -j ACCEPT
*nat *nat
:PREROUTING ACCEPT :PREROUTING ACCEPT
:OUTPUT DROP :OUTPUT DROP
...@@ -107,8 +106,7 @@ DUMP='*filter ...@@ -107,8 +106,7 @@ DUMP='*filter
:nat_foo DROP :nat_foo DROP
-A PREROUTING -j redirect -A PREROUTING -j redirect
-A OUTPUT -j ACCEPT -A OUTPUT -j ACCEPT
-A POSTROUTING -j ACCEPT -A POSTROUTING -j ACCEPT'
'
diff -u <(echo -e "$DUMP") <($XT_MULTI ebtables-save | grep -v '^#') diff -u <(echo -e "$DUMP") <($XT_MULTI ebtables-save | grep -v '^#')
......
...@@ -13,8 +13,7 @@ DUMP='*filter ...@@ -13,8 +13,7 @@ DUMP='*filter
-A FORWARD --limit 100 --limit-burst 42 -j ACCEPT -A FORWARD --limit 100 --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000 -j ACCEPT -A FORWARD --limit 1000 -j ACCEPT
-A FORWARD --log --log-prefix "foobar" -A FORWARD --log --log-prefix "foobar"
-A FORWARD --log -A FORWARD --log'
'
# note how limit-burst is 5 in second rule and log-prefix empty in fourth one # note how limit-burst is 5 in second rule and log-prefix empty in fourth one
...@@ -25,8 +24,7 @@ EXPECT='*filter ...@@ -25,8 +24,7 @@ EXPECT='*filter
-A FORWARD --limit 100/sec --limit-burst 42 -j ACCEPT -A FORWARD --limit 100/sec --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000/sec --limit-burst 5 -j ACCEPT -A FORWARD --limit 1000/sec --limit-burst 5 -j ACCEPT
-A FORWARD --log-level notice --log-prefix "foobar" -j CONTINUE -A FORWARD --log-level notice --log-prefix "foobar" -j CONTINUE
-A FORWARD --log-level notice --log-prefix "" -j CONTINUE -A FORWARD --log-level notice --log-prefix "" -j CONTINUE'
'
$XT_MULTI ebtables --init-table $XT_MULTI ebtables --init-table
$XT_MULTI ebtables-restore <<<$DUMP $XT_MULTI ebtables-restore <<<$DUMP
......
#!/bin/bash
set -e
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
$XT_MULTI ebtables --init-table
$XT_MULTI ebtables -A FORWARD -i nodev123 -o nodev432 -j ACCEPT
$XT_MULTI ebtables -A FORWARD -i nodev432 -o nodev123 -j ACCEPT
EXPECT='Bridge table: filter
Bridge chain: FORWARD, entries: 2, policy: ACCEPT
-i nodev123 -o nodev432 -j ACCEPT
-i nodev432 -o nodev123 -j ACCEPT'
echo "ebtables -L FORWARD"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables -L FORWARD)
EXPECT='Bridge table: filter
Bridge chain: FORWARD, entries: 2, policy: ACCEPT
-i nodev123 -o nodev432 -j ACCEPT , pcnt = 0 -- bcnt = 0
-i nodev432 -o nodev123 -j ACCEPT , pcnt = 0 -- bcnt = 0'
echo "ebtables -L FORWARD --Lc"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables -L FORWARD --Lc)
EXPECT='*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
-A FORWARD -i nodev123 -o nodev432 -j ACCEPT
-A FORWARD -i nodev432 -o nodev123 -j ACCEPT'
echo "ebtables-save"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
EXPECT='*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
[0:0] -A FORWARD -i nodev123 -o nodev432 -j ACCEPT
[0:0] -A FORWARD -i nodev432 -o nodev123 -j ACCEPT'
echo "ebtables-save -c"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save -c | grep -v '^#')
export EBTABLES_SAVE_COUNTER=yes
# -c flag overrides EBTABLES_SAVE_COUNTER variable
echo "EBTABLES_SAVE_COUNTER=yes ebtables-save -c"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save -c | grep -v '^#')
EXPECT='*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
-A FORWARD -i nodev123 -o nodev432 -j ACCEPT -c 0 0
-A FORWARD -i nodev432 -o nodev123 -j ACCEPT -c 0 0'
echo "EBTABLES_SAVE_COUNTER=yes ebtables-save"
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
#!/bin/bash
set -e
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
EXPECT='*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
:PVEFW-FORWARD ACCEPT
:PVEFW-FWBR-OUT ACCEPT
-A FORWARD -j PVEFW-FORWARD
-A PVEFW-FORWARD -p IPv4 -j ACCEPT
-A PVEFW-FORWARD -p IPv6 -j ACCEPT
-A PVEFW-FORWARD -i fwln+ -j ACCEPT
-A PVEFW-FORWARD -o fwln+ -j PVEFW-FWBR-OUT'
$XT_MULTI ebtables-restore <<<$EXPECT
exec diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
...@@ -14,7 +14,7 @@ ipt_show() { ...@@ -14,7 +14,7 @@ ipt_show() {
$XT_MULTI iptables-restore <<EOF $XT_MULTI iptables-restore <<EOF
*filter *filter
-A FORWARD -m comment --comment "appended rule" -j ACCEPT -A FORWARD -m comment --comment "rule 4" -j ACCEPT
-I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT -I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT
-I FORWARD 2 -m comment --comment "rule 2" -j ACCEPT -I FORWARD 2 -m comment --comment "rule 2" -j ACCEPT
-I FORWARD 3 -m comment --comment "rule 3" -j ACCEPT -I FORWARD 3 -m comment --comment "rule 3" -j ACCEPT
...@@ -24,7 +24,7 @@ EOF ...@@ -24,7 +24,7 @@ EOF
EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
-A FORWARD -m comment --comment "rule 2" -j ACCEPT -A FORWARD -m comment --comment "rule 2" -j ACCEPT
-A FORWARD -m comment --comment "rule 3" -j ACCEPT -A FORWARD -m comment --comment "rule 3" -j ACCEPT
-A FORWARD -m comment --comment "appended rule" -j ACCEPT' -A FORWARD -m comment --comment "rule 4" -j ACCEPT'
diff -u -Z <(echo -e "$EXPECT") <(ipt_show) diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
...@@ -32,11 +32,14 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show) ...@@ -32,11 +32,14 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
$XT_MULTI iptables-restore --noflush <<EOF $XT_MULTI iptables-restore --noflush <<EOF
*filter *filter
-A FORWARD -m comment --comment "rule 5" -j ACCEPT
-I FORWARD 1 -m comment --comment "rule 0.5" -j ACCEPT -I FORWARD 1 -m comment --comment "rule 0.5" -j ACCEPT
-I FORWARD 3 -m comment --comment "rule 1.5" -j ACCEPT -I FORWARD 3 -m comment --comment "rule 1.5" -j ACCEPT
-I FORWARD 5 -m comment --comment "rule 2.5" -j ACCEPT -I FORWARD 5 -m comment --comment "rule 2.5" -j ACCEPT
-I FORWARD 7 -m comment --comment "rule 3.5" -j ACCEPT -I FORWARD 7 -m comment --comment "rule 3.5" -j ACCEPT
-I FORWARD 9 -m comment --comment "appended rule 2" -j ACCEPT -I FORWARD 9 -m comment --comment "rule 4.5" -j ACCEPT
-I FORWARD 11 -m comment --comment "rule 5.5" -j ACCEPT
-A FORWARD -m comment --comment "rule 6" -j ACCEPT
COMMIT COMMIT
EOF EOF
...@@ -47,8 +50,11 @@ EXPECT='-A FORWARD -m comment --comment "rule 0.5" -j ACCEPT ...@@ -47,8 +50,11 @@ EXPECT='-A FORWARD -m comment --comment "rule 0.5" -j ACCEPT
-A FORWARD -m comment --comment "rule 2.5" -j ACCEPT -A FORWARD -m comment --comment "rule 2.5" -j ACCEPT
-A FORWARD -m comment --comment "rule 3" -j ACCEPT -A FORWARD -m comment --comment "rule 3" -j ACCEPT
-A FORWARD -m comment --comment "rule 3.5" -j ACCEPT -A FORWARD -m comment --comment "rule 3.5" -j ACCEPT
-A FORWARD -m comment --comment "appended rule" -j ACCEPT -A FORWARD -m comment --comment "rule 4" -j ACCEPT
-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT' -A FORWARD -m comment --comment "rule 4.5" -j ACCEPT
-A FORWARD -m comment --comment "rule 5" -j ACCEPT
-A FORWARD -m comment --comment "rule 5.5" -j ACCEPT
-A FORWARD -m comment --comment "rule 6" -j ACCEPT'
diff -u -Z <(echo -e "$EXPECT") <(ipt_show) diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
...@@ -78,6 +84,8 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show) ...@@ -78,6 +84,8 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
$XT_MULTI iptables-restore --noflush <<EOF $XT_MULTI iptables-restore --noflush <<EOF
*filter *filter
-A FORWARD -m comment --comment "appended rule 4" -j ACCEPT
-D FORWARD 7
-D FORWARD -m comment --comment "appended rule 1" -j ACCEPT -D FORWARD -m comment --comment "appended rule 1" -j ACCEPT
-D FORWARD 3 -D FORWARD 3
-I FORWARD 3 -m comment --comment "manually replaced rule 2" -j ACCEPT -I FORWARD 3 -m comment --comment "manually replaced rule 2" -j ACCEPT
......
...@@ -24,7 +24,7 @@ clean_tempfile() ...@@ -24,7 +24,7 @@ clean_tempfile()
trap clean_tempfile EXIT trap clean_tempfile EXIT
ENTRY_NUM=$((RANDOM%100)) ENTRY_NUM=$((RANDOM%10))
UCHAIN_NUM=$((RANDOM%10)) UCHAIN_NUM=$((RANDOM%10))
get_target() get_target()
...@@ -87,7 +87,7 @@ fi ...@@ -87,7 +87,7 @@ fi
case "$XT_MULTI" in case "$XT_MULTI" in
*/xtables-nft-multi) */xtables-nft-multi)
attempts=$((RANDOM%200)) attempts=$((RANDOM%10))
attempts=$((attempts+1)) attempts=$((attempts+1))
;; ;;
*) *)
......
#!/bin/bash
# Make sure iptables-restore simply ignores
# rules starting with -6
set -e
# show rules, drop uninteresting policy settings
ipt_show() {
$XT_MULTI iptables -S | grep -v '^-P'
}
# issue reproducer for iptables-restore
$XT_MULTI iptables-restore <<EOF
*filter
-A FORWARD -m comment --comment any -j ACCEPT
-4 -A FORWARD -m comment --comment ipv4 -j ACCEPT
-6 -A FORWARD -m comment --comment ipv6 -j ACCEPT
COMMIT
EOF
EXPECT='-A FORWARD -m comment --comment any -j ACCEPT
-A FORWARD -m comment --comment ipv4 -j ACCEPT'
diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
#!/bin/bash
# Make sure ip6tables-restore simply ignores
# rules starting with -4
set -e
# show rules, drop uninteresting policy settings
ipt_show() {
$XT_MULTI ip6tables -S | grep -v '^-P'
}
# issue reproducer for ip6tables-restore
$XT_MULTI ip6tables-restore <<EOF
*filter
-A FORWARD -m comment --comment any -j ACCEPT
-4 -A FORWARD -m comment --comment ipv4 -j ACCEPT
-6 -A FORWARD -m comment --comment ipv6 -j ACCEPT
COMMIT
EOF
EXPECT='-A FORWARD -m comment --comment any -j ACCEPT
-A FORWARD -m comment --comment ipv6 -j ACCEPT'
diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment