Commit 278668fa authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.0

parent 5beab31f
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <xtables.h> #include <xtables.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/xt_comment.h>
#include <libmnl/libmnl.h> #include <libmnl/libmnl.h>
#include <libnftnl/rule.h> #include <libnftnl/rule.h>
...@@ -83,7 +84,7 @@ void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor) ...@@ -83,7 +84,7 @@ void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor)
nftnl_rule_add_expr(r, expr); nftnl_rule_add_expr(r, expr);
} }
static 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)
{ {
struct nftnl_expr *expr; struct nftnl_expr *expr;
uint32_t xor[4] = { 0 }; uint32_t xor[4] = { 0 };
...@@ -138,9 +139,10 @@ void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op) ...@@ -138,9 +139,10 @@ void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op)
iface_len = strlen(iface); iface_len = strlen(iface);
add_meta(r, NFT_META_IIFNAME); add_meta(r, NFT_META_IIFNAME);
if (iface[iface_len - 1] == '+') if (iface[iface_len - 1] == '+') {
add_cmp_ptr(r, op, iface, iface_len - 1); if (iface_len > 1)
else add_cmp_ptr(r, op, iface, iface_len - 1);
} else
add_cmp_ptr(r, op, iface, iface_len + 1); add_cmp_ptr(r, op, iface, iface_len + 1);
} }
...@@ -151,17 +153,28 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op) ...@@ -151,17 +153,28 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
iface_len = strlen(iface); iface_len = strlen(iface);
add_meta(r, NFT_META_OIFNAME); add_meta(r, NFT_META_OIFNAME);
if (iface[iface_len - 1] == '+') if (iface[iface_len - 1] == '+') {
add_cmp_ptr(r, op, iface, iface_len - 1); if (iface_len > 1)
else add_cmp_ptr(r, op, iface, iface_len - 1);
} else
add_cmp_ptr(r, op, iface, iface_len + 1); add_cmp_ptr(r, op, iface, iface_len + 1);
} }
void add_addr(struct nftnl_rule *r, int offset, void add_addr(struct nftnl_rule *r, int offset,
void *data, void *mask, size_t len, uint32_t op) void *data, void *mask, size_t len, uint32_t op)
{ {
const char *m = mask;
int i;
add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER); add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
add_bitwise(r, mask, len);
for (i = 0; i < len; i++) {
if (m[i] != 0xff)
break;
}
if (i != len)
add_bitwise(r, mask, len);
add_cmp_ptr(r, op, data, len); add_cmp_ptr(r, op, data, len);
} }
...@@ -207,6 +220,30 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface, ...@@ -207,6 +220,30 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
return true; return true;
} }
static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned char *mask)
{
if (len == 0)
return;
memcpy(dst, name, len);
if (name[len - 1] == '\0') {
if (mask)
memset(mask, 0xff, len);
return;
}
if (len >= IFNAMSIZ)
return;
/* wildcard */
dst[len++] = '+';
if (len >= IFNAMSIZ)
return;
dst[len++] = 0;
if (mask)
memset(mask, 0xff, len + 1);
}
int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface, int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
unsigned char *iniface_mask, char *outiface, unsigned char *iniface_mask, char *outiface,
unsigned char *outiface_mask, uint8_t *invflags) unsigned char *outiface_mask, uint8_t *invflags)
...@@ -234,35 +271,21 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface, ...@@ -234,35 +271,21 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
memset(outiface_mask, 0xff, strlen(outiface)+1); memset(outiface_mask, 0xff, strlen(outiface)+1);
break; break;
case NFT_META_BRI_IIFNAME:
case NFT_META_IIFNAME: case NFT_META_IIFNAME:
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len); ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ) if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
*invflags |= IPT_INV_VIA_IN; *invflags |= IPT_INV_VIA_IN;
memcpy(iniface, ifname, len); parse_ifname(ifname, len, iniface, iniface_mask);
if (iniface[len] == '\0')
memset(iniface_mask, 0xff, len);
else {
iniface[len] = '+';
iniface[len+1] = '\0';
memset(iniface_mask, 0xff, len + 1);
}
break; break;
case NFT_META_BRI_OIFNAME:
case NFT_META_OIFNAME: case NFT_META_OIFNAME:
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len); ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ) if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
*invflags |= IPT_INV_VIA_OUT; *invflags |= IPT_INV_VIA_OUT;
memcpy(outiface, ifname, len); parse_ifname(ifname, len, outiface, outiface_mask);
if (outiface[len] == '\0')
memset(outiface_mask, 0xff, len);
else {
outiface[len] = '+';
outiface[len+1] = '\0';
memset(outiface_mask, 0xff, len + 1);
}
break; break;
default: default:
return -1; return -1;
...@@ -276,11 +299,10 @@ static void *nft_get_data(struct nft_xt_ctx *ctx) ...@@ -276,11 +299,10 @@ static void *nft_get_data(struct nft_xt_ctx *ctx)
switch(ctx->family) { switch(ctx->family) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
case NFPROTO_IPV6: case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
return ctx->state.cs; return ctx->state.cs;
case NFPROTO_ARP: case NFPROTO_ARP:
return ctx->state.cs_arp; return ctx->state.cs_arp;
case NFPROTO_BRIDGE:
return ctx->state.cs_eb;
default: default:
/* Should not happen */ /* Should not happen */
return NULL; return NULL;
...@@ -333,10 +355,8 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ...@@ -333,10 +355,8 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
switch (ctx->family) { switch (ctx->family) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
case NFPROTO_IPV6: case NFPROTO_IPV6:
matches = &ctx->state.cs->matches;
break;
case NFPROTO_BRIDGE: case NFPROTO_BRIDGE:
matches = &ctx->state.cs_eb->matches; matches = &ctx->state.cs->matches;
break; break;
default: default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n", fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
...@@ -394,10 +414,54 @@ void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv) ...@@ -394,10 +414,54 @@ void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
*inv = false; *inv = false;
} }
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;
const char *targname;
switch (ctx->meta.key) {
case NFT_META_NFTRACE:
if (ctx->immediate.data[0] == 0)
return;
targname = "TRACE";
break;
default:
return;
}
target = xtables_find_target(targname, XTF_TRY_LOAD);
if (target == NULL)
return;
size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
t = xtables_calloc(1, size);
t->u.target_size = size;
t->u.user.revision = target->revision;
strcpy(t->u.user.name, targname);
target->t = t;
ops = nft_family_ops_lookup(ctx->family);
ops->parse_target(target, nft_get_data(ctx));
}
void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e) void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{ {
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
ctx->meta.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY); ctx->meta.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY);
if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG) &&
(ctx->flags & NFT_XT_CTX_IMMEDIATE) &&
nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG) == ctx->immediate.reg) {
ctx->flags &= ~NFT_XT_CTX_IMMEDIATE;
nft_meta_set_to_target(ctx);
return;
}
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
ctx->flags |= NFT_XT_CTX_META; ctx->flags |= NFT_XT_CTX_META;
} }
...@@ -453,13 +517,30 @@ void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters) ...@@ -453,13 +517,30 @@ void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters)
void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e) void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{ {
int verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
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; struct nft_family_ops *ops;
const char *jumpto = NULL; const char *jumpto = NULL;
bool nft_goto = false; bool nft_goto = false;
void *data = nft_get_data(ctx); void *data = nft_get_data(ctx);
int verdict;
if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
const void *imm_data;
uint32_t len;
imm_data = nftnl_expr_get_data(e, NFTNL_EXPR_IMM_DATA, &len);
if (len > sizeof(ctx->immediate.data))
return;
memcpy(ctx->immediate.data, imm_data, len);
ctx->immediate.len = len;
ctx->immediate.reg = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_DREG);
ctx->flags |= NFT_XT_CTX_IMMEDIATE;
return;
}
verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
/* Standard target? */ /* Standard target? */
switch(verdict) { switch(verdict) {
case NF_ACCEPT: case NF_ACCEPT:
...@@ -537,7 +618,8 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r, ...@@ -537,7 +618,8 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
if (match == NULL) if (match == NULL)
return; return;
m = calloc(1, sizeof(struct xt_entry_match) + len); m = calloc(1, sizeof(struct xt_entry_match) +
sizeof(struct xt_comment_info));
if (m == NULL) { if (m == NULL) {
fprintf(stderr, "OOM"); fprintf(stderr, "OOM");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -838,7 +920,9 @@ bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2) ...@@ -838,7 +920,9 @@ bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2)
if (tg1 == NULL && tg2 == NULL) if (tg1 == NULL && tg2 == NULL)
return true; return true;
if ((tg1 == NULL && tg2 != NULL) || (tg1 != NULL && tg2 == NULL)) if (tg1 == NULL || tg2 == NULL)
return false;
if (tg1->userspacesize != tg2->userspacesize)
return false; return false;
if (strcmp(tg1->t->u.user.name, tg2->t->u.user.name) != 0) if (strcmp(tg1->t->u.user.name, tg2->t->u.user.name) != 0)
...@@ -881,3 +965,32 @@ bool nft_ipv46_rule_find(struct nft_family_ops *ops, ...@@ -881,3 +965,32 @@ bool nft_ipv46_rule_find(struct nft_family_ops *ops,
return true; return true;
} }
void nft_check_xt_legacy(int family, bool is_ipt_save)
{
static const char tables6[] = "/proc/net/ip6_tables_names";
static const char tables4[] = "/proc/net/ip_tables_names";
const char *prefix = "ip";
FILE *fp = NULL;
char buf[1024];
switch (family) {
case NFPROTO_IPV4:
fp = fopen(tables4, "r");
break;
case NFPROTO_IPV6:
fp = fopen(tables6, "r");
prefix = "ip6";
break;
default:
break;
}
if (!fp)
return;
if (fgets(buf, sizeof(buf), fp))
fprintf(stderr, "# Warning: %stables-legacy tables present, use %stables-legacy%s to see them\n",
prefix, prefix, is_ipt_save ? "-save" : "");
fclose(fp);
}
...@@ -43,13 +43,13 @@ enum { ...@@ -43,13 +43,13 @@ enum {
NFT_XT_CTX_PAYLOAD = (1 << 0), NFT_XT_CTX_PAYLOAD = (1 << 0),
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),
}; };
struct nft_xt_ctx { struct nft_xt_ctx {
union { union {
struct iptables_command_state *cs; struct iptables_command_state *cs;
struct arptables_command_state *cs_arp; struct arptables_command_state *cs_arp;
struct ebtables_command_state *cs_eb;
} state; } state;
struct nftnl_expr_iter *iter; struct nftnl_expr_iter *iter;
int family; int family;
...@@ -63,6 +63,10 @@ struct nft_xt_ctx { ...@@ -63,6 +63,10 @@ struct nft_xt_ctx {
struct { struct {
uint32_t key; uint32_t key;
} meta; } meta;
struct {
uint32_t data[4];
uint32_t len, reg;
} immediate;
struct { struct {
uint32_t mask[4]; uint32_t mask[4];
uint32_t xor[4]; uint32_t xor[4];
...@@ -107,6 +111,7 @@ struct nft_family_ops { ...@@ -107,6 +111,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_u16(struct nftnl_rule *r, int mask, int xor); void add_bitwise_u16(struct nftnl_rule *r, int mask, int 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);
...@@ -223,9 +228,9 @@ struct nft_xt_cmd_parse { ...@@ -223,9 +228,9 @@ struct nft_xt_cmd_parse {
unsigned int command; unsigned int command;
unsigned int rulenum; unsigned int rulenum;
char *table; char *table;
char *chain; const char *chain;
char *newname; const char *newname;
char *policy; const char *policy;
bool restore; bool restore;
int verbose; int verbose;
}; };
...@@ -245,17 +250,18 @@ struct nftnl_chain_list; ...@@ -245,17 +250,18 @@ 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); struct nftnl_chain_list *(*chain_list)(struct nft_handle *h);
int (*chains_purge)(struct nft_handle *h, const char *table,
struct nftnl_chain_list *clist);
void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable, void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable,
const char *chain); const char *chain);
int (*chain_user_flush)(struct nft_handle *h,
struct nftnl_chain_list *clist,
const char *table, const char *chain);
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);
int (*chain_user_add)(struct nft_handle *h, const char *chain, int (*chain_user_add)(struct nft_handle *h, const char *chain,
const char *table); const char *table);
int (*rule_flush)(struct nft_handle *h, const char *chain, const char *table); int (*table_flush)(struct nft_handle *h, const char *table);
int (*do_command)(struct nft_handle *h, int argc, char *argv[], int (*do_command)(struct nft_handle *h, int argc, char *argv[],
char **table, bool restore); char **table, bool restore);
...@@ -269,4 +275,5 @@ void xtables_restore_parse(struct nft_handle *h, ...@@ -269,4 +275,5 @@ void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_cb *cb, struct nft_xt_restore_cb *cb,
int argc, char *argv[]); int argc, char *argv[]);
void nft_check_xt_legacy(int family, bool is_ipt_save);
#endif #endif
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <time.h> #include <time.h>
#include <stdarg.h> #include <stdarg.h>
#include <inttypes.h> #include <inttypes.h>
#include <assert.h>
#include <xtables.h> #include <xtables.h>
#include <libiptc/libxtc.h> #include <libiptc/libxtc.h>
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
#include <libnftnl/expr.h> #include <libnftnl/expr.h>
#include <libnftnl/set.h> #include <libnftnl/set.h>
#include <libnftnl/udata.h> #include <libnftnl/udata.h>
#include <libnftnl/batch.h>
#include <netinet/in.h> /* inet_ntoa */ #include <netinet/in.h> /* inet_ntoa */
#include <arpa/inet.h> #include <arpa/inet.h>
...@@ -60,7 +62,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, ...@@ -60,7 +62,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
void *data) void *data)
{ {
int ret; int ret;
char buf[MNL_SOCKET_BUFFER_SIZE]; char buf[16536];
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;
...@@ -80,13 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, ...@@ -80,13 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
return 0; return 0;
} }
static LIST_HEAD(batch_page_list); #define NFT_NLMSG_MAXSIZE (UINT16_MAX + getpagesize())
static int batch_num_pages;
struct batch_page {
struct list_head head;
struct mnl_nlmsg_batch *batch;
};
/* selected batch page is 256 Kbytes long to load ruleset of /* selected batch page is 256 Kbytes long to load ruleset of
* half a million rules without hitting -EMSGSIZE due to large * half a million rules without hitting -EMSGSIZE due to large
...@@ -94,44 +90,74 @@ struct batch_page { ...@@ -94,44 +90,74 @@ struct batch_page {
*/ */
#define BATCH_PAGE_SIZE getpagesize() * 32 #define BATCH_PAGE_SIZE getpagesize() * 32
static struct mnl_nlmsg_batch *mnl_nftnl_batch_alloc(void) static struct nftnl_batch *mnl_batch_init(void)
{ {
static char *buf; struct nftnl_batch *batch;
/* libmnl needs higher buffer to handle batch overflows */ batch = nftnl_batch_alloc(BATCH_PAGE_SIZE, NFT_NLMSG_MAXSIZE);
buf = malloc(BATCH_PAGE_SIZE + getpagesize()); if (batch == NULL)
if (buf == NULL)
return NULL; return NULL;
return mnl_nlmsg_batch_start(buf, BATCH_PAGE_SIZE); return batch;
} }
static struct mnl_nlmsg_batch * static void mnl_nft_batch_continue(struct nftnl_batch *batch)
mnl_nftnl_batch_page_add(struct mnl_nlmsg_batch *batch)
{ {
struct batch_page *batch_page; assert(nftnl_batch_update(batch) >= 0);
}
batch_page = malloc(sizeof(struct batch_page)); static uint32_t mnl_batch_begin(struct nftnl_batch *batch, uint32_t seqnum)
if (batch_page == NULL) {
return NULL; nftnl_batch_begin(nftnl_batch_buffer(batch), seqnum);
mnl_nft_batch_continue(batch);
return seqnum;
}
static void mnl_batch_end(struct nftnl_batch *batch, uint32_t seqnum)
{
nftnl_batch_end(nftnl_batch_buffer(batch), seqnum);
mnl_nft_batch_continue(batch);
}
static void mnl_batch_reset(struct nftnl_batch *batch)
{
nftnl_batch_free(batch);
}
batch_page->batch = batch; struct mnl_err {
list_add_tail(&batch_page->head, &batch_page_list); struct list_head head;
batch_num_pages++; int err;
uint32_t seqnum;
};
static void mnl_err_list_node_add(struct list_head *err_list, int error,
int seqnum)
{
struct mnl_err *err = malloc(sizeof(struct mnl_err));
return mnl_nftnl_batch_alloc(); err->seqnum = seqnum;
err->err = error;
list_add_tail(&err->head, err_list);
}
static void mnl_err_list_free(struct mnl_err *err)
{
list_del(&err->head);
free(err);
} }
static int nlbuffsiz; static int nlbuffsiz;
static void mnl_nft_set_sndbuffer(const struct mnl_socket *nl) static void mnl_set_sndbuffer(const struct mnl_socket *nl,
struct nftnl_batch *batch)
{ {
int newbuffsiz; int newbuffsiz;
if (batch_num_pages * BATCH_PAGE_SIZE <= nlbuffsiz) if (nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz)
return; return;
newbuffsiz = batch_num_pages * BATCH_PAGE_SIZE; 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(nl), SOL_SOCKET, SO_SNDBUFFORCE,
...@@ -141,57 +167,32 @@ static void mnl_nft_set_sndbuffer(const struct mnl_socket *nl) ...@@ -141,57 +167,32 @@ static void mnl_nft_set_sndbuffer(const struct mnl_socket *nl)
nlbuffsiz = newbuffsiz; nlbuffsiz = newbuffsiz;
} }
static void mnl_nftnl_batch_reset(void) static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
{ struct nftnl_batch *batch)
struct batch_page *batch_page, *next;
list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
list_del(&batch_page->head);
free(mnl_nlmsg_batch_head(batch_page->batch));
mnl_nlmsg_batch_stop(batch_page->batch);
free(batch_page);
batch_num_pages--;
}
}
static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
{ {
static const struct sockaddr_nl snl = { static const struct sockaddr_nl snl = {
.nl_family = AF_NETLINK .nl_family = AF_NETLINK
}; };
struct iovec iov[batch_num_pages]; uint32_t iov_len = nftnl_batch_iovec_len(batch);
struct iovec iov[iov_len];
struct msghdr msg = { struct msghdr msg = {
.msg_name = (struct sockaddr *) &snl, .msg_name = (struct sockaddr *) &snl,
.msg_namelen = sizeof(snl), .msg_namelen = sizeof(snl),
.msg_iov = iov, .msg_iov = iov,
.msg_iovlen = batch_num_pages, .msg_iovlen = iov_len,
}; };
struct batch_page *batch_page;
int i = 0, ret;
mnl_nft_set_sndbuffer(nl);
list_for_each_entry(batch_page, &batch_page_list, head) {
iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch);
iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch);
i++;
#ifdef NL_DEBUG
mnl_nlmsg_fprintf(stdout,
mnl_nlmsg_batch_head(batch_page->batch),
mnl_nlmsg_batch_size(batch_page->batch),
sizeof(struct nfgenmsg));
#endif
}
ret = sendmsg(mnl_socket_get_fd(nl), &msg, 0); mnl_set_sndbuffer(nf_sock, batch);
mnl_nftnl_batch_reset(); nftnl_batch_iovec(batch, iov, iov_len);
return ret; return sendmsg(mnl_socket_get_fd(nf_sock), &msg, 0);
} }
static int mnl_nftnl_batch_talk(struct nft_handle *h) static int mnl_batch_talk(const struct mnl_socket *nf_sock,
struct nftnl_batch *batch, struct list_head *err_list)
{ {
int ret, fd = mnl_socket_get_fd(h->nl); const struct mnl_socket *nl = nf_sock;
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;
struct timeval tv = { struct timeval tv = {
...@@ -200,7 +201,7 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h) ...@@ -200,7 +201,7 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
}; };
int err = 0; int err = 0;
ret = mnl_nft_socket_sendmsg(h->nl); ret = mnl_nft_socket_sendmsg(nf_sock, batch);
if (ret == -1) if (ret == -1)
return -1; return -1;
...@@ -213,16 +214,18 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h) ...@@ -213,16 +214,18 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
return -1; return -1;
while (ret > 0 && FD_ISSET(fd, &readfds)) { while (ret > 0 && FD_ISSET(fd, &readfds)) {
ret = mnl_socket_recvfrom(h->nl, rcv_buf, sizeof(rcv_buf)); struct nlmsghdr *nlh = (struct nlmsghdr *)rcv_buf;
ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
if (ret == -1) if (ret == -1)
return -1; return -1;
ret = mnl_cb_run(rcv_buf, ret, 0, h->portid, NULL, NULL); ret = mnl_cb_run(rcv_buf, ret, 0, portid, NULL, NULL);
/* Annotate first error and continue, make sure we get all /* Continue on error, make sure we get all acknowledgments */
* acknoledgments. if (ret == -1) {
*/ mnl_err_list_node_add(err_list, errno, nlh->nlmsg_seq);
if (!err && ret == -1) err = -1;
err = errno; }
ret = select(fd+1, &readfds, NULL, NULL, &tv); ret = select(fd+1, &readfds, NULL, NULL, &tv);
if (ret == -1) if (ret == -1)
...@@ -231,29 +234,16 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h) ...@@ -231,29 +234,16 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(fd, &readfds); FD_SET(fd, &readfds);
} }
errno = err; return err;
return err ? -1 : 0;
}
static void mnl_nftnl_batch_begin(struct mnl_nlmsg_batch *batch, uint32_t seq)
{
nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq);
if (!mnl_nlmsg_batch_next(batch))
mnl_nftnl_batch_page_add(batch);
}
static void mnl_nftnl_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq)
{
nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq);
if (!mnl_nlmsg_batch_next(batch))
mnl_nftnl_batch_page_add(batch);
} }
enum obj_update_type { enum obj_update_type {
NFT_COMPAT_TABLE_ADD, NFT_COMPAT_TABLE_ADD,
NFT_COMPAT_TABLE_FLUSH,
NFT_COMPAT_CHAIN_ADD, NFT_COMPAT_CHAIN_ADD,
NFT_COMPAT_CHAIN_USER_ADD, NFT_COMPAT_CHAIN_USER_ADD,
NFT_COMPAT_CHAIN_USER_DEL, NFT_COMPAT_CHAIN_USER_DEL,
NFT_COMPAT_CHAIN_USER_FLUSH,
NFT_COMPAT_CHAIN_UPDATE, NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_CHAIN_RENAME, NFT_COMPAT_CHAIN_RENAME,
NFT_COMPAT_RULE_APPEND, NFT_COMPAT_RULE_APPEND,
...@@ -271,14 +261,83 @@ enum obj_action { ...@@ -271,14 +261,83 @@ enum obj_action {
struct obj_update { struct obj_update {
struct list_head head; struct list_head head;
enum obj_update_type type; enum obj_update_type type;
unsigned int seq;
union { union {
struct nftnl_table *table; struct nftnl_table *table;
struct nftnl_chain *chain; struct nftnl_chain *chain;
struct nftnl_rule *rule; struct nftnl_rule *rule;
void *ptr; void *ptr;
}; };
struct {
unsigned int lineno;
} error;
}; };
static int mnl_append_error(const struct nft_handle *h,
const struct obj_update *o,
const struct mnl_err *err,
char *buf, unsigned int len)
{
static const char *type_name[] = {
[NFT_COMPAT_TABLE_ADD] = "TABLE_ADD",
[NFT_COMPAT_TABLE_FLUSH] = "TABLE_FLUSH",
[NFT_COMPAT_CHAIN_ADD] = "CHAIN_ADD",
[NFT_COMPAT_CHAIN_USER_ADD] = "CHAIN_USER_ADD",
[NFT_COMPAT_CHAIN_USER_DEL] = "CHAIN_USER_DEL",
[NFT_COMPAT_CHAIN_USER_FLUSH] = "CHAIN_USER_FLUSH",
[NFT_COMPAT_CHAIN_UPDATE] = "CHAIN_UPDATE",
[NFT_COMPAT_CHAIN_RENAME] = "CHAIN_RENAME",
[NFT_COMPAT_RULE_APPEND] = "RULE_APPEND",
[NFT_COMPAT_RULE_INSERT] = "RULE_INSERT",
[NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE",
[NFT_COMPAT_RULE_DELETE] = "RULE_DELETE",
[NFT_COMPAT_RULE_FLUSH] = "RULE_FLUSH",
};
char errmsg[256];
char tcr[128];
if (o->error.lineno)
snprintf(errmsg, sizeof(errmsg), "\nline %u: %s failed (%s)",
o->error.lineno, type_name[o->type], strerror(err->err));
else
snprintf(errmsg, sizeof(errmsg), " %s failed (%s)",
type_name[o->type], strerror(err->err));
switch (o->type) {
case NFT_COMPAT_TABLE_ADD:
case NFT_COMPAT_TABLE_FLUSH:
snprintf(tcr, sizeof(tcr), "table %s",
nftnl_table_get_str(o->table, NFTNL_TABLE_NAME));
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
snprintf(tcr, sizeof(tcr), "chain %s",
nftnl_chain_get_str(o->chain, NFTNL_CHAIN_NAME));
break;
case NFT_COMPAT_RULE_APPEND:
case NFT_COMPAT_RULE_INSERT:
case NFT_COMPAT_RULE_REPLACE:
case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH:
snprintf(tcr, sizeof(tcr), "rule in chain %s",
nftnl_rule_get_str(o->rule, NFTNL_RULE_CHAIN));
#if 0
{
struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(o->rule, &cs);
nft_rule_print_save(&cs, o->rule, NFT_RULE_APPEND, FMT_NOCOUNTS);
}
#endif
break;
}
return snprintf(buf, len, "%s: %s", errmsg, tcr);
}
static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr) static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
{ {
struct obj_update *obj; struct obj_update *obj;
...@@ -288,6 +347,7 @@ static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr) ...@@ -288,6 +347,7 @@ static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
return -1; return -1;
obj->ptr = ptr; obj->ptr = ptr;
obj->error.lineno = h->error.lineno;
obj->type = type; obj->type = type;
list_add_tail(&obj->head, &h->obj_list); list_add_tail(&obj->head, &h->obj_list);
h->obj_list_num++; h->obj_list_num++;
...@@ -455,12 +515,6 @@ struct builtin_table xtables_arp[TABLES_MAX] = { ...@@ -455,12 +515,6 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
.prio = NF_IP_PRI_FILTER, .prio = NF_IP_PRI_FILTER,
.hook = NF_ARP_IN, .hook = NF_ARP_IN,
}, },
{
.name = "FORWARD",
.type = "filter",
.prio = NF_IP_PRI_FILTER,
.hook = NF_ARP_FORWARD,
},
{ {
.name = "OUTPUT", .name = "OUTPUT",
.type = "filter", .type = "filter",
...@@ -522,30 +576,6 @@ struct builtin_table xtables_bridge[TABLES_MAX] = { ...@@ -522,30 +576,6 @@ struct builtin_table xtables_bridge[TABLES_MAX] = {
}, },
}; };
int nft_table_add(struct nft_handle *h, struct nftnl_table *t, uint16_t flags)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
int ret;
nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
NLM_F_ACK|flags, h->seq);
nftnl_table_nlmsg_build_payload(nlh, t);
nftnl_table_free(t);
#ifdef NLDEBUG
char tmp[1024];
nft_table_snprintf(tmp, sizeof(tmp), t, 0, 0);
printf("DEBUG: table: %s\n", tmp);
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
#endif
ret = mnl_talk(h, nlh, NULL, NULL);
return (ret == 0 || (ret == -1 && errno == EEXIST)) ? 0 : -1;
}
static int nft_table_builtin_add(struct nft_handle *h, static int nft_table_builtin_add(struct nft_handle *h,
struct builtin_table *_t) struct builtin_table *_t)
{ {
...@@ -561,13 +591,7 @@ static int nft_table_builtin_add(struct nft_handle *h, ...@@ -561,13 +591,7 @@ static int nft_table_builtin_add(struct nft_handle *h,
nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name); nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name);
if (h->batch_support) ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
else
ret = nft_table_add(h, t, NLM_F_EXCL);
if (ret == 0)
_t->initialized = true;
return ret; return ret;
} }
...@@ -592,29 +616,6 @@ nft_chain_builtin_alloc(struct builtin_table *table, ...@@ -592,29 +616,6 @@ nft_chain_builtin_alloc(struct builtin_table *table,
return c; return c;
} }
int nft_chain_add(struct nft_handle *h, struct nftnl_chain *c, uint16_t flags)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
/* NLM_F_CREATE requests module autoloading */
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK|flags|NLM_F_CREATE,
h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
nftnl_chain_free(c);
#ifdef NLDEBUG
char tmp[1024];
nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
printf("DEBUG: chain: %s\n", tmp);
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
#endif
return mnl_talk(h, nlh, NULL, NULL);
}
static void nft_chain_builtin_add(struct nft_handle *h, static void nft_chain_builtin_add(struct nft_handle *h,
struct builtin_table *table, struct builtin_table *table,
struct builtin_chain *chain) struct builtin_chain *chain)
...@@ -625,10 +626,7 @@ static void nft_chain_builtin_add(struct nft_handle *h, ...@@ -625,10 +626,7 @@ static void nft_chain_builtin_add(struct nft_handle *h,
if (c == NULL) if (c == NULL)
return; return;
if (h->batch_support) batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
else
nft_chain_add(h, c, NLM_F_EXCL);
} }
/* find if built-in table already exists */ /* find if built-in table already exists */
...@@ -686,28 +684,27 @@ static void nft_chain_builtin_init(struct nft_handle *h, ...@@ -686,28 +684,27 @@ static void nft_chain_builtin_init(struct nft_handle *h,
nft_chain_builtin_add(h, table, &table->chains[i]); nft_chain_builtin_add(h, table, &table->chains[i]);
} }
nftnl_chain_list_free(list);
} }
static int nft_xt_builtin_init(struct nft_handle *h, const char *table) static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
{ {
int ret = 0;
struct builtin_table *t; struct builtin_table *t;
t = nft_table_builtin_find(h, table); t = nft_table_builtin_find(h, table);
if (t == NULL) { if (t == NULL)
ret = -1; return -1;
goto out;
} if (t->initialized)
if (nft_table_builtin_add(h, t) < 0) { return 0;
/* Built-in table already initialized, skip. */
if (errno == EEXIST) if (nft_table_builtin_add(h, t) < 0)
goto out; return -1;
}
nft_chain_builtin_init(h, t); nft_chain_builtin_init(h, t);
out:
return ret; t->initialized = true;
return 0;
} }
static bool nft_chain_builtin(struct nftnl_chain *c) static bool nft_chain_builtin(struct nftnl_chain *c)
...@@ -718,47 +715,20 @@ static bool nft_chain_builtin(struct nftnl_chain *c) ...@@ -718,47 +715,20 @@ 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 bool mnl_batch_supported(struct nft_handle *h) static int nft_restart(struct nft_handle *h)
{ {
char buf[MNL_SOCKET_BUFFER_SIZE]; mnl_socket_close(h->nl);
uint32_t seq = 1;
int ret;
mnl_nftnl_batch_begin(h->batch, seq++);
nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
NFT_MSG_NEWSET, AF_INET,
NLM_F_ACK, seq++);
mnl_nlmsg_batch_next(h->batch);
mnl_nftnl_batch_end(h->batch, seq++);
ret = mnl_socket_sendto(h->nl, mnl_nlmsg_batch_head(h->batch),
mnl_nlmsg_batch_size(h->batch));
if (ret < 0)
goto err;
mnl_nlmsg_batch_reset(h->batch); h->nl = mnl_socket_open(NETLINK_NETFILTER);
if (h->nl == NULL)
return -1;
ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf)); if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
while (ret > 0) { return -1;
ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
NULL, NULL);
if (ret <= 0)
break;
ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf)); h->portid = mnl_socket_get_portid(h->nl);
}
/* We're sending an incomplete message to see if the kernel supports return 0;
* set messages in batches. EINVAL means that we sent an incomplete
* message with missing attributes. The kernel just ignores messages
* that we cannot include in the batch.
*/
return (ret == -1 && errno == EINVAL) ? true : false;
err:
mnl_nlmsg_batch_reset(h->batch);
return ret;
} }
int nft_init(struct nft_handle *h, struct builtin_table *t) int nft_init(struct nft_handle *h, struct builtin_table *t)
...@@ -767,35 +737,77 @@ int nft_init(struct nft_handle *h, struct builtin_table *t) ...@@ -767,35 +737,77 @@ int nft_init(struct nft_handle *h, struct builtin_table *t)
if (h->nl == NULL) if (h->nl == NULL)
return -1; return -1;
if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
mnl_socket_close(h->nl);
return -1; return -1;
}
h->portid = mnl_socket_get_portid(h->nl); h->portid = mnl_socket_get_portid(h->nl);
h->tables = t; h->tables = t;
INIT_LIST_HEAD(&h->obj_list); INIT_LIST_HEAD(&h->obj_list);
INIT_LIST_HEAD(&h->err_list);
return 0;
}
h->batch = mnl_nftnl_batch_alloc(); static int __flush_rule_cache(struct nftnl_rule *r, void *data)
h->batch_support = mnl_batch_supported(h); {
const char *tablename = data;
if (!strcmp(nftnl_rule_get_str(r, NFTNL_RULE_TABLE), tablename)) {
nftnl_rule_list_del(r);
nftnl_rule_free(r);
}
return 0; return 0;
} }
static void flush_rule_cache(struct nft_handle *h) static void flush_rule_cache(struct nft_handle *h, const char *tablename)
{ {
if (!h->rule_cache) if (!h->rule_cache)
return; return;
nftnl_rule_list_free(h->rule_cache); if (tablename) {
h->rule_cache = NULL; nftnl_rule_list_foreach(h->rule_cache, __flush_rule_cache,
(void *)tablename);
} else {
nftnl_rule_list_free(h->rule_cache);
h->rule_cache = NULL;
}
}
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
{
const char *tablename = data;
if (!strcmp(nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), tablename)) {
nftnl_chain_list_del(c);
nftnl_chain_free(c);
}
return 0;
}
static void flush_chain_cache(struct nft_handle *h, const char *tablename)
{
if (!h->chain_cache)
return;
if (tablename) {
nftnl_chain_list_foreach(h->chain_cache, __flush_chain_cache,
(void *)tablename);
} else {
nftnl_chain_list_free(h->chain_cache);
h->chain_cache = NULL;
}
} }
void nft_fini(struct nft_handle *h) void nft_fini(struct nft_handle *h)
{ {
flush_rule_cache(h); flush_chain_cache(h, NULL);
flush_rule_cache(h, NULL);
mnl_socket_close(h->nl); mnl_socket_close(h->nl);
free(mnl_nlmsg_batch_head(h->batch));
mnl_nlmsg_batch_stop(h->batch);
} }
static void nft_chain_print_debug(struct nftnl_chain *c, struct nlmsghdr *nlh) static void nft_chain_print_debug(struct nftnl_chain *c, struct nlmsghdr *nlh)
...@@ -861,10 +873,7 @@ int nft_chain_set(struct nft_handle *h, const char *table, ...@@ -861,10 +873,7 @@ int nft_chain_set(struct nft_handle *h, const char *table,
if (c == NULL) if (c == NULL)
return 0; return 0;
if (h->batch_support) ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
else
ret = nft_chain_add(h, c, 0);
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
...@@ -920,11 +929,36 @@ static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t) ...@@ -920,11 +929,36 @@ static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
return 0; return 0;
} }
static int add_meta_nftrace(struct nftnl_rule *r)
{
struct nftnl_expr *expr;
expr = nftnl_expr_alloc("immediate");
if (expr == NULL)
return -ENOMEM;
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG32_01);
nftnl_expr_set_u8(expr, NFTNL_EXPR_IMM_DATA, 1);
nftnl_rule_add_expr(r, expr);
expr = nftnl_expr_alloc("meta");
if (expr == NULL)
return -ENOMEM;
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, NFT_META_NFTRACE);
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_SREG, NFT_REG32_01);
nftnl_rule_add_expr(r, expr);
return 0;
}
int add_target(struct nftnl_rule *r, struct xt_entry_target *t) int add_target(struct nftnl_rule *r, struct xt_entry_target *t)
{ {
struct nftnl_expr *expr; struct nftnl_expr *expr;
int ret; int ret;
if (strcmp(t->u.user.name, "TRACE") == 0)
return add_meta_nftrace(r);
expr = nftnl_expr_alloc("target"); expr = nftnl_expr_alloc("target");
if (expr == NULL) if (expr == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1028,13 +1062,21 @@ enum udata_type { ...@@ -1028,13 +1062,21 @@ enum udata_type {
int add_comment(struct nftnl_rule *r, const char *comment) int add_comment(struct nftnl_rule *r, const char *comment)
{ {
struct nftnl_udata_buf *udata; struct nftnl_udata_buf *udata;
uint32_t len;
if (nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len))
return -EALREADY;
udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
if (!udata) if (!udata)
return -ENOMEM; return -ENOMEM;
if (strnlen(comment, 255) == 255)
return -ENOSPC;
if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment)) if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment))
return -ENOMEM; return -ENOMEM;
nftnl_rule_set_data(r, NFTNL_RULE_USERDATA, nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
nftnl_udata_buf_data(udata), nftnl_udata_buf_data(udata),
nftnl_udata_buf_len(udata)); nftnl_udata_buf_len(udata));
...@@ -1106,6 +1148,8 @@ err: ...@@ -1106,6 +1148,8 @@ err:
return NULL; return NULL;
} }
static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h);
int int
nft_rule_append(struct nft_handle *h, const char *chain, const char *table, nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
void *data, uint64_t handle, bool verbose) void *data, uint64_t handle, bool verbose)
...@@ -1132,7 +1176,10 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, ...@@ -1132,7 +1176,10 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
if (batch_rule_add(h, type, r) < 0) if (batch_rule_add(h, type, r) < 0)
nftnl_rule_free(r); nftnl_rule_free(r);
flush_rule_cache(h); nft_rule_list_get(h);
nftnl_rule_list_add_tail(r, h->rule_cache);
return 1; return 1;
} }
...@@ -1188,10 +1235,14 @@ err: ...@@ -1188,10 +1235,14 @@ err:
static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h) static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h)
{ {
char buf[MNL_SOCKET_BUFFER_SIZE]; char buf[16536];
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
int ret;
if (h->chain_cache)
return h->chain_cache;
retry:
list = nftnl_chain_list_alloc(); list = nftnl_chain_list_alloc();
if (list == NULL) { if (list == NULL) {
errno = ENOMEM; errno = ENOMEM;
...@@ -1201,7 +1252,14 @@ static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h) ...@@ -1201,7 +1252,14 @@ static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h)
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq); NLM_F_DUMP, h->seq);
mnl_talk(h, nlh, nftnl_chain_list_cb, list); ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
nftnl_chain_list_free(list);
goto retry;
}
h->chain_cache = list;
return list; return list;
} }
...@@ -1262,7 +1320,6 @@ next: ...@@ -1262,7 +1320,6 @@ next:
} }
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
nftnl_chain_list_free(list);
return 1; return 1;
} }
...@@ -1291,7 +1348,7 @@ err: ...@@ -1291,7 +1348,7 @@ err:
static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
{ {
char buf[MNL_SOCKET_BUFFER_SIZE]; char buf[16536];
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct nftnl_rule_list *list; struct nftnl_rule_list *list;
int ret; int ret;
...@@ -1299,6 +1356,7 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) ...@@ -1299,6 +1356,7 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
if (h->rule_cache) if (h->rule_cache)
return h->rule_cache; return h->rule_cache;
retry:
list = nftnl_rule_list_alloc(); list = nftnl_rule_list_alloc();
if (list == NULL) if (list == NULL)
return 0; return 0;
...@@ -1308,6 +1366,12 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) ...@@ -1308,6 +1366,12 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list); ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list);
if (ret < 0) { if (ret < 0) {
if (errno == EINTR) {
assert(nft_restart(h) >= 0);
nftnl_rule_list_free(list);
goto retry;
}
nftnl_rule_list_free(list); nftnl_rule_list_free(list);
return NULL; return NULL;
} }
...@@ -1370,6 +1434,55 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain) ...@@ -1370,6 +1434,55 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
nftnl_rule_free(r); nftnl_rule_free(r);
} }
struct chain_user_flush_data {
struct nft_handle *handle;
const char *table;
const char *chain;
};
static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
{
const char *table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
struct chain_user_flush_data *d = data;
struct nft_handle *h = d->handle;
const char *table = d->table;
const char *chain = d->chain;
int ret;
if (strcmp(table, table_name) != 0)
return 0;
if (strcmp(chain, chain_name) != 0)
return 0;
if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_FLUSH, c);
if (ret < 0)
return ret;
nftnl_chain_list_del(c);
}
return 0;
}
int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
const char *table, const char *chain)
{
struct chain_user_flush_data d = {
.handle = h,
.table = table,
.chain = chain,
};
nft_fn = nft_chain_user_flush;
nftnl_chain_list_foreach(list, __nft_chain_user_flush, &d);
return 1;
}
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)
{ {
int ret; int ret;
...@@ -1377,6 +1490,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table) ...@@ -1377,6 +1490,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
struct nftnl_chain_list_iter *iter; struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c; struct nftnl_chain *c;
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_flush; nft_fn = nft_rule_flush;
list = nftnl_chain_list_get(h); list = nftnl_chain_list_get(h);
...@@ -1409,12 +1525,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table) ...@@ -1409,12 +1525,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
next: next:
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);
flush_rule_cache(h); flush_rule_cache(h, table);
err: err:
nftnl_chain_list_free(list);
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
} }
...@@ -1437,19 +1550,11 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1437,19 +1550,11 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table); nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain); nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
if (h->batch_support) { ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
} else {
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, nft_chain_dump(h);
h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq); nftnl_chain_list_add(c, h->chain_cache);
nftnl_chain_nlmsg_build_payload(nlh, c);
nftnl_chain_free(c);
ret = mnl_talk(h, nlh, NULL, NULL);
}
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
...@@ -1460,18 +1565,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1460,18 +1565,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
#define NLM_F_NONREC 0x100 /* Do not delete recursively */ #define NLM_F_NONREC 0x100 /* Do not delete recursively */
#endif #endif
static int __nft_chain_del(struct nft_handle *h, struct nftnl_chain *c)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
NLM_F_NONREC | NLM_F_ACK, h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
return mnl_talk(h, nlh, NULL, NULL);
}
int nft_chain_user_del(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)
{ {
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
...@@ -1480,6 +1573,8 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1480,6 +1573,8 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
int ret = 0; int ret = 0;
int deleted_ctr = 0; int deleted_ctr = 0;
nft_fn = nft_chain_user_del;
list = nftnl_chain_list_get(h); list = nftnl_chain_list_get(h);
if (list == NULL) if (list == NULL)
goto err; goto err;
...@@ -1505,15 +1600,13 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1505,15 +1600,13 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
if (chain != NULL && strcmp(chain, chain_name) != 0) if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next; goto next;
if (h->batch_support) ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
else
ret = __nft_chain_del(h, c);
if (ret < 0) if (ret < 0)
break; break;
deleted_ctr++; deleted_ctr++;
nftnl_chain_list_del(c);
if (chain != NULL) if (chain != NULL)
break; break;
...@@ -1523,11 +1616,9 @@ next: ...@@ -1523,11 +1616,9 @@ next:
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
err: err:
if (!h->batch_support)
nftnl_chain_list_free(list);
/* chain not found */ /* chain not found */
if (deleted_ctr == 0) { if (chain != NULL && deleted_ctr == 0) {
ret = -1; ret = -1;
errno = ENOENT; errno = ENOENT;
} }
...@@ -1614,19 +1705,7 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -1614,19 +1705,7 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname); nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname);
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle); nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
if (h->batch_support) { ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
} else {
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
h->family, NLM_F_ACK, h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
nftnl_chain_free(c);
ret = mnl_talk(h, nlh, NULL, NULL);
}
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
...@@ -1655,10 +1734,12 @@ err: ...@@ -1655,10 +1734,12 @@ err:
static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
{ {
char buf[MNL_SOCKET_BUFFER_SIZE]; char buf[16536];
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct nftnl_table_list *list; struct nftnl_table_list *list;
int ret;
retry:
list = nftnl_table_list_alloc(); list = nftnl_table_list_alloc();
if (list == NULL) if (list == NULL)
return 0; return 0;
...@@ -1666,7 +1747,12 @@ static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) ...@@ -1666,7 +1747,12 @@ static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
NLM_F_DUMP, h->seq); NLM_F_DUMP, h->seq);
mnl_talk(h, nlh, nftnl_table_list_cb, list); ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
nftnl_table_list_free(list);
goto retry;
}
return list; return list;
} }
...@@ -1707,20 +1793,17 @@ int nft_for_each_table(struct nft_handle *h, ...@@ -1707,20 +1793,17 @@ 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, bool counters),
bool counters) bool counters)
{ {
int ret = 1;
struct nftnl_table_list *list; struct nftnl_table_list *list;
struct nftnl_table_list_iter *iter; struct nftnl_table_list_iter *iter;
struct nftnl_table *t; struct nftnl_table *t;
list = nftnl_table_list_get(h); list = nftnl_table_list_get(h);
if (list == NULL) { if (list == NULL)
ret = 0; return -1;
goto err;
}
iter = nftnl_table_list_iter_create(list); iter = nftnl_table_list_iter_create(list);
if (iter == NULL) if (iter == NULL)
return 0; return -1;
t = nftnl_table_list_iter_next(iter); t = nftnl_table_list_iter_next(iter);
while (t != NULL) { while (t != NULL) {
...@@ -1733,43 +1816,85 @@ int nft_for_each_table(struct nft_handle *h, ...@@ -1733,43 +1816,85 @@ int nft_for_each_table(struct nft_handle *h,
} }
nftnl_table_list_free(list); nftnl_table_list_free(list);
return 0;
}
err: static int __nft_table_flush(struct nft_handle *h, const char *table)
/* the core expects 1 for success and 0 for error */ {
return ret == 0 ? 1 : 0; struct builtin_table *_t;
struct nftnl_table *t;
t = nftnl_table_alloc();
if (t == NULL)
return -1;
nftnl_table_set_str(t, NFTNL_TABLE_NAME, table);
batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t);
_t = nft_table_builtin_find(h, table);
assert(t);
_t->initialized = false;
flush_chain_cache(h, table);
flush_rule_cache(h, table);
return 0;
} }
int nft_table_purge_chains(struct nft_handle *h, const char *this_table, int nft_table_flush(struct nft_handle *h, const char *table)
struct nftnl_chain_list *chain_list)
{ {
struct nftnl_chain_list_iter *iter; struct nftnl_table_list_iter *iter;
struct nftnl_chain *chain_obj; struct nftnl_table_list *list;
struct nftnl_table *t;
int ret = 0;
iter = nftnl_chain_list_iter_create(chain_list); nft_fn = nft_table_flush;
if (iter == NULL)
return 0;
chain_obj = nftnl_chain_list_iter_next(iter); list = nftnl_table_list_get(h);
while (chain_obj != NULL) { if (list == NULL) {
const char *table = ret = -1;
nftnl_chain_get_str(chain_obj, NFTNL_CHAIN_TABLE); goto err_out;
}
if (strcmp(this_table, table) != 0) iter = nftnl_table_list_iter_create(list);
goto next; if (iter == NULL) {
ret = -1;
goto err_table_list;
}
t = nftnl_table_list_iter_next(iter);
while (t != NULL) {
const char *table_name =
nftnl_table_get_str(t, NFTNL_TABLE_NAME);
if (nft_chain_builtin(chain_obj)) if (strcmp(table_name, table) != 0)
goto next; goto next;
if ( __nft_chain_del(h, chain_obj) < 0) { ret = __nft_table_flush(h, table);
if (errno != EBUSY) if (ret < 0)
return -1; goto err_table_iter;
}
next: next:
chain_obj = nftnl_chain_list_iter_next(iter); t = nftnl_table_list_iter_next(iter);
} }
nftnl_chain_list_iter_destroy(iter);
return 0; h->rule_cache = nftnl_rule_list_alloc();
if (h->rule_cache == NULL)
return -1;
err_table_iter:
nftnl_table_list_iter_destroy(iter);
err_table_list:
nftnl_table_list_free(list);
err_out:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
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);
} }
static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list, static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list,
...@@ -1874,12 +1999,10 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, ...@@ -1874,12 +1999,10 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
} else } else
errno = ENOENT; errno = ENOENT;
flush_rule_cache(h);
return ret; return ret;
} }
static int static struct nftnl_rule *
nft_rule_add(struct nft_handle *h, const char *chain, nft_rule_add(struct nft_handle *h, const char *chain,
const char *table, struct iptables_command_state *cs, const char *table, struct iptables_command_state *cs,
uint64_t handle, bool verbose) uint64_t handle, bool verbose)
...@@ -1888,25 +2011,24 @@ nft_rule_add(struct nft_handle *h, const char *chain, ...@@ -1888,25 +2011,24 @@ nft_rule_add(struct nft_handle *h, const char *chain,
r = nft_rule_new(h, chain, table, cs); r = nft_rule_new(h, chain, table, cs);
if (r == NULL) if (r == NULL)
return 0; return NULL;
if (handle > 0) if (handle > 0)
nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle); nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) { if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
nftnl_rule_free(r); nftnl_rule_free(r);
return 0; return NULL;
} }
flush_rule_cache(h); return r;
return 1;
} }
int nft_rule_insert(struct nft_handle *h, const char *chain, int nft_rule_insert(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose) const char *table, void *data, int rulenum, bool verbose)
{ {
struct nftnl_rule *r, *new_rule;
struct nftnl_rule_list *list; struct nftnl_rule_list *list;
struct nftnl_rule *r;
uint64_t handle = 0; uint64_t handle = 0;
/* If built-in chains don't exist for this table, create them */ /* If built-in chains don't exist for this table, create them */
...@@ -1927,11 +2049,9 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, ...@@ -1927,11 +2049,9 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
*/ */
r = nft_rule_find(h, list, chain, table, data, r = nft_rule_find(h, list, chain, table, data,
rulenum - 1); rulenum - 1);
if (r != NULL) { if (r != NULL)
flush_rule_cache(h);
return nft_rule_append(h, chain, table, data, return nft_rule_append(h, chain, table, data,
0, verbose); 0, verbose);
}
errno = ENOENT; errno = ENOENT;
goto err; goto err;
...@@ -1939,13 +2059,21 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, ...@@ -1939,13 +2059,21 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE); handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
DEBUGP("adding after rule handle %"PRIu64"\n", handle); DEBUGP("adding after rule handle %"PRIu64"\n", handle);
} else {
flush_rule_cache(h); nft_rule_list_get(h);
} }
return nft_rule_add(h, chain, table, data, handle, verbose); new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
if (!new_rule)
goto err;
if (handle)
nftnl_rule_list_insert_at(new_rule, r);
else
nftnl_rule_list_add(new_rule, h->rule_cache);
return 1;
err: err:
flush_rule_cache(h);
return 0; return 0;
} }
...@@ -1973,8 +2101,6 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain, ...@@ -1973,8 +2101,6 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
} else } else
errno = ENOENT; errno = ENOENT;
flush_rule_cache(h);
return ret; return ret;
} }
...@@ -1997,14 +2123,14 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, ...@@ -1997,14 +2123,14 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
(unsigned long long) (unsigned long long)
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE)); nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
nftnl_rule_list_del(r);
ret = nft_rule_append(h, chain, table, data, ret = nft_rule_append(h, chain, table, data,
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE), nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
verbose); verbose);
} else } else
errno = ENOENT; errno = ENOENT;
flush_rule_cache(h);
return ret; return ret;
} }
...@@ -2084,6 +2210,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, ...@@ -2084,6 +2210,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
ops = nft_family_ops_lookup(h->family); 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;
}
if (chain && rulenum) { if (chain && rulenum) {
__nft_rule_list(h, chain, table, __nft_rule_list(h, chain, table,
rulenum, format, ops->print_firewall); rulenum, format, ops->print_firewall);
...@@ -2144,8 +2275,6 @@ next: ...@@ -2144,8 +2275,6 @@ next:
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
err: err:
nftnl_chain_list_free(list);
return 1; return 1;
} }
...@@ -2249,8 +2378,6 @@ next: ...@@ -2249,8 +2378,6 @@ next:
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
err: err:
nftnl_chain_list_free(list);
return ret; return ret;
} }
...@@ -2284,8 +2411,6 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, ...@@ -2284,8 +2411,6 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
false); false);
error: error:
flush_rule_cache(h);
return ret; return ret;
} }
...@@ -2295,10 +2420,9 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type, ...@@ -2295,10 +2420,9 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
{ {
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch), nlh = nftnl_table_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
type, h->family, flags, seq); type, h->family, flags, seq);
nftnl_table_nlmsg_build_payload(nlh, table); nftnl_table_nlmsg_build_payload(nlh, table);
nftnl_table_free(table);
} }
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,
...@@ -2307,11 +2431,10 @@ static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type, ...@@ -2307,11 +2431,10 @@ static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
{ {
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch), nlh = nftnl_chain_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
type, h->family, flags, seq); type, h->family, flags, seq);
nftnl_chain_nlmsg_build_payload(nlh, chain); nftnl_chain_nlmsg_build_payload(nlh, chain);
nft_chain_print_debug(chain, nlh); nft_chain_print_debug(chain, nlh);
nftnl_chain_free(chain);
} }
static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type, static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
...@@ -2320,97 +2443,160 @@ static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type, ...@@ -2320,97 +2443,160 @@ static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
{ {
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch), nlh = nftnl_rule_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
type, h->family, flags, seq); type, h->family, flags, seq);
nftnl_rule_nlmsg_build_payload(nlh, rule); nftnl_rule_nlmsg_build_payload(nlh, rule);
nft_rule_print_debug(rule, nlh); nft_rule_print_debug(rule, nlh);
nftnl_rule_free(rule); }
static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
{
switch (o->type) {
case NFT_COMPAT_TABLE_ADD:
case NFT_COMPAT_TABLE_FLUSH:
nftnl_table_free(o->table);
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
break;
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
nftnl_chain_free(o->chain);
break;
case NFT_COMPAT_RULE_APPEND:
case NFT_COMPAT_RULE_INSERT:
case NFT_COMPAT_RULE_REPLACE:
case NFT_COMPAT_RULE_DELETE:
break;
case NFT_COMPAT_RULE_FLUSH:
nftnl_rule_free(o->rule);
break;
}
h->obj_list_num--;
list_del(&o->head);
free(o);
} }
static int nft_action(struct nft_handle *h, int action) static int nft_action(struct nft_handle *h, int action)
{ {
struct obj_update *n, *tmp; struct obj_update *n, *tmp;
struct mnl_err *err, *ne;
unsigned int buflen, i, len;
bool show_errors = true;
char errmsg[1024];
uint32_t seq = 1; uint32_t seq = 1;
int ret = 0; int ret = 0;
mnl_nftnl_batch_begin(h->batch, seq++); h->batch = mnl_batch_init();
list_for_each_entry_safe(n, tmp, &h->obj_list, head) { mnl_batch_begin(h->batch, seq++);
list_for_each_entry(n, &h->obj_list, head) {
n->seq = seq++;
switch (n->type) { switch (n->type) {
case NFT_COMPAT_TABLE_ADD: case NFT_COMPAT_TABLE_ADD:
nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE, nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE,
NLM_F_CREATE, seq++, NLM_F_CREATE, n->seq,
n->table); n->table);
break; break;
case NFT_COMPAT_TABLE_FLUSH:
nft_compat_table_batch_add(h, NFT_MSG_DELTABLE,
0,
n->seq, n->table);
break;
case NFT_COMPAT_CHAIN_ADD: case NFT_COMPAT_CHAIN_ADD:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
NLM_F_CREATE, seq++, NLM_F_CREATE, n->seq,
n->chain); n->chain);
break; break;
case NFT_COMPAT_CHAIN_USER_ADD: case NFT_COMPAT_CHAIN_USER_ADD:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
NLM_F_EXCL, seq++, NLM_F_EXCL, n->seq,
n->chain); n->chain);
break; break;
case NFT_COMPAT_CHAIN_USER_DEL: case NFT_COMPAT_CHAIN_USER_DEL:
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN, nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
NLM_F_NONREC, seq++, NLM_F_NONREC, n->seq,
n->chain);
break;
case NFT_COMPAT_CHAIN_USER_FLUSH:
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
0, n->seq,
n->chain); n->chain);
break; break;
case NFT_COMPAT_CHAIN_UPDATE: case NFT_COMPAT_CHAIN_UPDATE:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
h->restore ? h->restore ?
NLM_F_CREATE : 0, NLM_F_CREATE : 0,
seq++, n->chain); n->seq, n->chain);
break; break;
case NFT_COMPAT_CHAIN_RENAME: case NFT_COMPAT_CHAIN_RENAME:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, 0, nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, 0,
seq++, n->chain); n->seq, n->chain);
break; break;
case NFT_COMPAT_RULE_APPEND: case NFT_COMPAT_RULE_APPEND:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE, nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE | NLM_F_APPEND, NLM_F_CREATE | NLM_F_APPEND,
seq++, n->rule); n->seq, n->rule);
break; break;
case NFT_COMPAT_RULE_INSERT: case NFT_COMPAT_RULE_INSERT:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE, nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE, seq++, NLM_F_CREATE, n->seq,
n->rule); n->rule);
break; break;
case NFT_COMPAT_RULE_REPLACE: case NFT_COMPAT_RULE_REPLACE:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE, nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE | NLM_F_REPLACE, NLM_F_CREATE | NLM_F_REPLACE,
seq++, n->rule); n->seq, n->rule);
break; break;
case NFT_COMPAT_RULE_DELETE: case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH: case NFT_COMPAT_RULE_FLUSH:
nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0, nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
seq++, n->rule); n->seq, n->rule);
break; break;
} }
h->obj_list_num--; mnl_nft_batch_continue(h->batch);
list_del(&n->head);
free(n);
if (!mnl_nlmsg_batch_next(h->batch))
h->batch = mnl_nftnl_batch_page_add(h->batch);
} }
switch (action) { switch (action) {
case NFT_COMPAT_COMMIT: case NFT_COMPAT_COMMIT:
mnl_nftnl_batch_end(h->batch, seq++); mnl_batch_end(h->batch, seq++);
break; break;
case NFT_COMPAT_ABORT: case NFT_COMPAT_ABORT:
break; break;
} }
if (!mnl_nlmsg_batch_is_empty(h->batch)) ret = mnl_batch_talk(h->nl, h->batch, &h->err_list);
h->batch = mnl_nftnl_batch_page_add(h->batch);
i = 0;
buflen = sizeof(errmsg);
ret = mnl_nftnl_batch_talk(h); list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
list_for_each_entry_safe(err, ne, &h->err_list, head) {
if (err->seqnum > n->seq)
break;
mnl_nlmsg_batch_reset(h->batch); if (err->seqnum == n->seq && show_errors) {
if (n->error.lineno == 0)
show_errors = false;
len = mnl_append_error(h, n, err, errmsg + i, buflen);
if (len > 0 && len <= buflen) {
buflen -= len;
i += len;
}
}
mnl_err_list_free(err);
}
batch_obj_del(h, n);
}
mnl_batch_reset(h->batch);
if (i)
xtables_error(RESOURCE_PROBLEM, "%s", errmsg);
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
} }
...@@ -2428,16 +2614,29 @@ int nft_abort(struct nft_handle *h) ...@@ -2428,16 +2614,29 @@ int nft_abort(struct nft_handle *h)
int nft_compatible_revision(const char *name, uint8_t rev, int opt) int nft_compatible_revision(const char *name, uint8_t rev, int opt)
{ {
struct mnl_socket *nl; struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE]; char buf[16536];
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
uint32_t portid, seq, type; uint32_t portid, seq, type = 0;
uint32_t pf = AF_INET;
int ret = 0; int ret = 0;
if (opt == IPT_SO_GET_REVISION_MATCH || switch (opt) {
opt == IP6T_SO_GET_REVISION_MATCH) case IPT_SO_GET_REVISION_MATCH:
type = 0; break;
else case IP6T_SO_GET_REVISION_MATCH:
pf = AF_INET6;
break;
case IPT_SO_GET_REVISION_TARGET:
type = 1;
break;
case IP6T_SO_GET_REVISION_TARGET:
type = 1; type = 1;
pf = AF_INET6;
break;
default:
/* No revision support (arp, ebtables), assume latest version ok */
return 1;
}
nlh = mnl_nlmsg_put_header(buf); nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET; nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
...@@ -2445,7 +2644,7 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt) ...@@ -2445,7 +2644,7 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt)
nlh->nlmsg_seq = seq = time(NULL); nlh->nlmsg_seq = seq = time(NULL);
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
nfg->nfgen_family = AF_INET; nfg->nfgen_family = pf;
nfg->version = NFNETLINK_V0; nfg->version = NFNETLINK_V0;
nfg->res_id = 0; nfg->res_id = 0;
...@@ -2498,19 +2697,18 @@ const char *nft_strerror(int err) ...@@ -2498,19 +2697,18 @@ const char *nft_strerror(int err)
{ nft_chain_user_del, EMLINK, { nft_chain_user_del, EMLINK,
"Can't delete chain with references left" }, "Can't delete chain with references left" },
{ nft_chain_user_add, EEXIST, "Chain already exists" }, { nft_chain_user_add, EEXIST, "Chain already exists" },
{ nft_rule_add, E2BIG, "Index of insertion too big" }, { nft_rule_insert, ENOENT, "Index of insertion too big" },
{ nft_rule_check, ENOENT, "Bad rule (does a matching rule exist in that chain?)" }, { nft_rule_check, ENOENT, "Bad rule (does a matching rule exist in that chain?)" },
{ nft_rule_replace, ENOENT, "Index of replacement too big" }, { nft_rule_replace, ENOENT, "Index of replacement too big" },
{ nft_rule_delete_num, E2BIG, "Index of deletion too big" }, { nft_rule_delete_num, ENOENT, "Index of deletion too big" },
/* { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, /* { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
{ TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */ { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
{ nft_rule_add, ELOOP, "Loop found in table" },
{ nft_rule_add, EINVAL, "Target problem" },
/* ENOENT for DELETE probably means no matching rule */ /* ENOENT for DELETE probably means no matching rule */
{ nft_rule_delete, ENOENT, { nft_rule_delete, ENOENT,
"Bad rule (does a matching rule exist in that chain?)" }, "Bad rule (does a matching rule exist in that chain?)" },
{ nft_chain_set, ENOENT, "Bad built-in chain name" }, { nft_chain_set, ENOENT, "Bad built-in chain name" },
{ nft_chain_set, EINVAL, "Bad policy name" }, { nft_chain_set, EINVAL, "Bad policy name" },
{ NULL, ELOOP, "Loop found in table" },
{ NULL, EPERM, "Permission denied (you must be root)" }, { NULL, EPERM, "Permission denied (you must be root)" },
{ NULL, 0, "Incompatible with this kernel" }, { NULL, 0, "Incompatible with this kernel" },
{ NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
...@@ -2540,8 +2738,8 @@ static void xtables_config_perror(uint32_t flags, const char *fmt, ...) ...@@ -2540,8 +2738,8 @@ static void xtables_config_perror(uint32_t flags, const char *fmt, ...)
va_end(args); va_end(args);
} }
int nft_xtables_config_load(struct nft_handle *h, const char *filename, static int __nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags) uint32_t flags)
{ {
struct nftnl_table_list *table_list = NULL; struct nftnl_table_list *table_list = NULL;
struct nftnl_chain_list *chain_list = NULL; struct nftnl_chain_list *chain_list = NULL;
...@@ -2552,9 +2750,6 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename, ...@@ -2552,9 +2750,6 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t table_family, chain_family; uint32_t table_family, chain_family;
bool found = false; bool found = false;
if (h->restore)
return 0;
table_list = nftnl_table_list_alloc(); table_list = nftnl_table_list_alloc();
chain_list = nftnl_chain_list_alloc(); chain_list = nftnl_chain_list_alloc();
...@@ -2636,6 +2831,8 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename, ...@@ -2636,6 +2831,8 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
nftnl_chain_list_iter_destroy(citer); nftnl_chain_list_iter_destroy(citer);
nftnl_chain_list_free(chain_list); nftnl_chain_list_free(chain_list);
h->config_done = 1;
return 0; return 0;
err: err:
...@@ -2647,9 +2844,20 @@ err: ...@@ -2647,9 +2844,20 @@ err:
if (citer != NULL) if (citer != NULL)
nftnl_chain_list_iter_destroy(citer); nftnl_chain_list_iter_destroy(citer);
h->config_done = -1;
return -1; return -1;
} }
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);
return h->config_done;
}
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
const char *table) const char *table)
{ {
...@@ -2684,18 +2892,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, ...@@ -2684,18 +2892,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
if (h->batch_support) { ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
} else {
struct nlmsghdr *nlh;
char buf[MNL_SOCKET_BUFFER_SIZE];
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
h->family, NLM_F_ACK,
h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
ret = mnl_talk(h, nlh, NULL, NULL);
}
if (chain != NULL) if (chain != NULL)
break; break;
...@@ -2703,9 +2900,6 @@ next: ...@@ -2703,9 +2900,6 @@ next:
c = nftnl_chain_list_iter_next(iter); c = nftnl_chain_list_iter_next(iter);
} }
if (!h->batch_support)
nftnl_chain_list_free(list);
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
err: err:
...@@ -2747,15 +2941,15 @@ static int nft_is_expr_compatible(const char *name) ...@@ -2747,15 +2941,15 @@ static int nft_is_expr_compatible(const char *name)
return 1; return 1;
} }
static int nft_is_rule_compatible(struct nftnl_rule *rule) static bool nft_is_rule_compatible(struct nftnl_rule *rule)
{ {
struct nftnl_expr_iter *iter; struct nftnl_expr_iter *iter;
struct nftnl_expr *expr; struct nftnl_expr *expr;
int ret = 0; bool compatible = false;
iter = nftnl_expr_iter_create(rule); iter = nftnl_expr_iter_create(rule);
if (iter == NULL) if (iter == NULL)
return -1; return false;
expr = nftnl_expr_iter_next(iter); expr = nftnl_expr_iter_next(iter);
while (expr != NULL) { while (expr != NULL) {
...@@ -2766,37 +2960,51 @@ static int nft_is_rule_compatible(struct nftnl_rule *rule) ...@@ -2766,37 +2960,51 @@ static int nft_is_rule_compatible(struct nftnl_rule *rule)
continue; continue;
} }
ret = 1; compatible = true;
break; break;
} }
nftnl_expr_iter_destroy(iter); nftnl_expr_iter_destroy(iter);
return ret; return compatible;
} }
static int nft_is_chain_compatible(const char *table, const char *chain) static int nft_is_chain_compatible(const struct nft_handle *h,
const struct nftnl_chain *chain)
{ {
const char *cur_table; const char *table, *name, *type, *cur_table;
struct builtin_chain *chains; struct builtin_chain *chains;
int i, j; int i, j, prio;
enum nf_inet_hooks hook;
table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE);
prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
for (i = 0; i < TABLES_MAX; i++) { for (i = 0; i < TABLES_MAX; i++) {
cur_table = xtables_ipv4[i].name; cur_table = h->tables[i].name;
chains = xtables_ipv4[i].chains; chains = h->tables[i].chains;
if (strcmp(table, cur_table) != 0) if (!cur_table || strcmp(table, cur_table) != 0)
continue; continue;
for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) { for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
if (strcmp(chain, chains[j].name) == 0) if (strcmp(name, chains[j].name) != 0)
continue;
if (strcmp(type, chains[j].type) == 0 &&
prio == chains[j].prio &&
hook == chains[j].hook)
return 0; return 0;
break;
} }
} }
return 1; return 1;
} }
static int nft_are_chains_compatible(struct nft_handle *h) static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename)
{ {
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter; struct nftnl_chain_list_iter *iter;
...@@ -2816,101 +3024,55 @@ static int nft_are_chains_compatible(struct nft_handle *h) ...@@ -2816,101 +3024,55 @@ static int nft_are_chains_compatible(struct nft_handle *h)
if (!nft_chain_builtin(chain)) if (!nft_chain_builtin(chain))
goto next; goto next;
const char *table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE); ret = nft_is_chain_compatible(h, chain);
const char *name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME); if (ret != 0)
if (nft_is_chain_compatible(table, name) == 1) {
ret = 1;
break; break;
}
next: next:
chain = nftnl_chain_list_iter_next(iter); chain = nftnl_chain_list_iter_next(iter);
} }
nftnl_chain_list_iter_destroy(iter); nftnl_chain_list_iter_destroy(iter);
nftnl_chain_list_free(list);
return ret;
}
static int nft_is_table_compatible(const char *name)
{
int i;
for (i = 0; i < TABLES_MAX; i++) {
if (strcmp(xtables_ipv4[i].name, name) == 0)
return 0;
}
return 1;
}
static int nft_are_tables_compatible(struct nft_handle *h)
{
struct nftnl_table_list *list;
struct nftnl_table_list_iter *iter;
struct nftnl_table *table;
int ret = 0;
list = nftnl_table_list_get(h);
if (list == NULL)
return -1;
iter = nftnl_table_list_iter_create(list);
if (iter == NULL)
return -1;
table = nftnl_table_list_iter_next(iter);
while (table != NULL) {
const char *name = nftnl_table_get(table, NFTNL_TABLE_NAME);
if (nft_is_table_compatible(name) == 0) {
table = nftnl_table_list_iter_next(iter);
continue;
}
ret = 1;
break;
}
nftnl_table_list_iter_destroy(iter);
nftnl_table_list_free(list);
return ret; return ret;
} }
int nft_is_ruleset_compatible(struct nft_handle *h) bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
{ {
struct nftnl_rule_list *list; struct nftnl_rule_list *list;
struct nftnl_rule_list_iter *iter; struct nftnl_rule_list_iter *iter;
struct nftnl_rule *rule; struct nftnl_rule *rule;
int ret = 0; int ret = 0, i;
ret = nft_are_tables_compatible(h); for (i = 0; i < TABLES_MAX; i++) {
if (ret != 0) if (!h->tables[i].name)
return ret; continue;
if (strcmp(h->tables[i].name, tablename) == 0)
break;
}
if (i == TABLES_MAX)
return false;
ret = nft_are_chains_compatible(h); ret = nft_are_chains_compatible(h, tablename);
if (ret != 0) if (ret != 0)
return ret; return false;
list = nft_rule_list_get(h); list = nft_rule_list_get(h);
if (list == NULL) if (list == NULL)
return -1; return true;
iter = nftnl_rule_list_iter_create(list); iter = nftnl_rule_list_iter_create(list);
if (iter == NULL) if (iter == NULL)
return -1; return true;
rule = nftnl_rule_list_iter_next(iter); rule = nftnl_rule_list_iter_next(iter);
while (rule != NULL) { while (rule != NULL) {
ret = nft_is_rule_compatible(rule); ret = nft_is_rule_compatible(rule);
if (ret != 0) if (ret != 0)
break; break;
rule = nftnl_rule_list_iter_next(iter); rule = nftnl_rule_list_iter_next(iter);
} }
nftnl_rule_list_iter_destroy(iter); nftnl_rule_list_iter_destroy(iter);
return ret; return ret == 0;
} }
...@@ -32,12 +32,19 @@ struct nft_handle { ...@@ -32,12 +32,19 @@ struct nft_handle {
uint32_t seq; uint32_t seq;
struct list_head obj_list; struct list_head obj_list;
int obj_list_num; int obj_list_num;
struct mnl_nlmsg_batch *batch; struct nftnl_batch *batch;
struct list_head err_list;
struct nft_family_ops *ops; struct nft_family_ops *ops;
struct builtin_table *tables; struct builtin_table *tables;
struct nftnl_chain_list *chain_cache;
struct nftnl_rule_list *rule_cache; struct nftnl_rule_list *rule_cache;
bool restore; bool restore;
bool batch_support; int8_t config_done;
/* meta data, for error reporting */
struct {
unsigned int lineno;
} error;
}; };
extern struct builtin_table xtables_ipv4[TABLES_MAX]; extern struct builtin_table xtables_ipv4[TABLES_MAX];
...@@ -56,23 +63,25 @@ void nft_fini(struct nft_handle *h); ...@@ -56,23 +63,25 @@ void nft_fini(struct nft_handle *h);
struct nftnl_table; struct nftnl_table;
struct nftnl_chain_list; struct nftnl_chain_list;
int nft_table_add(struct nft_handle *h, struct nftnl_table *t, uint16_t flags);
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, bool counters), bool counters);
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);
void nft_table_new(struct nft_handle *h, const char *table);
/* /*
* Operations with chains. * Operations with chains.
*/ */
struct nftnl_chain; struct nftnl_chain;
int nft_chain_add(struct nft_handle *h, struct nftnl_chain *c, uint16_t flags);
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_dump(struct nft_handle *h); struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h);
struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain); struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table); int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table);
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); int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
const char *chain, const char *table);
int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname); int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname);
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table); int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table);
...@@ -182,6 +191,6 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain, ...@@ -182,6 +191,6 @@ 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);
int nft_is_ruleset_compatible(struct nft_handle *h); bool nft_is_table_compatible(struct nft_handle *h, const char *name);
#endif #endif
#!/bin/bash
#configuration
TESTDIR="./$(dirname $0)/"
RETURNCODE_SEPARATOR="_"
XTABLES_NFT_MULTI="$(dirname $0)/../../xtables-nft-multi"
XTABLES_LEGACY_MULTI="$(dirname $0)/../../xtables-legacy-multi"
export XTABLES_LIBDIR=${TESTDIR}/../../../extensions
msg_error() {
echo "E: $1 ..." >&2
exit 1
}
msg_warn() {
echo "W: $1" >&2
}
msg_info() {
echo "I: $1"
}
if [ "$(id -u)" != "0" ] ; then
msg_error "this requires root!"
fi
if [ ! -d "$TESTDIR" ] ; then
msg_error "missing testdir $TESTDIR"
fi
if [ "$1" == "-v" ] ; then
VERBOSE=y
shift
fi
for arg in "$@"; do
if grep ^.*${RETURNCODE_SEPARATOR}[0-9]\\+$ <<< $arg >/dev/null ; then
SINGLE+=" $arg"
VERBOSE=y
else
msg_error "unknown parameter '$arg'"
fi
done
find_tests() {
if [ ! -z "$SINGLE" ] ; then
echo $SINGLE
return
fi
find ${TESTDIR} -executable -regex \
.*${RETURNCODE_SEPARATOR}[0-9]+ | sort
}
ok=0
failed=0
do_test() {
testfile="$1"
xtables_multi="$2"
rc_spec=`echo $(basename ${testfile}) | cut -d _ -f2-`
msg_info "[EXECUTING] $testfile"
if [ "$VERBOSE" = "y" ]; then
XT_MULTI=$xtables_multi unshare -n ${testfile}
else
XT_MULTI=$xtables_multi unshare -n ${testfile} > /dev/null 2>&1
fi
rc_got=$?
echo -en "\033[1A\033[K" # clean the [EXECUTING] foobar line
if [ "$rc_got" == "$rc_spec" ] ; then
msg_info "[OK] $testfile"
((ok++))
else
((failed++))
msg_warn "[FAILED] $testfile: expected $rc_spec but got $rc_got"
fi
}
echo ""
for testfile in $(find_tests);do
do_test "$testfile" "$XTABLES_LEGACY_MULTI"
done
msg_info "legacy results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
legacy_ok=$ok
legacy_fail=$failed
ok=0
failed=0
for testfile in $(find_tests);do
do_test "$testfile" "$XTABLES_NFT_MULTI"
done
msg_info "nft results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
ok=$((legacy_ok+ok))
failed=$((legacy_fail+failed))
msg_info "combined results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
exit 0
#!/bin/bash
set -x
$XT_MULTI iptables -t filter -N c1 || exit 0
$XT_MULTI iptables -t filter -N c1 || exit 1
$XT_MULTI ip6tables -t filter -N c1 || exit 0
$XT_MULTI ip6tables -t filter -N c1 || exit 1
echo "E: Duplicate chains" >&2
exit 0
#!/bin/bash
set -e
$XT_MULTI iptables -N c1
$XT_MULTI ip6tables -N c1
$XT_MULTI iptables -N c2
$XT_MULTI ip6tables -N c2
#!/bin/bash
$XT_MULTI iptables -N c1 || exit 0
$XT_MULTI iptables -N c2 || exit 0
$XT_MULTI iptables -E c1 c2 || exit 1
$XT_MULTI ip6tables -N c1 || exit 0
$XT_MULTI ip6tables -N c2 || exit 0
$XT_MULTI ip6tables -E c1 c2 || exit 1
echo "E: Renamed with existing chain" >&2
exit 0
#!/bin/sh
set -x
case "$XT_MULTI" in
*/xtables-nft-multi)
for t in filter nat;do
$XT_MULTI ebtables -t $t -L || exit 1
$XT_MULTI ebtables -t $t -X || exit 1
$XT_MULTI ebtables -t $t -F || exit 1
done
for t in broute foobar ;do
$XT_MULTI ebtables -t $t -L &&
$XT_MULTI ebtables -t $t -X &&
$XT_MULTI ebtables -t $t -F
if [ $? -eq 0 ]; then
echo "Expect nonzero return for unsupported table"
exit 1
fi
done
$XT_MULTI ebtables -t filter -N FOO || exit 1
$XT_MULTI ebtables -t filter -N FOO
if [ $? -eq 0 ]; then
echo "Duplicate chain FOO"
$XT_MULTI ebtables -t filter -L
exit 1
fi
$XT_MULTI ebtables -t filter -N BAR || exit 1
$XT_MULTI ebtables -t filter -N BAZ || exit 1
$XT_MULTI ebtables -t filter -L | grep -q FOO || exit 1
$XT_MULTI ebtables -t filter -L | grep -q BAR || exit 1
$XT_MULTI ebtables -t filter -L | grep -q BAZ || exit 1
$XT_MULTI ebtables -t filter -L BAZ || exit 1
$XT_MULTI ebtables -t filter -X BAZ || exit 1
$XT_MULTI ebtables -t filter -L BAZ | grep -q BAZ
if [ $? -eq 0 ]; then
echo "Deleted chain -L BAZ ok, expected failure"
$XT_MULTI ebtables -t filter -L
exit 1
fi
$XT_MULTI ebtables -t $t -F || exit 0
;;
*)
echo "skip $XT_MULTI"
;;
esac
#!/bin/sh
$XT_MULTI iptables -w -L -n > /dev/null || exit 1
$XT_MULTI iptables -w2 -L -n > /dev/null || exit 1
echo -n '#foo' | $XT_MULTI iptables-restore -w || exit 1
# table probing
for table in security raw mangle nat filter;do
$XT_MULTI iptables -w2 -t $table -L -n > /dev/null
done
$XT_MULTI iptables -w2 -p icmp --help | grep -q 'Valid ICMP Types' || exit 1
cat <<EOF | $XT_MULTI iptables-restore -w -n
*nat
-F
-X
-Z
-N PREROUTING_direct
-I PREROUTING 1 -j PREROUTING_direct
-N PREROUTING_ZONES_SOURCE
-N PREROUTING_ZONES
-I PREROUTING 2 -j PREROUTING_ZONES_SOURCE
-I PREROUTING 3 -j PREROUTING_ZONES
-N POSTROUTING_direct
-I POSTROUTING 1 -j POSTROUTING_direct
-N POSTROUTING_ZONES_SOURCE
-N POSTROUTING_ZONES
-I POSTROUTING 2 -j POSTROUTING_ZONES_SOURCE
-I POSTROUTING 3 -j POSTROUTING_ZONES
-N OUTPUT_direct
-I OUTPUT 1 -j OUTPUT_direct
COMMIT
*mangle
-F
-X
-Z
-N PREROUTING_direct
-I PREROUTING 1 -j PREROUTING_direct
-N PREROUTING_ZONES_SOURCE
-N PREROUTING_ZONES
-I PREROUTING 2 -j PREROUTING_ZONES_SOURCE
-I PREROUTING 3 -j PREROUTING_ZONES
-N POSTROUTING_direct
-I POSTROUTING 1 -j POSTROUTING_direct
-N INPUT_direct
-I INPUT 1 -j INPUT_direct
-N OUTPUT_direct
-I OUTPUT 1 -j OUTPUT_direct
-N FORWARD_direct
-I FORWARD 1 -j FORWARD_direct
COMMIT
*raw
-F
-X
-Z
-N PREROUTING_direct
-I PREROUTING 1 -j PREROUTING_direct
-N PREROUTING_ZONES_SOURCE
-N PREROUTING_ZONES
-I PREROUTING 2 -j PREROUTING_ZONES_SOURCE
-I PREROUTING 3 -j PREROUTING_ZONES
-N OUTPUT_direct
-I OUTPUT 1 -j OUTPUT_direct
COMMIT
*filter
-F
-X
-Z
-N INPUT_direct
-N INPUT_ZONES_SOURCE
-N INPUT_ZONES
-I INPUT 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-I INPUT 2 -i lo -j ACCEPT
-I INPUT 3 -j INPUT_direct
-I INPUT 4 -j INPUT_ZONES_SOURCE
-I INPUT 5 -j INPUT_ZONES
-I INPUT 6 -m conntrack --ctstate INVALID -j DROP
-I INPUT 7 -j REJECT --reject-with icmp-host-prohibited
-N FORWARD_direct
-N FORWARD_IN_ZONES_SOURCE
-N FORWARD_IN_ZONES
-N FORWARD_OUT_ZONES_SOURCE
-N FORWARD_OUT_ZONES
-I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-I FORWARD 2 -i lo -j ACCEPT
-I FORWARD 3 -j FORWARD_direct
-I FORWARD 4 -j FORWARD_IN_ZONES_SOURCE
-I FORWARD 5 -j FORWARD_IN_ZONES
-I FORWARD 6 -j FORWARD_OUT_ZONES_SOURCE
-I FORWARD 7 -j FORWARD_OUT_ZONES
-I FORWARD 8 -m conntrack --ctstate INVALID -j DROP
-I FORWARD 9 -j REJECT --reject-with icmp-host-prohibited
-N OUTPUT_direct
-I OUTPUT 1 -j OUTPUT_direct
COMMIT
EOF
if [ $? -ne 0 ]; then
echo "Error during first iptables-restore"
exit 1
fi
cat <<EOF | $XT_MULTI iptables-restore -w -n
*raw
-N PRE_public
-N PRE_public_log
-N PRE_public_deny
-N PRE_public_allow
-I PRE_public 1 -j PRE_public_log
-I PRE_public 2 -j PRE_public_deny
-I PRE_public 3 -j PRE_public_allow
-A PREROUTING_ZONES -i + -g PRE_public
COMMIT
*filter
-N IN_public
-N IN_public_log
-N IN_public_deny
-N IN_public_allow
-I IN_public 1 -j IN_public_log
-I IN_public 2 -j IN_public_deny
-I IN_public 3 -j IN_public_allow
-A IN_public_allow -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -p udp --dport 5353 -d 224.0.0.251 -m conntrack --ctstate NEW -j ACCEPT
-N FWDI_public
-N FWDI_public_log
-N FWDI_public_deny
-N FWDI_public_allow
-I FWDI_public 1 -j FWDI_public_log
-I FWDI_public 2 -j FWDI_public_deny
-I FWDI_public 3 -j FWDI_public_allow
-I IN_public 4 -p icmp -j ACCEPT
-I FWDI_public 4 -p icmp -j ACCEPT
-A INPUT_ZONES -i + -g IN_public
-A FORWARD_IN_ZONES -i + -g FWDI_public
-N FWDO_public
-N FWDO_public_log
-N FWDO_public_deny
-N FWDO_public_allow
-I FWDO_public 1 -j FWDO_public_log
-I FWDO_public 2 -j FWDO_public_deny
-I FWDO_public 3 -j FWDO_public_allow
-A FORWARD_OUT_ZONES -o + -g FWDO_public
COMMIT
*nat
-N PRE_public
-N PRE_public_log
-N PRE_public_deny
-N PRE_public_allow
-I PRE_public 1 -j PRE_public_log
-I PRE_public 2 -j PRE_public_deny
-I PRE_public 3 -j PRE_public_allow
-A PREROUTING_ZONES -i + -g PRE_public
-N POST_public
-N POST_public_log
-N POST_public_deny
-N POST_public_allow
-I POST_public 1 -j POST_public_log
-I POST_public 2 -j POST_public_deny
-I POST_public 3 -j POST_public_allow
-A POSTROUTING_ZONES -o + -g POST_public
COMMIT
*mangle
-N PRE_public
-N PRE_public_log
-N PRE_public_deny
-N PRE_public_allow
-I PRE_public 1 -j PRE_public_log
-I PRE_public 2 -j PRE_public_deny
-I PRE_public 3 -j PRE_public_allow
-A PREROUTING_ZONES -i + -g PRE_public
COMMIT
EOF
if [ $? -ne 0 ]; then
echo "Error during 2nd iptables-restore"
exit 1
fi
cat <<EOF | $XT_MULTI iptables-restore -w -n
*mangle
-P PREROUTING ACCEPT
-P POSTROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P FORWARD ACCEPT
COMMIT
*raw
-P PREROUTING ACCEPT
-P OUTPUT ACCEPT
COMMIT
*filter
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P FORWARD ACCEPT
COMMIT
EOF
if [ $? -ne 0 ]; then
echo "Error during 3rd iptables-restore"
exit 1
fi
cat <<EOF | $XT_MULTI iptables-restore -w -n
*filter
-I INPUT_ZONES 1 -i enp3s0 -g IN_public
-I FORWARD_IN_ZONES 1 -i enp3s0 -g FWDI_public
-I FORWARD_OUT_ZONES 1 -o enp3s0 -g FWDO_public
COMMIT
*nat
-I PREROUTING_ZONES 1 -i enp3s0 -g PRE_public
-I POSTROUTING_ZONES 1 -o enp3s0 -g POST_public
COMMIT
*mangle
-I PREROUTING_ZONES 1 -i enp3s0 -g PRE_public
COMMIT
*raw
-I PREROUTING_ZONES 1 -i enp3s0 -g PRE_public
COMMIT
EOF
if [ $? -ne 0 ]; then
echo "Error during 4th iptables-restore"
exit 1
fi
tmpfile=$(mktemp) || exit 1
for table in nat mangle raw filter;do
$XT_MULTI iptables-save -t $table | grep -v '^#' >> "$tmpfile"
done
case "$XT_MULTI" in
*/xtables-nft-multi)
# nft-multi displays chain names in different order, work around this for now
tmpfile2=$(mktemp)
sort "$tmpfile" > "$tmpfile2"
sort $(dirname "$0")/dumps/ipt-save-completed.txt > "$tmpfile"
diff -u $tmpfile $tmpfile2
RET=$?
rm -f "$tmpfile2"
;;
*)
diff -u $tmpfile $(dirname "$0")/dumps/ipt-save-completed.txt
RET=$?
;;
esac
rm -f "$tmpfile"
exit $RET
#!/bin/sh
# simulate restart after it went down, so first restore
# the complete ruleset
$XT_MULTI iptables-restore < $(dirname "$0")/dumps/ipt-save-completed.txt
# add dummy rules to see if they get cleared or not.
for table in raw mangle nat filter;do
$XT_MULTI iptables -t $table -N FOO$table || exit 1
$XT_MULTI iptables -t $table -A OUTPUT -m comment --comment '"dummy rule in table $table OUTPUT"' || exit 1
$XT_MULTI iptables -t $table -A FOO$table -m comment --comment '"dummy rule in table $table FOO$table"' || exit 1
done
# then run the other test script so it finds already-existing ruleset.
exec $(dirname "$0")/0001-firewalld_0
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_ZONES - [0:0]
:POSTROUTING_ZONES_SOURCE - [0:0]
:POSTROUTING_direct - [0:0]
:POST_public - [0:0]
:POST_public_allow - [0:0]
:POST_public_deny - [0:0]
:POST_public_log - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A POSTROUTING -j POSTROUTING_ZONES_SOURCE
-A POSTROUTING -j POSTROUTING_ZONES
-A POSTROUTING_ZONES -o enp3s0 -g POST_public
-A POSTROUTING_ZONES -g POST_public
-A POST_public -j POST_public_log
-A POST_public -j POST_public_deny
-A POST_public -j POST_public_allow
-A PREROUTING_ZONES -i enp3s0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A PREROUTING_ZONES -i enp3s0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A PREROUTING_ZONES -i enp3s0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_public - [0:0]
:FWDI_public_allow - [0:0]
:FWDI_public_deny - [0:0]
:FWDI_public_log - [0:0]
:FWDO_public - [0:0]
:FWDO_public_allow - [0:0]
:FWDO_public_deny - [0:0]
:FWDO_public_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_public - [0:0]
:IN_public_allow - [0:0]
:IN_public_deny - [0:0]
:IN_public_log - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -j OUTPUT_direct
-A FORWARD_IN_ZONES -i enp3s0 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
-A FORWARD_OUT_ZONES -o enp3s0 -g FWDO_public
-A FORWARD_OUT_ZONES -g FWDO_public
-A FWDI_public -j FWDI_public_log
-A FWDI_public -j FWDI_public_deny
-A FWDI_public -j FWDI_public_allow
-A FWDI_public -p icmp -j ACCEPT
-A FWDO_public -j FWDO_public_log
-A FWDO_public -j FWDO_public_deny
-A FWDO_public -j FWDO_public_allow
-A INPUT_ZONES -i enp3s0 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -p icmp -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -d 224.0.0.251/32 -p udp -m udp --dport 5353 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
#!/bin/bash
RET=0
tmpfile=""
set -x
clean_tmpfile()
{
if [ ! -z "$tmpfile" ];then
rm -f "$tmpfile"
fi
}
trap clean_tmpfile EXIT
do_diff()
{
A="$1"
B="$2"
AT=$(mktemp)
grep -v "^#" "$A" > "$AT"
diff -u "$AT" "$B"
x=$?
rm -f "$AT"
echo "Return $x for $XT_MULTI $A"
return $x
}
tmpfile=$(mktemp) || exit 1
do_simple()
{
iptables="$1"
dumpfile="$2"
$XT_MULTI ${iptables}-restore < "$dumpfile"
$XT_MULTI ${iptables}-save | grep -v "^#" > "$tmpfile"
do_diff $dumpfile "$tmpfile"
if [ $? -ne 0 ]; then
# cp "$tmpfile" "$dumpfile.got"
RET=1
fi
}
do_simple "iptables" $(dirname "$0")/dumps/ipt-save-filter.txt
do_simple "iptables" $(dirname "$0")/dumps/policy-drop.txt
do_simple "iptables" $(dirname "$0")/dumps/wireless.txt
exit $RET
#!/bin/bash
RET=0
tmpfile=""
clean_tmpfile()
{
if [ ! -z "$tmpfile" ];then
rm -f "$tmpfile"
fi
}
trap clean_tmpfile EXIT
do_diff()
{
A="$1"
B="$2"
AT=$(mktemp)
grep -v "^#" "$A" > "$AT"
diff -u "$AT" "$B"
x=$?
rm -f "$AT"
return $x
}
tmpfile=$(mktemp) || exit 1
do_simple()
{
iptables="$1"
dumpfile="$2"
opt="$3"
$XT_MULTI ${iptables}-restore $opt < "$dumpfile"
if [ $? -ne 0 ]; then
echo "$XT_MULTI ${iptables}-restore $opt $dumpfile failed" 1>&2
exit 1
fi
:> "$tmpfile"
for table in mangle raw filter; do
$XT_MULTI ${iptables}-save -t $table $opt | grep -v "^#" >> "$tmpfile"
done
do_diff $dumpfile "$tmpfile"
if [ $? -ne 0 ]; then
RET=1
fi
}
# fedora27-iptables dump contains chain counters to test counter restore/save
do_simple "iptables" $(dirname "$0")/dumps/fedora27-iptables "-c"
do_simple "ip6tables" $(dirname "$0")/dumps/fedora27-ip6tables
exit $RET
# Generated by ip6tables-save v1.6.1 on Sat Feb 17 10:51:39 2018
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_FedoraWorkstation - [0:0]
:PRE_FedoraWorkstation_allow - [0:0]
:PRE_FedoraWorkstation_deny - [0:0]
:PRE_FedoraWorkstation_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A PREROUTING_ZONES -i wlp58s0 -g PRE_FedoraWorkstation
-A PREROUTING_ZONES -g PRE_FedoraWorkstation
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_log
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_deny
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_allow
COMMIT
# Completed on Sat Feb 17 10:51:39 2018
# Generated by ip6tables-save v1.6.1 on Sat Feb 17 10:51:39 2018
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_FedoraWorkstation - [0:0]
:PRE_FedoraWorkstation_allow - [0:0]
:PRE_FedoraWorkstation_deny - [0:0]
:PRE_FedoraWorkstation_log - [0:0]
-A PREROUTING -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j ACCEPT
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A PREROUTING_ZONES -i wlp58s0 -g PRE_FedoraWorkstation
-A PREROUTING_ZONES -g PRE_FedoraWorkstation
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_log
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_deny
-A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_allow
COMMIT
# Completed on Sat Feb 17 10:51:39 2018
# Generated by ip6tables-save v1.6.1 on Sat Feb 17 10:51:39 2018
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_FedoraWorkstation - [0:0]
:FWDI_FedoraWorkstation_allow - [0:0]
:FWDI_FedoraWorkstation_deny - [0:0]
:FWDI_FedoraWorkstation_log - [0:0]
:FWDO_FedoraWorkstation - [0:0]
:FWDO_FedoraWorkstation_allow - [0:0]
:FWDO_FedoraWorkstation_deny - [0:0]
:FWDO_FedoraWorkstation_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_FedoraWorkstation - [0:0]
:IN_FedoraWorkstation_allow - [0:0]
:IN_FedoraWorkstation_deny - [0:0]
:IN_FedoraWorkstation_log - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
-A OUTPUT -j OUTPUT_direct
-A FORWARD_IN_ZONES -i wlp58s0 -g FWDI_FedoraWorkstation
-A FORWARD_IN_ZONES -g FWDI_FedoraWorkstation
-A FORWARD_OUT_ZONES -o wlp58s0 -g FWDO_FedoraWorkstation
-A FORWARD_OUT_ZONES -g FWDO_FedoraWorkstation
-A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_log
-A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_deny
-A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_allow
-A FWDI_FedoraWorkstation -p ipv6-icmp -j ACCEPT
-A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_log
-A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_deny
-A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_allow
-A INPUT_ZONES -i wlp58s0 -g IN_FedoraWorkstation
-A INPUT_ZONES -g IN_FedoraWorkstation
-A IN_FedoraWorkstation -j IN_FedoraWorkstation_log
-A IN_FedoraWorkstation -j IN_FedoraWorkstation_deny
-A IN_FedoraWorkstation -j IN_FedoraWorkstation_allow
-A IN_FedoraWorkstation -p ipv6-icmp -j ACCEPT
-A IN_FedoraWorkstation_allow -p udp -m udp --dport 137 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -p udp -m udp --dport 138 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -d ff02::fb/128 -p udp -m udp --dport 5353 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -d fe80::/64 -p udp -m udp --dport 546 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -p udp -m udp --dport 1025:65535 -m conntrack --ctstate NEW -j ACCEPT
-A IN_FedoraWorkstation_allow -p tcp -m tcp --dport 1025:65535 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Feb 17 10:51:39 2018
# Completed on Sat Feb 17 10:50:33 2018
# Generated by iptables-save v1.6.1 on Sat Feb 17 10:50:33 2018
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_FedoraWorkstation - [0:0]
:PRE_FedoraWorkstation_allow - [0:0]
:PRE_FedoraWorkstation_deny - [0:0]
:PRE_FedoraWorkstation_log - [0:0]
[1:2] -A PREROUTING -j PREROUTING_direct
[3:4] -A PREROUTING -j PREROUTING_ZONES_SOURCE
[0:0] -A PREROUTING -j PREROUTING_ZONES
[0:0] -A INPUT -j INPUT_direct
[0:0] -A FORWARD -j FORWARD_direct
[0:0] -A OUTPUT -j OUTPUT_direct
[0:0] -A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
[0:0] -A POSTROUTING -j POSTROUTING_direct
[0:0] -A PREROUTING_ZONES -i wlp58s0 -g PRE_FedoraWorkstation
[0:0] -A PREROUTING_ZONES -g PRE_FedoraWorkstation
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_log
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_deny
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_allow
COMMIT
# Completed on Sat Feb 17 10:50:33 2018
# Generated by iptables-save v1.6.1 on Sat Feb 17 10:50:33 2018
*raw
:PREROUTING ACCEPT [1681:2620433]
:OUTPUT ACCEPT [1619:171281]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_FedoraWorkstation - [0:0]
:PRE_FedoraWorkstation_allow - [0:0]
:PRE_FedoraWorkstation_deny - [0:0]
:PRE_FedoraWorkstation_log - [0:0]
[0:0] -A PREROUTING -j PREROUTING_direct
[0:0] -A PREROUTING -j PREROUTING_ZONES_SOURCE
[0:0] -A PREROUTING -j PREROUTING_ZONES
[0:0] -A OUTPUT -j OUTPUT_direct
[0:0] -A PREROUTING_ZONES -i wlp58s0 -g PRE_FedoraWorkstation
[0:0] -A PREROUTING_ZONES -g PRE_FedoraWorkstation
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_log
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_deny
[0:0] -A PRE_FedoraWorkstation -j PRE_FedoraWorkstation_allow
[0:0] -A PRE_FedoraWorkstation_allow -p udp -m udp --dport 137 -j CT --helper netbios-ns
COMMIT
# Completed on Sat Feb 17 10:50:33 2018
# Generated by iptables-save v1.6.1 on Sat Feb 17 10:50:33 2018
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1619:171281]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_FedoraWorkstation - [0:0]
:FWDI_FedoraWorkstation_allow - [0:0]
:FWDI_FedoraWorkstation_deny - [0:0]
:FWDI_FedoraWorkstation_log - [0:0]
:FWDO_FedoraWorkstation - [0:0]
:FWDO_FedoraWorkstation_allow - [0:0]
:FWDO_FedoraWorkstation_deny - [0:0]
:FWDO_FedoraWorkstation_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_FedoraWorkstation - [0:0]
:IN_FedoraWorkstation_allow - [0:0]
:IN_FedoraWorkstation_deny - [0:0]
:IN_FedoraWorkstation_log - [0:0]
:OUTPUT_direct - [0:0]
[5:6] -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
[0:123456789] -A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
[0:0] -A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
[0:0] -A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
[0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[0:0] -A INPUT -i lo -j ACCEPT
[0:0] -A INPUT -j INPUT_direct
[0:0] -A INPUT -j INPUT_ZONES_SOURCE
[0:0] -A INPUT -j INPUT_ZONES
[0:0] -A INPUT -m conntrack --ctstate INVALID -j DROP
[0:0] -A INPUT -j REJECT --reject-with icmp-host-prohibited
[0:0] -A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
[0:0] -A FORWARD -i virbr0 -o virbr0 -j ACCEPT
[0:0] -A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
[0:0] -A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
[0:0] -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -i lo -j ACCEPT
[0:0] -A FORWARD -j FORWARD_direct
[0:0] -A FORWARD -j FORWARD_IN_ZONES_SOURCE
[0:0] -A FORWARD -j FORWARD_IN_ZONES
[0:0] -A FORWARD -j FORWARD_OUT_ZONES_SOURCE
[0:0] -A FORWARD -j FORWARD_OUT_ZONES
[0:0] -A FORWARD -m conntrack --ctstate INVALID -j DROP
[0:0] -A FORWARD -j REJECT --reject-with icmp-host-prohibited
[0:0] -A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
[0:0] -A OUTPUT -j OUTPUT_direct
[0:0] -A FORWARD_IN_ZONES -i wlp58s0 -g FWDI_FedoraWorkstation
[0:0] -A FORWARD_IN_ZONES -g FWDI_FedoraWorkstation
[0:0] -A FORWARD_OUT_ZONES -o wlp58s0 -g FWDO_FedoraWorkstation
[0:0] -A FORWARD_OUT_ZONES -g FWDO_FedoraWorkstation
[0:0] -A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_log
[0:0] -A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_deny
[0:0] -A FWDI_FedoraWorkstation -j FWDI_FedoraWorkstation_allow
[0:0] -A FWDI_FedoraWorkstation -p icmp -j ACCEPT
[0:0] -A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_log
[0:0] -A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_deny
[0:0] -A FWDO_FedoraWorkstation -j FWDO_FedoraWorkstation_allow
[0:0] -A INPUT_ZONES -i wlp58s0 -g IN_FedoraWorkstation
[0:0] -A INPUT_ZONES -g IN_FedoraWorkstation
[0:0] -A IN_FedoraWorkstation -j IN_FedoraWorkstation_log
[0:0] -A IN_FedoraWorkstation -j IN_FedoraWorkstation_deny
[0:0] -A IN_FedoraWorkstation -j IN_FedoraWorkstation_allow
[0:0] -A IN_FedoraWorkstation -p icmp -j ACCEPT
[0:0] -A IN_FedoraWorkstation_allow -p udp -m udp --dport 137 -m conntrack --ctstate NEW -j ACCEPT
[0:0] -A IN_FedoraWorkstation_allow -p udp -m udp --dport 138 -m conntrack --ctstate NEW -j ACCEPT
[0:0] -A IN_FedoraWorkstation_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
[0:0] -A IN_FedoraWorkstation_allow -d 224.0.0.251/32 -p udp -m udp --dport 5353 -m conntrack --ctstate NEW -j ACCEPT
[0:0] -A IN_FedoraWorkstation_allow -p udp -m udp --dport 1025:65535 -m conntrack --ctstate NEW -j ACCEPT
[7:8] -A IN_FedoraWorkstation_allow -p tcp -m tcp --dport 1025:65535 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Feb 17 10:50:33 2018
# Generated by iptables-save v1.2.4 on Mon Mar 17 19:59:10 2003
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:WLAN - [0:0]
:accept_log - [0:0]
:block - [0:0]
:in_icmp - [0:0]
:in_trusted - [0:0]
:reject_log - [0:0]
:wlanout - [0:0]
-A INPUT -i wlan0 -j WLAN
-A INPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -i lo -j ACCEPT
-A INPUT -i ppp0 -p icmp -m limit --limit 1/sec -j in_icmp
-A INPUT -i ppp0 -p tcp -m tcp --dport 22 -j in_trusted
-A INPUT -j block
-A FORWARD -d 192.168.100.77/32 -i ppp0 -p udp -m udp --dport 4166 -j ACCEPT
-A FORWARD -d 192.168.100.77/32 -i ppp0 -p tcp -m tcp --dport 4180 -j ACCEPT
-A FORWARD -d 192.168.100.77/32 -i ppp0 -p tcp -m tcp --dport 4162 -j ACCEPT
-A FORWARD -d 192.168.100.77/32 -i ppp0 -p tcp -m tcp --dport 20376 -j ACCEPT
-A FORWARD -d 192.168.100.2/32 -i ppp0 -p tcp -m tcp --dport 10209 -j ACCEPT
-A FORWARD -d 192.168.100.2/32 -i ppp0 -p tcp -m tcp --dport 881 -j ACCEPT
-A FORWARD ! -s 192.168.0.0/24 -i eth2 -p icmp -j DROP
-A FORWARD ! -s 192.168.0.0/24 -i eth2 -p udp -j DROP
-A FORWARD ! -s 192.168.0.0/24 -i eth2 -p tcp -j DROP
-A FORWARD ! -s 192.168.100.0/24 -i eth1 -p icmp -j DROP
-A FORWARD ! -s 192.168.100.0/24 -i eth1 -p udp -j DROP
-A FORWARD ! -s 192.168.100.0/24 -i eth1 -p tcp -j DROP
-A FORWARD -o ppp0 -p udp -m udp --sport 137:139 -j DROP
-A FORWARD -o ppp0 -p udp -m udp --sport 445 -j DROP
-A FORWARD -o ppp0 -p tcp -m tcp --sport 137:139 -j DROP
-A FORWARD -o ppp0 -p tcp -m tcp --sport 445 -j DROP
-A FORWARD -i ppp0 -p udp -m udp --dport 137:139 -j DROP
-A FORWARD -i ppp0 -p udp -m udp --dport 445 -j DROP
-A FORWARD -i ppp0 -p tcp -m tcp --dport 137:139 -j DROP
-A FORWARD -i ppp0 -p tcp -m tcp --dport 445 -j DROP
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -j block
-A OUTPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -o lo -j ACCEPT
-A OUTPUT -o wlan0 -j wlanout
-A OUTPUT -j block
-A WLAN -s 192.168.200.4/32 -m mac --mac-source 00:00:F1:05:A0:E0 -j RETURN
-A WLAN -s 192.168.200.9/32 -m mac --mac-source 00:00:F1:05:99:85 -j RETURN
-A WLAN -m limit --limit 12/min -j LOG --log-prefix "UNKNOWN WLAN dropped:"
-A WLAN -j DROP
-A accept_log -i ppp0 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 1/sec -j LOG --log-prefix "TCPConnect on ppp0:"
-A accept_log -i ppp0 ! -p tcp -m limit --limit 1/sec -j LOG --log-prefix "Accepted Datagram on ppp0:"
-A accept_log -j ACCEPT
-A block -m state --state RELATED,ESTABLISHED -j ACCEPT
-A block ! -i ppp0 -m state --state NEW -j ACCEPT
-A block -p tcp -j reject_log
-A block -p udp -j reject_log
-A in_icmp -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A in_icmp -p icmp -m icmp --icmp-type 4 -j ACCEPT
-A in_icmp -p icmp -m icmp --icmp-type 1 -j ACCEPT
-A in_icmp -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A in_icmp -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A in_icmp -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A in_trusted -s 10.230.173.148/32 -j ACCEPT
-A in_trusted -s 10.230.173.151/32 -j ACCEPT
-A reject_log -i ppp0 -p tcp -m tcp --dport 22:80 --tcp-flags SYN,RST,ACK SYN -m limit --limit 1/sec -j LOG --log-prefix "RejectTCPConnectReq on ppp0:"
-A reject_log -p tcp -j REJECT --reject-with tcp-reset
-A reject_log -p udp -j REJECT --reject-with icmp-port-unreachable
-A wlanout -d 192.168.200.4/32 -j RETURN
-A wlanout -d 192.168.200.9/32 -j RETURN
-A wlanout -j DROP
COMMIT
# Completed on Mon Mar 17 19:59:10 2003
# Generated by xtables-save v1.6.2 on Tue Jun 26 22:28:41 2018
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A OUTPUT -j ACCEPT
COMMIT
# Completed on Tue Jun 26 22:28:41 2018
# Generated by iptables-save v1.4.21 on Thu Jun 29 18:03:06 2017
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:port_assignment - [0:0]
-A PREROUTING -j port_assignment
-A OUTPUT -j port_assignment
-A port_assignment -p tcp -m tcp --dport 1723 -j CT --helper pptp
COMMIT
# Completed on Thu Jun 29 18:03:06 2017
# Generated by iptables-save v1.4.21 on Thu Jun 29 18:03:06 2017
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:CUST_I15_IN - [0:0]
:CUST_I15_OUT - [0:0]
:CUST_I16_IN - [0:0]
:CUST_I16_OUT - [0:0]
:L_ACCEPT - [0:0]
:L_DROP - [0:0]
:L_REJECT - [0:0]
:VPN_USERS_IN - [0:0]
:VPN_USERS_OUT - [0:0]
-A INPUT -m conntrack --ctstate INVALID -j L_DROP
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j L_ACCEPT
-A INPUT -i lo -j L_ACCEPT
-A INPUT -s 10.78.129.130/32 -p tcp -m tcp --dport 5666 -j L_ACCEPT
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 22,80,443,873,1723 -j L_ACCEPT
-A INPUT -p udp -m udp -m multiport --dports 500,1701,4500 -j L_ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j L_ACCEPT
-A INPUT -s 10.31.70.8/29 -i bond0.208 -p tcp -m tcp --dport 179 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A INPUT -s 10.44.224.8/29 -i bond0.686 -p tcp -m tcp --dport 179 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A INPUT -p esp -j L_ACCEPT
-A INPUT -s 168.209.255.75/32 -p gre -j L_ACCEPT
-A INPUT -s 168.209.255.106/32 -p gre -j L_ACCEPT
-A INPUT -s 10.35.167.46/32 -p gre -j L_ACCEPT
-A INPUT -s 10.35.167.45/32 -p gre -j L_ACCEPT
-A INPUT -i gre-wbcore -j L_ACCEPT
-A INPUT -i gre-davo-+ -j L_ACCEPT
-A INPUT -i bond0.208 -j L_DROP
-A INPUT -i bond0.686 -j L_DROP
-A INPUT -j L_ACCEPT
-A FORWARD -i bond0.10 -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j L_DROP
-A FORWARD -p tcp -m tcp --tcp-flags FIN,SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j L_ACCEPT
-A FORWARD -d 10.31.63.80/30 -o bond0.10 -j L_ACCEPT
-A FORWARD -o bond0.11 -j CUST_I16_IN
-A FORWARD -i bond0.11 -j CUST_I16_OUT
-A FORWARD -o bond0.12 -j CUST_I15_IN
-A FORWARD -i bond0.12 -j CUST_I15_OUT
-A FORWARD -s 192.168.255.0/24 -i ppp+ -o bond0.208 -j L_DROP
-A FORWARD -s 192.168.255.0/24 -i ppp+ -o bond0.686 -j L_DROP
-A FORWARD -j L_ACCEPT
-A CUST_I15_IN -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I15_IN -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I15_IN -p tcp -m tcp --dport 433 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I15_IN -p tcp -m tcp --dport 3306 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I15_IN -p tcp -m tcp --dport 3390 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I15_IN -j L_DROP
-A CUST_I15_OUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 80,443 -j L_ACCEPT
-A CUST_I15_OUT -j L_DROP
-A CUST_I16_IN -p tcp -m tcp --dport 3390 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I16_IN -p tcp -m tcp --dport 21 --tcp-flags FIN,SYN,RST,ACK SYN -j L_ACCEPT
-A CUST_I16_IN -p icmp -m icmp --icmp-type 8 -j L_ACCEPT
-A CUST_I16_IN -j L_DROP
-A CUST_I16_OUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 80,443 -j L_ACCEPT
-A CUST_I16_OUT -d 154.73.34.12/32 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 25 -j L_ACCEPT
-A CUST_I16_OUT -j L_DROP
-A L_ACCEPT -j NFLOG --nflog-group 1 --nflog-threshold 5
-A L_ACCEPT -j ACCEPT
-A L_DROP -j LOG --log-prefix "L_DROP: "
-A L_DROP -j NFLOG --nflog-group 2 --nflog-threshold 5
-A L_DROP -j DROP
-A L_REJECT -j NFLOG --nflog-group 3 --nflog-threshold 5
-A L_REJECT -j REJECT --reject-with icmp-port-unreachable
-A VPN_USERS_IN -i ppp0 -m comment --comment "User: " -j ACCEPT
-A VPN_USERS_OUT -o ppp0 -m comment --comment "User: " -j ACCEPT
COMMIT
# Completed on Thu Jun 29 18:03:06 2017
...@@ -48,8 +48,39 @@ struct xtables_afinfo { ...@@ -48,8 +48,39 @@ struct xtables_afinfo {
int so_rev_target; int so_rev_target;
}; };
/* trick for ebtables-compat, since watchers are targets */
struct ebt_match {
struct ebt_match *next;
union {
struct xtables_match *match;
struct xtables_target *watcher;
} u;
bool ismatch;
};
/* Fake ebt_entry */
struct ebt_entry {
/* this needs to be the first field */
unsigned int bitmask;
unsigned int invflags;
uint16_t ethproto;
/* the physical in-dev */
char in[IFNAMSIZ];
/* the logical in-dev */
char logical_in[IFNAMSIZ];
/* the physical out-dev */
char out[IFNAMSIZ];
/* the logical out-dev */
char logical_out[IFNAMSIZ];
unsigned char sourcemac[6];
unsigned char sourcemsk[6];
unsigned char destmac[6];
unsigned char destmsk[6];
};
struct iptables_command_state { struct iptables_command_state {
union { union {
struct ebt_entry eb;
struct ipt_entry fw; struct ipt_entry fw;
struct ip6t_entry fw6; struct ip6t_entry fw6;
}; };
...@@ -57,6 +88,7 @@ struct iptables_command_state { ...@@ -57,6 +88,7 @@ struct iptables_command_state {
int c; int c;
unsigned int options; unsigned int options;
struct xtables_rule_match *matches; struct xtables_rule_match *matches;
struct ebt_match *match_list;
struct xtables_target *target; struct xtables_target *target;
struct xt_counters counters; struct xt_counters counters;
char *protocol; char *protocol;
......
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