Commit c2d7e04a authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Update upstream source from tag 'upstream/1.8.1'

Update to upstream version '1.8.1'
with Debian dir f7eefdbc289bc01f3d8a1522cd469a3564de9051
parents 698f2511 dab1e98e
......@@ -405,27 +405,6 @@ parse_chain(const char *chainname)
"Invalid chain name `%s'", chainname);
}
static const char *
parse_target(const char *targetname)
{
const char *ptr;
if (strlen(targetname) < 1)
xtables_error(PARAMETER_PROBLEM,
"Invalid target name (too short)");
if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid target name `%s' (%u chars max)",
targetname, XT_EXTENSION_MAXNAMELEN - 1);
for (ptr = targetname; *ptr; ptr++)
if (isspace(*ptr))
xtables_error(PARAMETER_PROBLEM,
"Invalid target name `%s'", targetname);
return targetname;
}
static void
set_option(unsigned int *options, unsigned int option, uint8_t *invflg,
int invert)
......@@ -535,7 +514,6 @@ print_firewall(const struct ipt_entry *fw,
struct xtables_target *target, *tg;
const struct xt_entry_target *t;
uint8_t flags;
char buf[BUFSIZ];
if (!iptc_is_chain(targname, handle))
target = xtables_find_target(targname, XTF_TRY_LOAD);
......@@ -574,59 +552,9 @@ print_firewall(const struct ipt_entry *fw,
fputc(' ', stdout);
}
if (format & FMT_VIA) {
char iface[IFNAMSIZ+2];
print_ifaces(fw->ip.iniface, fw->ip.outiface, fw->ip.invflags, format);
if (fw->ip.invflags & IPT_INV_VIA_IN) {
iface[0] = '!';
iface[1] = '\0';
}
else iface[0] = '\0';
if (fw->ip.iniface[0] != '\0') {
strcat(iface, fw->ip.iniface);
}
else if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
printf(FMT(" %-6s ","in %s "), iface);
if (fw->ip.invflags & IPT_INV_VIA_OUT) {
iface[0] = '!';
iface[1] = '\0';
}
else iface[0] = '\0';
if (fw->ip.outiface[0] != '\0') {
strcat(iface, fw->ip.outiface);
}
else if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
printf(FMT("%-6s ","out %s "), iface);
}
fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
if (fw->ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
printf(FMT("%-19s ","%s "), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf, xtables_ipaddr_to_numeric(&fw->ip.src));
else
strcpy(buf, xtables_ipaddr_to_anyname(&fw->ip.src));
strcat(buf, xtables_ipmask_to_numeric(&fw->ip.smsk));
printf(FMT("%-19s ","%s "), buf);
}
fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
if (fw->ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
printf(FMT("%-19s ","-> %s"), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf, xtables_ipaddr_to_numeric(&fw->ip.dst));
else
strcpy(buf, xtables_ipaddr_to_anyname(&fw->ip.dst));
strcat(buf, xtables_ipmask_to_numeric(&fw->ip.dmsk));
printf(FMT("%-19s ","-> %s"), buf);
}
print_ipv4_addresses(fw, format);
if (format & FMT_NOTABLE)
fputs(" ", stdout);
......@@ -1262,90 +1190,13 @@ generate_entry(const struct ipt_entry *fw,
return e;
}
static void command_jump(struct iptables_command_state *cs)
{
size_t size;
set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, cs->invert);
cs->jumpto = parse_target(optarg);
/* TRY_LOAD (may be chain name) */
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
if (cs->target == NULL)
return;
size = XT_ALIGN(sizeof(struct xt_entry_target))
+ cs->target->size;
cs->target->t = xtables_calloc(1, size);
cs->target->t->u.target_size = size;
if (cs->target->real_name == NULL) {
strcpy(cs->target->t->u.user.name, cs->jumpto);
} else {
/* Alias support for userspace side */
strcpy(cs->target->t->u.user.name, cs->target->real_name);
if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
fprintf(stderr, "Notice: The %s target is converted into %s target "
"in rule listing and saving.\n",
cs->jumpto, cs->target->real_name);
}
cs->target->t->u.user.revision = cs->target->revision;
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
opts = xtables_options_xfrm(iptables_globals.orig_opts, opts,
cs->target->x6_options,
&cs->target->option_offset);
else
opts = xtables_merge_options(iptables_globals.orig_opts, opts,
cs->target->extra_opts,
&cs->target->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
}
static void command_match(struct iptables_command_state *cs)
{
struct xtables_match *m;
size_t size;
if (cs->invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --match");
m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
m->m = xtables_calloc(1, size);
m->m->u.match_size = size;
if (m->real_name == NULL) {
strcpy(m->m->u.user.name, m->name);
} else {
strcpy(m->m->u.user.name, m->real_name);
if (!(m->ext_flags & XTABLES_EXT_ALIAS))
fprintf(stderr, "Notice: the %s match is converted into %s match "
"in rule listing and saving.\n", m->name, m->real_name);
}
m->m->u.user.revision = m->revision;
xs_init_match(m);
if (m == m->next)
return;
/* Merge options for non-cloned matches */
if (m->x6_options != NULL)
opts = xtables_options_xfrm(iptables_globals.orig_opts, opts,
m->x6_options, &m->option_offset);
else if (m->extra_opts != NULL)
opts = xtables_merge_options(iptables_globals.orig_opts, opts,
m->extra_opts, &m->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
}
int do_command4(int argc, char *argv[], char **table,
struct xtc_handle **handle, bool restore)
{
struct iptables_command_state cs;
struct iptables_command_state cs = {
.jumpto = "",
.argv = argv,
};
struct ipt_entry *e = NULL;
unsigned int nsaddrs = 0, ndaddrs = 0;
struct in_addr *saddrs = NULL, *smasks = NULL;
......@@ -1367,10 +1218,6 @@ int do_command4(int argc, char *argv[], char **table,
struct xtables_target *t;
unsigned long long cnt;
memset(&cs, 0, sizeof(cs));
cs.jumpto = "";
cs.argv = argv;
/* re-set optind to 0 in case do_command4 gets called
* a second time */
optind = 0;
......@@ -1567,11 +1414,13 @@ int do_command4(int argc, char *argv[], char **table,
set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags,
cs.invert);
cs.fw.ip.flags |= IPT_F_GOTO;
cs.jumpto = parse_target(optarg);
cs.jumpto = xt_parse_target(optarg);
break;
#endif
case 'j':
set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags,
cs.invert);
command_jump(&cs);
break;
......
......@@ -139,8 +139,8 @@ static void print_mac_and_mask(const unsigned char *mac, const unsigned char *ma
static int nft_arp_add(struct nftnl_rule *r, void *data)
{
struct arptables_command_state *cs = data;
struct arpt_entry *fw = &cs->fw;
struct iptables_command_state *cs = data;
struct arpt_entry *fw = &cs->arp;
uint32_t op;
int ret = 0;
......@@ -260,8 +260,8 @@ static uint16_t ipt_to_arpt_flags(uint8_t invflags)
static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
void *data)
{
struct arptables_command_state *cs = data;
struct arpt_entry *fw = &cs->fw;
struct iptables_command_state *cs = data;
struct arpt_entry *fw = &cs->arp;
uint8_t flags = 0;
parse_meta(e, ctx->meta.key, fw->arp.iniface, fw->arp.iniface_mask,
......@@ -271,17 +271,10 @@ static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
fw->arp.invflags |= ipt_to_arpt_flags(flags);
}
static void nft_arp_parse_target(struct xtables_target *target, void *data)
{
struct arptables_command_state *cs = data;
cs->target = target;
}
static void nft_arp_parse_immediate(const char *jumpto, bool nft_goto,
void *data)
{
struct arptables_command_state *cs = data;
struct iptables_command_state *cs = data;
cs->jumpto = jumpto;
}
......@@ -294,8 +287,8 @@ static void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask)
static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
struct nftnl_expr *e, void *data)
{
struct arptables_command_state *cs = data;
struct arpt_entry *fw = &cs->fw;
struct iptables_command_state *cs = data;
struct arpt_entry *fw = &cs->arp;
struct in_addr addr;
unsigned short int ar_hrd, ar_pro, ar_op, ar_hln;
bool inv;
......@@ -330,9 +323,6 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
fw->arp.invflags |= ARPT_INV_ARPOP;
break;
default:
if (fw->arp.arhln < 0)
break;
if (ctx->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln) {
get_cmp_data(e, &addr, sizeof(addr), &inv);
......@@ -365,14 +355,14 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
}
}
void nft_rule_to_arptables_command_state(struct nftnl_rule *r,
struct arptables_command_state *cs)
static void nft_arp_rule_to_cs(const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
struct nftnl_expr_iter *iter;
struct nftnl_expr *expr;
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct nft_xt_ctx ctx = {
.state.cs_arp = cs,
.cs = cs,
.family = family,
};
......@@ -387,7 +377,7 @@ void nft_rule_to_arptables_command_state(struct nftnl_rule *r,
nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
if (strcmp(name, "counter") == 0)
nft_parse_counter(expr, &ctx.state.cs_arp->fw.counters);
nft_parse_counter(expr, &ctx.cs->arp.counters);
else if (strcmp(name, "payload") == 0)
nft_parse_payload(&ctx, expr);
else if (strcmp(name, "meta") == 0)
......@@ -418,10 +408,11 @@ void nft_rule_to_arptables_command_state(struct nftnl_rule *r,
static void nft_arp_print_header(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters,
bool basechain, uint32_t refs)
bool basechain, uint32_t refs,
uint32_t entries)
{
printf("Chain %s", chain);
if (pol) {
if (basechain && pol) {
printf(" (policy %s", pol);
if (!(format & FMT_NOCOUNTS)) {
fputc(' ', stdout);
......@@ -436,7 +427,8 @@ static void nft_arp_print_header(unsigned int format, const char *chain,
}
}
static void print_fw_details(struct arpt_entry *fw, unsigned int format)
static void nft_arp_print_rule_details(const struct arpt_entry *fw,
unsigned int format)
{
char buf[BUFSIZ];
char iface[IFNAMSIZ+2];
......@@ -542,6 +534,7 @@ after_devdst:
if (tmp <= NUMOPCODES && !(format & FMT_NUMERIC))
printf("--opcode %s", opcodes[tmp-1]);
else
printf("--opcode %d", tmp);
if (fw->arp.arpop_mask != 65535)
printf("/%d", ntohs(fw->arp.arpop_mask));
......@@ -578,36 +571,48 @@ after_devdst:
}
static void
nft_arp_print_firewall(struct nftnl_rule *r, unsigned int num,
unsigned int format)
__nft_arp_save_rule(const void *data, unsigned int format)
{
struct arptables_command_state cs = {};
nft_rule_to_arptables_command_state(r, &cs);
const struct iptables_command_state *cs = data;
if (format & FMT_LINENUMBERS)
printf("%u ", num);
nft_arp_print_rule_details(&cs->arp, format);
print_fw_details(&cs.fw, format);
if (cs.jumpto != NULL && strcmp(cs.jumpto, "") != 0) {
printf("-j %s", cs.jumpto);
} else if (cs.target) {
printf("-j %s", cs.target->name);
cs.target->print(&cs.fw, cs.target->t, format & FMT_NUMERIC);
if (cs->jumpto != NULL && strcmp(cs->jumpto, "") != 0) {
printf("-j %s", cs->jumpto);
} else if (cs->target) {
printf("-j %s", cs->target->name);
cs->target->print(&cs->arp, cs->target->t, format & FMT_NUMERIC);
}
if (!(format & FMT_NOCOUNTS)) {
printf(", pcnt=");
xtables_print_num(cs.fw.counters.pcnt, format);
xtables_print_num(cs->arp.counters.pcnt, format);
printf("-- bcnt=");
xtables_print_num(cs.fw.counters.bcnt, format);
xtables_print_num(cs->arp.counters.bcnt, format);
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
static void
nft_arp_save_rule(const void *data, unsigned int format)
{
__nft_arp_save_rule(data, format | FMT_NUMERIC);
}
static void
nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
{
struct iptables_command_state cs = {};
if (format & FMT_LINENUMBERS)
printf("%u ", num);
nft_arp_rule_to_cs(r, &cs);
__nft_arp_save_rule(&cs, format);
}
static bool nft_arp_is_same(const void *data_a,
const void *data_b)
{
......@@ -637,24 +642,31 @@ static bool nft_arp_is_same(const void *data_a,
static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
void *data)
{
const struct arptables_command_state *cs = data;
struct arptables_command_state this = {};
const struct iptables_command_state *cs = data;
struct iptables_command_state this = {};
/* Delete by matching rule case */
nft_rule_to_arptables_command_state(r, &this);
nft_arp_rule_to_cs(r, &this);
if (!nft_arp_is_same(cs, &this))
if (!nft_arp_is_same(&cs->arp, &this.arp))
return false;
if (!compare_targets(cs->target, this.target))
return false;
if (strcmp(cs->jumpto, this.jumpto) != 0)
if (this.jumpto && strcmp(cs->jumpto, this.jumpto) != 0)
return false;
return true;
}
static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy)
{
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
printf(":%s %s\n", chain, policy ?: "-");
}
struct nft_family_ops nft_family_ops_arp = {
.add = nft_arp_add,
.is_same = nft_arp_is_same,
......@@ -663,10 +675,13 @@ struct nft_family_ops nft_family_ops_arp = {
.parse_payload = nft_arp_parse_payload,
.parse_immediate = nft_arp_parse_immediate,
.print_header = nft_arp_print_header,
.print_firewall = nft_arp_print_firewall,
.save_firewall = NULL,
.print_rule = nft_arp_print_rule,
.save_rule = nft_arp_save_rule,
.save_counters = NULL,
.save_chain = nft_arp_save_chain,
.post_parse = NULL,
.rule_to_cs = nft_arp_rule_to_cs,
.clear_cs = nft_clear_iptables_command_state,
.rule_find = nft_arp_rule_find,
.parse_target = nft_arp_parse_target,
.parse_target = nft_ipv46_parse_target,
};
......@@ -4,13 +4,4 @@
extern char *opcodes[];
#define NUMOPCODES 9
struct arptables_command_state {
struct arpt_entry fw;
struct xtables_target *target;
const char *jumpto;
};
void nft_rule_to_arptables_command_state(struct nftnl_rule *r,
struct arptables_command_state *cs);
#endif
......@@ -16,7 +16,6 @@
#include <xtables.h>
#include <libiptc/libxtc.h>
#include <linux/netfilter/nf_tables.h>
#include <ebtables/ethernetdb.h>
#include "nft-shared.h"
#include "nft-bridge.h"
......@@ -29,9 +28,18 @@ void ebt_cs_clean(struct iptables_command_state *cs)
xtables_rule_matches_free(&cs->matches);
for (m = cs->match_list; m;) {
if (!m->ismatch) {
struct xtables_target *target = m->u.watcher;
if (target->t) {
free(target->t);
target->t = NULL;
}
if (target == target->next)
free(target);
}
nm = m->next;
if (!m->ismatch)
free(m->u.watcher->t);
free(m);
m = nm;
}
......@@ -193,7 +201,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
add_cmp_u16(r, fw->ethproto, op);
}
add_compat(r, fw->ethproto, fw->invflags);
add_compat(r, fw->ethproto, fw->invflags & EBT_IPROTO);
for (iter = cs->match_list; iter; iter = iter->next) {
if (iter->ismatch) {
......@@ -217,10 +225,7 @@ static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
struct iptables_command_state *cs = data;
struct ebt_entry *fw = &cs->eb;
uint8_t invflags = 0;
char iifname[IFNAMSIZ], oifname[IFNAMSIZ];
memset(iifname, 0, sizeof(iifname));
memset(oifname, 0, sizeof(oifname));
char iifname[IFNAMSIZ] = {}, oifname[IFNAMSIZ] = {};
parse_meta(e, ctx->meta.key, iifname, NULL, oifname, NULL, &invflags);
......@@ -350,7 +355,7 @@ static void nft_bridge_parse_target(struct xtables_target *t, void *data)
cs->target = t;
}
static void nft_rule_to_ebtables_command_state(struct nftnl_rule *r,
static void nft_rule_to_ebtables_command_state(const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
cs->eb.bitmask = EBT_NOPROTO;
......@@ -371,10 +376,10 @@ static void nft_bridge_print_table_header(const char *tablename)
static void nft_bridge_print_header(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters,
bool basechain, uint32_t refs)
bool basechain, uint32_t refs, uint32_t entries)
{
printf("Bridge chain: %s, entries: %u, policy: %s\n",
chain, refs, basechain ? pol : "RETURN");
chain, entries, basechain ? pol : "RETURN");
}
static void print_matches_and_watchers(const struct iptables_command_state *cs,
......@@ -415,7 +420,7 @@ static void print_mac(char option, const unsigned char *mac,
static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
{
struct ethertypeent *ent;
struct xt_ethertypeent *ent;
/* Dont print anything about the protocol if no protocol was
* specified, obviously this means any protocol will do. */
......@@ -431,59 +436,87 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
return;
}
ent = getethertypebynumber(ntohs(ethproto));
ent = xtables_getethertypebynumber(ntohs(ethproto));
if (!ent)
printf("0x%x ", ntohs(ethproto));
else
printf("%s ", ent->e_name);
}
static void nft_bridge_print_firewall(struct nftnl_rule *r, unsigned int num,
unsigned int format)
static void nft_bridge_save_rule(const void *data, unsigned int format)
{
struct iptables_command_state cs = {};
nft_rule_to_ebtables_command_state(r, &cs);
if (format & FMT_LINENUMBERS)
printf("%d ", num);
const struct iptables_command_state *cs = data;
print_protocol(cs.eb.ethproto, cs.eb.invflags & EBT_IPROTO, cs.eb.bitmask);
if (cs.eb.bitmask & EBT_ISOURCE)
print_mac('s', cs.eb.sourcemac, cs.eb.sourcemsk,
cs.eb.invflags & EBT_ISOURCE);
if (cs.eb.bitmask & EBT_IDEST)
print_mac('d', cs.eb.destmac, cs.eb.destmsk,
cs.eb.invflags & EBT_IDEST);
if (cs->eb.ethproto)
print_protocol(cs->eb.ethproto, cs->eb.invflags & EBT_IPROTO,
cs->eb.bitmask);
if (cs->eb.bitmask & EBT_ISOURCE)
print_mac('s', cs->eb.sourcemac, cs->eb.sourcemsk,
cs->eb.invflags & EBT_ISOURCE);
if (cs->eb.bitmask & EBT_IDEST)
print_mac('d', cs->eb.destmac, cs->eb.destmsk,
cs->eb.invflags & EBT_IDEST);
print_iface("-i", cs.eb.in, cs.eb.invflags & EBT_IIN);
print_iface("--logical-in", cs.eb.logical_in, cs.eb.invflags & EBT_ILOGICALIN);
print_iface("-o", cs.eb.out, cs.eb.invflags & EBT_IOUT);
print_iface("--logical-out", cs.eb.logical_out, cs.eb.invflags & EBT_ILOGICALOUT);
print_iface("-i", cs->eb.in, cs->eb.invflags & EBT_IIN);
print_iface("--logical-in", cs->eb.logical_in,
cs->eb.invflags & EBT_ILOGICALIN);
print_iface("-o", cs->eb.out, cs->eb.invflags & EBT_IOUT);
print_iface("--logical-out", cs->eb.logical_out,
cs->eb.invflags & EBT_ILOGICALOUT);
print_matches_and_watchers(&cs, format);
print_matches_and_watchers(cs, format);
printf("-j ");
if (cs.jumpto != NULL) {
if (strcmp(cs.jumpto, "") != 0)
printf("%s", cs.jumpto);
if (cs->jumpto != NULL) {
if (strcmp(cs->jumpto, "") != 0)
printf("%s", cs->jumpto);
else
printf("CONTINUE");
}
else if (cs.target != NULL && cs.target->print != NULL)
cs.target->print(&cs.fw, cs.target->t, format & FMT_NUMERIC);
if (cs->target != NULL && cs->target->print != NULL) {
printf(" ");
cs->target->print(&cs->fw, cs->target->t, format & FMT_NUMERIC);
}
if (!(format & FMT_NOCOUNTS)) {
const char *counter_fmt;
if (!(format & FMT_NOCOUNTS))
printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
(uint64_t)cs.counters.pcnt, (uint64_t)cs.counters.bcnt);
if (format & FMT_EBT_SAVE)
counter_fmt = " -c %"PRIu64" %"PRIu64"";
else
counter_fmt = " , pcnt = %"PRIu64" -- bcnt = %"PRIu64"";
printf(counter_fmt,
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
{
struct iptables_command_state cs = {};
if (format & FMT_LINENUMBERS)
printf("%d ", num);
nft_rule_to_ebtables_command_state(r, &cs);
nft_bridge_save_rule(&cs, format);
ebt_cs_clean(&cs);
}
static void nft_bridge_save_chain(const struct nftnl_chain *c,
const char *policy)
{
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
printf(":%s %s\n", chain, policy ?: "ACCEPT");
}
static bool nft_bridge_is_same(const void *data_a, const void *data_b)
{
const struct ebt_entry *a = data_a;
......@@ -732,10 +765,13 @@ struct nft_family_ops nft_family_ops_bridge = {
.parse_target = nft_bridge_parse_target,
.print_table_header = nft_bridge_print_table_header,
.print_header = nft_bridge_print_header,
.print_firewall = nft_bridge_print_firewall,
.save_firewall = NULL,
.print_rule = nft_bridge_print_rule,
.save_rule = nft_bridge_save_rule,
.save_counters = NULL,
.save_chain = nft_bridge_save_chain,
.post_parse = NULL,
.rule_to_cs = nft_rule_to_ebtables_command_state,
.clear_cs = ebt_cs_clean,
.rule_find = nft_bridge_rule_find,
.xlate = nft_bridge_xlate,
};
......@@ -78,7 +78,7 @@ static const char *ebt_standard_targets[NUM_STANDARD_TARGETS] = {
static inline const char *nft_ebt_standard_target(unsigned int num)
{
if (num > NUM_STANDARD_TARGETS)
if (num >= NUM_STANDARD_TARGETS)
return NULL;
return ebt_standard_targets[num];
......@@ -120,5 +120,7 @@ void ebt_add_match(struct xtables_match *m,
struct iptables_command_state *cs);
void ebt_add_watcher(struct xtables_target *watcher,
struct iptables_command_state *cs);
int ebt_command_default(struct iptables_command_state *cs);
struct xtables_target *ebt_command_jump(const char *jumpto);
#endif
......@@ -45,8 +45,7 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
if (cs->fw.ip.proto != 0) {
op = nft_invflags2cmp(cs->fw.ip.invflags, XT_INV_PROTO);
add_proto(r, offsetof(struct iphdr, protocol), 1,
cs->fw.ip.proto, op);
add_l4proto(r, cs->fw.ip.proto, op);
}
if (cs->fw.ip.src.s_addr != 0) {
......@@ -75,7 +74,7 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
add_cmp_u16(r, 0, op);
}
add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags);
add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) {
/* Use nft built-in comments support instead of comment match */
......@@ -172,6 +171,16 @@ static void nft_ipv4_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
{
struct iptables_command_state *cs = data;
switch (ctx->meta.key) {
case NFT_META_L4PROTO:
cs->fw.ip.proto = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
cs->fw.ip.invflags |= XT_INV_PROTO;
return;
default:
break;
}
parse_meta(e, ctx->meta.key, cs->fw.ip.iniface, cs->fw.ip.iniface_mask,
cs->fw.ip.outiface, cs->fw.ip.outiface_mask,
&cs->fw.ip.invflags);
......@@ -225,6 +234,7 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
break;
case offsetof(struct iphdr, frag_off):
cs->fw.ip.flags |= IPT_F_FRAG;
inv = false;
get_frag(ctx, e, &inv);
if (inv)
cs->fw.ip.invflags |= IPT_INV_FRAG;
......@@ -246,44 +256,6 @@ static void nft_ipv4_parse_immediate(const char *jumpto, bool nft_goto,
cs->fw.ip.flags |= IPT_F_GOTO;
}
static void nft_ipv4_print_header(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters,
bool basechain, uint32_t refs)
{
print_header(format, chain, pol, counters, basechain, refs);
}
static void print_ipv4_addr(const struct iptables_command_state *cs,
unsigned int format)
{
char buf[BUFSIZ];
fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
printf(FMT("%-19s ","%s "), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src));
else
strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src));
strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
printf(FMT("%-19s ","%s "), buf);
}
fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
printf(FMT("%-19s ","-> %s"), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
else
strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
printf(FMT("%-19s ","-> %s"), buf);
}
}
static void print_fragment(unsigned int flags, unsigned int invflags,
unsigned int format)
{
......@@ -297,20 +269,19 @@ static void print_fragment(unsigned int flags, unsigned int invflags,
fputc(' ', stdout);
}
static void nft_ipv4_print_firewall(struct nftnl_rule *r, unsigned int num,
static void nft_ipv4_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
{
struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(r, &cs);
print_firewall_details(&cs, cs.jumpto, cs.fw.ip.flags,
cs.fw.ip.invflags, cs.fw.ip.proto,
num, format);
print_rule_details(&cs, cs.jumpto, cs.fw.ip.flags,
cs.fw.ip.invflags, cs.fw.ip.proto, num, format);
print_fragment(cs.fw.ip.flags, cs.fw.ip.invflags, format);
print_ifaces(cs.fw.ip.iniface, cs.fw.ip.outiface, cs.fw.ip.invflags,
format);
print_ipv4_addr(&cs, format);
print_ipv4_addresses(&cs.fw, format);
if (format & FMT_NOTABLE)
fputs(" ", stdout);
......@@ -338,7 +309,7 @@ static void save_ipv4_addr(char letter, const struct in_addr *addr,
mask_to_str(mask));
}
static void nft_ipv4_save_firewall(const void *data, unsigned int format)
static void nft_ipv4_save_rule(const void *data, unsigned int format)
{
const struct iptables_command_state *cs = data;
......@@ -347,7 +318,7 @@ static void nft_ipv4_save_firewall(const void *data, unsigned int format)
save_ipv4_addr('d', &cs->fw.ip.dst, cs->fw.ip.dmsk.s_addr,
cs->fw.ip.invflags & IPT_INV_DSTIP);
save_firewall_details(cs, cs->fw.ip.invflags, cs->fw.ip.proto,
save_rule_details(cs, cs->fw.ip.invflags, cs->fw.ip.proto,
cs->fw.ip.iniface, cs->fw.ip.iniface_mask,
cs->fw.ip.outiface, cs->fw.ip.outiface_mask);
......@@ -357,14 +328,8 @@ static void nft_ipv4_save_firewall(const void *data, unsigned int format)
printf("-f ");
}
save_matches_and_target(cs->matches, cs->target,
cs->jumpto, cs->fw.ip.flags, &cs->fw);
if (cs->target == NULL && strlen(cs->jumpto) > 0) {
printf("-%c %s", cs->fw.ip.flags & IPT_F_GOTO ? 'g' : 'j',
cs->jumpto);
}
printf("\n");
save_matches_and_target(cs, cs->fw.ip.flags & IPT_F_GOTO,
&cs->fw, format);
}
static void nft_ipv4_proto_parse(struct iptables_command_state *cs,
......@@ -422,28 +387,6 @@ static void nft_ipv4_post_parse(int command,
" source or destination IP addresses");
}
static void nft_ipv4_parse_target(struct xtables_target *t, void *data)
{
struct iptables_command_state *cs = data;
cs->target = t;
}
static bool nft_ipv4_rule_find(struct nft_family_ops *ops,
struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data;
return nft_ipv46_rule_find(ops, r, cs);
}
static void nft_ipv4_save_counters(const void *data)
{
const struct iptables_command_state *cs = data;
save_counters(cs->counters.pcnt, cs->counters.bcnt);
}
static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
{
const struct iptables_command_state *cs = data;
......@@ -512,13 +455,16 @@ struct nft_family_ops nft_family_ops_ipv4 = {
.parse_meta = nft_ipv4_parse_meta,
.parse_payload = nft_ipv4_parse_payload,
.parse_immediate = nft_ipv4_parse_immediate,
.print_header = nft_ipv4_print_header,
.print_firewall = nft_ipv4_print_firewall,
.save_firewall = nft_ipv4_save_firewall,
.save_counters = nft_ipv4_save_counters,
.print_header = print_header,
.print_rule = nft_ipv4_print_rule,
.save_rule = nft_ipv4_save_rule,
.save_counters = save_counters,
.save_chain = nft_ipv46_save_chain,
.proto_parse = nft_ipv4_proto_parse,
.post_parse = nft_ipv4_post_parse,
.parse_target = nft_ipv4_parse_target,
.rule_find = nft_ipv4_rule_find,
.parse_target = nft_ipv46_parse_target,
.rule_to_cs = nft_rule_to_iptables_command_state,
.clear_cs = nft_clear_iptables_command_state,
.rule_find = nft_ipv46_rule_find,
.xlate = nft_ipv4_xlate,
};
......@@ -44,8 +44,7 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data)
if (cs->fw6.ipv6.proto != 0) {
op = nft_invflags2cmp(cs->fw6.ipv6.invflags, XT_INV_PROTO);
add_proto(r, offsetof(struct ip6_hdr, ip6_nxt), 1,
cs->fw6.ipv6.proto, op);
add_l4proto(r, cs->fw6.ipv6.proto, op);
}
if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)) {
......@@ -60,7 +59,7 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data)
&cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
sizeof(struct in6_addr), op);
}
add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags);
add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) {
/* Use nft built-in comments support instead of comment match */
......@@ -115,6 +114,16 @@ static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
{
struct iptables_command_state *cs = data;
switch (ctx->meta.key) {
case NFT_META_L4PROTO:
cs->fw6.ipv6.proto = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
cs->fw6.ipv6.invflags |= XT_INV_PROTO;
return;
default:
break;
}
parse_meta(e, ctx->meta.key, cs->fw6.ipv6.iniface,
cs->fw6.ipv6.iniface_mask, cs->fw6.ipv6.outiface,
cs->fw6.ipv6.outiface_mask, &cs->fw6.ipv6.invflags);
......@@ -162,7 +171,6 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
break;
case offsetof(struct ip6_hdr, ip6_nxt):
get_cmp_data(e, &proto, sizeof(proto), &inv);
cs->fw6.ipv6.flags |= IP6T_F_PROTO;
cs->fw6.ipv6.proto = proto;
if (inv)
cs->fw6.ipv6.invflags |= IP6T_INV_PROTO;
......@@ -183,64 +191,24 @@ static void nft_ipv6_parse_immediate(const char *jumpto, bool nft_goto,
cs->fw6.ipv6.flags |= IP6T_F_GOTO;
}
static void nft_ipv6_print_header(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters,
bool basechain, uint32_t refs)
{
print_header(format, chain, pol, counters, basechain, refs);
}
static void print_ipv6_addr(const struct iptables_command_state *cs,
unsigned int format)
{
char buf[BUFSIZ];
fputc(cs->fw6.ipv6.invflags & IP6T_INV_SRCIP ? '!' : ' ', stdout);
if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)
&& !(format & FMT_NUMERIC))
printf(FMT("%-19s ","%s "), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf,
xtables_ip6addr_to_numeric(&cs->fw6.ipv6.src));
else
strcpy(buf,
xtables_ip6addr_to_anyname(&cs->fw6.ipv6.src));
strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.smsk));
printf(FMT("%-19s ","%s "), buf);
}
fputc(cs->fw6.ipv6.invflags & IP6T_INV_DSTIP ? '!' : ' ', stdout);
if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)
&& !(format & FMT_NUMERIC))
printf(FMT("%-19s ","-> %s"), "anywhere");
else {
if (format & FMT_NUMERIC)
strcpy(buf,
xtables_ip6addr_to_numeric(&cs->fw6.ipv6.dst));
else
strcpy(buf,
xtables_ip6addr_to_anyname(&cs->fw6.ipv6.dst));
strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.dmsk));
printf(FMT("%-19s ","-> %s"), buf);
}
}
static void nft_ipv6_print_firewall(struct nftnl_rule *r, unsigned int num,
static void nft_ipv6_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
{
struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(r, &cs);
print_firewall_details(&cs, cs.jumpto, cs.fw6.ipv6.flags,
print_rule_details(&cs, cs.jumpto, cs.fw6.ipv6.flags,
cs.fw6.ipv6.invflags, cs.fw6.ipv6.proto,
num, format);
if (format & FMT_OPTIONS) {
if (format & FMT_NOTABLE)
fputs("opt ", stdout);
fputs(" ", stdout);
}
print_ifaces(cs.fw6.ipv6.iniface, cs.fw6.ipv6.outiface,
cs.fw6.ipv6.invflags, format);
print_ipv6_addr(&cs, format);
print_ipv6_addresses(&cs.fw6, format);
if (format & FMT_NOTABLE)
fputs(" ", stdout);
......@@ -276,7 +244,7 @@ static void save_ipv6_addr(char letter, const struct in6_addr *addr,
printf("/%d ", l);
}
static void nft_ipv6_save_firewall(const void *data, unsigned int format)
static void nft_ipv6_save_rule(const void *data, unsigned int format)
{
const struct iptables_command_state *cs = data;
......@@ -285,19 +253,12 @@ static void nft_ipv6_save_firewall(const void *data, unsigned int format)
save_ipv6_addr('d', &cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
cs->fw6.ipv6.invflags & IP6T_INV_DSTIP);
save_firewall_details(cs, cs->fw6.ipv6.invflags, cs->fw6.ipv6.proto,
save_rule_details(cs, cs->fw6.ipv6.invflags, cs->fw6.ipv6.proto,
cs->fw6.ipv6.iniface, cs->fw6.ipv6.iniface_mask,
cs->fw6.ipv6.outiface,
cs->fw6.ipv6.outiface_mask);
save_matches_and_target(cs->matches, cs->target,
cs->jumpto, cs->fw6.ipv6.flags, &cs->fw6);
cs->fw6.ipv6.outiface, cs->fw6.ipv6.outiface_mask);
if (cs->target == NULL && strlen(cs->jumpto) > 0) {
printf("-%c %s", cs->fw6.ipv6.flags & IP6T_F_GOTO ? 'g' : 'j',
cs->jumpto);
}
printf("\n");
save_matches_and_target(cs, cs->fw6.ipv6.flags & IP6T_F_GOTO,
&cs->fw6, format);
}
/* These are invalid numbers as upper layer protocol */
......@@ -326,9 +287,6 @@ static void nft_ipv6_proto_parse(struct iptables_command_state *cs,
static void nft_ipv6_post_parse(int command, struct iptables_command_state *cs,
struct xtables_args *args)
{
if (args->proto != 0)
args->flags |= IP6T_F_PROTO;
cs->fw6.ipv6.flags = args->flags;
/* We already set invflags in proto_parse, but we need to refresh it
* to include new parsed options.
......@@ -375,28 +333,6 @@ static void nft_ipv6_post_parse(int command, struct iptables_command_state *cs,
" source or destination IP addresses");
}
static void nft_ipv6_parse_target(struct xtables_target *t, void *data)
{
struct iptables_command_state *cs = data;
cs->target = t;
}
static bool nft_ipv6_rule_find(struct nft_family_ops *ops,
struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data;
return nft_ipv46_rule_find(ops, r, cs);
}
static void nft_ipv6_save_counters(const void *data)
{
const struct iptables_command_state *cs = data;
save_counters(cs->counters.pcnt, cs->counters.bcnt);
}
static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr,
const struct in6_addr *mask,
int invert, struct xt_xlate *xl)
......@@ -467,13 +403,16 @@ struct nft_family_ops nft_family_ops_ipv6 = {
.parse_meta = nft_ipv6_parse_meta,
.parse_payload = nft_ipv6_parse_payload,
.parse_immediate = nft_ipv6_parse_immediate,
.print_header = nft_ipv6_print_header,
.print_firewall = nft_ipv6_print_firewall,
.save_firewall = nft_ipv6_save_firewall,
.save_counters = nft_ipv6_save_counters,
.print_header = print_header,
.print_rule = nft_ipv6_print_rule,
.save_rule = nft_ipv6_save_rule,
.save_counters = save_counters,
.save_chain = nft_ipv46_save_chain,
.proto_parse = nft_ipv6_proto_parse,
.post_parse = nft_ipv6_post_parse,
.parse_target = nft_ipv6_parse_target,
.rule_find = nft_ipv6_rule_find,
.parse_target = nft_ipv46_parse_target,
.rule_to_cs = nft_rule_to_iptables_command_state,
.clear_cs = nft_clear_iptables_command_state,
.rule_find = nft_ipv46_rule_find,
.xlate = nft_ipv6_xlate,
};
......@@ -16,11 +16,13 @@
#include <stdbool.h>
#include <netdb.h>
#include <errno.h>
#include <inttypes.h>
#include <xtables.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/xt_comment.h>
#include <linux/netfilter/xt_limit.h>
#include <libmnl/libmnl.h>
#include <libnftnl/rule.h>
......@@ -186,6 +188,12 @@ void add_proto(struct nftnl_rule *r, int offset, size_t len,
add_cmp_u8(r, proto, op);
}
void add_l4proto(struct nftnl_rule *r, uint8_t proto, uint32_t op)
{
add_meta(r, NFT_META_L4PROTO);
add_cmp_u8(r, proto, op);
}
bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
unsigned const char *a_iniface_mask,
unsigned const char *a_outiface_mask,
......@@ -294,21 +302,6 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
return 0;
}
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;
default:
/* Should not happen */
return NULL;
}
}
void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
uint32_t tg_len;
......@@ -318,7 +311,7 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
struct xt_entry_target *t;
size_t size;
struct nft_family_ops *ops;
void *data = nft_get_data(ctx);
void *data = ctx->cs;
target = xtables_find_target(targname, XTF_TRY_LOAD);
if (target == NULL)
......@@ -326,11 +319,7 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
t = calloc(1, size);
if (t == NULL) {
fprintf(stderr, "OOM");
exit(EXIT_FAILURE);
}
t = xtables_calloc(1, size);
memcpy(&t->data, targinfo, tg_len);
t->u.target_size = size;
t->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
......@@ -356,7 +345,7 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
matches = &ctx->state.cs->matches;
matches = &ctx->cs->matches;
break;
default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
......@@ -368,12 +357,7 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
if (match == NULL)
return;
m = calloc(1, sizeof(struct xt_entry_match) + mt_len);
if (m == NULL) {
fprintf(stderr, "OOM");
exit(EXIT_FAILURE);
}
m = xtables_calloc(1, sizeof(struct xt_entry_match) + mt_len);
memcpy(&m->data, mt_info, mt_len);
m->u.match_size = mt_len + XT_ALIGN(sizeof(struct xt_entry_match));
m->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
......@@ -383,7 +367,7 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
ops = nft_family_ops_lookup(ctx->family);
if (ops->parse_match != NULL)
ops->parse_match(match, nft_get_data(ctx));
ops->parse_match(match, ctx->cs);
}
void print_proto(uint16_t proto, int invert)
......@@ -446,7 +430,7 @@ static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
target->t = t;
ops = nft_family_ops_lookup(ctx->family);
ops->parse_target(target, nft_get_data(ctx));
ops->parse_target(target, ctx->cs);
}
void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
......@@ -491,7 +475,7 @@ void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
void *data = nft_get_data(ctx);
void *data = ctx->cs;
uint32_t reg;
reg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
......@@ -521,7 +505,7 @@ void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
struct nft_family_ops *ops;
const char *jumpto = NULL;
bool nft_goto = false;
void *data = nft_get_data(ctx);
void *data = ctx->cs;
int verdict;
if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
......@@ -554,6 +538,7 @@ void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
break;;
case NFT_GOTO:
nft_goto = true;
/* fall through */
case NFT_JUMP:
jumpto = chain;
break;
......@@ -563,14 +548,57 @@ void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
ops->parse_immediate(jumpto, nft_goto, data);
}
void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
__u32 burst = nftnl_expr_get_u32(e, NFTNL_EXPR_LIMIT_BURST);
__u64 unit = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_UNIT);
__u64 rate = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_RATE);
struct xtables_rule_match **matches;
struct xtables_match *match;
struct nft_family_ops *ops;
struct xt_rateinfo *rinfo;
size_t size;
switch (ctx->family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_BRIDGE:
matches = &ctx->cs->matches;
break;
default:
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
ctx->family);
exit(EXIT_FAILURE);
}
match = xtables_find_match("limit", XTF_TRY_LOAD, matches);
if (match == NULL)
return;
size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
match->m = xtables_calloc(1, size);
match->m->u.match_size = size;
strcpy(match->m->u.user.name, match->name);
match->m->u.user.revision = match->revision;
xs_init_match(match);
rinfo = (void *)match->m->data;
rinfo->avg = XT_LIMIT_SCALE * unit / rate;
rinfo->burst = burst;
ops = nft_family_ops_lookup(ctx->family);
if (ops->parse_match != NULL)
ops->parse_match(match, ctx->cs);
}
void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
struct nftnl_expr_iter *iter;
struct nftnl_expr *expr;
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct nft_xt_ctx ctx = {
.state.cs = cs,
.cs = cs,
.family = family,
};
......@@ -585,7 +613,7 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
if (strcmp(name, "counter") == 0)
nft_parse_counter(expr, &ctx.state.cs->counters);
nft_parse_counter(expr, &ctx.cs->counters);
else if (strcmp(name, "payload") == 0)
nft_parse_payload(&ctx, expr);
else if (strcmp(name, "meta") == 0)
......@@ -600,6 +628,8 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
nft_parse_match(&ctx, expr);
else if (strcmp(name, "target") == 0)
nft_parse_target(&ctx, expr);
else if (strcmp(name, "limit") == 0)
nft_parse_limit(&ctx, expr);
expr = nftnl_expr_iter_next(iter);
}
......@@ -608,7 +638,7 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
if (nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) {
const void *data;
uint32_t len;
uint32_t len, size;
struct xtables_match *match;
struct xt_entry_match *m;
......@@ -618,15 +648,12 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
if (match == NULL)
return;
m = calloc(1, sizeof(struct xt_entry_match) +
sizeof(struct xt_comment_info));
if (m == NULL) {
fprintf(stderr, "OOM");
exit(EXIT_FAILURE);
}
size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
m = xtables_calloc(1, size);
memcpy(&m->data, get_comment(data, len), len);
m->u.match_size = len + XT_ALIGN(sizeof(struct xt_entry_match));
strncpy((char *)m->data, get_comment(data, len),
match->size - 1);
m->u.match_size = size;
m->u.user.revision = 0;
strcpy(m->u.user.name, match->name);
......@@ -641,9 +668,16 @@ void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
cs->jumpto = "";
}
void nft_clear_iptables_command_state(struct iptables_command_state *cs)
{
xtables_rule_matches_free(&cs->matches);
if (cs->target)
free(cs->target->t);
}
void print_header(unsigned int format, const char *chain, const char *pol,
const struct xt_counters *counters, bool basechain,
uint32_t refs)
uint32_t refs, uint32_t entries)
{
printf("Chain %s", chain);
if (basechain) {
......@@ -685,7 +719,7 @@ void print_header(unsigned int format, const char *chain, const char *pol,
printf("\n");
}
void print_firewall_details(const struct iptables_command_state *cs,
void print_rule_details(const struct iptables_command_state *cs,
const char *targname, uint8_t flags,
uint8_t invflags, uint8_t proto,
unsigned int num, unsigned int format)
......@@ -712,45 +746,6 @@ void print_firewall_details(const struct iptables_command_state *cs,
}
}
void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags,
unsigned int format)
{
char iface[IFNAMSIZ+2];
if (!(format & FMT_VIA))
return;
if (invflags & IPT_INV_VIA_IN) {
iface[0] = '!';
iface[1] = '\0';
} else
iface[0] = '\0';
if (iniface[0] != '\0')
strcat(iface, iniface);
else if (format & FMT_NUMERIC)
strcat(iface, "*");
else
strcat(iface, "any");
printf(FMT(" %-6s ","in %s "), iface);
if (invflags & IPT_INV_VIA_OUT) {
iface[0] = '!';
iface[1] = '\0';
} else
iface[0] = '\0';
if (outiface[0] != '\0')
strcat(iface, outiface);
else if (format & FMT_NUMERIC)
strcat(iface, "*");
else
strcat(iface, "any");
printf(FMT("%-6s ","out %s "), iface);
}
static void
print_iface(char letter, const char *iface, const unsigned char *mask, int inv)
{
......@@ -775,7 +770,7 @@ print_iface(char letter, const char *iface, const unsigned char *mask, int inv)
printf(" ");
}
void save_firewall_details(const struct iptables_command_state *cs,
void save_rule_details(const struct iptables_command_state *cs,
uint8_t invflags, uint16_t proto,
const char *iniface,
unsigned const char *iniface_mask,
......@@ -804,19 +799,31 @@ void save_firewall_details(const struct iptables_command_state *cs,
}
}
void save_counters(uint64_t pcnt, uint64_t bcnt)
void save_counters(const void *data)
{
printf("[%llu:%llu] ", (unsigned long long)pcnt,
(unsigned long long)bcnt);
const struct iptables_command_state *cs = data;
printf("[%llu:%llu] ", (unsigned long long)cs->counters.pcnt,
(unsigned long long)cs->counters.bcnt);
}
void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy)
{
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
uint64_t pkts = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS);
uint64_t bytes = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES);
printf(":%s %s [%"PRIu64":%"PRIu64"]\n",
chain, policy ?: "-", pkts, bytes);
}
void save_matches_and_target(struct xtables_rule_match *m,
struct xtables_target *target,
const char *jumpto, uint8_t flags, const void *fw)
void save_matches_and_target(const struct iptables_command_state *cs,
bool goto_flag, const void *fw,
unsigned int format)
{
struct xtables_rule_match *matchp;
for (matchp = m; matchp; matchp = matchp->next) {
for (matchp = cs->matches; matchp; matchp = matchp->next) {
if (matchp->match->alias) {
printf("-m %s",
matchp->match->alias(matchp->match->m));
......@@ -830,15 +837,24 @@ void save_matches_and_target(struct xtables_rule_match *m,
printf(" ");
}
if (target != NULL) {
if (target->alias) {
printf("-j %s", target->alias(target->t));
if ((format & (FMT_NOCOUNTS | FMT_C_COUNTS)) == FMT_C_COUNTS)
printf("-c %llu %llu ",
(unsigned long long)cs->counters.pcnt,
(unsigned long long)cs->counters.bcnt);
if (cs->target != NULL) {
if (cs->target->alias) {
printf("-j %s", cs->target->alias(cs->target->t));
} else
printf("-j %s", jumpto);
printf("-j %s", cs->jumpto);
if (target->save != NULL)
target->save(fw, target->t);
if (cs->target->save != NULL)
cs->target->save(fw, cs->target->t);
} else if (strlen(cs->jumpto) > 0) {
printf("-%c %s", goto_flag ? 'g' : 'j', cs->jumpto);
}
printf("\n");
}
void print_matches_and_target(struct iptables_command_state *cs,
......@@ -934,16 +950,23 @@ bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2)
return true;
}
void nft_ipv46_parse_target(struct xtables_target *t, void *data)
{
struct iptables_command_state *cs = data;
cs->target = t;
}
bool nft_ipv46_rule_find(struct nft_family_ops *ops,
struct nftnl_rule *r, struct iptables_command_state *cs)
struct nftnl_rule *r, void *data)
{
struct iptables_command_state this = {};
struct iptables_command_state *cs = data, this = {};
nft_rule_to_iptables_command_state(r, &this);
DEBUGP("comparing with... ");
#ifdef DEBUG_DEL
nft_rule_print_save(&this, r, NFT_RULE_APPEND, 0);
nft_rule_print_save(r, NFT_RULE_APPEND, 0);
#endif
if (!ops->is_same(cs, &this))
return false;
......
......@@ -5,17 +5,15 @@
#include <libnftnl/rule.h>
#include <libnftnl/expr.h>
#include <libnftnl/chain.h>
#include <linux/netfilter_arp/arp_tables.h>
#include "xshared.h"
#if 0
#define DEBUGP(x, args...) fprintf(stdout, x, ## args)
#ifdef DEBUG
#define NLDEBUG
#define DEBUG_DEL
#else
#define DEBUGP(x, args...)
#endif
/*
......@@ -47,10 +45,7 @@ enum {
};
struct nft_xt_ctx {
union {
struct iptables_command_state *cs;
struct arptables_command_state *cs_arp;
} state;
struct nftnl_expr_iter *iter;
int family;
uint32_t flags;
......@@ -93,17 +88,21 @@ struct nft_family_ops {
void (*print_header)(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters, bool basechain,
uint32_t refs);
void (*print_firewall)(struct nftnl_rule *r, unsigned int num,
uint32_t refs, uint32_t entries);
void (*print_rule)(struct nftnl_rule *r, unsigned int num,
unsigned int format);
void (*save_firewall)(const void *data, unsigned int format);
void (*save_rule)(const void *data, unsigned int format);
void (*save_counters)(const void *data);
void (*save_chain)(const struct nftnl_chain *c, const char *policy);
void (*proto_parse)(struct iptables_command_state *cs,
struct xtables_args *args);
void (*post_parse)(int command, struct iptables_command_state *cs,
struct xtables_args *args);
void (*parse_match)(struct xtables_match *m, void *data);
void (*parse_target)(struct xtables_target *t, void *data);
void (*rule_to_cs)(const struct nftnl_rule *r,
struct iptables_command_state *cs);
void (*clear_cs)(struct iptables_command_state *cs);
bool (*rule_find)(struct nft_family_ops *ops, struct nftnl_rule *r,
void *data);
int (*xlate)(const void *data, struct xt_xlate *xl);
......@@ -123,6 +122,7 @@ void add_addr(struct nftnl_rule *r, int offset,
void *data, void *mask, size_t len, uint32_t op);
void add_proto(struct nftnl_rule *r, int offset, size_t len,
uint8_t proto, uint32_t op);
void add_l4proto(struct nftnl_rule *r, uint8_t proto, uint32_t op);
void add_compat(struct nftnl_rule *r, uint32_t proto, bool inv);
bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
......@@ -145,36 +145,36 @@ void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e);
void nft_parse_payload(struct nft_xt_ctx *ctx, struct nftnl_expr *e);
void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters);
void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e);
void nft_rule_to_iptables_command_state(struct nftnl_rule *r,
void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
struct iptables_command_state *cs);
void nft_clear_iptables_command_state(struct iptables_command_state *cs);
void print_header(unsigned int format, const char *chain, const char *pol,
const struct xt_counters *counters, bool basechain,
uint32_t refs);
void print_firewall_details(const struct iptables_command_state *cs,
uint32_t refs, uint32_t entries);
void print_rule_details(const struct iptables_command_state *cs,
const char *targname, uint8_t flags,
uint8_t invflags, uint8_t proto,
unsigned int num, unsigned int format);
void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags,
unsigned int format);
void print_matches_and_target(struct iptables_command_state *cs,
unsigned int format);
void save_firewall_details(const struct iptables_command_state *cs,
void save_rule_details(const struct iptables_command_state *cs,
uint8_t invflags, uint16_t proto,
const char *iniface,
unsigned const char *iniface_mask,
const char *outiface,
unsigned const char *outiface_mask);
void save_counters(uint64_t pcnt, uint64_t bcnt);
void save_matches_and_target(struct xtables_rule_match *m,
struct xtables_target *target,
const char *jumpto,
uint8_t flags, const void *fw);
void save_counters(const void *data);
void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy);
void save_matches_and_target(const struct iptables_command_state *cs,
bool goto_flag, const void *fw,
unsigned int format);
struct nft_family_ops *nft_family_ops_lookup(int family);
struct nft_handle;
void nft_ipv46_parse_target(struct xtables_target *t, void *data);
bool nft_ipv46_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
struct iptables_command_state *cs);
void *data);
bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2);
bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2);
......@@ -243,6 +243,7 @@ struct nft_xt_restore_parse {
FILE *in;
int testing;
const char *tablename;
bool commit;
};
struct nftnl_chain_list;
......
......@@ -38,6 +38,8 @@
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_tables_compat.h>
#include <linux/netfilter/xt_limit.h>
#include <libmnl/libmnl.h>
#include <libnftnl/table.h>
#include <libnftnl/chain.h>
......@@ -246,6 +248,7 @@ enum obj_update_type {
NFT_COMPAT_CHAIN_USER_FLUSH,
NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_CHAIN_RENAME,
NFT_COMPAT_CHAIN_ZERO,
NFT_COMPAT_RULE_APPEND,
NFT_COMPAT_RULE_INSERT,
NFT_COMPAT_RULE_REPLACE,
......@@ -310,6 +313,7 @@ static int mnl_append_error(const struct nft_handle *h,
nftnl_table_get_str(o->table, NFTNL_TABLE_NAME));
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO:
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
......@@ -327,9 +331,7 @@ static int mnl_append_error(const struct nft_handle *h,
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);
nft_rule_print_save(o->rule, NFT_RULE_APPEND, FMT_NOCOUNTS);
}
#endif
break;
......@@ -630,7 +632,7 @@ static void nft_chain_builtin_add(struct nft_handle *h,
}
/* find if built-in table already exists */
static struct builtin_table *
struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{
int i;
......@@ -651,7 +653,7 @@ nft_table_builtin_find(struct nft_handle *h, const char *table)
}
/* find if built-in chain already exists */
static struct builtin_chain *
struct builtin_chain *
nft_chain_builtin_find(struct builtin_table *t, const char *chain)
{
int i;
......@@ -675,7 +677,7 @@ static void nft_chain_builtin_init(struct nft_handle *h,
struct nftnl_chain *c;
/* Initialize built-in chains if they don't exist yet */
for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
c = nft_chain_list_find(list, table->name,
table->chains[i].name);
......@@ -815,7 +817,7 @@ static void nft_chain_print_debug(struct nftnl_chain *c, struct nlmsghdr *nlh)
#ifdef NLDEBUG
char tmp[1024];
nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
nftnl_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
......@@ -831,8 +833,12 @@ static struct nftnl_chain *nft_chain_new(struct nft_handle *h,
struct builtin_chain *_c;
_t = nft_table_builtin_find(h, table);
if (!_t) {
errno = ENXIO;
return NULL;
}
/* if this built-in table does not exists, create it */
if (_t != NULL)
nft_table_builtin_add(h, _t);
_c = nft_chain_builtin_find(_t, chain);
......@@ -869,6 +875,8 @@ int nft_chain_set(struct nft_handle *h, const char *table,
c = nft_chain_new(h, table, chain, NF_DROP, counters);
else if (strcmp(policy, "ACCEPT") == 0)
c = nft_chain_new(h, table, chain, NF_ACCEPT, counters);
else
errno = EINVAL;
if (c == NULL)
return 0;
......@@ -896,11 +904,50 @@ static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
return 0;
}
static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
{
struct xt_rateinfo *rinfo = (void *)m->data;
static const uint32_t mult[] = {
XT_LIMIT_SCALE*24*60*60, /* day */
XT_LIMIT_SCALE*60*60, /* hour */
XT_LIMIT_SCALE*60, /* min */
XT_LIMIT_SCALE, /* sec */
};
struct nftnl_expr *expr;
int i;
expr = nftnl_expr_alloc("limit");
if (!expr)
return -ENOMEM;
for (i = 1; i < ARRAY_SIZE(mult); i++) {
if (rinfo->avg > mult[i] ||
mult[i] / rinfo->avg < mult[i] % rinfo->avg)
break;
}
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_TYPE, NFT_LIMIT_PKTS);
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_FLAGS, 0);
nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_RATE,
mult[i - 1] / rinfo->avg);
nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_UNIT,
mult[i - 1] / XT_LIMIT_SCALE);
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_BURST, rinfo->burst);
nftnl_rule_add_expr(r, expr);
return 0;
}
int add_match(struct nftnl_rule *r, struct xt_entry_match *m)
{
struct nftnl_expr *expr;
int ret;
if (!strcmp(m->u.user.name, "limit"))
return add_nft_limit(r, m);
expr = nftnl_expr_alloc("match");
if (expr == NULL)
return -ENOMEM;
......@@ -1031,7 +1078,7 @@ static void nft_rule_print_debug(struct nftnl_rule *r, struct nlmsghdr *nlh)
#ifdef NLDEBUG
char tmp[1024];
nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
nftnl_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
printf("DEBUG: rule: %s\n", tmp);
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
#endif
......@@ -1173,10 +1220,16 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
} else
type = NFT_COMPAT_RULE_APPEND;
if (batch_rule_add(h, type, r) < 0)
if (batch_rule_add(h, type, r) < 0) {
nftnl_rule_free(r);
return 0;
}
nft_rule_list_get(h);
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
if (!nft_rule_list_get(h))
return 0;
nftnl_rule_list_add_tail(r, h->rule_cache);
......@@ -1184,18 +1237,19 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
}
void
nft_rule_print_save(const void *data,
struct nftnl_rule *r, enum nft_rule_print type,
nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
unsigned int format)
{
const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
struct iptables_command_state cs = {};
struct nft_family_ops *ops;
ops = nft_family_ops_lookup(family);
ops->rule_to_cs(r, &cs);
if (!(format & FMT_NOCOUNTS) && ops->save_counters)
ops->save_counters(data);
if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters)
ops->save_counters(&cs);
/* print chain name */
switch(type) {
......@@ -1207,9 +1261,11 @@ nft_rule_print_save(const void *data,
break;
}
if (ops->save_firewall)
ops->save_firewall(data, format);
if (ops->save_rule)
ops->save_rule(&cs, format);
if (ops->clear_cs)
ops->clear_cs(&cs);
}
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
......@@ -1274,32 +1330,15 @@ static const char *policy_name[NF_ACCEPT+1] = {
[NF_ACCEPT] = "ACCEPT",
};
static void nft_chain_print_save(struct nftnl_chain *c, bool basechain)
{
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
uint64_t pkts = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS);
uint64_t bytes = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES);
/* print chain name */
if (basechain) {
uint32_t pol = NF_ACCEPT;
/* no default chain policy? don't crash, display accept */
if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy_name[pol],
pkts, bytes);
} else
printf(":%s - [%"PRIu64":%"PRIu64"]\n", chain, pkts, bytes);
}
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
const char *table)
{
struct nftnl_chain_list_iter *iter;
struct nft_family_ops *ops;
struct nftnl_chain *c;
ops = nft_family_ops_lookup(h->family);
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
return 0;
......@@ -1308,13 +1347,21 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
while (c != NULL) {
const char *chain_table =
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
bool basechain = false;
const char *policy = NULL;
if (strcmp(table, chain_table) != 0)
goto next;
basechain = nft_chain_builtin(c);
nft_chain_print_save(c, basechain);
if (nft_chain_builtin(c)) {
uint32_t pol = NF_ACCEPT;
if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
policy = policy_name[pol];
}
if (ops->save_chain)
ops->save_chain(c, policy);
next:
c = nftnl_chain_list_iter_next(iter);
}
......@@ -1380,7 +1427,7 @@ retry:
return list;
}
int nft_rule_save(struct nft_handle *h, const char *table, bool counters)
int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
{
struct nftnl_rule_list *list;
struct nftnl_rule_list_iter *iter;
......@@ -1398,15 +1445,11 @@ int nft_rule_save(struct nft_handle *h, const char *table, bool counters)
while (r != NULL) {
const char *rule_table =
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
struct iptables_command_state cs = {};
if (strcmp(table, rule_table) != 0)
goto next;
nft_rule_to_iptables_command_state(r, &cs);
nft_rule_print_save(&cs, r, NFT_RULE_APPEND,
counters ? 0 : FMT_NOCOUNTS);
nft_rule_print_save(r, NFT_RULE_APPEND, format);
next:
r = nftnl_rule_list_iter_next(iter);
......@@ -1448,7 +1491,6 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *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;
......@@ -1456,13 +1498,8 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
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);
}
if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
__nft_rule_flush(h, table, chain);
return 0;
}
......@@ -1483,9 +1520,10 @@ int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
return 1;
}
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
bool verbose)
{
int ret;
int ret = 0;
struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c;
......@@ -1497,13 +1535,15 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
list = nftnl_chain_list_get(h);
if (list == NULL) {
ret = 0;
ret = 1;
goto err;
}
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
if (iter == NULL) {
ret = 1;
goto err;
}
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
......@@ -1518,6 +1558,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
if (verbose)
fprintf(stdout, "Flushing chain `%s'\n", chain_name);
__nft_rule_flush(h, table_name, chain_name);
if (chain != NULL)
......@@ -1565,7 +1608,8 @@ 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
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
int nft_chain_user_del(struct nft_handle *h, const char *chain,
const char *table, bool verbose)
{
struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
......@@ -1600,6 +1644,9 @@ 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 (verbose)
fprintf(stdout, "Deleting chain `%s'\n", chain);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
if (ret < 0)
......@@ -1672,6 +1719,21 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
return nft_chain_list_find(list, table, chain);
}
bool nft_chain_exists(struct nft_handle *h,
const char *table, const char *chain)
{
struct builtin_table *t = nft_table_builtin_find(h, table);
/* xtables does not support custom tables */
if (!t)
return false;
if (nft_chain_builtin_find(t, chain))
return true;
return !!nft_chain_find(h, table, chain);
}
int nft_chain_user_rename(struct nft_handle *h,const char *chain,
const char *table, const char *newname)
{
......@@ -1777,12 +1839,15 @@ bool nft_table_find(struct nft_handle *h, const char *tablename)
const char *this_tablename =
nftnl_table_get(t, NFTNL_TABLE_NAME);
if (strcmp(tablename, this_tablename) == 0)
return true;
if (strcmp(tablename, this_tablename) == 0) {
ret = true;
break;
}
t = nftnl_table_list_iter_next(iter);
}
nftnl_table_list_iter_destroy(iter);
nftnl_table_list_free(list);
err:
......@@ -1815,6 +1880,7 @@ int nft_for_each_table(struct nft_handle *h,
t = nftnl_table_list_iter_next(iter);
}
nftnl_table_list_iter_destroy(iter);
nftnl_table_list_free(list);
return 0;
}
......@@ -1833,7 +1899,7 @@ static int __nft_table_flush(struct nft_handle *h, const char *table)
batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t);
_t = nft_table_builtin_find(h, table);
assert(t);
assert(_t);
_t->initialized = false;
flush_chain_cache(h, table);
......@@ -1878,9 +1944,11 @@ next:
t = nftnl_table_list_iter_next(iter);
}
if (!h->rule_cache) {
h->rule_cache = nftnl_rule_list_alloc();
if (h->rule_cache == NULL)
return -1;
}
err_table_iter:
nftnl_table_list_iter_destroy(iter);
......@@ -1963,7 +2031,7 @@ int nft_rule_check(struct nft_handle *h, const char *chain,
const char *table, void *data, bool verbose)
{
struct nftnl_rule_list *list;
int ret;
struct nftnl_rule *r;
nft_fn = nft_rule_check;
......@@ -1971,11 +2039,15 @@ int nft_rule_check(struct nft_handle *h, const char *chain,
if (list == NULL)
return 0;
ret = nft_rule_find(h, list, chain, table, data, -1) ? 1 : 0;
if (ret == 0)
r = nft_rule_find(h, list, chain, table, data, -1);
if (r == NULL) {
errno = ENOENT;
return 0;
}
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
return ret;
return 1;
}
int nft_rule_delete(struct nft_handle *h, const char *chain,
......@@ -1996,6 +2068,8 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
ret =__nft_rule_del(h, list, r);
if (ret < 0)
errno = ENOMEM;
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
} else
errno = ENOENT;
......@@ -2021,6 +2095,9 @@ nft_rule_add(struct nft_handle *h, const char *chain,
return NULL;
}
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
return r;
}
......@@ -2092,8 +2169,6 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
r = nft_rule_find(h, list, chain, table, NULL, rulenum);
if (r != NULL) {
ret = 1;
DEBUGP("deleting rule by number %d\n", rulenum);
ret = __nft_rule_del(h, list, r);
if (ret < 0)
......@@ -2143,7 +2218,7 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
struct nftnl_rule_list *list;
struct nftnl_rule_list_iter *iter;
struct nftnl_rule *r;
int rule_ctr = 0, ret = 0;
int rule_ctr = 0;
list = nft_rule_list_get(h);
if (list == NULL)
......@@ -2151,7 +2226,7 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
iter = nftnl_rule_list_iter_create(list);
if (iter == NULL)
goto err;
return 0;
r = nftnl_rule_list_iter_next(iter);
while (r != NULL) {
......@@ -2172,21 +2247,51 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
}
cb(r, rule_ctr, format);
if (rulenum > 0 && rule_ctr == rulenum) {
ret = 1;
if (rulenum > 0)
break;
}
next:
r = nftnl_rule_list_iter_next(iter);
}
nftnl_rule_list_iter_destroy(iter);
err:
if (ret == 0)
errno = ENOENT;
return 1;
}
return ret;
static int nft_rule_count(struct nft_handle *h,
const char *chain, const char *table)
{
struct nftnl_rule_list_iter *iter;
struct nftnl_rule_list *list;
struct nftnl_rule *r;
int rule_ctr = 0;
list = nft_rule_list_get(h);
if (list == NULL)
return 0;
iter = nftnl_rule_list_iter_create(list);
if (iter == NULL)
return 0;
r = nftnl_rule_list_iter_next(iter);
while (r != NULL) {
const char *rule_table =
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
const char *rule_chain =
nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
if (strcmp(table, rule_table) != 0 ||
strcmp(chain, rule_chain) != 0)
goto next;
rule_ctr++;
next:
r = nftnl_rule_list_iter_next(iter);
}
nftnl_rule_list_iter_destroy(iter);
return rule_ctr;
}
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
......@@ -2204,8 +2309,10 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
/* Force table and chain creation, otherwise first iptables -L
* lists no table/chains.
*/
if (!list_empty(&h->obj_list))
if (!list_empty(&h->obj_list)) {
nft_commit(h);
flush_chain_cache(h, NULL);
}
}
ops = nft_family_ops_lookup(h->family);
......@@ -2217,7 +2324,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (chain && rulenum) {
__nft_rule_list(h, chain, table,
rulenum, format, ops->print_firewall);
rulenum, format, ops->print_rule);
return 1;
}
......@@ -2227,7 +2334,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (iter == NULL)
goto err;
if (ops->print_table_header)
if (!chain && ops->print_table_header)
ops->print_table_header(table);
c = nftnl_chain_list_iter_next(iter);
......@@ -2245,47 +2352,52 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
.bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
};
bool basechain = false;
uint32_t entries;
if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
basechain = true;
if (strcmp(table, chain_table) != 0)
goto next;
if (chain && strcmp(chain, chain_name) != 0)
if (chain) {
if (strcmp(chain, chain_name) != 0)
goto next;
else if (ops->print_table_header)
ops->print_table_header(table);
}
if (found)
printf("\n");
entries = nft_rule_count(h, chain_name, table);
ops->print_header(format, chain_name, policy_name[policy],
&ctrs, basechain, refs);
&ctrs, basechain, refs - entries, entries);
__nft_rule_list(h, chain_name, table,
rulenum, format, ops->print_firewall);
rulenum, format, ops->print_rule);
found = true;
/* we printed the chain we wanted, stop processing. */
if (chain)
break;
found = true;
next:
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
err:
if (chain && !found)
return 0;
return 1;
}
static void
list_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
{
struct iptables_command_state cs = {};
nft_rule_to_iptables_command_state(r, &cs);
nft_rule_print_save(&cs, r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
nft_rule_print_save(r, NFT_RULE_APPEND, format);
}
static int
......@@ -2340,8 +2452,26 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
{
struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
unsigned int format = 0;
struct nftnl_chain *c;
int ret = 1;
int ret = 0;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
nft_xt_builtin_init(h, table);
/* Force table and chain creation, otherwise first iptables -L
* lists no table/chains.
*/
if (!list_empty(&h->obj_list)) {
nft_commit(h);
flush_chain_cache(h, NULL);
}
}
if (!nft_is_table_compatible(h, table)) {
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
return 0;
}
list = nft_chain_dump(h);
......@@ -2354,6 +2484,11 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
if (iter == NULL)
goto err;
if (counters < 0)
format = FMT_C_COUNTS;
else if (counters == 0)
format = FMT_NOCOUNTS;
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
const char *chain_table =
......@@ -2367,7 +2502,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
goto next;
ret = __nft_rule_list(h, chain_name, table, rulenum,
counters ? 0 : FMT_NOCOUNTS, list_save);
format, list_save);
/* we printed the chain we wanted, stop processing. */
if (chain)
......@@ -2456,10 +2591,11 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_TABLE_FLUSH:
nftnl_table_free(o->table);
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO:
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
......@@ -2507,6 +2643,7 @@ static int nft_action(struct nft_handle *h, int action)
n->seq, n->table);
break;
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
NLM_F_CREATE, n->seq,
n->chain);
......@@ -2708,6 +2845,7 @@ const char *nft_strerror(int err)
"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" },
{ nft_chain_set, ENXIO, "Bad table name" },
{ NULL, ELOOP, "Loop found in table" },
{ NULL, EPERM, "Permission denied (you must be root)" },
{ NULL, 0, "Incompatible with this kernel" },
......@@ -2859,7 +2997,7 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
}
int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
const char *table)
const char *table, bool verbose)
{
struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
......@@ -2887,12 +3025,15 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
if (verbose)
fprintf(stdout, "Zeroing chain `%s'\n", chain_name);
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c);
if (chain != NULL)
break;
......@@ -2929,8 +3070,9 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
};
static int nft_is_expr_compatible(const char *name)
static int nft_is_expr_compatible(const struct nftnl_expr *expr)
{
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
int i;
for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) {
......@@ -2938,6 +3080,11 @@ static int nft_is_expr_compatible(const char *name)
return 0;
}
if (!strcmp(name, "limit") &&
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_TYPE) == NFT_LIMIT_PKTS &&
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0)
return 0;
return 1;
}
......@@ -2953,9 +3100,7 @@ static bool nft_is_rule_compatible(struct nftnl_rule *rule)
expr = nftnl_expr_iter_next(iter);
while (expr != NULL) {
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
if (nft_is_expr_compatible(name) == 0) {
if (nft_is_expr_compatible(expr) == 0) {
expr = nftnl_expr_iter_next(iter);
continue;
}
......@@ -3021,7 +3166,12 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename
chain = nftnl_chain_list_iter_next(iter);
while (chain != NULL) {
if (!nft_chain_builtin(chain))
const char *chain_table;
chain_table = nftnl_chain_get_str(chain, NFTNL_CHAIN_TABLE);
if (strcmp(chain_table, tablename) ||
!nft_chain_builtin(chain))
goto next;
ret = nft_is_chain_compatible(h, chain);
......@@ -3041,16 +3191,9 @@ 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, i;
for (i = 0; i < TABLES_MAX; i++) {
if (!h->tables[i].name)
continue;
if (strcmp(h->tables[i].name, tablename) == 0)
break;
}
int ret = 0;
if (i == TABLES_MAX)
if (!nft_table_builtin_find(h, tablename))
return false;
ret = nft_are_chains_compatible(h, tablename);
......@@ -3067,9 +3210,15 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
rule = nftnl_rule_list_iter_next(iter);
while (rule != NULL) {
const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
if (strcmp(table, tablename))
goto next_rule;
ret = nft_is_rule_compatible(rule);
if (ret != 0)
break;
next_rule:
rule = nftnl_rule_list_iter_next(iter);
}
......
......@@ -68,6 +68,7 @@ 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);
struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
/*
* Operations with chains.
......@@ -79,11 +80,13 @@ 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_del(struct nft_handle *h, const char *chain, const char *table, bool verbose);
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);
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose);
struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain);
bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain);
/*
* Operations with rule-set.
......@@ -98,8 +101,8 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain, const char *tab
int nft_rule_replace(struct nft_handle *h, const char *chain, const char *table, void *data, int rulenum, bool verbose);
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, int rulenum, unsigned int format);
int nft_rule_list_save(struct nft_handle *h, const char *chain, const char *table, int rulenum, int counters);
int nft_rule_save(struct nft_handle *h, const char *table, bool counters);
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table);
int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format);
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, bool verbose);
int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *table, int rulenum);
/*
......@@ -119,8 +122,7 @@ enum nft_rule_print {
NFT_RULE_DEL,
};
void nft_rule_print_save(const void *data,
struct nftnl_rule *r, enum nft_rule_print type,
void nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
unsigned int format);
uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);
......@@ -144,9 +146,12 @@ const char *nft_strerror(int err);
/* For xtables.c */
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, bool restore);
/* For xtables-arptables.c */
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table);
int nft_init_arp(struct nft_handle *h, const char *pname);
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, bool restore);
/* For xtables-eb.c */
int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table);
int nft_init_eb(struct nft_handle *h, const char *pname);
int ebt_get_current_chain(const char *chain);
int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table, bool restore);
/*
* Parse config for tables and chain helper functions
......
To run the test suite (as root):
$ cd iptables/tests/shell
# ./run-tests.sh
Test files are executable files with the pattern <<name_N>> , where N is the
expected return code of the executable. Since they are located with `find',
test-files can be spreaded in any sub-directories.
You can turn on a verbose execution by calling:
# ./run-tests.sh -v
And to run test suite for pariticular test files:
# ./run-tests.sh <PATH_OF_TESTFILES>
Also, test-files will receive the environment variable $XT_MULTI which contains
the path to the old iptables (xtables-legacy-multi) or new iptables (xtables-nft-multi)
binary being tested.
......@@ -65,12 +65,12 @@ do_test() {
if [ "$VERBOSE" = "y" ]; then
XT_MULTI=$xtables_multi unshare -n ${testfile}
rc_got=$?
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
fi
if [ "$rc_got" == "$rc_spec" ] ; then
msg_info "[OK] $testfile"
......
#!/bin/bash
set -e
#set -x
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
# fill arptables manually
$XT_MULTI arptables -F
$XT_MULTI arptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
$XT_MULTI arptables -A INPUT -d 192.168.123.1 -j ACCEPT
#$XT_MULTI arptables -A INPUT --source-mac fe:ed:ba:be:00:01 -j ACCEPT
#$XT_MULTI arptables -A INPUT --destination-mac fe:ed:ba:be:00:01 -j ACCEPT
$XT_MULTI arptables -N foo
$XT_MULTI arptables -A foo -i lo -j ACCEPT
$XT_MULTI arptables -A foo -l 6 -j ACCEPT
$XT_MULTI arptables -A foo --opcode Request -j ACCEPT
$XT_MULTI arptables -A foo --h-type 1 --proto-type 0x800 -j ACCEPT
$XT_MULTI arptables -A foo -l 6 --h-type 1 --proto-type 0x800 -i lo --opcode Request -j ACCEPT
$XT_MULTI arptables -A INPUT -j foo
$XT_MULTI arptables -A INPUT
$XT_MULTI arptables -A OUTPUT -o lo -j ACCEPT
$XT_MULTI arptables -A OUTPUT -o eth134 -j mangle --mangle-ip-s 10.0.0.1
$XT_MULTI arptables -A OUTPUT -o eth432 -j CLASSIFY --set-class feed:babe
$XT_MULTI arptables -A OUTPUT -o eth432 --opcode Request -j CLASSIFY --set-class feed:babe
$XT_MULTI arptables -P OUTPUT DROP
# compare against stored arptables dump
DUMP='*filter
:INPUT ACCEPT
:OUTPUT DROP
:foo -
-A INPUT -s 10.0.0.0/8 -j ACCEPT
-A INPUT -d 192.168.123.1 -j ACCEPT
-A INPUT -j foo
-A INPUT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth134 -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -o eth432 -j CLASSIFY --set-class feed:babe
-A OUTPUT -o eth432 --opcode 1 -j CLASSIFY --set-class feed:babe
-A foo -i lo -j ACCEPT
-A foo --h-length 6 -j ACCEPT
-A foo --opcode 1 -j ACCEPT
-A foo --h-type 1 --proto-type 0x800 -j ACCEPT
-A foo -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 -j ACCEPT
'
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save)
# make sure dump can be restored and check it didn't change
$XT_MULTI arptables -F
$XT_MULTI arptables-restore <<<$DUMP
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save)
#!/bin/bash
set -e
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
# arptables-restore reuses preloaded targets and matches, make sure defaults
# apply to consecutive rules using the same target/match as a previous one
DUMP='*filter
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
'
# note how mangle-ip-s is unset in second rule
EXPECT='*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
'
$XT_MULTI arptables -F
$XT_MULTI arptables-restore <<<$DUMP
diff -u <(echo -e "$EXPECT") <($XT_MULTI arptables-save | grep -v '^#')
......@@ -28,6 +28,36 @@ case "$XT_MULTI" in
exit 1
fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in empty unreferenced chain"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -A FORWARD -j FOO
$XT_MULTI ebtables -L FORWARD | grep -q 'entries: 1'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in FORWARD chain"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -L FOO | grep -q 'entries: 0'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in empty referenced chain"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -A FOO -j ACCEPT
$XT_MULTI ebtables -L FOO | grep -q 'entries: 1'
if [ $? -ne 0 ]; then
echo "Unexpected entries count in non-empty referenced chain"
$XT_MULTI ebtables -L
exit 1
fi
$XT_MULTI ebtables -t filter -N BAR || exit 1
$XT_MULTI ebtables -t filter -N BAZ || exit 1
......
#!/bin/bash
set -e
#set -x
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
# fill ebtables manually
$XT_MULTI ebtables --init-table
$XT_MULTI ebtables -A INPUT -p IPv4 -i lo -j ACCEPT
$XT_MULTI ebtables -P FORWARD DROP
$XT_MULTI ebtables -A OUTPUT -s ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff -j DROP
$XT_MULTI ebtables -N foo
$XT_MULTI ebtables -A foo --802_3-sap 0x23 -j ACCEPT
$XT_MULTI ebtables -A foo --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
#$XT_MULTI ebtables -A foo --among-dst fe:ed:ba:be:00:01,fe:ed:ba:be:00:02,fe:ed:ba:be:00:03 -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-gratuitous -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-opcode Request -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-ip-src 10.0.0.1 -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-ip-dst 10.0.0.0/8 -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-mac-src fe:ed:ba:be:00:01 -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-mac-dst fe:ed:ba:be:00:01/ff:ff:ff:00:00:00 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv4 --ip-src 10.0.0.1 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv4 --ip-dst 10.0.0.0/8 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv4 --ip-tos 0x10 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv4 --ip-protocol tcp -j ACCEPT
#$XT_MULTI ebtables -A foo -p IPv4 --ip-sport 23 -j ACCEPT
#$XT_MULTI ebtables -A foo -p IPv4 --ip-dport 1024:4096 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv6 --ip6-src feed:babe::1 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv6 --ip6-dst feed:babe::/64 -j ACCEPT
$XT_MULTI ebtables -A foo -p IPv6 --ip6-proto tcp -j ACCEPT
#$XT_MULTI ebtables -A foo -p IPv6 --ip6-sport 23 -j ACCEPT
#$XT_MULTI ebtables -A foo -p IPv6 --ip6-dport 1024:4096 -j ACCEPT
$XT_MULTI ebtables -A foo --limit 100 --limit-burst 42 -j ACCEPT
$XT_MULTI ebtables -A foo --log
$XT_MULTI ebtables -A foo --mark-set 0x23 --mark-target ACCEPT
$XT_MULTI ebtables -A foo --nflog
$XT_MULTI ebtables -A foo --pkttype-type multicast -j ACCEPT
$XT_MULTI ebtables -A foo --stp-type config -j ACCEPT
#$XT_MULTI ebtables -A foo --vlan-id 42 -j ACCEPT
$XT_MULTI ebtables -A foo --802_3-sap 0x23 --limit 100 -j ACCEPT
$XT_MULTI ebtables -A foo --pkttype-type multicast --log
$XT_MULTI ebtables -A foo --pkttype-type multicast --limit 100 -j ACCEPT
$XT_MULTI ebtables -A FORWARD -j foo
$XT_MULTI ebtables -t nat -A PREROUTING --redirect-target ACCEPT
#$XT_MULTI ebtables -t nat -A PREROUTING --to-src fe:ed:ba:be:00:01
$XT_MULTI ebtables -t nat -A OUTPUT -j ACCEPT
$XT_MULTI ebtables -t nat -P OUTPUT DROP
$XT_MULTI ebtables -t nat -A POSTROUTING -j ACCEPT
#$XT_MULTI ebtables -t nat -A POSTROUTING --to-dst fe:ed:ba:be:00:01 --dnat-target ACCEPT
# compare against stored ebtables dump
DUMP='*filter
:INPUT ACCEPT
:FORWARD DROP
:OUTPUT ACCEPT
:foo ACCEPT
-A INPUT -p IPv4 -i lo -j ACCEPT
-A FORWARD -j foo
-A OUTPUT -s Broadcast -j DROP
-A foo --802_3-sap 0x23 -j ACCEPT
-A foo --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
-A foo -p ARP --arp-gratuitous -j ACCEPT
-A foo -p ARP --arp-op Request -j ACCEPT
-A foo -p ARP --arp-ip-src 10.0.0.1 -j ACCEPT
-A foo -p ARP --arp-ip-dst 10.0.0.0/8 -j ACCEPT
-A foo -p ARP --arp-mac-src fe:ed:ba:be:0:1 -j ACCEPT
-A foo -p ARP --arp-mac-dst fe:ed:ba:0:0:0/ff:ff:ff:0:0:0 -j ACCEPT
-A foo -p IPv4 --ip-src 10.0.0.1 -j ACCEPT
-A foo -p IPv4 --ip-dst 10.0.0.0/8 -j ACCEPT
-A foo -p IPv4 --ip-tos 0x10 -j ACCEPT
-A foo -p IPv4 --ip-proto tcp -j ACCEPT
-A foo -p IPv6 --ip6-src feed:babe::1 -j ACCEPT
-A foo -p IPv6 --ip6-dst feed:babe::/64 -j ACCEPT
-A foo -p IPv6 --ip6-proto tcp -j ACCEPT
-A foo --limit 100/sec --limit-burst 42 -j ACCEPT
-A foo --log-level notice --log-prefix "" -j CONTINUE
-A foo -j mark --mark-set 0x23 --mark-target ACCEPT
-A foo --nflog-group 1 -j CONTINUE
-A foo --pkttype-type multicast -j ACCEPT
-A foo --stp-type config -j ACCEPT
-A foo --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT
-A foo --pkttype-type multicast --log-level notice --log-prefix "" -j CONTINUE
-A foo --pkttype-type multicast --limit 100/sec --limit-burst 5 -j ACCEPT
*nat
:PREROUTING ACCEPT
:OUTPUT DROP
:POSTROUTING ACCEPT
-A PREROUTING -j redirect
-A OUTPUT -j ACCEPT
-A POSTROUTING -j ACCEPT
'
diff -u <(echo -e "$DUMP") <($XT_MULTI ebtables-save | grep -v '^#')
# make sure dump can be restored and check it didn't change
$XT_MULTI ebtables --init-table
$XT_MULTI ebtables-restore <<<$DUMP
diff -u <(echo -e "$DUMP") <($XT_MULTI ebtables-save | grep -v '^#')
#!/bin/bash
set -e
# there is no legacy backend to test
[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
# ebtables-restore reuses preloaded targets and matches, make sure defaults
# apply to consecutive rules using the same target/match as a previous one
DUMP='*filter
:FORWARD ACCEPT
-A FORWARD --limit 100 --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000 -j ACCEPT
-A FORWARD --log --log-prefix "foobar"
-A FORWARD --log
'
# note how limit-burst is 5 in second rule and log-prefix empty in fourth one
EXPECT='*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
-A FORWARD --limit 100/sec --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000/sec --limit-burst 5 -j ACCEPT
-A FORWARD --log-level notice --log-prefix "foobar" -j CONTINUE
-A FORWARD --log-level notice --log-prefix "" -j CONTINUE
'
$XT_MULTI ebtables --init-table
$XT_MULTI ebtables-restore <<<$DUMP
diff -u <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
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