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;
......
This diff is collapsed.
......@@ -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