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 @@
#include <xtables.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/xt_comment.h>
#include <libmnl/libmnl.h>
#include <libnftnl/rule.h>
......@@ -83,7 +84,7 @@ void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor)
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;
uint32_t xor[4] = { 0 };
......@@ -138,9 +139,10 @@ void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op)
iface_len = strlen(iface);
add_meta(r, NFT_META_IIFNAME);
if (iface[iface_len - 1] == '+')
add_cmp_ptr(r, op, iface, iface_len - 1);
else
if (iface[iface_len - 1] == '+') {
if (iface_len > 1)
add_cmp_ptr(r, op, iface, iface_len - 1);
} else
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)
iface_len = strlen(iface);
add_meta(r, NFT_META_OIFNAME);
if (iface[iface_len - 1] == '+')
add_cmp_ptr(r, op, iface, iface_len - 1);
else
if (iface[iface_len - 1] == '+') {
if (iface_len > 1)
add_cmp_ptr(r, op, iface, iface_len - 1);
} else
add_cmp_ptr(r, op, iface, iface_len + 1);
}
void add_addr(struct nftnl_rule *r, int offset,
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_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);
}
......@@ -207,6 +220,30 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
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,
unsigned char *iniface_mask, char *outiface,
unsigned char *outiface_mask, uint8_t *invflags)
......@@ -234,35 +271,21 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
memset(outiface_mask, 0xff, strlen(outiface)+1);
break;
case NFT_META_BRI_IIFNAME:
case NFT_META_IIFNAME:
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
*invflags |= IPT_INV_VIA_IN;
memcpy(iniface, ifname, len);
if (iniface[len] == '\0')
memset(iniface_mask, 0xff, len);
else {
iniface[len] = '+';
iniface[len+1] = '\0';
memset(iniface_mask, 0xff, len + 1);
}
parse_ifname(ifname, len, iniface, iniface_mask);
break;
case NFT_META_BRI_OIFNAME:
case NFT_META_OIFNAME:
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
*invflags |= IPT_INV_VIA_OUT;
memcpy(outiface, ifname, len);
if (outiface[len] == '\0')
memset(outiface_mask, 0xff, len);
else {
outiface[len] = '+';
outiface[len+1] = '\0';
memset(outiface_mask, 0xff, len + 1);
}
parse_ifname(ifname, len, outiface, outiface_mask);
break;
default:
return -1;
......@@ -276,11 +299,10 @@ static void *nft_get_data(struct nft_xt_ctx *ctx)
switch(ctx->family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
return ctx->state.cs;
case NFPROTO_ARP:
return ctx->state.cs_arp;
case NFPROTO_BRIDGE:
return ctx->state.cs_eb;
default:
/* Should not happen */
return NULL;
......@@ -333,10 +355,8 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
switch (ctx->family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6:
matches = &ctx->state.cs->matches;
break;
case NFPROTO_BRIDGE:
matches = &ctx->state.cs_eb->matches;
matches = &ctx->state.cs->matches;
break;
default:
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)
*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)
{
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
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;
}
......@@ -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)
{
int verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
struct nft_family_ops *ops;
const char *jumpto = NULL;
bool nft_goto = false;
void *data = 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? */
switch(verdict) {
case NF_ACCEPT:
......@@ -537,7 +618,8 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
if (match == NULL)
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) {
fprintf(stderr, "OOM");
exit(EXIT_FAILURE);
......@@ -838,7 +920,9 @@ bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2)
if (tg1 == NULL && tg2 == NULL)
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;
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,
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 {
NFT_XT_CTX_PAYLOAD = (1 << 0),
NFT_XT_CTX_META = (1 << 1),
NFT_XT_CTX_BITWISE = (1 << 2),
NFT_XT_CTX_IMMEDIATE = (1 << 3),
};
struct nft_xt_ctx {
union {
struct iptables_command_state *cs;
struct arptables_command_state *cs_arp;
struct ebtables_command_state *cs_eb;
} state;
struct nftnl_expr_iter *iter;
int family;
......@@ -63,6 +63,10 @@ struct nft_xt_ctx {
struct {
uint32_t key;
} meta;
struct {
uint32_t data[4];
uint32_t len, reg;
} immediate;
struct {
uint32_t mask[4];
uint32_t xor[4];
......@@ -107,6 +111,7 @@ struct nft_family_ops {
void add_meta(struct nftnl_rule *r, uint32_t key);
void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base);
void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len);
void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor);
void add_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);
......@@ -223,9 +228,9 @@ struct nft_xt_cmd_parse {
unsigned int command;
unsigned int rulenum;
char *table;
char *chain;
char *newname;
char *policy;
const char *chain;
const char *newname;
const char *policy;
bool restore;
int verbose;
};
......@@ -245,17 +250,18 @@ struct nftnl_chain_list;
struct nft_xt_restore_cb {
void (*table_new)(struct nft_handle *h, const char *table);
struct nftnl_chain_list *(*chain_list)(struct nft_handle *h);
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,
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,
const char *chain, const char *policy,
const struct xt_counters *counters);
int (*chain_user_add)(struct nft_handle *h, const char *chain,
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[],
char **table, bool restore);
......@@ -269,4 +275,5 @@ void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_cb *cb,
int argc, char *argv[]);
void nft_check_xt_legacy(int family, bool is_ipt_save);
#endif
......@@ -19,6 +19,7 @@
#include <time.h>
#include <stdarg.h>
#include <inttypes.h>
#include <assert.h>
#include <xtables.h>
#include <libiptc/libxtc.h>
......@@ -44,6 +45,7 @@
#include <libnftnl/expr.h>
#include <libnftnl/set.h>
#include <libnftnl/udata.h>
#include <libnftnl/batch.h>
#include <netinet/in.h> /* inet_ntoa */
#include <arpa/inet.h>
......@@ -60,7 +62,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
void *data)
{
int ret;
char buf[MNL_SOCKET_BUFFER_SIZE];
char buf[16536];
if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
return -1;
......@@ -80,13 +82,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
return 0;
}
static LIST_HEAD(batch_page_list);
static int batch_num_pages;
struct batch_page {
struct list_head head;
struct mnl_nlmsg_batch *batch;
};
#define NFT_NLMSG_MAXSIZE (UINT16_MAX + getpagesize())
/* selected batch page is 256 Kbytes long to load ruleset of
* half a million rules without hitting -EMSGSIZE due to large
......@@ -94,44 +90,74 @@ struct batch_page {
*/
#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 */
buf = malloc(BATCH_PAGE_SIZE + getpagesize());
if (buf == NULL)
batch = nftnl_batch_alloc(BATCH_PAGE_SIZE, NFT_NLMSG_MAXSIZE);
if (batch == NULL)
return NULL;
return mnl_nlmsg_batch_start(buf, BATCH_PAGE_SIZE);
return batch;
}
static struct mnl_nlmsg_batch *
mnl_nftnl_batch_page_add(struct mnl_nlmsg_batch *batch)
static void mnl_nft_batch_continue(struct nftnl_batch *batch)
{
struct batch_page *batch_page;
assert(nftnl_batch_update(batch) >= 0);
}
batch_page = malloc(sizeof(struct batch_page));
if (batch_page == NULL)
return NULL;
static uint32_t mnl_batch_begin(struct nftnl_batch *batch, uint32_t seqnum)
{
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;
list_add_tail(&batch_page->head, &batch_page_list);
batch_num_pages++;
struct mnl_err {
struct list_head head;
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 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;
if (batch_num_pages * BATCH_PAGE_SIZE <= nlbuffsiz)
if (nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz)
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 */
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)
nlbuffsiz = newbuffsiz;
}
static void mnl_nftnl_batch_reset(void)
{
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 ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
struct nftnl_batch *batch)
{
static const struct sockaddr_nl snl = {
.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 = {
.msg_name = (struct sockaddr *) &snl,
.msg_namelen = sizeof(snl),
.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_nftnl_batch_reset();
mnl_set_sndbuffer(nf_sock, batch);
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];
fd_set readfds;
struct timeval tv = {
......@@ -200,7 +201,7 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
};
int err = 0;
ret = mnl_nft_socket_sendmsg(h->nl);
ret = mnl_nft_socket_sendmsg(nf_sock, batch);
if (ret == -1)
return -1;
......@@ -213,16 +214,18 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
return -1;
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)
return -1;
ret = mnl_cb_run(rcv_buf, ret, 0, h->portid, NULL, NULL);
/* Annotate first error and continue, make sure we get all
* acknoledgments.
*/
if (!err && ret == -1)
err = errno;
ret = mnl_cb_run(rcv_buf, ret, 0, portid, NULL, NULL);
/* Continue on error, make sure we get all acknowledgments */
if (ret == -1) {
mnl_err_list_node_add(err_list, errno, nlh->nlmsg_seq);
err = -1;
}
ret = select(fd+1, &readfds, NULL, NULL, &tv);
if (ret == -1)
......@@ -231,29 +234,16 @@ static int mnl_nftnl_batch_talk(struct nft_handle *h)
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
}
errno = 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);
return err;
}
enum obj_update_type {
NFT_COMPAT_TABLE_ADD,
NFT_COMPAT_TABLE_FLUSH,
NFT_COMPAT_CHAIN_ADD,
NFT_COMPAT_CHAIN_USER_ADD,
NFT_COMPAT_CHAIN_USER_DEL,
NFT_COMPAT_CHAIN_USER_FLUSH,
NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_CHAIN_RENAME,
NFT_COMPAT_RULE_APPEND,
......@@ -271,14 +261,83 @@ enum obj_action {
struct obj_update {
struct list_head head;
enum obj_update_type type;
unsigned int seq;
union {
struct nftnl_table *table;
struct nftnl_chain *chain;
struct nftnl_rule *rule;
struct nftnl_rule *rule;
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)
{
struct obj_update *obj;
......@@ -288,6 +347,7 @@ static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
return -1;
obj->ptr = ptr;
obj->error.lineno = h->error.lineno;
obj->type = type;
list_add_tail(&obj->head, &h->obj_list);
h->obj_list_num++;
......@@ -455,12 +515,6 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
.prio = NF_IP_PRI_FILTER,
.hook = NF_ARP_IN,
},
{
.name = "FORWARD",
.type = "filter",
.prio = NF_IP_PRI_FILTER,
.hook = NF_ARP_FORWARD,
},
{
.name = "OUTPUT",
.type = "filter",
......@@ -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,
struct builtin_table *_t)
{
......@@ -561,13 +591,7 @@ static int nft_table_builtin_add(struct nft_handle *h,
nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name);
if (h->batch_support)
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;
ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
return ret;
}
......@@ -592,29 +616,6 @@ nft_chain_builtin_alloc(struct builtin_table *table,
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,
struct builtin_table *table,
struct builtin_chain *chain)
......@@ -625,10 +626,7 @@ static void nft_chain_builtin_add(struct nft_handle *h,
if (c == NULL)
return;
if (h->batch_support)
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
else
nft_chain_add(h, c, NLM_F_EXCL);
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
}
/* find if built-in table already exists */
......@@ -686,28 +684,27 @@ static void nft_chain_builtin_init(struct nft_handle *h,
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)
{
int ret = 0;
struct builtin_table *t;
t = nft_table_builtin_find(h, table);
if (t == NULL) {
ret = -1;
goto out;
}
if (nft_table_builtin_add(h, t) < 0) {
/* Built-in table already initialized, skip. */
if (errno == EEXIST)
goto out;
}
if (t == NULL)
return -1;
if (t->initialized)
return 0;
if (nft_table_builtin_add(h, t) < 0)
return -1;
nft_chain_builtin_init(h, t);
out:
return ret;
t->initialized = true;
return 0;
}
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;
}
static bool mnl_batch_supported(struct nft_handle *h)
static int nft_restart(struct nft_handle *h)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
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_socket_close(h->nl);
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));
while (ret > 0) {
ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
NULL, NULL);
if (ret <= 0)
break;
if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
return -1;
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
* 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;
return 0;
}
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)
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;
}
h->portid = mnl_socket_get_portid(h->nl);
h->tables = t;
INIT_LIST_HEAD(&h->obj_list);
INIT_LIST_HEAD(&h->err_list);
return 0;
}
h->batch = mnl_nftnl_batch_alloc();
h->batch_support = mnl_batch_supported(h);
static int __flush_rule_cache(struct nftnl_rule *r, void *data)
{
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;
}
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)
return;
nftnl_rule_list_free(h->rule_cache);
h->rule_cache = NULL;
if (tablename) {
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)
{
flush_rule_cache(h);
flush_chain_cache(h, NULL);
flush_rule_cache(h, NULL);
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)
......@@ -861,10 +873,7 @@ int nft_chain_set(struct nft_handle *h, const char *table,
if (c == NULL)
return 0;
if (h->batch_support)
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
else
ret = nft_chain_add(h, c, 0);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
......@@ -920,11 +929,36 @@ static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
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)
{
struct nftnl_expr *expr;
int ret;
if (strcmp(t->u.user.name, "TRACE") == 0)
return add_meta_nftrace(r);
expr = nftnl_expr_alloc("target");
if (expr == NULL)
return -ENOMEM;
......@@ -1028,13 +1062,21 @@ enum udata_type {
int add_comment(struct nftnl_rule *r, const char *comment)
{
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);
if (!udata)
return -ENOMEM;
if (strnlen(comment, 255) == 255)
return -ENOSPC;
if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment))
return -ENOMEM;
nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
nftnl_udata_buf_data(udata),
nftnl_udata_buf_len(udata));
......@@ -1106,6 +1148,8 @@ err:
return NULL;
}
static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h);
int
nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
void *data, uint64_t handle, bool verbose)
......@@ -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)
nftnl_rule_free(r);
flush_rule_cache(h);
nft_rule_list_get(h);
nftnl_rule_list_add_tail(r, h->rule_cache);
return 1;
}
......@@ -1188,10 +1235,14 @@ err:
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 nftnl_chain_list *list;
int ret;
if (h->chain_cache)
return h->chain_cache;
retry:
list = nftnl_chain_list_alloc();
if (list == NULL) {
errno = ENOMEM;
......@@ -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,
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;
}
......@@ -1262,7 +1320,6 @@ next:
}
nftnl_chain_list_iter_destroy(iter);
nftnl_chain_list_free(list);
return 1;
}
......@@ -1291,7 +1348,7 @@ err:
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 nftnl_rule_list *list;
int ret;
......@@ -1299,6 +1356,7 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
if (h->rule_cache)
return h->rule_cache;
retry:
list = nftnl_rule_list_alloc();
if (list == NULL)
return 0;
......@@ -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);
if (ret < 0) {
if (errno == EINTR) {
assert(nft_restart(h) >= 0);
nftnl_rule_list_free(list);
goto retry;
}
nftnl_rule_list_free(list);
return NULL;
}
......@@ -1370,6 +1434,55 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
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 ret;
......@@ -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 *c;
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_flush;
list = nftnl_chain_list_get(h);
......@@ -1409,12 +1525,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
next:
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
flush_rule_cache(h);
flush_rule_cache(h, table);
err:
nftnl_chain_list_free(list);
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
......@@ -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_NAME, (char *)chain);
if (h->batch_support) {
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
} else {
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
nftnl_chain_free(c);
ret = mnl_talk(h, nlh, NULL, NULL);
}
nft_chain_dump(h);
nftnl_chain_list_add(c, h->chain_cache);
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
......@@ -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 */
#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)
{
struct nftnl_chain_list *list;
......@@ -1480,6 +1573,8 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
int ret = 0;
int deleted_ctr = 0;
nft_fn = nft_chain_user_del;
list = nftnl_chain_list_get(h);
if (list == NULL)
goto err;
......@@ -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)
goto next;
if (h->batch_support)
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
else
ret = __nft_chain_del(h, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
if (ret < 0)
break;
deleted_ctr++;
nftnl_chain_list_del(c);
if (chain != NULL)
break;
......@@ -1523,11 +1616,9 @@ next:
nftnl_chain_list_iter_destroy(iter);
err:
if (!h->batch_support)
nftnl_chain_list_free(list);
/* chain not found */
if (deleted_ctr == 0) {
if (chain != NULL && deleted_ctr == 0) {
ret = -1;
errno = ENOENT;
}
......@@ -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_u64(c, NFTNL_CHAIN_HANDLE, handle);
if (h->batch_support) {
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);
}
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
......@@ -1655,10 +1734,12 @@ err:
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 nftnl_table_list *list;
int ret;
retry:
list = nftnl_table_list_alloc();
if (list == NULL)
return 0;
......@@ -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,
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;
}
......@@ -1707,20 +1793,17 @@ int nft_for_each_table(struct nft_handle *h,
int (*func)(struct nft_handle *h, const char *tablename, bool counters),
bool counters)
{
int ret = 1;
struct nftnl_table_list *list;
struct nftnl_table_list_iter *iter;
struct nftnl_table *t;
list = nftnl_table_list_get(h);
if (list == NULL) {
ret = 0;
goto err;
}
if (list == NULL)
return -1;
iter = nftnl_table_list_iter_create(list);
if (iter == NULL)
return 0;
return -1;
t = nftnl_table_list_iter_next(iter);
while (t != NULL) {
......@@ -1733,43 +1816,85 @@ int nft_for_each_table(struct nft_handle *h,
}
nftnl_table_list_free(list);
return 0;
}
err:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
static int __nft_table_flush(struct nft_handle *h, const char *table)
{
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,
struct nftnl_chain_list *chain_list)
int nft_table_flush(struct nft_handle *h, const char *table)
{
struct nftnl_chain_list_iter *iter;
struct nftnl_chain *chain_obj;
struct nftnl_table_list_iter *iter;
struct nftnl_table_list *list;
struct nftnl_table *t;
int ret = 0;
iter = nftnl_chain_list_iter_create(chain_list);
if (iter == NULL)
return 0;
nft_fn = nft_table_flush;
chain_obj = nftnl_chain_list_iter_next(iter);
while (chain_obj != NULL) {
const char *table =
nftnl_chain_get_str(chain_obj, NFTNL_CHAIN_TABLE);
list = nftnl_table_list_get(h);
if (list == NULL) {
ret = -1;
goto err_out;
}
if (strcmp(this_table, table) != 0)
goto next;
iter = nftnl_table_list_iter_create(list);
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;
if ( __nft_chain_del(h, chain_obj) < 0) {
if (errno != EBUSY)
return -1;
}
ret = __nft_table_flush(h, table);
if (ret < 0)
goto err_table_iter;
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,
......@@ -1874,12 +1999,10 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
} else
errno = ENOENT;
flush_rule_cache(h);
return ret;
}
static int
static struct nftnl_rule *
nft_rule_add(struct nft_handle *h, const char *chain,
const char *table, struct iptables_command_state *cs,
uint64_t handle, bool verbose)
......@@ -1888,25 +2011,24 @@ nft_rule_add(struct nft_handle *h, const char *chain,
r = nft_rule_new(h, chain, table, cs);
if (r == NULL)
return 0;
return NULL;
if (handle > 0)
nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
nftnl_rule_free(r);
return 0;
return NULL;
}
flush_rule_cache(h);
return 1;
return r;
}
int nft_rule_insert(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose)
{
struct nftnl_rule *r, *new_rule;
struct nftnl_rule_list *list;
struct nftnl_rule *r;
uint64_t handle = 0;
/* 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,
*/
r = nft_rule_find(h, list, chain, table, data,
rulenum - 1);
if (r != NULL) {
flush_rule_cache(h);
if (r != NULL)
return nft_rule_append(h, chain, table, data,
0, verbose);
}
errno = ENOENT;
goto err;
......@@ -1939,13 +2059,21 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
DEBUGP("adding after rule handle %"PRIu64"\n", handle);
flush_rule_cache(h);
} else {
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:
flush_rule_cache(h);
return 0;
}
......@@ -1973,8 +2101,6 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
} else
errno = ENOENT;
flush_rule_cache(h);
return ret;
}
......@@ -1997,14 +2123,14 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
(unsigned long long)
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
nftnl_rule_list_del(r);
ret = nft_rule_append(h, chain, table, data,
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
verbose);
} else
errno = ENOENT;
flush_rule_cache(h);
return ret;
}
......@@ -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);
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) {
__nft_rule_list(h, chain, table,
rulenum, format, ops->print_firewall);
......@@ -2144,8 +2275,6 @@ next:
nftnl_chain_list_iter_destroy(iter);
err:
nftnl_chain_list_free(list);
return 1;
}
......@@ -2249,8 +2378,6 @@ next:
nftnl_chain_list_iter_destroy(iter);
err:
nftnl_chain_list_free(list);
return ret;
}
......@@ -2284,8 +2411,6 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
false);
error:
flush_rule_cache(h);
return ret;
}
......@@ -2295,10 +2420,9 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
{
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);
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,
......@@ -2307,11 +2431,10 @@ static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
{
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);
nftnl_chain_nlmsg_build_payload(nlh, chain);
nft_chain_print_debug(chain, nlh);
nftnl_chain_free(chain);
}
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;
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);
nftnl_rule_nlmsg_build_payload(nlh, rule);
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)
{
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;
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) {
case NFT_COMPAT_TABLE_ADD:
nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE,
NLM_F_CREATE, seq++,
NLM_F_CREATE, n->seq,
n->table);
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:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
NLM_F_CREATE, seq++,
NLM_F_CREATE, n->seq,
n->chain);
break;
case NFT_COMPAT_CHAIN_USER_ADD:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
NLM_F_EXCL, seq++,
NLM_F_EXCL, n->seq,
n->chain);
break;
case NFT_COMPAT_CHAIN_USER_DEL:
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);
break;
case NFT_COMPAT_CHAIN_UPDATE:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
h->restore ?
NLM_F_CREATE : 0,
seq++, n->chain);
n->seq, n->chain);
break;
case NFT_COMPAT_CHAIN_RENAME:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, 0,
seq++, n->chain);
n->seq, n->chain);
break;
case NFT_COMPAT_RULE_APPEND:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE | NLM_F_APPEND,
seq++, n->rule);
n->seq, n->rule);
break;
case NFT_COMPAT_RULE_INSERT:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE, seq++,
NLM_F_CREATE, n->seq,
n->rule);
break;
case NFT_COMPAT_RULE_REPLACE:
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
NLM_F_CREATE | NLM_F_REPLACE,
seq++, n->rule);
n->seq, n->rule);
break;
case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH:
nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
seq++, n->rule);
n->seq, n->rule);
break;
}
h->obj_list_num--;
list_del(&n->head);
free(n);
if (!mnl_nlmsg_batch_next(h->batch))
h->batch = mnl_nftnl_batch_page_add(h->batch);
mnl_nft_batch_continue(h->batch);
}
switch (action) {
case NFT_COMPAT_COMMIT:
mnl_nftnl_batch_end(h->batch, seq++);
mnl_batch_end(h->batch, seq++);
break;
case NFT_COMPAT_ABORT:
break;
}
if (!mnl_nlmsg_batch_is_empty(h->batch))
h->batch = mnl_nftnl_batch_page_add(h->batch);
ret = mnl_batch_talk(h->nl, h->batch, &h->err_list);
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;
}
......@@ -2428,16 +2614,29 @@ int nft_abort(struct nft_handle *h)
int nft_compatible_revision(const char *name, uint8_t rev, int opt)
{
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
char buf[16536];
struct nlmsghdr *nlh;
uint32_t portid, seq, type;
uint32_t portid, seq, type = 0;
uint32_t pf = AF_INET;
int ret = 0;
if (opt == IPT_SO_GET_REVISION_MATCH ||
opt == IP6T_SO_GET_REVISION_MATCH)
type = 0;
else
switch (opt) {
case IPT_SO_GET_REVISION_MATCH:
break;
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;
pf = AF_INET6;
break;
default:
/* No revision support (arp, ebtables), assume latest version ok */
return 1;
}
nlh = mnl_nlmsg_put_header(buf);
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)
nlh->nlmsg_seq = seq = time(NULL);
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->res_id = 0;
......@@ -2498,19 +2697,18 @@ const char *nft_strerror(int err)
{ nft_chain_user_del, EMLINK,
"Can't delete chain with references left" },
{ 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_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_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 */
{ nft_rule_delete, ENOENT,
"Bad rule (does a matching rule exist in that chain?)" },
{ nft_chain_set, ENOENT, "Bad built-in chain name" },
{ nft_chain_set, EINVAL, "Bad policy name" },
{ NULL, ELOOP, "Loop found in table" },
{ NULL, EPERM, "Permission denied (you must be root)" },
{ NULL, 0, "Incompatible with this kernel" },
{ NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
......@@ -2540,8 +2738,8 @@ static void xtables_config_perror(uint32_t flags, const char *fmt, ...)
va_end(args);
}
int nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags)
static int __nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags)
{
struct nftnl_table_list *table_list = NULL;
struct nftnl_chain_list *chain_list = NULL;
......@@ -2552,9 +2750,6 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t table_family, chain_family;
bool found = false;
if (h->restore)
return 0;
table_list = nftnl_table_list_alloc();
chain_list = nftnl_chain_list_alloc();
......@@ -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_free(chain_list);
h->config_done = 1;
return 0;
err:
......@@ -2647,9 +2844,20 @@ err:
if (citer != NULL)
nftnl_chain_list_iter_destroy(citer);
h->config_done = -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,
const char *table)
{
......@@ -2684,18 +2892,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
if (h->batch_support) {
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);
}
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
if (chain != NULL)
break;
......@@ -2703,9 +2900,6 @@ next:
c = nftnl_chain_list_iter_next(iter);
}
if (!h->batch_support)
nftnl_chain_list_free(list);
nftnl_chain_list_iter_destroy(iter);
err:
......@@ -2747,15 +2941,15 @@ static int nft_is_expr_compatible(const char *name)
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 *expr;
int ret = 0;
bool compatible = false;
iter = nftnl_expr_iter_create(rule);
if (iter == NULL)
return -1;
return false;
expr = nftnl_expr_iter_next(iter);
while (expr != NULL) {
......@@ -2766,37 +2960,51 @@ static int nft_is_rule_compatible(struct nftnl_rule *rule)
continue;
}
ret = 1;
compatible = true;
break;
}
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;
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++) {
cur_table = xtables_ipv4[i].name;
chains = xtables_ipv4[i].chains;
cur_table = h->tables[i].name;
chains = h->tables[i].chains;
if (strcmp(table, cur_table) != 0)
if (!cur_table || strcmp(table, cur_table) != 0)
continue;
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;
break;
}
}
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_iter *iter;
......@@ -2816,101 +3024,55 @@ static int nft_are_chains_compatible(struct nft_handle *h)
if (!nft_chain_builtin(chain))
goto next;
const char *table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
const char *name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
if (nft_is_chain_compatible(table, name) == 1) {
ret = 1;
ret = nft_is_chain_compatible(h, chain);
if (ret != 0)
break;
}
next:
chain = nftnl_chain_list_iter_next(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;
}
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_iter *iter;
struct nftnl_rule *rule;
int ret = 0;
int ret = 0, i;
ret = nft_are_tables_compatible(h);
if (ret != 0)
return ret;
for (i = 0; i < TABLES_MAX; i++) {
if (!h->tables[i].name)
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)
return ret;
return false;
list = nft_rule_list_get(h);
if (list == NULL)
return -1;
return true;
iter = nftnl_rule_list_iter_create(list);
if (iter == NULL)
return -1;
return true;
rule = nftnl_rule_list_iter_next(iter);
while (rule != NULL) {
ret = nft_is_rule_compatible(rule);
if (ret != 0)
break;
rule = nftnl_rule_list_iter_next(iter);
}
nftnl_rule_list_iter_destroy(iter);
return ret;
return ret == 0;
}
......@@ -32,12 +32,19 @@ struct nft_handle {
uint32_t seq;
struct list_head obj_list;
int obj_list_num;
struct mnl_nlmsg_batch *batch;
struct nftnl_batch *batch;
struct list_head err_list;
struct nft_family_ops *ops;
struct builtin_table *tables;
struct nftnl_chain_list *chain_cache;
struct nftnl_rule_list *rule_cache;
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];
......@@ -56,23 +63,25 @@ void nft_fini(struct nft_handle *h);
struct nftnl_table;
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);
bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
int nft_table_flush(struct nft_handle *h, const char *table);
void nft_table_new(struct nft_handle *h, const char *table);
/*
* Operations with chains.
*/
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);
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);
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_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_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,
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
#!/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 {
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 {
union {
struct ebt_entry eb;
struct ipt_entry fw;
struct ip6t_entry fw6;
};
......@@ -57,6 +88,7 @@ struct iptables_command_state {
int c;
unsigned int options;
struct xtables_rule_match *matches;
struct ebt_match *match_list;
struct xtables_target *target;
struct xt_counters counters;
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