Commit 0309474b authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.2

parent 3bc9369c
......@@ -556,6 +556,9 @@ extern void xtables_save_string(const char *value);
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
extern void xtables_print_num(uint64_t number, unsigned int format);
extern void xtables_print_mac(const unsigned char *macaddress);
extern void xtables_print_mac_and_mask(const unsigned char *mac,
const unsigned char *mask);
extern void xtables_parse_val_mask(struct xt_option_call *cb,
unsigned int *val, unsigned int *mask,
......@@ -624,7 +627,7 @@ extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
/* xlate infrastructure */
struct xt_xlate *xt_xlate_alloc(int size);
void xt_xlate_free(struct xt_xlate *xl);
void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...);
void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment);
const char *xt_xlate_get_comment(struct xt_xlate *xl);
const char *xt_xlate_get(struct xt_xlate *xl);
......
......@@ -137,6 +137,18 @@ static void print_mac_and_mask(const unsigned char *mac, const unsigned char *ma
print_mac(mask, l);
}
static bool need_devaddr(struct arpt_devaddr_info *info)
{
int i;
for (i = 0; i < ETH_ALEN; i++) {
if (info->addr[i] || info->mask[i])
return true;
}
return false;
}
static int nft_arp_add(struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data;
......@@ -154,21 +166,24 @@ static int nft_arp_add(struct nftnl_rule *r, void *data)
add_outiface(r, fw->arp.outiface, op);
}
if (fw->arp.arhrd != 0) {
if (fw->arp.arhrd != 0 ||
fw->arp.invflags & ARPT_INV_ARPHRD) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHRD);
add_payload(r, offsetof(struct arphdr, ar_hrd), 2,
NFT_PAYLOAD_NETWORK_HEADER);
add_cmp_u16(r, fw->arp.arhrd, op);
}
if (fw->arp.arpro != 0) {
if (fw->arp.arpro != 0 ||
fw->arp.invflags & ARPT_INV_ARPPRO) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPPRO);
add_payload(r, offsetof(struct arphdr, ar_pro), 2,
NFT_PAYLOAD_NETWORK_HEADER);
add_cmp_u16(r, fw->arp.arpro, op);
}
if (fw->arp.arhln != 0) {
if (fw->arp.arhln != 0 ||
fw->arp.invflags & ARPT_INV_ARPHLN) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHLN);
add_proto(r, offsetof(struct arphdr, ar_hln), 1,
fw->arp.arhln, op);
......@@ -176,37 +191,46 @@ static int nft_arp_add(struct nftnl_rule *r, void *data)
add_proto(r, offsetof(struct arphdr, ar_pln), 1, 4, NFT_CMP_EQ);
if (fw->arp.arpop != 0) {
if (fw->arp.arpop != 0 ||
fw->arp.invflags & ARPT_INV_ARPOP) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPOP);
add_payload(r, offsetof(struct arphdr, ar_op), 2,
NFT_PAYLOAD_NETWORK_HEADER);
add_cmp_u16(r, fw->arp.arpop, op);
}
if (fw->arp.src_devaddr.addr[0] != '\0') {
if (need_devaddr(&fw->arp.src_devaddr)) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR);
add_payload(r, sizeof(struct arphdr), fw->arp.arhln,
NFT_PAYLOAD_NETWORK_HEADER);
add_cmp_ptr(r, op, fw->arp.src_devaddr.addr, fw->arp.arhln);
add_addr(r, sizeof(struct arphdr),
&fw->arp.src_devaddr.addr,
&fw->arp.src_devaddr.mask,
fw->arp.arhln, op);
}
if (fw->arp.src.s_addr != 0) {
if (fw->arp.src.s_addr != 0 ||
fw->arp.smsk.s_addr != 0 ||
fw->arp.invflags & ARPT_INV_SRCIP) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP);
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln,
&fw->arp.src.s_addr, &fw->arp.smsk.s_addr,
sizeof(struct in_addr), op);
}
if (fw->arp.tgt_devaddr.addr[0] != '\0') {
if (need_devaddr(&fw->arp.tgt_devaddr)) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTDEVADDR);
add_payload(r, sizeof(struct arphdr) + fw->arp.arhln + 4,
fw->arp.arhln, NFT_PAYLOAD_NETWORK_HEADER);
add_cmp_ptr(r, op, fw->arp.tgt_devaddr.addr, fw->arp.arhln);
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
&fw->arp.tgt_devaddr.addr,
&fw->arp.tgt_devaddr.mask,
fw->arp.arhln, op);
}
if (fw->arp.tgt.s_addr != 0) {
if (fw->arp.tgt.s_addr != 0 ||
fw->arp.tmsk.s_addr != 0 ||
fw->arp.invflags & ARPT_INV_TGTIP) {
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
&fw->arp.tgt.s_addr, &fw->arp.tmsk.s_addr,
sizeof(struct in_addr), op);
}
......@@ -284,6 +308,30 @@ static void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask)
mask->s_addr = ctx->bitwise.mask[0];
}
static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
struct nftnl_expr *e,
struct arpt_devaddr_info *info)
{
uint32_t hlen;
bool inv;
nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &hlen);
if (hlen != ETH_ALEN)
return false;
get_cmp_data(e, info->addr, ETH_ALEN, &inv);
if (ctx->flags & NFT_XT_CTX_BITWISE) {
memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
ctx->flags &= ~NFT_XT_CTX_BITWISE;
} else {
memset(info->mask, 0xff, ETH_ALEN);
}
return inv;
}
static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
struct nftnl_expr *e, void *data)
{
......@@ -323,7 +371,10 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
fw->arp.invflags |= ARPT_INV_ARPOP;
break;
default:
if (ctx->payload.offset == sizeof(struct arphdr) +
if (ctx->payload.offset == sizeof(struct arphdr)) {
if (nft_arp_parse_devaddr(ctx, e, &fw->arp.src_devaddr))
fw->arp.invflags |= ARPT_INV_SRCDEVADDR;
} else if (ctx->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln) {
get_cmp_data(e, &addr, sizeof(addr), &inv);
fw->arp.src.s_addr = addr.s_addr;
......@@ -339,6 +390,12 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
} else if (ctx->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln +
sizeof(struct in_addr)) {
if (nft_arp_parse_devaddr(ctx, e, &fw->arp.tgt_devaddr))
fw->arp.invflags |= ARPT_INV_TGTDEVADDR;
} else if (ctx->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln +
sizeof(struct in_addr) +
fw->arp.arhln) {
get_cmp_data(e, &addr, sizeof(addr), &inv);
fw->arp.tgt.s_addr = addr.s_addr;
if (ctx->flags & NFT_XT_CTX_BITWISE) {
......@@ -570,37 +627,35 @@ after_devdst:
}
}
static void nft_arp_save_counters(const void *data)
{
const struct iptables_command_state *cs = data;
printf("[%llu:%llu] ", (unsigned long long)cs->arp.counters.pcnt,
(unsigned long long)cs->arp.counters.bcnt);
}
static void
__nft_arp_save_rule(const void *data, unsigned int format)
nft_arp_save_rule(const void *data, unsigned int format)
{
const struct iptables_command_state *cs = data;
format |= FMT_NUMERIC;
nft_arp_print_rule_details(&cs->arp, 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->arp, cs->target->t, format & FMT_NUMERIC);
}
if (!(format & FMT_NOCOUNTS)) {
printf(", pcnt=");
xtables_print_num(cs->arp.counters.pcnt, format);
printf("-- bcnt=");
xtables_print_num(cs->arp.counters.bcnt, format);
if (cs->target->save != NULL)
cs->target->save(&cs->arp, cs->target->t);
}
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)
{
......@@ -610,7 +665,25 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
printf("%u ", num);
nft_arp_rule_to_cs(r, &cs);
__nft_arp_save_rule(&cs, format);
nft_arp_print_rule_details(&cs.arp, 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.arp, cs.target->t, format & FMT_NUMERIC);
}
if (!(format & FMT_NOCOUNTS)) {
printf(", pcnt=");
xtables_print_num(cs.arp.counters.pcnt, format);
printf("-- bcnt=");
xtables_print_num(cs.arp.counters.bcnt, format);
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
static bool nft_arp_is_same(const void *data_a,
......@@ -621,7 +694,8 @@ static bool nft_arp_is_same(const void *data_a,
if (a->arp.src.s_addr != b->arp.src.s_addr
|| a->arp.tgt.s_addr != b->arp.tgt.s_addr
|| a->arp.smsk.s_addr != b->arp.tmsk.s_addr
|| a->arp.smsk.s_addr != b->arp.smsk.s_addr
|| a->arp.tmsk.s_addr != b->arp.tmsk.s_addr
|| a->arp.arpro != b->arp.arpro
|| a->arp.flags != b->arp.flags
|| a->arp.invflags != b->arp.invflags) {
......@@ -677,7 +751,7 @@ struct nft_family_ops nft_family_ops_arp = {
.print_header = nft_arp_print_header,
.print_rule = nft_arp_print_rule,
.save_rule = nft_arp_save_rule,
.save_counters = NULL,
.save_counters = nft_arp_save_counters,
.save_chain = nft_arp_save_chain,
.post_parse = NULL,
.rule_to_cs = nft_arp_rule_to_cs,
......
......@@ -21,6 +21,8 @@
#include "nft-bridge.h"
#include "nft.h"
static bool ebt_legacy_counter_fmt;
void ebt_cs_clean(struct iptables_command_state *cs)
{
struct ebt_match *m, *nm;
......@@ -45,21 +47,12 @@ void ebt_cs_clean(struct iptables_command_state *cs)
}
}
/* 0: default, print only 2 digits if necessary
* 2: always print 2 digits, a printed mac address
* then always has the same length
*/
int ebt_printstyle_mac;
static void ebt_print_mac(const unsigned char *mac)
{
if (ebt_printstyle_mac == 2) {
int j;
for (j = 0; j < ETH_ALEN; j++)
printf("%02x%s", mac[j],
(j==ETH_ALEN-1) ? "" : ":");
} else
printf("%s", ether_ntoa((struct ether_addr *) mac));
printf("%02x%s", mac[j], (j==ETH_ALEN-1) ? "" : ":");
}
static bool mac_all_ones(const unsigned char *mac)
......@@ -120,33 +113,9 @@ static void add_logical_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
add_cmp_ptr(r, op, iface, iface_len + 1);
}
/* TODO: Use generic add_action() once we convert this to use
* iptables_command_state.
*/
static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
{
int ret = 0;
if (cs->jumpto == NULL || strcmp(cs->jumpto, "CONTINUE") == 0)
return 0;
/* If no target at all, add nothing (default to continue) */
if (cs->target != NULL) {
/* Standard target? */
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
ret = add_verdict(r, NF_ACCEPT);
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
ret = add_verdict(r, NF_DROP);
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
ret = add_verdict(r, NFT_RETURN);
else
ret = add_target(r, cs->target->t);
} else if (strlen(cs->jumpto) > 0) {
/* Not standard, then it's a jump to chain */
ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
}
return ret;
return add_action(r, cs, false);
}
static int nft_bridge_add(struct nftnl_rule *r, void *data)
......@@ -410,9 +379,9 @@ static void print_mac(char option, const unsigned char *mac,
const unsigned char *mask,
bool invert)
{
printf("-%c ", option);
if (invert)
printf("! ");
printf("-%c ", option);
ebt_print_mac_and_mask(mac, mask);
printf(" ");
}
......@@ -427,9 +396,9 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
if (bitmask & EBT_NOPROTO)
return;
printf("-p ");
if (invert)
printf("! ");
printf("-p ");
if (bitmask & EBT_802_3) {
printf("length ");
......@@ -443,6 +412,22 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
printf("%s ", ent->e_name);
}
static void nft_bridge_save_counters(const void *data)
{
const char *ctr;
if (ebt_legacy_counter_fmt)
return;
ctr = getenv("EBTABLES_SAVE_COUNTER");
if (ctr) {
ebt_legacy_counter_fmt = true;
return;
}
save_counters(data);
}
static void nft_bridge_save_rule(const void *data, unsigned int format)
{
const struct iptables_command_state *cs = data;
......@@ -479,18 +464,10 @@ static void nft_bridge_save_rule(const void *data, unsigned int format)
cs->target->print(&cs->fw, cs->target->t, format & FMT_NUMERIC);
}
if (!(format & FMT_NOCOUNTS)) {
const char *counter_fmt;
if (format & FMT_EBT_SAVE)
counter_fmt = " -c %"PRIu64" %"PRIu64"";
else
counter_fmt = " , pcnt = %"PRIu64" -- bcnt = %"PRIu64"";
printf(counter_fmt,
printf(" -c %"PRIu64" %"PRIu64"",
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
......@@ -505,7 +482,11 @@ static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num,
printf("%d ", num);
nft_rule_to_ebtables_command_state(r, &cs);
nft_bridge_save_rule(&cs, format);
nft_bridge_save_rule(&cs, format & ~FMT_EBT_SAVE);
if (!(format & FMT_NOCOUNTS))
printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
(uint64_t)cs.counters.pcnt,
(uint64_t)cs.counters.bcnt);
ebt_cs_clean(&cs);
}
......@@ -767,7 +748,7 @@ struct nft_family_ops nft_family_ops_bridge = {
.print_header = nft_bridge_print_header,
.print_rule = nft_bridge_print_rule,
.save_rule = nft_bridge_save_rule,
.save_counters = NULL,
.save_counters = nft_bridge_save_counters,
.save_chain = nft_bridge_save_chain,
.post_parse = NULL,
.rule_to_cs = nft_rule_to_ebtables_command_state,
......
......@@ -68,6 +68,7 @@ int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mas
#define EBT_VERDICT_BITS 0x0000000F
struct nftnl_rule;
struct iptables_command_state;
static const char *ebt_standard_targets[NUM_STANDARD_TARGETS] = {
"ACCEPT",
......
......@@ -48,13 +48,13 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
add_l4proto(r, cs->fw.ip.proto, op);
}
if (cs->fw.ip.src.s_addr != 0) {
if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
add_addr(r, offsetof(struct iphdr, saddr),
&cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
sizeof(struct in_addr), op);
}
if (cs->fw.ip.dst.s_addr != 0) {
if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
add_addr(r, offsetof(struct iphdr, daddr),
&cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
......@@ -64,7 +64,7 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
add_payload(r, offsetof(struct iphdr, frag_off), 2,
NFT_PAYLOAD_NETWORK_HEADER);
/* get the 13 bits that contain the fragment offset */
add_bitwise_u16(r, 0x1fff, 0);
add_bitwise_u16(r, htons(0x1fff), 0);
/* if offset is non-zero, this is a fragment */
op = NFT_CMP_NEQ;
......
......@@ -47,13 +47,17 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data)
add_l4proto(r, cs->fw6.ipv6.proto, op);
}
if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)) {
if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src) ||
!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.smsk) ||
(cs->fw6.ipv6.invflags & IPT_INV_SRCIP)) {
op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_SRCIP);
add_addr(r, offsetof(struct ip6_hdr, ip6_src),
&cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
sizeof(struct in6_addr), op);
}
if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)) {
if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst) ||
!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dmsk) ||
(cs->fw6.ipv6.invflags & IPT_INV_DSTIP)) {
op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_DSTIP);
add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
&cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
......@@ -235,7 +239,7 @@ static void save_ipv6_addr(char letter, const struct in6_addr *addr,
return;
printf("%s-%c %s",
invert ? " !" : "", letter,
invert ? "! " : "", letter,
inet_ntop(AF_INET6, addr, addr_str, sizeof(addr_str)));
if (l == -1)
......
......@@ -249,7 +249,7 @@ static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned
return;
dst[len++] = 0;
if (mask)
memset(mask, 0xff, len + 1);
memset(mask, 0xff, len - 2);
}
int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
......
......@@ -233,6 +233,7 @@ struct nft_xt_cmd_parse {
const char *policy;
bool restore;
int verbose;
bool xlate;
};
void do_parse(struct nft_handle *h, int argc, char *argv[],
......
......@@ -290,6 +290,7 @@ static int mnl_append_error(const struct nft_handle *h,
[NFT_COMPAT_CHAIN_USER_FLUSH] = "CHAIN_USER_FLUSH",
[NFT_COMPAT_CHAIN_UPDATE] = "CHAIN_UPDATE",
[NFT_COMPAT_CHAIN_RENAME] = "CHAIN_RENAME",
[NFT_COMPAT_CHAIN_ZERO] = "CHAIN_ZERO",
[NFT_COMPAT_RULE_APPEND] = "RULE_APPEND",
[NFT_COMPAT_RULE_INSERT] = "RULE_INSERT",
[NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE",
......@@ -375,8 +376,8 @@ static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
return batch_add(h, type, r);
}
struct builtin_table xtables_ipv4[TABLES_MAX] = {
[RAW] = {
struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
[NFT_TABLE_RAW] = {
.name = "raw",
.chains = {
{
......@@ -393,7 +394,7 @@ struct builtin_table xtables_ipv4[TABLES_MAX] = {
},
},
},
[MANGLE] = {
[NFT_TABLE_MANGLE] = {
.name = "mangle",
.chains = {
{
......@@ -428,7 +429,7 @@ struct builtin_table xtables_ipv4[TABLES_MAX] = {
},
},
},
[FILTER] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
.chains = {
{
......@@ -451,7 +452,7 @@ struct builtin_table xtables_ipv4[TABLES_MAX] = {
},
},
},
[SECURITY] = {
[NFT_TABLE_SECURITY] = {
.name = "security",
.chains = {
{
......@@ -474,7 +475,7 @@ struct builtin_table xtables_ipv4[TABLES_MAX] = {
},
},
},
[NAT] = {
[NFT_TABLE_NAT] = {
.name = "nat",
.chains = {
{
......@@ -507,8 +508,8 @@ struct builtin_table xtables_ipv4[TABLES_MAX] = {
#include <linux/netfilter_arp.h>
struct builtin_table xtables_arp[TABLES_MAX] = {
[FILTER] = {
struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
.chains = {
{
......@@ -529,8 +530,8 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
#include <linux/netfilter_bridge.h>
struct builtin_table xtables_bridge[TABLES_MAX] = {
[FILTER] = {
struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
.chains = {
{
......@@ -553,7 +554,7 @@ struct builtin_table xtables_bridge[TABLES_MAX] = {
},
},
},
[NAT] = {
[NFT_TABLE_NAT] = {
.name = "nat",
.chains = {
{
......@@ -638,7 +639,7 @@ nft_table_builtin_find(struct nft_handle *h, const char *table)
int i;
bool found = false;
for (i=0; i<TABLES_MAX; i++) {
for (i = 0; i < NFT_TABLE_MAX; i++) {
if (h->tables[i].name == NULL)
continue;
......@@ -672,9 +673,9 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain)
static void nft_chain_builtin_init(struct nft_handle *h,
struct builtin_table *table)
{
int i;
struct nftnl_chain_list *list = nft_chain_dump(h);
struct nftnl_chain_list *list = nft_chain_list_get(h);
struct nftnl_chain *c;
int i;
/* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
......@@ -1289,7 +1290,7 @@ err:
return MNL_CB_OK;
}
static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h)
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
......@@ -1320,11 +1321,6 @@ retry:
return list;
}
struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h)
{
return nftnl_chain_list_get(h);
}
static const char *policy_name[NF_ACCEPT+1] = {
[NF_DROP] = "DROP",
[NF_ACCEPT] = "ACCEPT",
......@@ -1533,7 +1529,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
nft_fn = nft_rule_flush;
list = nftnl_chain_list_get(h);
list = nft_chain_list_get(h);
if (list == NULL) {
ret = 1;
goto err;
......@@ -1595,7 +1591,7 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
nft_chain_dump(h);
nft_chain_list_get(h);
nftnl_chain_list_add(c, h->chain_cache);
......@@ -1619,7 +1615,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
nft_fn = nft_chain_user_del;
list = nftnl_chain_list_get(h);
list = nft_chain_list_get(h);
if (list == NULL)
goto err;
......@@ -1712,7 +1708,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{
struct nftnl_chain_list *list;
list = nftnl_chain_list_get(h);
list = nft_chain_list_get(h);
if (list == NULL)
return NULL;
......@@ -1754,14 +1750,14 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
c = nft_chain_find(h, table, chain);
if (c == NULL) {
errno = ENOENT;
return -1;
return 0;
}
handle = nftnl_chain_get_u64(c, NFTNL_CHAIN_HANDLE);
/* Now prepare the new name for the chain */
c = nftnl_chain_alloc();
if (c == NULL)
return -1;
return 0;
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname);
......@@ -2328,7 +2324,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
return 1;
}
list = nft_chain_dump(h);
list = nft_chain_list_get(h);
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
......@@ -2473,7 +2469,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
return 0;
}
list = nft_chain_dump(h);
list = nft_chain_list_get(h);
/* Dump policies and custom chains first */
if (!rulenum)
......@@ -2996,6 +2992,78 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
return h->config_done;
}
static void nft_chain_zero_rule_counters(struct nft_handle *h,
struct nftnl_chain *c)
{
struct nftnl_rule_list_iter *iter;
struct nftnl_rule_list *list;
const char *table_name;
const char *chain_name;
struct nftnl_rule *r;
list = nft_rule_list_get(h);
if (list == NULL)
return;
iter = nftnl_rule_list_iter_create(list);
if (iter == NULL)
return;
table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
r = nftnl_rule_list_iter_next(iter);
while (r != NULL) {
struct nftnl_expr_iter *ei;
const char *table_chain;
const char *rule_chain;
struct nftnl_expr *e;
bool zero_needed;
table_chain = nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
if (strcmp(table_chain, table_name))
goto next;
rule_chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
if (strcmp(rule_chain, chain_name))
goto next;
ei = nftnl_expr_iter_create(r);
if (!ei)
break;
e = nftnl_expr_iter_next(ei);
zero_needed = false;
while (e != NULL) {
const char *en = nftnl_expr_get_str(e, NFTNL_EXPR_NAME);
if (strcmp(en, "counter") == 0 && (
nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS) ||
nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES))) {
nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_PACKETS, 0);
nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_BYTES, 0);
zero_needed = true;
}
e = nftnl_expr_iter_next(ei);
}
nftnl_expr_iter_destroy(ei);
if (zero_needed) {
/*
* Unset RULE_POSITION for older kernels, we want to replace
* rule based on its handle only.
*/
nftnl_rule_unset(r, NFTNL_RULE_POSITION);
batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
}
next:
r = nftnl_rule_list_iter_next(iter);
}
nftnl_rule_list_iter_destroy(iter);
}
int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
const char *table, bool verbose)
{
......@@ -3004,7 +3072,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 0;
list = nftnl_chain_list_get(h);
list = nft_chain_list_get(h);
if (list == NULL)
goto err;
......@@ -3028,8 +3096,13 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
if (verbose)
fprintf(stdout, "Zeroing chain `%s'\n", chain_name);
if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
/* zero base chain counters. */
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
}
nft_chain_zero_rule_counters(h, c);
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
......@@ -3127,7 +3200,7 @@ static int nft_is_chain_compatible(const struct nft_handle *h,
prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
for (i = 0; i < TABLES_MAX; i++) {
for (i = 0; i < NFT_TABLE_MAX; i++) {
cur_table = h->tables[i].name;
chains = h->tables[i].chains;
......@@ -3156,7 +3229,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename
struct nftnl_chain *chain;
int ret = 0;
list = nftnl_chain_list_get(h);
list = nft_chain_list_get(h);
if (list == NULL)
return -1;
......
......@@ -5,12 +5,14 @@
#include "nft-shared.h"
#include <libiptc/linux_list.h>
#define FILTER 0
#define MANGLE 1
#define RAW 2
#define SECURITY 3
#define NAT 4
#define TABLES_MAX 5
enum nft_table_type {
NFT_TABLE_FILTER = 0,
NFT_TABLE_MANGLE,
NFT_TABLE_RAW,
NFT_TABLE_SECURITY,
NFT_TABLE_NAT,
};
#define NFT_TABLE_MAX (NFT_TABLE_NAT + 1)
struct builtin_chain {
const char *name;
......@@ -47,9 +49,9 @@ struct nft_handle {
} error;
};
extern struct builtin_table xtables_ipv4[TABLES_MAX];
extern struct builtin_table xtables_arp[TABLES_MAX];
extern struct builtin_table xtables_bridge[TABLES_MAX];
extern struct builtin_table xtables_ipv4[NFT_TABLE_MAX];
extern struct builtin_table xtables_arp[NFT_TABLE_MAX];
extern struct builtin_table xtables_bridge[NFT_TABLE_MAX];
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int (*cb)(const struct nlmsghdr *nlh, void *data),
......@@ -76,7 +78,7 @@ struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *t
struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h);
struct nftnl_chain_list *nft_chain_list_get(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);
......
......@@ -11,11 +11,12 @@ set -e
$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 -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 -j MARK --set-mark 12345
$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
......@@ -34,18 +35,21 @@ 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 INPUT -s 10.0.0.0/8 --h-length 6 --h-type 1 -j ACCEPT
-A INPUT -d 192.168.123.1 --h-length 6 --h-type 1 -j ACCEPT
-A INPUT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT
-A INPUT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT
-A INPUT --h-length 6 --h-type 1 -j foo
-A INPUT --h-length 6 --h-type 1
-A OUTPUT -o lo --h-length 6 --h-type 1 -j ACCEPT
-A OUTPUT -o eth134 --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -o eth432 --h-length 6 --h-type 1 -j CLASSIFY --set-class feed:babe
-A OUTPUT -o eth432 --h-length 6 --opcode 1 --h-type 1 -j CLASSIFY --set-class feed:babe
-A foo -i lo --h-length 6 --h-type 1 -j ACCEPT
-A foo --h-length 6 --h-type 1 -j ACCEPT
-A foo --h-length 6 --h-type 1 -j MARK --set-xmark 0x3039/0xffffffff
-A foo --h-length 6 --opcode 1 --h-type 1 -j ACCEPT
-A foo --h-length 6 --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
'
......
......@@ -11,7 +11,7 @@ set -e
DUMP='*filter
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
-A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2
'
# note how mangle-ip-s is unset in second rule
......@@ -19,8 +19,8 @@ DUMP='*filter
EXPECT='*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
-A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1
-A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2
'
$XT_MULTI arptables -F
......
......@@ -75,8 +75,8 @@ DUMP='*filter
-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 ARP --arp-mac-src fe:ed:ba:be:00:01 -j ACCEPT
-A foo -p ARP --arp-mac-dst fe:ed:ba:00:00:00/ff:ff:ff:00:00:00 -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
......
......@@ -23,6 +23,10 @@ cmd 1 iptables -N foo
# iptables-nft allows this - bug or feature?
#cmd 2 iptables -N "invalid name"
# test chain rename
cmd 0 iptables -E foo bar
cmd 1 iptables -E foo bar
# test rule adding
cmd 0 iptables -A INPUT -j ACCEPT
cmd 1 iptables -A noexist -j ACCEPT
......
......@@ -208,9 +208,6 @@ static int inverse_for_options[NUMBER_OF_OPT] =
/* -c */ 0,
};
const char *program_version = XTABLES_VERSION;
const char *program_name = "arptables";
/* A few hardcoded protocols for 'all' and in case the user has no
/etc/protocols */
struct pprot {
......@@ -233,12 +230,12 @@ struct pprot {
/* ARPTABLES SPECIFIC NEW FUNCTIONS ADDED HERE */
/***********************************************/
unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
static unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
static unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
static unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
static unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
static unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
static unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
/*
* put the mac address into 6 (ETH_ALEN) bytes
......@@ -406,7 +403,8 @@ static void
exit_tryhelp(int status)
{
fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
program_name, program_name );
arptables_globals.program_name,
arptables_globals.program_version);
exit(status);
}
......@@ -425,10 +423,16 @@ exit_printhelp(void)
" %s -E old-chain-name new-chain-name\n"
" %s -P chain target [options]\n"
" %s -h (print this help information)\n\n",
program_name, program_version, program_name, program_name,
program_name, program_name, program_name, program_name,
program_name, program_name);
arptables_globals.program_name,
arptables_globals.program_version,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name);
printf(
"Commands:\n"
"Either long or short options are allowed.\n"
......@@ -905,6 +909,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
{
struct iptables_command_state cs = {
.jumpto = "",
.arp.arp.arhln = 6,
.arp.arp.arhrd = htons(ARPHRD_ETHER),
};
int invert = 0;
unsigned int nsaddrs = 0, ndaddrs = 0;
......@@ -1104,18 +1110,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
break;
case 8:/* protocol length */
case 8: /* was never supported, not even in arptables-legacy */
xtables_error(PARAMETER_PROBLEM, "not supported");
/*
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_P_LENGTH, &cs.arp.arp.invflags,
invert);
getlength_and_mask(argv[optind - 1], &cs.arp.arp.arpln,
&cs.arp.arp.arpln_mask);
break;
*/
case 4:/* opcode */
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_OPCODE, &cs.arp.arp.invflags,
......@@ -1170,7 +1166,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
parse_interface(argv[optind-1],
cs.arp.arp.iniface,
cs.arp.arp.iniface_mask);
/* cs.arp.nfcache |= NFC_IP_IF_IN; */
break;
case 'o':
......@@ -1180,7 +1175,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
parse_interface(argv[optind-1],
cs.arp.arp.outiface,
cs.arp.arp.outiface_mask);
/* cs.arp.nfcache |= NFC_IP_IF_OUT; */
break;
case 'v':
......@@ -1190,24 +1184,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
verbose++;
break;
case 'm': /*{
size_t size;
if (invert)
exit_error(PARAMETER_PROBLEM,
"unexpected ! flag before --match");
m = find_match(optarg, LOAD_MUST_SUCCEED);
size = ARPT_ALIGN(sizeof(struct arpt_entry_match))
+ m->size;
m->m = fw_calloc(1, size);
m->m->u.match_size = size;
strcpy(m->m->u.user.name, m->name);
m->init(m->m, &fw.nfcache);
opts = merge_options(opts, m->extra_opts, &m->option_offset);
}*/
case 'm': /* ignored by arptables-legacy */
break;
case 'n':
set_option(&options, OPT_NUMERIC, &cs.arp.arp.invflags,
invert);
......@@ -1217,15 +1195,19 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
if (invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --table");
*table = argv[optind-1];
/* ignore this option.
* arptables-legacy parses it, but libarptc doesn't use it.
* arptables only has a 'filter' table anyway.
*/
break;
case 'V':
if (invert)
printf("Not %s ;-)\n", program_version);
printf("Not %s ;-)\n", arptables_globals.program_version);
else
printf("%s v%s (nf_tables)\n",
program_name, program_version);
arptables_globals.program_name,
arptables_globals.program_version);
exit(0);
case '0':
......
......@@ -655,6 +655,7 @@ void ebt_load_match_extensions(void)
ebt_load_target("mark");
ebt_load_target("dnat");
ebt_load_target("snat");
ebt_load_target("arpreply");
ebt_load_target("redirect");
ebt_load_target("standard");
}
......@@ -824,6 +825,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
struct xtables_target *t;
struct iptables_command_state cs = {
.argv = argv,
.jumpto = "",
.eb.bitmask = EBT_NOPROTO,
};
char command = 'h';
......@@ -999,9 +1001,6 @@ print_zero:
}
break;
case 't': /* Table */
if (OPT_COMMANDS)
xtables_error(PARAMETER_PROBLEM,
"Please put the -t option first");
ebt_check_option2(&flags, OPT_TABLE);
if (strlen(optarg) > EBT_TABLE_MAXNAMELEN - 1)
xtables_error(PARAMETER_PROBLEM,
......@@ -1066,8 +1065,10 @@ print_zero:
break;
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
if (strcmp(optarg, "CONTINUE") != 0) {
cs.jumpto = parse_target(optarg);
cs.target = ebt_command_jump(cs.jumpto);
}
break;
} else if (c == 's') {
ebt_check_option2(&flags, OPT_SOURCE);
......
......@@ -60,7 +60,7 @@ static struct nftnl_chain_list *get_chain_list(struct nft_handle *h)
{
struct nftnl_chain_list *chain_list;
chain_list = nft_chain_dump(h);
chain_list = nft_chain_list_get(h);
if (chain_list == NULL)
xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
......
......@@ -43,6 +43,23 @@ static const struct option options[] = {
{NULL},
};
static const struct option arp_save_options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
{NULL},
};
static const struct option ebt_save_options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
{.name = "table", .has_arg = true, .val = 't'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
{NULL},
};
static bool ebt_legacy_counter_format;
static int
__do_output(struct nft_handle *h, const char *tablename, bool counters)
{
......@@ -56,7 +73,7 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters)
return 0;
}
chain_list = nft_chain_dump(h);
chain_list = nft_chain_list_get(h);
time_t now = time(NULL);
......@@ -226,6 +243,7 @@ int xtables_ip6_save_main(int argc, char *argv[])
static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters)
{
struct nftnl_chain_list *chain_list;
unsigned int format = FMT_NOCOUNTS;
static bool first = true;
time_t now;
......@@ -239,7 +257,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters
return 0;
}
chain_list = nft_chain_dump(h);
chain_list = nft_chain_list_get(h);
if (first) {
now = time(NULL);
......@@ -249,25 +267,40 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters
}
printf("*%s\n", tablename);
if (counters)
format = ebt_legacy_counter_format ? FMT_EBT_SAVE : 0;
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list, tablename);
nft_rule_save(h, tablename,
FMT_EBT_SAVE | (counters ? 0 : FMT_NOCOUNTS));
nft_rule_save(h, tablename, format);
printf("\n");
return 0;
}
static int ebt_save(struct nft_handle *h, const char *tablename, bool counters)
{
if (!tablename)
return nft_for_each_table(h, __ebt_save, counters);
return __ebt_save(h, tablename, counters);
}
int xtables_eb_save_main(int argc_, char *argv_[])
{
const char *ctr = getenv("EBTABLES_SAVE_COUNTER");
const char *tablename = NULL;
struct nft_handle h = {
.family = NFPROTO_BRIDGE,
};
int c;
if (ctr && strcmp(ctr, "yes"))
ctr = NULL;
if (ctr) {
if (strcmp(ctr, "yes") == 0) {
ebt_legacy_counter_format = true;
show_counters = true;
}
}
xtables_globals.program_name = "ebtables-save";
c = xtables_init_all(&xtables_globals, h.family);
......@@ -278,6 +311,30 @@ int xtables_eb_save_main(int argc_, char *argv_[])
exit(1);
}
while ((c = getopt_long(argc_, argv_, "ct:M:V", ebt_save_options, NULL)) != -1) {
switch (c) {
case 'c':
unsetenv("EBTABLES_SAVE_COUNTER");
show_counters = true;
ebt_legacy_counter_format = false;
break;
case 't':
/* Select specific table. */
tablename = optarg;
break;
case 'M':
xtables_modprobe_program = optarg;
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
default:
fprintf(stderr,
"Look at manual page `xtables-save.8' for more information.\n");
exit(1);
}
}
if (nft_init(&h, xtables_bridge) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
......@@ -286,7 +343,7 @@ int xtables_eb_save_main(int argc_, char *argv_[])
exit(EXIT_FAILURE);
}
nft_for_each_table(&h, __ebt_save, !!ctr);
ebt_save(&h, tablename, show_counters);
nft_fini(&h);
return 0;
}
......@@ -307,6 +364,24 @@ int xtables_arp_save_main(int argc, char **argv)
exit(1);
}
while ((c = getopt_long(argc, argv, "cM:V", arp_save_options, NULL)) != -1) {
switch (c) {
case 'c':
show_counters = true;
break;
case 'M':
xtables_modprobe_program = optarg;
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
default:
fprintf(stderr,
"Look at manual page `xtables-save.8' for more information.\n");
exit(1);
}
}
if (nft_init(&h, xtables_arp) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
......@@ -324,8 +399,8 @@ int xtables_arp_save_main(int argc, char **argv)
}
printf("*filter\n");
nft_chain_save(&h, nft_chain_dump(&h), "filter");
nft_rule_save(&h, "filter", FMT_NOCOUNTS);
nft_chain_save(&h, nft_chain_list_get(&h), "filter");
nft_rule_save(&h, "filter", show_counters ? 0 : FMT_NOCOUNTS);
printf("\n");
nft_fini(&h);
return 0;
......
......@@ -216,6 +216,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
struct nft_xt_cmd_parse p = {
.table = *table,
.restore = restore,
.xlate = true,
};
struct iptables_command_state cs;
struct xtables_args args = {
......
......@@ -1040,6 +1040,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
if (p->command == CMD_APPEND ||
p->command == CMD_DELETE ||
p->command == CMD_DELETE_NUM ||
p->command == CMD_CHECK ||
p->command == CMD_INSERT ||
p->command == CMD_REPLACE) {
......@@ -1063,16 +1064,16 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
p->chain);
}
if (!nft_chain_exists(h, p->table, p->chain))
if (!p->xlate && !nft_chain_exists(h, p->table, p->chain))
xtables_error(OTHER_PROBLEM,
"Chain '%s' does not exist", cs->jumpto);
"Chain '%s' does not exist", p->chain);
if (!cs->target && strlen(cs->jumpto) > 0 &&
if (!p->xlate && !cs->target && strlen(cs->jumpto) > 0 &&
!nft_chain_exists(h, p->table, cs->jumpto))
xtables_error(PARAMETER_PROBLEM,
"Chain '%s' does not exist", cs->jumpto);
}
if (p->command == CMD_NEW_CHAIN &&
if (!p->xlate && p->command == CMD_NEW_CHAIN &&
nft_chain_exists(h, p->table, p->chain))
xtables_error(OTHER_PROBLEM, "Chain already exists");
}
......
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