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 @@
#include "nft.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 xtables_rule_match *matchp;
......@@ -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);
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)
return ret;
}
......@@ -261,12 +261,12 @@ static void print_fragment(unsigned int flags, unsigned int invflags,
fputc(' ', stdout);
}
static void nft_ipv4_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
static void nft_ipv4_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format)
{
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,
cs.fw.ip.invflags, cs.fw.ip.proto, num, format);
......
......@@ -25,7 +25,7 @@
#include "nft.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 xtables_rule_match *matchp;
......@@ -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);
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)
return ret;
}
......@@ -187,12 +187,12 @@ static void nft_ipv6_parse_immediate(const char *jumpto, bool nft_goto,
cs->fw6.ipv6.flags |= IP6T_F_GOTO;
}
static void nft_ipv6_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
static void nft_ipv6_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format)
{
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,
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)
}
/* 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;
......@@ -310,7 +310,6 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
struct xtables_target *target;
struct xt_entry_target *t;
size_t size;
struct nft_family_ops *ops;
void *data = ctx->cs;
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)
target->t = t;
ops = nft_family_ops_lookup(ctx->family);
ops->parse_target(target, data);
ctx->h->ops->parse_target(target, data);
}
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_rule_match **matches;
struct xt_entry_match *m;
struct nft_family_ops *ops;
switch (ctx->family) {
switch (ctx->h->family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
......@@ -349,7 +346,7 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
break;
default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
ctx->family);
ctx->h->family);
exit(EXIT_FAILURE);
}
......@@ -365,9 +362,8 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
match->m = m;
ops = nft_family_ops_lookup(ctx->family);
if (ops->parse_match != NULL)
ops->parse_match(match, ctx->cs);
if (ctx->h->ops->parse_match != NULL)
ctx->h->ops->parse_match(match, ctx->cs);
}
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)
static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
{
const struct nft_family_ops *ops;
struct xtables_target *target;
struct xt_entry_target *t;
unsigned int size;
......@@ -429,8 +424,7 @@ static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
target->t = t;
ops = nft_family_ops_lookup(ctx->family);
ops->parse_target(target, ctx->cs);
ctx->h->ops->parse_target(target, ctx->cs);
}
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)
{
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->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.len = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_LEN);
ctx->flags |= NFT_XT_CTX_PAYLOAD;
}
......@@ -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)
{
struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
void *data = ctx->cs;
uint32_t reg;
......@@ -483,12 +484,12 @@ static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
return;
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;
}
/* bitwise context is interpreted from 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;
}
}
......@@ -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)
{
const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
struct nft_family_ops *ops;
const char *jumpto = NULL;
bool nft_goto = false;
void *data = ctx->cs;
......@@ -544,8 +544,7 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
break;
}
ops = nft_family_ops_lookup(ctx->family);
ops->parse_immediate(jumpto, nft_goto, data);
ctx->h->ops->parse_immediate(jumpto, nft_goto, data);
}
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);
struct xtables_rule_match **matches;
struct xtables_match *match;
struct nft_family_ops *ops;
struct xt_rateinfo *rinfo;
size_t size;
switch (ctx->family) {
switch (ctx->h->family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
matches = &ctx->cs->matches;
break;
default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
ctx->family);
fprintf(stderr, "BUG: nft_parse_limit() unknown family %d\n",
ctx->h->family);
exit(EXIT_FAILURE);
}
......@@ -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->burst = burst;
ops = nft_family_ops_lookup(ctx->family);
if (ops->parse_match != NULL)
ops->parse_match(match, ctx->cs);
if (ctx->h->ops->parse_match != NULL)
ctx->h->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 nftnl_expr_iter *iter;
struct nftnl_expr *expr;
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct nft_xt_ctx ctx = {
.cs = cs,
.family = family,
.h = h,
.table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE),
};
iter = nftnl_expr_iter_create(r);
......@@ -630,6 +635,8 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
nft_parse_target(&ctx, expr);
else if (strcmp(name, "limit") == 0)
nft_parse_limit(&ctx, expr);
else if (strcmp(name, "lookup") == 0)
nft_parse_lookup(&ctx, h, expr);
expr = nftnl_expr_iter_next(iter);
}
......@@ -982,19 +989,18 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data)
cs->target = t;
}
bool nft_ipv46_rule_find(struct nft_family_ops *ops,
struct nftnl_rule *r, void *data)
bool nft_ipv46_rule_find(struct nft_handle *h, struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data, this = {};
bool ret = false;
nft_rule_to_iptables_command_state(r, &this);
nft_rule_to_iptables_command_state(h, r, &this);
DEBUGP("comparing with... ");
#ifdef DEBUG_DEL
nft_rule_print_save(r, NFT_RULE_APPEND, 0);
#endif
if (!ops->is_same(cs, &this))
if (!h->ops->is_same(cs, &this))
goto out;
if (!compare_matches(cs->matches, this.matches)) {
......@@ -1014,7 +1020,7 @@ bool nft_ipv46_rule_find(struct nft_family_ops *ops,
ret = true;
out:
ops->clear_cs(&this);
h->ops->clear_cs(&this);
return ret;
}
......
......@@ -35,6 +35,7 @@
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
struct xtables_args;
struct nft_handle;
struct xt_xlate;
enum {
......@@ -42,19 +43,22 @@ enum {
NFT_XT_CTX_META = (1 << 1),
NFT_XT_CTX_BITWISE = (1 << 2),
NFT_XT_CTX_IMMEDIATE = (1 << 3),
NFT_XT_CTX_PREV_PAYLOAD = (1 << 4),
};
struct nft_xt_ctx {
struct iptables_command_state *cs;
struct nftnl_expr_iter *iter;
int family;
struct nft_handle *h;
uint32_t flags;
const char *table;
uint32_t reg;
struct {
uint32_t base;
uint32_t offset;
uint32_t len;
} payload;
} payload, prev_payload;
struct {
uint32_t key;
} meta;
......@@ -69,7 +73,7 @@ struct nft_xt_ctx {
};
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,
const void *data_b);
void (*print_payload)(struct nftnl_expr *e,
......@@ -82,6 +86,8 @@ struct nft_family_ops {
void *data);
void (*parse_cmp)(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
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 (*print_table_header)(const char *tablename);
......@@ -89,8 +95,8 @@ struct nft_family_ops {
const char *pol,
const struct xt_counters *counters, bool basechain,
uint32_t refs, uint32_t entries);
void (*print_rule)(struct nftnl_rule *r, unsigned int num,
unsigned int format);
void (*print_rule)(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format);
void (*save_rule)(const void *data, unsigned int format);
void (*save_counters)(const void *data);
void (*save_chain)(const struct nftnl_chain *c, const char *policy);
......@@ -100,10 +106,10 @@ struct nft_family_ops {
struct xtables_args *args);
void (*parse_match)(struct xtables_match *m, 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);
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);
int (*xlate)(const void *data, struct xt_xlate *xl);
};
......@@ -111,7 +117,7 @@ struct nft_family_ops {
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_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_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);
......@@ -137,7 +143,8 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
unsigned char *outiface_mask, uint8_t *invflags);
void print_proto(uint16_t proto, int invert);
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);
void nft_clear_iptables_command_state(struct iptables_command_state *cs);
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,
struct nft_family_ops *nft_family_ops_lookup(int family);
struct nft_handle;
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);
bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2);
......@@ -199,23 +205,6 @@ struct xtables_args {
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 {
unsigned int command;
unsigned int rulenum;
......@@ -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 xtables_args *args);
struct nft_xt_restore_parse {
FILE *in;
int testing;
const char *tablename;
bool commit;
};
struct nftnl_chain_list;
struct nft_xt_restore_cb {
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,
const char *chain, const char *policy,
const struct xt_counters *counters);
......@@ -260,10 +240,16 @@ struct nft_xt_restore_cb {
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,
struct nft_xt_restore_parse *p,
struct nft_xt_restore_cb *cb,
int argc, char *argv[]);
const struct nft_xt_restore_parse *p);
void nft_check_xt_legacy(int family, bool is_ipt_save);
#endif
......@@ -55,48 +55,18 @@
#include "nft.h"
#include "xshared.h" /* proto_to_name */
#include "nft-cache.h"
#include "nft-shared.h"
#include "nft-bridge.h" /* EBT_NOPROTO */
#include "xtables-config-parser.h"
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 (*cb)(const struct nlmsghdr *nlh, void *data),
void *data)
{
int ret;
char buf[16536];
char buf[32768];
if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
return -1;
......@@ -186,33 +156,42 @@ static void mnl_err_list_free(struct mnl_err *err)
free(err);
}
static int nlbuffsiz;
static void mnl_set_sndbuffer(const struct mnl_socket *nl,
struct nftnl_batch *batch)
static void mnl_set_sndbuffer(struct nft_handle *h)
{
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;
newbuffsiz = nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE;
/* 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)
return;
nlbuffsiz = newbuffsiz;
h->nlrcvbuffsiz = newbuffsiz;
}
static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
struct nftnl_batch *batch)
static ssize_t mnl_nft_socket_sendmsg(struct nft_handle *h, int numcmds)
{
static const struct sockaddr_nl snl = {
.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 msghdr msg = {
.msg_name = (struct sockaddr *) &snl,
......@@ -221,16 +200,16 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
.msg_iovlen = iov_len,
};
mnl_set_sndbuffer(nf_sock, batch);
nftnl_batch_iovec(batch, iov, iov_len);
mnl_set_sndbuffer(h);
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,
struct nftnl_batch *batch, struct list_head *err_list)
static int mnl_batch_talk(struct nft_handle *h, int numcmds)
{
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);
char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
fd_set readfds;
......@@ -240,7 +219,7 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock,
};
int err = 0;
ret = mnl_nft_socket_sendmsg(nf_sock, batch);
ret = mnl_nft_socket_sendmsg(h, numcmds);
if (ret == -1)
return -1;
......@@ -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);
/* Continue on error, make sure we get all acknowledgments */
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;
}
......@@ -291,6 +271,7 @@ enum obj_update_type {
NFT_COMPAT_RULE_REPLACE,
NFT_COMPAT_RULE_DELETE,
NFT_COMPAT_RULE_FLUSH,
NFT_COMPAT_SET_ADD,
};
enum obj_action {
......@@ -308,6 +289,7 @@ struct obj_update {
struct nftnl_table *table;
struct nftnl_chain *chain;
struct nftnl_rule *rule;
struct nftnl_set *set;
void *ptr;
};
struct {
......@@ -335,6 +317,7 @@ static int mnl_append_error(const struct nft_handle *h,
[NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE",
[NFT_COMPAT_RULE_DELETE] = "RULE_DELETE",
[NFT_COMPAT_RULE_FLUSH] = "RULE_FLUSH",
[NFT_COMPAT_SET_ADD] = "SET_ADD",
};
char errmsg[256];
char tcr[128];
......@@ -371,10 +354,14 @@ static int mnl_append_error(const struct nft_handle *h,
nftnl_rule_get_str(o->rule, NFTNL_RULE_CHAIN));
#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
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);
......@@ -404,6 +391,13 @@ batch_table_add(struct nft_handle *h, enum obj_update_type type,
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,
struct nftnl_chain *c)
{
......@@ -647,7 +641,7 @@ static int nft_table_builtin_add(struct nft_handle *h,
if (t == NULL)
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;
......@@ -664,12 +658,12 @@ nft_chain_builtin_alloc(const struct builtin_table *table,
if (c == NULL)
return NULL;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table->name);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain->name);
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table->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_PRIO, chain->prio);
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;
}
......@@ -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);
}
static const struct builtin_table *
__nft_table_builtin_find(const struct builtin_table *tables, const char *table)
/* find if built-in table already exists */
const struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{
int i;
bool found = false;
for (i = 0; i < NFT_TABLE_MAX; i++) {
if (tables[i].name == NULL)
if (h->tables[i].name == NULL)
continue;
if (strcmp(tables[i].name, table) != 0)
if (strcmp(h->tables[i].name, table) != 0)
continue;
found = true;
break;
}
return found ? &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);
return found ? &h->tables[i] : NULL;
}
/* find if built-in chain already exists */
......@@ -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,
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;
int i;
if (!list)
return;
/* Initialize built-in chains if they don't exist yet */
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);
if (c != NULL)
......@@ -782,7 +771,7 @@ static bool nft_chain_builtin(struct nftnl_chain *c)
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);
......@@ -794,7 +783,8 @@ static int nft_restart(struct nft_handle *h)
return -1;
h->portid = mnl_socket_get_portid(h->nl);
nlbuffsiz = 0;
h->nlsndbuffsiz = 0;
h->nlrcvbuffsiz = 0;
return 0;
}
......@@ -820,67 +810,6 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t)
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)
{
flush_chain_cache(h, NULL);
......@@ -1015,13 +944,163 @@ static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
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;
int ret;
if (!strcmp(m->u.user.name, "limit"))
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");
if (expr == NULL)
......@@ -1234,10 +1313,10 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
return NULL;
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, h->family);
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
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;
return r;
......@@ -1257,10 +1336,16 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
struct nftnl_rule *r;
int type;
/* If built-in chains don't exist for this table, create them */
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;
r = nft_rule_new(h, chain, table, data);
......@@ -1280,7 +1365,7 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
}
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
if (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,
}
void
nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
unsigned int format)
nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
enum nft_rule_print type, unsigned int format)
{
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 nft_family_ops *ops;
struct nft_family_ops *ops = h->ops;
ops = nft_family_ops_lookup(family);
ops->rule_to_cs(r, &cs);
ops->rule_to_cs(h, r, &cs);
if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters)
ops->save_counters(&cs);
......@@ -1329,106 +1412,6 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
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)
{
const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
......@@ -1467,7 +1450,7 @@ static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c)
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_rule *last = nft_chain_last_rule(c);
......@@ -1509,138 +1492,6 @@ static void nft_bridge_chain_postprocess(struct nft_handle *h,
out_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] = {
[NF_DROP] = "DROP",
[NF_ACCEPT] = "ACCEPT",
......@@ -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)
{
struct nft_family_ops *ops = h->ops;
struct nftnl_chain_list_iter *iter;
struct nft_family_ops *ops;
struct nftnl_chain *c;
ops = nft_family_ops_lookup(h->family);
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
return 0;
......@@ -1702,7 +1551,7 @@ static int nft_chain_save_rules(struct nft_handle *h,
r = nftnl_rule_iter_next(iter);
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);
}
......@@ -1717,7 +1566,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
struct nftnl_chain *c;
int ret = 0;
list = nft_chain_list_get(h, table);
list = nft_chain_list_get(h, table, NULL);
if (!list)
return 0;
......@@ -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);
while (c) {
nft_build_cache(h, c);
ret = nft_chain_save_rules(h, c, format);
if (ret != 0)
break;
......@@ -1747,15 +1597,16 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
struct obj_update *obj;
struct nftnl_rule *r;
if (verbose)
if (verbose && chain)
fprintf(stdout, "Flushing chain `%s'\n", chain);
r = nftnl_rule_alloc();
if (r == NULL)
return;
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
if (chain)
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
obj = batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r);
if (!obj) {
......@@ -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,
bool verbose)
{
int ret = 0;
struct nftnl_chain_list *list;
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_fn = nft_rule_flush;
list = nft_chain_list_get(h, table);
if (chain || verbose) {
list = nft_chain_list_get(h, table, chain);
if (list == NULL) {
ret = 1;
goto err;
}
}
if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain);
if (!c)
if (!c) {
errno = ENOENT;
return 0;
}
}
if (chain || !verbose) {
__nft_rule_flush(h, table, chain, verbose, false);
flush_rule_cache(c);
flush_rule_cache(h, table, c);
return 1;
}
......@@ -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);
while (c != NULL) {
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
__nft_rule_flush(h, table, chain_name, verbose, false);
flush_rule_cache(c);
__nft_rule_flush(h, table, chain, verbose, false);
flush_rule_cache(h, table, c);
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
......@@ -1824,8 +1679,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nft_fn = nft_chain_user_add;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
if (nft_chain_exists(h, table, chain)) {
......@@ -1837,14 +1690,14 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
if (c == NULL)
return 0;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
if (h->family == NFPROTO_BRIDGE)
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
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)
nftnl_chain_list_add(c, list);
......@@ -1871,8 +1724,8 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
if (!c)
return -1;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
created = true;
}
......@@ -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);
list = nft_chain_list_get(h, table);
list = nft_chain_list_get(h, table, chain);
if (list)
nftnl_chain_list_add(c, list);
......@@ -1916,6 +1769,10 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
fprintf(stdout, "Deleting chain `%s'\n",
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. */
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
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,
nft_fn = nft_chain_user_del;
list = nft_chain_list_get(h, table);
list = nft_chain_list_get(h, table, chain);
if (list == NULL)
return 0;
......@@ -1967,7 +1824,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{
struct nftnl_chain_list *list;
list = nft_chain_list_get(h, table);
list = nft_chain_list_get(h, table, chain);
if (list == NULL)
return NULL;
......@@ -2003,8 +1860,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
return 0;
}
/* If built-in chains don't exist for this table, create them */
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. */
......@@ -2023,8 +1878,8 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
if (c == NULL)
return 0;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname);
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, newname);
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
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,
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)
{
struct nftnl_table_list_iter *iter;
......@@ -2075,8 +1923,8 @@ err:
}
int nft_for_each_table(struct nft_handle *h,
int (*func)(struct nft_handle *h, const char *tablename, bool counters),
bool counters)
int (*func)(struct nft_handle *h, const char *tablename, void *data),
void *data)
{
struct nftnl_table_list *list;
struct nftnl_table_list_iter *iter;
......@@ -2095,7 +1943,7 @@ int nft_for_each_table(struct nft_handle *h,
const char *tablename =
nftnl_table_get(t, NFTNL_TABLE_NAME);
func(h, tablename, counters);
func(h, tablename, data);
t = nftnl_table_list_iter_next(iter);
}
......@@ -2179,7 +2027,6 @@ err_out:
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);
}
......@@ -2189,6 +2036,9 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *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);
if (!obj) {
nftnl_rule_free(r);
......@@ -2204,6 +2054,8 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen
struct nftnl_rule_iter *iter;
bool found = false;
nft_build_cache(h, c);
if (rulenum >= 0)
/* Delete by rule number case */
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
r = nftnl_rule_iter_next(iter);
while (r != NULL) {
found = h->ops->rule_find(h->ops, r, data);
found = h->ops->rule_find(h, r, data);
if (found)
break;
r = nftnl_rule_iter_next(iter);
......@@ -2242,7 +2094,7 @@ int nft_rule_check(struct nft_handle *h, const char *chain,
goto fail_enoent;
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
return 1;
fail_enoent:
......@@ -2271,7 +2123,7 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
if (ret < 0)
errno = ENOMEM;
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
} else
errno = ENOENT;
......@@ -2312,7 +2164,7 @@ nft_rule_add(struct nft_handle *h, const char *chain,
}
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
h->ops->print_rule(h, r, 0, FMT_PRINT_RULE);
return r;
}
......@@ -2323,8 +2175,6 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
struct nftnl_rule *r = NULL, *new_rule;
struct nftnl_chain *c;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_insert;
......@@ -2423,8 +2273,8 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
static int
__nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
int rulenum, unsigned int format,
void (*cb)(struct nftnl_rule *r, unsigned int num,
unsigned int format))
void (*cb)(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format))
{
struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
......@@ -2437,7 +2287,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
* valid chain but invalid rule number
*/
return 1;
cb(r, rulenum, format);
cb(h, r, rulenum, format);
return 1;
}
......@@ -2447,7 +2297,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
r = nftnl_rule_iter_next(iter);
while (r != NULL) {
cb(r, ++rule_ctr, format);
cb(h, r, ++rule_ctr, format);
r = nftnl_rule_iter_next(iter);
}
......@@ -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,
const struct nft_family_ops *ops,
struct nftnl_chain *c, unsigned int format)
{
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,
if (nftnl_chain_is_set(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);
}
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
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_iter *iter;
struct nftnl_chain *c;
bool found = false;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_assert_table_compatible(h, table, chain);
ops = nft_family_ops_lookup(h->family);
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);
list = nft_chain_list_get(h, table, chain);
if (!list)
return 0;
......@@ -2528,7 +2369,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (!rulenum) {
if (ops->print_table_header)
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);
return 1;
......@@ -2546,7 +2387,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (found)
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);
found = true;
......@@ -2557,9 +2398,10 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
}
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)
......@@ -2612,16 +2454,10 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 0;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_assert_table_compatible(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);
list = nft_chain_list_get(h, table, chain);
if (!list)
return 0;
......@@ -2677,7 +2513,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
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;
......@@ -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);
}
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,
uint16_t flags, uint32_t seq,
struct nftnl_chain *chain)
......@@ -2747,6 +2616,9 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_RULE_FLUSH:
nftnl_rule_free(o->rule);
break;
case NFT_COMPAT_SET_ADD:
nftnl_set_free(o->set);
break;
}
h->obj_list_num--;
list_del(&o->head);
......@@ -2813,6 +2685,7 @@ static void nft_refresh_transaction(struct nft_handle *h)
case NFT_COMPAT_RULE_REPLACE:
case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH:
case NFT_COMPAT_SET_ADD:
break;
}
}
......@@ -2903,6 +2776,13 @@ retry:
nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
n->seq, n->rule);
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);
......@@ -2917,7 +2797,7 @@ retry:
}
errno = 0;
ret = mnl_batch_talk(h->nl, h->batch, &h->err_list);
ret = mnl_batch_talk(h, seq);
if (ret && errno == ERESTART) {
nft_rebuild_cache(h);
......@@ -3039,6 +2919,8 @@ int ebt_set_user_chain_policy(struct nft_handle *h, const char *table,
else
return 0;
nft_build_cache(h, c);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval);
return 1;
}
......@@ -3065,11 +2947,15 @@ static void nft_bridge_commit_prepare(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);
}
int nft_bridge_commit(struct nft_handle *h)
{
nft_bridge_commit_prepare(h);
return nft_commit(h);
}
int nft_abort(struct nft_handle *h)
{
return nft_action(h, NFT_COMPAT_ABORT);
......@@ -3204,7 +3090,7 @@ const char *nft_strerror(int err)
{ 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)
&& table[i].err == err)
return table[i].message;
......@@ -3213,136 +3099,42 @@ const char *nft_strerror(int 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_chain_list *chain_list = NULL;
struct nftnl_table_list_iter *titer = NULL;
struct nftnl_chain_list_iter *citer = NULL;
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;
struct nftnl_expr_iter *iter;
struct nftnl_expr *e;
uint32_t reg;
int ret = -1;
return 0;
iter = nftnl_expr_iter_create(r);
if (!iter)
return -1;
err:
nftnl_table_list_free(table_list);
nftnl_chain_list_free(chain_list);
next_expr:
e = nftnl_expr_iter_next(iter);
if (!e)
goto out;
if (titer != NULL)
nftnl_table_list_iter_destroy(titer);
if (citer != NULL)
nftnl_chain_list_iter_destroy(citer);
if (strcmp("meta", nftnl_expr_get_str(e, NFTNL_EXPR_NAME)) ||
nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY) != NFT_META_L4PROTO)
goto next_expr;
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,
uint32_t flags)
{
if (!h->config_done)
return __nft_xtables_config_load(h, filename, flags);
if (strcmp("cmp", nftnl_expr_get_str(e, NFTNL_EXPR_NAME)) ||
reg != nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG))
goto next_expr;
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 {
......@@ -3370,6 +3162,8 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
return -1;
}
nft_build_cache(h, c);
iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return -1;
......@@ -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
* rule based on its handle only.
*/
recover_rule_compat(r);
nftnl_rule_unset(r, NFTNL_RULE_POSITION);
if (!batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r)) {
nftnl_rule_iter_destroy(iter);
......@@ -3431,7 +3226,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 0;
list = nft_chain_list_get(h, table);
list = nft_chain_list_get(h, table, chain);
if (list == NULL)
goto err;
......@@ -3460,9 +3255,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag)
return NFT_CMP_EQ;
}
#define NFT_COMPAT_EXPR_MAX 8
static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
static const char *supported_exprs[] = {
"match",
"target",
"payload",
......@@ -3470,7 +3263,8 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
"cmp",
"bitwise",
"counter",
"immediate"
"immediate",
"lookup",
};
......@@ -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);
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)
return 0;
}
......@@ -3506,6 +3300,8 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
enum nf_inet_hooks hook;
int prio;
nft_build_cache(h, c);
if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL))
return -1;
......@@ -3533,11 +3329,12 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
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;
clist = nft_chain_list_get(h, tablename);
clist = nft_chain_list_get(h, table, chain);
if (clist == NULL)
return false;
......@@ -3546,3 +3343,22 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
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 {
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 nftnl_table_list *tables;
struct {
struct nftnl_chain_list *chains;
struct nftnl_set_list *sets;
bool initialized;
} table[NFT_TABLE_MAX];
};
......@@ -38,6 +47,8 @@ struct nft_cache {
struct nft_handle {
int family;
struct mnl_socket *nl;
int nlsndbuffsiz;
int nlrcvbuffsiz;
uint32_t portid;
uint32_t seq;
uint32_t nft_genid;
......@@ -51,7 +62,7 @@ struct nft_handle {
unsigned int cache_index;
struct nft_cache __cache[2];
struct nft_cache *cache;
bool have_cache;
enum nft_cache_level cache_level;
bool restore;
bool noflush;
int8_t config_done;
......@@ -71,7 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
void *data);
int nft_init(struct nft_handle *h, const struct builtin_table *t);
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.
......@@ -79,7 +90,7 @@ void nft_build_cache(struct nft_handle *h);
struct nftnl_table;
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);
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);
......@@ -92,8 +103,6 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c
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);
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_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);
......@@ -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);
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);
void nft_bridge_chain_postprocess(struct nft_handle *h,
struct nftnl_chain *c);
/*
* Operations with rule-set.
......@@ -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_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_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);
......@@ -136,8 +148,8 @@ enum nft_rule_print {
NFT_RULE_DEL,
};
void nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
unsigned int format);
void nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
enum nft_rule_print type, unsigned int format);
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
*/
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_policy_rule(struct nft_handle *h, const char *table);
......@@ -168,22 +181,6 @@ int nft_init_eb(struct nft_handle *h, const char *pname);
int ebt_get_current_chain(const char *chain);
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
*/
......@@ -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);
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,
const char *chain, const char *policy);
......
......@@ -38,6 +38,14 @@ while [ -n "$1" ]; do
HOST=y
shift
;;
-l|--legacy)
LEGACY_ONLY=y
shift
;;
-n|--nft)
NFT_ONLY=y
shift
;;
*${RETURNCODE_SEPARATOR}+([0-9]))
SINGLE+=" $1"
VERBOSE=y
......@@ -98,19 +106,23 @@ do_test() {
}
echo ""
for testfile in $(find_tests);do
if [ "$NFT_ONLY" != "y" ]; then
for testfile in $(find_tests);do
do_test "$testfile" "$XTABLES_LEGACY_MULTI"
done
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_fail=$failed
ok=0
failed=0
for testfile in $(find_tests);do
if [ "$LEGACY_ONLY" != "y" ]; then
for testfile in $(find_tests);do
do_test "$testfile" "$XTABLES_NFT_MULTI"
done
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))
failed=$((legacy_fail+failed))
......
......@@ -50,13 +50,12 @@ DUMP='*filter
-A foo -j MARK --set-mark 12345
-A foo -j ACCEPT --opcode 1
-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
$XT_MULTI arptables -F
$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
DUMP='*filter
:OUTPUT ACCEPT
-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
......@@ -20,8 +19,7 @@ EXPECT='*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
-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-restore <<<$DUMP
......
......@@ -58,7 +58,6 @@ EXPECT='*filter
-A INPUT -j MARK -i eth23 --set-mark 42
-A OUTPUT -j CLASSIFY -o eth23 --set-class 23:42
-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
get_entries_count() { # (chain)
$XT_MULTI ebtables -L $1 | sed -n 's/.*entries: \([0-9]*\).*/\1/p'
}
set -x
case "$XT_MULTI" in
*/xtables-nft-multi)
......@@ -28,32 +32,32 @@ case "$XT_MULTI" in
exit 1
fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in empty unreferenced chain"
entries=$(get_entries_count FOO)
if [ $entries -ne 0 ]; then
echo "Unexpected entries count in empty unreferenced chain (expected 0, have $entries)"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -A FORWARD -j FOO
$XT_MULTI ebtables -L FORWARD | grep -q 'entries: 1'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in FORWARD chain"
entries=$(get_entries_count FORWARD)
if [ $entries -ne 1 ]; then
echo "Unexpected entries count in FORWARD chain (expected 1, have $entries)"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in empty referenced chain"
entries=$(get_entries_count FOO)
if [ $entries -ne 0 ]; then
echo "Unexpected entries count in empty referenced chain (expected 0, have $entries)"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -A FOO -j ACCEPT
$XT_MULTI ebtables -L FOO | grep -q 'entries: 1'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in non-empty referenced chain"
entries=$(get_entries_count FOO)
if [ $entries -ne 1 ]; then
echo "Unexpected entries count in non-empty referenced chain (expected 1, have $entries)"
$XT_MULTI ebtables -L
exit 1
fi
......
......@@ -99,7 +99,6 @@ DUMP='*filter
-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 --limit 100/sec --limit-burst 5 -j ACCEPT
*nat
:PREROUTING ACCEPT
:OUTPUT DROP
......@@ -107,8 +106,7 @@ DUMP='*filter
:nat_foo DROP
-A PREROUTING -j redirect
-A OUTPUT -j ACCEPT
-A POSTROUTING -j ACCEPT
'
-A POSTROUTING -j ACCEPT'
diff -u <(echo -e "$DUMP") <($XT_MULTI ebtables-save | grep -v '^#')
......
......@@ -13,8 +13,7 @@ DUMP='*filter
-A FORWARD --limit 100 --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000 -j ACCEPT
-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
......@@ -25,8 +24,7 @@ EXPECT='*filter
-A FORWARD --limit 100/sec --limit-burst 42 -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 "" -j CONTINUE
'
-A FORWARD --log-level notice --log-prefix "" -j CONTINUE'
$XT_MULTI ebtables --init-table
$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() {
$XT_MULTI iptables-restore <<EOF
*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 2 -m comment --comment "rule 2" -j ACCEPT
-I FORWARD 3 -m comment --comment "rule 3" -j ACCEPT
......@@ -24,7 +24,7 @@ EOF
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 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)
......@@ -32,11 +32,14 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
$XT_MULTI iptables-restore --noflush <<EOF
*filter
-A FORWARD -m comment --comment "rule 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 5 -m comment --comment "rule 2.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
EOF
......@@ -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 3" -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 "appended rule 2" -j ACCEPT'
-A FORWARD -m comment --comment "rule 4" -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)
......@@ -78,6 +84,8 @@ diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
$XT_MULTI iptables-restore --noflush <<EOF
*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 3
-I FORWARD 3 -m comment --comment "manually replaced rule 2" -j ACCEPT
......
......@@ -24,7 +24,7 @@ clean_tempfile()
trap clean_tempfile EXIT
ENTRY_NUM=$((RANDOM%100))
ENTRY_NUM=$((RANDOM%10))
UCHAIN_NUM=$((RANDOM%10))
get_target()
......@@ -87,7 +87,7 @@ fi
case "$XT_MULTI" in
*/xtables-nft-multi)
attempts=$((RANDOM%200))
attempts=$((RANDOM%10))
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