aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Żenczykowski <maze@google.com>2020-04-08 07:13:35 -0700
committerMaciej Żenczykowski <maze@google.com>2020-04-08 07:13:46 -0700
commitea80eaf31e509bdd4d0e05ccd652b8f9e4896842 (patch)
treea49ad639f248dbfec523b80a54cd31a5a335539c
parent65a64d8480b9d2bb78feb93e744756839d713f4e (diff)
parentbba6bc692b0e6137e13881a1f398c134822e9f83 (diff)
downloadiptables-ea80eaf31e509bdd4d0e05ccd652b8f9e4896842.tar.gz
Merge tag 'v1.8.2' of git://git.netfilter.org/iptables into work
iptables 1.8.2 release Generated via: git fetch git://git.netfilter.org/iptables v1.8.2 git merge FETCH_HEAD Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: I6216c80e1d8b2dc86b580cf77dbfd19396ebd71c
-rw-r--r--configure.ac6
-rw-r--r--extensions/iptables.t6
-rw-r--r--extensions/libarpt_CLASSIFY.t4
-rw-r--r--extensions/libarpt_MARK.t4
-rw-r--r--extensions/libarpt_mangle.c6
-rw-r--r--extensions/libarpt_mangle.t5
-rw-r--r--extensions/libarpt_standard.t14
-rw-r--r--extensions/libebt_802_3.c4
-rw-r--r--extensions/libebt_802_3.t3
-rw-r--r--extensions/libebt_arp.c27
-rw-r--r--extensions/libebt_arp.t12
-rw-r--r--extensions/libebt_arpreply.c101
-rw-r--r--extensions/libebt_arpreply.t4
-rw-r--r--extensions/libebt_dnat.c7
-rw-r--r--extensions/libebt_dnat.t5
-rw-r--r--extensions/libebt_ip.c25
-rw-r--r--extensions/libebt_ip.t13
-rw-r--r--extensions/libebt_ip6.c16
-rw-r--r--extensions/libebt_ip6.t15
-rw-r--r--extensions/libebt_log.t6
-rw-r--r--extensions/libebt_mark.t5
-rw-r--r--extensions/libebt_mark_m.c10
-rw-r--r--extensions/libebt_mark_m.t6
-rw-r--r--extensions/libebt_nflog.t5
-rw-r--r--extensions/libebt_pkttype.c5
-rw-r--r--extensions/libebt_pkttype.t13
-rw-r--r--extensions/libebt_redirect.c2
-rw-r--r--extensions/libebt_redirect.t4
-rw-r--r--extensions/libebt_snat.c7
-rw-r--r--extensions/libebt_snat.t4
-rw-r--r--extensions/libebt_standard.t11
-rw-r--r--extensions/libebt_stp.c34
-rw-r--r--extensions/libebt_stp.t13
-rw-r--r--extensions/libebt_vlan.c13
-rw-r--r--extensions/libebt_vlan.t13
-rw-r--r--extensions/libip6t_standard.t5
-rw-r--r--extensions/libxt_CLASSIFY.c47
-rw-r--r--extensions/libxt_MARK.c6
-rw-r--r--extensions/libxt_conntrack.c6
-rw-r--r--extensions/libxt_hashlimit.c6
-rw-r--r--extensions/libxt_limit.c1
-rw-r--r--extensions/libxt_rateest.t8
-rw-r--r--extensions/libxt_standard.t7
-rw-r--r--include/xtables.h5
-rwxr-xr-xiptables-test.py52
-rw-r--r--iptables/nft-arp.c142
-rw-r--r--iptables/nft-bridge.c85
-rw-r--r--iptables/nft-bridge.h1
-rw-r--r--iptables/nft-ipv4.c6
-rw-r--r--iptables/nft-ipv6.c10
-rw-r--r--iptables/nft-shared.c2
-rw-r--r--iptables/nft-shared.h1
-rw-r--r--iptables/nft.c139
-rw-r--r--iptables/nft.h22
-rwxr-xr-xiptables/tests/shell/testcases/arptables/0001-arptables-save-restore_032
-rwxr-xr-xiptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_06
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_04
-rwxr-xr-xiptables/tests/shell/testcases/iptables/0004-return-codes_04
-rw-r--r--iptables/xtables-arp.c78
-rw-r--r--iptables/xtables-eb.c11
-rw-r--r--iptables/xtables-restore.c2
-rw-r--r--iptables/xtables-save.c93
-rw-r--r--iptables/xtables-translate.c1
-rw-r--r--iptables/xtables.c9
-rw-r--r--libxtables/xtables.c23
65 files changed, 861 insertions, 381 deletions
diff --git a/configure.ac b/configure.ac
index 1da8555e..448ec918 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,9 @@
-AC_INIT([iptables], [1.8.1])
+AC_INIT([iptables], [1.8.2])
# See libtool.info "Libtool's versioning system"
-libxtables_vcurrent=13
-libxtables_vage=1
+libxtables_vcurrent=14
+libxtables_vage=2
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
diff --git a/extensions/iptables.t b/extensions/iptables.t
new file mode 100644
index 00000000..b4b6d677
--- /dev/null
+++ b/extensions/iptables.t
@@ -0,0 +1,6 @@
+:FORWARD
+-i alongifacename0;=;OK
+-i thisinterfaceistoolong0;;FAIL
+-i eth+ -o alongifacename+;=;OK
+! -i eth0;=;OK
+! -o eth+;=;OK
diff --git a/extensions/libarpt_CLASSIFY.t b/extensions/libarpt_CLASSIFY.t
new file mode 100644
index 00000000..c30480d2
--- /dev/null
+++ b/extensions/libarpt_CLASSIFY.t
@@ -0,0 +1,4 @@
+:OUTPUT
+-o lo --destination-mac 11:22:33:44:55:66;-o lo --dst-mac 11:22:33:44:55:66;OK
+--dst-mac Broadcast ;--dst-mac ff:ff:ff:ff:ff:ff;OK
+! -o eth+ -d 1.2.3.4/24 -j CLASSIFY --set-class 0000:0000;! -o eth+ -d 1.2.3.0/24 --h-length 6 --h-type 1 -j CLASSIFY --set-class 0000:0000;OK
diff --git a/extensions/libarpt_MARK.t b/extensions/libarpt_MARK.t
new file mode 100644
index 00000000..cb4c2cb6
--- /dev/null
+++ b/extensions/libarpt_MARK.t
@@ -0,0 +1,4 @@
+:INPUT,OUTPUT
+-d 0.0.0.0/8 -j MARK --set-mark 0x1;-d 0.0.0.0/8 --h-length 6 --h-type 1 -j MARK --set-xmark 0x1/0xffffffff;OK
+-s ! 0.0.0.0 -j MARK --and-mark 0x17;! -s 0.0.0.0 --h-length 6 --h-type 1 -j MARK --set-xmark 0x0/0xffffffe8;OK
+-s 0.0.0.0 -j MARK --or-mark 0x17;-s 0.0.0.0 --h-length 6 --h-type 1 -j MARK --set-xmark 0x17/0x17;OK
diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c
index 547f5b61..2fea6185 100644
--- a/extensions/libarpt_mangle.c
+++ b/extensions/libarpt_mangle.c
@@ -175,6 +175,11 @@ arpmangle_print(const void *ip, const struct xt_entry_target *target,
}
}
+static void arpmangle_save(const void *ip, const struct xt_entry_target *target)
+{
+ arpmangle_print(ip, target, 0);
+}
+
static struct xtables_target arpmangle_target = {
.name = "mangle",
.revision = 0,
@@ -187,6 +192,7 @@ static struct xtables_target arpmangle_target = {
.parse = arpmangle_parse,
.final_check = arpmangle_final_check,
.print = arpmangle_print,
+ .save = arpmangle_save,
.extra_opts = arpmangle_opts,
};
diff --git a/extensions/libarpt_mangle.t b/extensions/libarpt_mangle.t
new file mode 100644
index 00000000..1d4c3977
--- /dev/null
+++ b/extensions/libarpt_mangle.t
@@ -0,0 +1,5 @@
+:OUTPUT
+-s 1.2.3.4 -j mangle --mangle-ip-s 1.2.3.5;-s 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-ip-s 1.2.3.5;OK
+-d 1.2.3.4 -j mangle --mangle-ip-d 1.2.3.5;-d 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-ip-d 1.2.3.5;OK
+-d 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-mac-d 00:01:02:03:04:05;=;OK
+-d 1.2.3.4 -j mangle --mangle-mac-s 00:01:02:03:04:05;=;FAIL
diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t
new file mode 100644
index 00000000..bef682af
--- /dev/null
+++ b/extensions/libarpt_standard.t
@@ -0,0 +1,14 @@
+:INPUT
+-s 192.168.0.1;=;OK
+-s 0.0.0.0/8;=;OK
+-s ! 0.0.0.0;! -s 0.0.0.0;OK
+-d 192.168.0.1;=;OK
+! -d 0.0.0.0;=;OK
+-d 0.0.0.0/24;=;OK
+-i lo;=;OK
+! -i lo;=;OK
+-i ppp+;=;OK
+! -i ppp+;=;OK
+-i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK
+--source-mac Unicast;--src-mac 00:00:00:00:00:00/01:00:00:00:00:00;OK
+! --src-mac Multicast;! --src-mac 01:00:00:00:00:00/01:00:00:00:00:00;OK
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
index f05d02ea..9e91d052 100644
--- a/extensions/libebt_802_3.c
+++ b/extensions/libebt_802_3.c
@@ -98,15 +98,15 @@ static void br802_3_print(const void *ip, const struct xt_entry_match *match,
struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
if (info->bitmask & EBT_802_3_SAP) {
- printf("--802_3-sap ");
if (info->invflags & EBT_802_3_SAP)
printf("! ");
+ printf("--802_3-sap ");
printf("0x%.2x ", info->sap);
}
if (info->bitmask & EBT_802_3_TYPE) {
- printf("--802_3-type ");
if (info->invflags & EBT_802_3_TYPE)
printf("! ");
+ printf("--802_3-type ");
printf("0x%.4x ", ntohs(info->type));
}
}
diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t
new file mode 100644
index 00000000..61081bd6
--- /dev/null
+++ b/extensions/libebt_802_3.t
@@ -0,0 +1,3 @@
+:INPUT,FORWARD,OUTPUT
+! --802_3-sap 0x0a -j CONTINUE;=;OK
+--802_3-type 0x000a -j RETURN;=;OK
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index 522c57c0..c1b0ab1d 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -332,67 +332,58 @@ brarp_parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void brarp_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
-{
- char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- printf("%s", ether_ntoa((struct ether_addr *) mac));
- if (memcmp(mask, hlpmsk, 6))
- printf("/%s", ether_ntoa((struct ether_addr *) mask));
-}
-
static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
if (arpinfo->bitmask & EBT_ARP_OPCODE) {
int opcode = ntohs(arpinfo->opcode);
- printf("--arp-op ");
if (arpinfo->invflags & EBT_ARP_OPCODE)
printf("! ");
+ printf("--arp-op ");
if (opcode > 0 && opcode <= ARRAY_SIZE(opcodes))
printf("%s ", opcodes[opcode - 1]);
else
printf("%d ", opcode);
}
if (arpinfo->bitmask & EBT_ARP_HTYPE) {
- printf("--arp-htype ");
if (arpinfo->invflags & EBT_ARP_HTYPE)
printf("! ");
+ printf("--arp-htype ");
printf("%d ", ntohs(arpinfo->htype));
}
if (arpinfo->bitmask & EBT_ARP_PTYPE) {
- printf("--arp-ptype ");
if (arpinfo->invflags & EBT_ARP_PTYPE)
printf("! ");
+ printf("--arp-ptype ");
printf("0x%x ", ntohs(arpinfo->ptype));
}
if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
- printf("--arp-ip-src ");
if (arpinfo->invflags & EBT_ARP_SRC_IP)
printf("! ");
+ printf("--arp-ip-src ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk));
}
if (arpinfo->bitmask & EBT_ARP_DST_IP) {
- printf("--arp-ip-dst ");
if (arpinfo->invflags & EBT_ARP_DST_IP)
printf("! ");
+ printf("--arp-ip-dst ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk));
}
if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
- printf("--arp-mac-src ");
if (arpinfo->invflags & EBT_ARP_SRC_MAC)
printf("! ");
- brarp_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
+ printf("--arp-mac-src ");
+ xtables_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
printf(" ");
}
if (arpinfo->bitmask & EBT_ARP_DST_MAC) {
- printf("--arp-mac-dst ");
if (arpinfo->invflags & EBT_ARP_DST_MAC)
printf("! ");
- brarp_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
+ printf("--arp-mac-dst ");
+ xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
printf(" ");
}
if (arpinfo->bitmask & EBT_ARP_GRAT) {
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
new file mode 100644
index 00000000..a05ab12d
--- /dev/null
+++ b/extensions/libebt_arp.t
@@ -0,0 +1,12 @@
+:INPUT,FORWARD,OUTPUT
+-p ARP --arp-op Request;=;OK
+-p ARP ! --arp-htype 1;=;OK
+-p ARP --arp-ptype 0x2;=;OK
+-p ARP --arp-ip-src 1.2.3.4;=;OK
+-p ARP ! --arp-ip-dst 1.2.3.4;=;OK
+-p ARP ! --arp-ip-src 0.0.0.0;=;OK
+-p ARP ! --arp-ip-dst 0.0.0.0/8;=;OK
+-p ARP --arp-mac-src 00:de:ad:be:ef:00;=;OK
+-p ARP --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
+-p ARP --arp-gratuitous;=;OK
+--arp-htype 1;=;FAIL
diff --git a/extensions/libebt_arpreply.c b/extensions/libebt_arpreply.c
new file mode 100644
index 00000000..80ba2159
--- /dev/null
+++ b/extensions/libebt_arpreply.c
@@ -0,0 +1,101 @@
+/* ebt_arpreply
+ *
+ * Authors:
+ * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * August, 2003
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <netinet/ether.h>
+#include <linux/netfilter_bridge/ebt_arpreply.h>
+#include "iptables/nft.h"
+#include "iptables/nft-bridge.h"
+
+#define OPT_REPLY_MAC 0x01
+#define OPT_REPLY_TARGET 0x02
+
+#define REPLY_MAC '1'
+#define REPLY_TARGET '2'
+static const struct option brarpreply_opts[] = {
+ { "arpreply-mac" , required_argument, 0, REPLY_MAC },
+ { "arpreply-target" , required_argument, 0, REPLY_TARGET },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brarpreply_print_help(void)
+{
+ printf(
+ "arpreply target options:\n"
+ " --arpreply-mac address : source MAC of generated reply\n"
+ " --arpreply-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
+ " (standard target is DROP)\n");
+}
+
+static void brarpreply_init(struct xt_entry_target *target)
+{
+ struct ebt_arpreply_info *replyinfo = (void *)target->data;
+
+ replyinfo->target = EBT_DROP;
+}
+
+static int
+brarpreply_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **tg)
+
+{
+ struct ebt_arpreply_info *replyinfo = (void *)(*tg)->data;
+ struct ether_addr *addr;
+
+ switch (c) {
+ case REPLY_MAC:
+ EBT_CHECK_OPTION(flags, OPT_REPLY_MAC);
+ if (!(addr = ether_aton(optarg)))
+ xtables_error(PARAMETER_PROBLEM, "Problem with specified --arpreply-mac mac");
+ memcpy(replyinfo->mac, addr, ETH_ALEN);
+ break;
+ case REPLY_TARGET:
+ EBT_CHECK_OPTION(flags, OPT_REPLY_TARGET);
+ if (ebt_fill_target(optarg, (unsigned int *)&replyinfo->target))
+ xtables_error(PARAMETER_PROBLEM, "Illegal --arpreply-target target");
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void brarpreply_print(const void *ip, const struct xt_entry_target *t, int numeric)
+{
+ struct ebt_arpreply_info *replyinfo = (void *)t->data;
+
+ printf("--arpreply-mac ");
+ xtables_print_mac(replyinfo->mac);
+ if (replyinfo->target == EBT_DROP)
+ return;
+ printf(" --arpreply-target %s", ebt_target_name(replyinfo->target));
+}
+
+static struct xtables_target arpreply_target = {
+ .name = "arpreply",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .init = brarpreply_init,
+ .size = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
+ .help = brarpreply_print_help,
+ .parse = brarpreply_parse,
+ .print = brarpreply_print,
+ .extra_opts = brarpreply_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&arpreply_target);
+}
diff --git a/extensions/libebt_arpreply.t b/extensions/libebt_arpreply.t
new file mode 100644
index 00000000..6734501a
--- /dev/null
+++ b/extensions/libebt_arpreply.t
@@ -0,0 +1,4 @@
+:PREROUTING
+*nat
+-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff --arpreply-target ACCEPT;=;OK
+-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff;=;OK
diff --git a/extensions/libebt_dnat.c b/extensions/libebt_dnat.c
index c179d8c1..9f5f721e 100644
--- a/extensions/libebt_dnat.c
+++ b/extensions/libebt_dnat.c
@@ -74,17 +74,12 @@ static void brdnat_final_check(unsigned int flags)
"You must specify proper arguments");
}
-static void ebt_print_mac(const unsigned char *mac)
-{
- printf("%s", ether_ntoa((struct ether_addr *) mac));
-}
-
static void brdnat_print(const void *ip, const struct xt_entry_target *target, int numeric)
{
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
printf("--to-dst ");
- ebt_print_mac(natinfo->mac);
+ xtables_print_mac(natinfo->mac);
printf(" --dnat-target %s", ebt_target_name(natinfo->target));
}
diff --git a/extensions/libebt_dnat.t b/extensions/libebt_dnat.t
new file mode 100644
index 00000000..9428d237
--- /dev/null
+++ b/extensions/libebt_dnat.t
@@ -0,0 +1,5 @@
+:PREROUTING
+*nat
+-i someport -j dnat --to-dst de:ad:0:be:ee:ff;-i someport -j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;OK
+-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;=;OK
+-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE;=;OK
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 2b28c615..d48704fe 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -424,14 +424,17 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
info->igmp_type, NULL);
info->bitmask |= EBT_IP_IGMP;
break;
- case IP_EBT_TOS:
+ case IP_EBT_TOS: {
+ uintmax_t tosvalue;
+
if (invert)
info->invflags |= EBT_IP_TOS;
- if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos,
- 0, 255))
+ if (!xtables_strtoul(optarg, NULL, &tosvalue, 0, 255))
xtables_error(PARAMETER_PROBLEM,
"Problem with specified IP tos");
+ info->tos = tosvalue;
info->bitmask |= EBT_IP_TOS;
+ }
break;
case IP_PROTO:
if (invert)
@@ -469,35 +472,35 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
struct in_addr *addrp, *maskp;
if (info->bitmask & EBT_IP_SOURCE) {
- printf("--ip-src ");
if (info->invflags & EBT_IP_SOURCE)
printf("! ");
+ printf("--ip-src ");
addrp = (struct in_addr *)&info->saddr;
maskp = (struct in_addr *)&info->smsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_DEST) {
- printf("--ip-dst ");
if (info->invflags & EBT_IP_DEST)
printf("! ");
+ printf("--ip-dst ");
addrp = (struct in_addr *)&info->daddr;
maskp = (struct in_addr *)&info->dmsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_TOS) {
- printf("--ip-tos ");
if (info->invflags & EBT_IP_TOS)
printf("! ");
+ printf("--ip-tos ");
printf("0x%02X ", info->tos);
}
if (info->bitmask & EBT_IP_PROTO) {
struct protoent *pe;
- printf("--ip-proto ");
if (info->invflags & EBT_IP_PROTO)
printf("! ");
+ printf("--ip-proto ");
pe = getprotobynumber(info->protocol);
if (pe == NULL) {
printf("%d ", info->protocol);
@@ -506,28 +509,28 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
}
}
if (info->bitmask & EBT_IP_SPORT) {
- printf("--ip-sport ");
if (info->invflags & EBT_IP_SPORT)
printf("! ");
+ printf("--ip-sport ");
print_port_range(info->sport);
}
if (info->bitmask & EBT_IP_DPORT) {
- printf("--ip-dport ");
if (info->invflags & EBT_IP_DPORT)
printf("! ");
+ printf("--ip-dport ");
print_port_range(info->dport);
}
if (info->bitmask & EBT_IP_ICMP) {
- printf("--ip-icmp-type ");
if (info->invflags & EBT_IP_ICMP)
printf("! ");
+ printf("--ip-icmp-type ");
ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
info->icmp_type, info->icmp_code);
}
if (info->bitmask & EBT_IP_IGMP) {
- printf("--ip-igmp-type ");
if (info->invflags & EBT_IP_IGMP)
printf("! ");
+ printf("--ip-igmp-type ");
ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types),
info->igmp_type, NULL);
}
diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t
new file mode 100644
index 00000000..01a91a73
--- /dev/null
+++ b/extensions/libebt_ip.t
@@ -0,0 +1,13 @@
+:INPUT,FORWARD,OUTPUT
+-p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 ! --ip-src 192.168.0.0/24 -j ACCEPT;OK
+-p IPv4 --ip-dst 10.0.0.1;=;OK
+-p IPv4 --ip-tos 0xFF;=;OK
+-p IPv4 ! --ip-tos 0xFF;=;OK
+-p IPv4 --ip-proto tcp --ip-dport 22;=;OK
+-p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK
+-p IPv4 --ip-proto 253;=;OK
+-p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK
+-p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK
+-p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp ! --ip-icmp-type 1:10/0:255 -j CONTINUE;OK
+--ip-proto icmp --ip-icmp-type 1/1;=;FAIL
+! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index ab1413ba..b7277649 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -353,7 +353,7 @@ brip6_parse(int c, char **argv, int invert, unsigned int *flags,
break;
case IP_DPORT:
if (invert)
- info->invflags |= EBT_IP6_DEST;
+ info->invflags |= EBT_IP6_DPORT;
parse_port_range(NULL, optarg, info->dport);
info->bitmask |= EBT_IP6_DPORT;
break;
@@ -399,31 +399,31 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match,
struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
if (ipinfo->bitmask & EBT_IP6_SOURCE) {
- printf("--ip6-src ");
if (ipinfo->invflags & EBT_IP6_SOURCE)
printf("! ");
+ printf("--ip6-src ");
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->saddr));
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->smsk));
}
if (ipinfo->bitmask & EBT_IP6_DEST) {
- printf("--ip6-dst ");
if (ipinfo->invflags & EBT_IP6_DEST)
printf("! ");
+ printf("--ip6-dst ");
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->daddr));
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->dmsk));
}
if (ipinfo->bitmask & EBT_IP6_TCLASS) {
- printf("--ip6-tclass ");
if (ipinfo->invflags & EBT_IP6_TCLASS)
printf("! ");
+ printf("--ip6-tclass ");
printf("0x%02X ", ipinfo->tclass);
}
if (ipinfo->bitmask & EBT_IP6_PROTO) {
struct protoent *pe;
- printf("--ip6-proto ");
if (ipinfo->invflags & EBT_IP6_PROTO)
printf("! ");
+ printf("--ip6-proto ");
pe = getprotobynumber(ipinfo->protocol);
if (pe == NULL) {
printf("%d ", ipinfo->protocol);
@@ -432,21 +432,21 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match,
}
}
if (ipinfo->bitmask & EBT_IP6_SPORT) {
- printf("--ip6-sport ");
if (ipinfo->invflags & EBT_IP6_SPORT)
printf("! ");
+ printf("--ip6-sport ");
print_port_range(ipinfo->sport);
}
if (ipinfo->bitmask & EBT_IP6_DPORT) {
- printf("--ip6-dport ");
if (ipinfo->invflags & EBT_IP6_DPORT)
printf("! ");
+ printf("--ip6-dport ");
print_port_range(ipinfo->dport);
}
if (ipinfo->bitmask & EBT_IP6_ICMP6) {
- printf("--ip6-icmp-type ");
if (ipinfo->invflags & EBT_IP6_ICMP6)
printf("! ");
+ printf("--ip6-icmp-type ");
print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
}
}
diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t
new file mode 100644
index 00000000..6b3221ea
--- /dev/null
+++ b/extensions/libebt_ip6.t
@@ -0,0 +1,15 @@
+:INPUT,FORWARD,OUTPUT
+-p ip6 ! --ip6-src dead::beef/64 -j ACCEPT;-p IPv6 ! --ip6-src dead::/64 -j ACCEPT;OK
+-p IPv6 --ip6-dst dead:beef::/64 -j ACCEPT;=;OK
+-p IPv6 --ip6-dst f00:ba::;=;OK
+-p IPv6 --ip6-tclass 0xFF;=;OK
+-p IPv6 --ip6-proto tcp --ip6-dport 22;=;OK
+-p IPv6 --ip6-proto tcp ! --ip6-dport 22;=;OK
+-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK
+-p IPv6 --ip6-proto 253;=;OK
+-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request -j CONTINUE;=;OK
+-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request;=;OK
+-p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1;-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type communication-prohibited -j CONTINUE;OK
+-p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;OK
+--ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
+! -p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
diff --git a/extensions/libebt_log.t b/extensions/libebt_log.t
new file mode 100644
index 00000000..a0df6169
--- /dev/null
+++ b/extensions/libebt_log.t
@@ -0,0 +1,6 @@
+:INPUT,FORWARD,OUTPUT
+--log;=;OK
+--log-level crit;=;OK
+--log-level 1;--log-level alert --log-prefix "";OK
+--log-level emerg --log-ip --log-arp --log-ip6;--log-level emerg --log-prefix "" --log-ip --log-arp --log-ip6 -j CONTINUE;OK
+--log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo;--log-level crit --log-prefix "foo" --log-ip --log-arp --log-ip6 -j CONTINUE;OK
diff --git a/extensions/libebt_mark.t b/extensions/libebt_mark.t
new file mode 100644
index 00000000..2d8f9d7a
--- /dev/null
+++ b/extensions/libebt_mark.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-j mark --mark-set 1;-j mark --mark-set 0x1 --mark-target ACCEPT;OK
+-j mark --mark-or 0xa --mark-target CONTINUE;=;OK
+-j mark --mark-and 0x1 --mark-target RETURN;=;OK
+-j mark --mark-xor 0x1 --mark-target CONTINUE;=;OK
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index 244fe12a..64ad926f 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -86,9 +86,9 @@ static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
- printf("--mark ");
if (info->invert)
printf("! ");
+ printf("--mark ");
if (info->bitmask == EBT_MARK_OR)
printf("/0x%lx ", info->mask);
else if (info->mask != 0xffffffff)
@@ -109,14 +109,14 @@ static int brmark_m_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "meta mark ");
if (info->bitmask == EBT_MARK_OR) {
- xt_xlate_add(xl, "and 0x%x %s0 ", info->mask,
+ xt_xlate_add(xl, "and 0x%x %s0 ", (uint32_t)info->mask,
info->invert ? "" : "!= ");
} else if (info->mask != 0xffffffffU) {
- xt_xlate_add(xl, "and 0x%x %s0x%x ", info->mask,
- op == XT_OP_EQ ? "" : "!= ", info->mark);
+ xt_xlate_add(xl, "and 0x%x %s0x%x ", (uint32_t)info->mask,
+ op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
} else {
xt_xlate_add(xl, "%s0x%x ",
- op == XT_OP_EQ ? "" : "!= ", info->mark);
+ op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
}
return 1;
diff --git a/extensions/libebt_mark_m.t b/extensions/libebt_mark_m.t
new file mode 100644
index 00000000..9ad41704
--- /dev/null
+++ b/extensions/libebt_mark_m.t
@@ -0,0 +1,6 @@
+:INPUT,FORWARD,OUTPUT
+--mark 42;--mark 0x2a;OK
+--mark ! 42;! --mark 0x2a;OK
+--mark 42/0xff;--mark 0x2a/0xff;OK
+! --mark 0x1/0xff;=;OK
+--mark /0x2;=;OK
diff --git a/extensions/libebt_nflog.t b/extensions/libebt_nflog.t
new file mode 100644
index 00000000..f867df30
--- /dev/null
+++ b/extensions/libebt_nflog.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+--nflog;=;OK
+--nflog-group 42;=;OK
+--nflog-range 42;--nflog-group 1 --nflog-range 42 -j CONTINUE;OK
+--nflog-threshold 100 --nflog-prefix foo;--nflog-prefix "foo" --nflog-group 1 --nflog-threshold 100 -j CONTINUE;OK
diff --git a/extensions/libebt_pkttype.c b/extensions/libebt_pkttype.c
index 4e2d19de..265674d1 100644
--- a/extensions/libebt_pkttype.c
+++ b/extensions/libebt_pkttype.c
@@ -75,7 +75,10 @@ static void brpkttype_print(const void *ip, const struct xt_entry_match *match,
{
struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data;
- printf("--pkttype-type %s", pt->invert ? "! " : "");
+ if (pt->invert)
+ printf("! ");
+
+ printf("--pkttype-type ");
if (pt->pkt_type < ARRAY_SIZE(classes))
printf("%s ", classes[pt->pkt_type]);
diff --git a/extensions/libebt_pkttype.t b/extensions/libebt_pkttype.t
new file mode 100644
index 00000000..f870f5c7
--- /dev/null
+++ b/extensions/libebt_pkttype.t
@@ -0,0 +1,13 @@
+:INPUT,FORWARD,OUTPUT
+--pkttype-type host;=;OK
+! --pkttype-type host;=;OK
+--pkttype-type broadcast;=;OK
+! --pkttype-type broadcast;=;OK
+--pkttype-type multicast;=;OK
+! --pkttype-type multicast;=;OK
+--pkttype-type otherhost;=;OK
+! --pkttype-type otherhost;=;OK
+--pkttype-type outgoing;=;OK
+! --pkttype-type outgoing;=;OK
+--pkttype-type loopback;=;OK
+! --pkttype-type loopback;=;OK
diff --git a/extensions/libebt_redirect.c b/extensions/libebt_redirect.c
index a88713d3..6e653997 100644
--- a/extensions/libebt_redirect.c
+++ b/extensions/libebt_redirect.c
@@ -63,7 +63,7 @@ static void brredir_print(const void *ip, const struct xt_entry_target *target,
if (redirectinfo->target == EBT_ACCEPT)
return;
- printf(" --redirect-target %s", ebt_target_name(redirectinfo->target));
+ printf("--redirect-target %s", ebt_target_name(redirectinfo->target));
}
static const char* brredir_verdict(int verdict)
diff --git a/extensions/libebt_redirect.t b/extensions/libebt_redirect.t
new file mode 100644
index 00000000..23858afa
--- /dev/null
+++ b/extensions/libebt_redirect.t
@@ -0,0 +1,4 @@
+:PREROUTING
+*nat
+-j redirect;=;OK
+-j redirect --redirect-target RETURN;=;OK
diff --git a/extensions/libebt_snat.c b/extensions/libebt_snat.c
index 95b32f9c..c1124bf3 100644
--- a/extensions/libebt_snat.c
+++ b/extensions/libebt_snat.c
@@ -85,17 +85,12 @@ static void brsnat_final_check(unsigned int flags)
"You must specify proper arguments");
}
-static void ebt_print_mac(const unsigned char *mac)
-{
- printf("%s", ether_ntoa((struct ether_addr *) mac));
-}
-
static void brsnat_print(const void *ip, const struct xt_entry_target *target, int numeric)
{
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
printf("--to-src ");
- ebt_print_mac(natinfo->mac);
+ xtables_print_mac(natinfo->mac);
if (!(natinfo->target&NAT_ARP_BIT))
printf(" --snat-arp");
printf(" --snat-target %s", ebt_target_name((natinfo->target|~EBT_VERDICT_BITS)));
diff --git a/extensions/libebt_snat.t b/extensions/libebt_snat.t
new file mode 100644
index 00000000..639b13f3
--- /dev/null
+++ b/extensions/libebt_snat.t
@@ -0,0 +1,4 @@
+:POSTROUTING
+*nat
+-o someport -j snat --to-source a:b:c:d:e:f;-o someport -j snat --to-src 0a:0b:0c:0d:0e:0f --snat-target ACCEPT;OK
+-o someport+ -j snat --to-src de:ad:00:be:ee:ff --snat-target CONTINUE;=;OK
diff --git a/extensions/libebt_standard.t b/extensions/libebt_standard.t
new file mode 100644
index 00000000..72081fd6
--- /dev/null
+++ b/extensions/libebt_standard.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-d de:ad:be:ef:00:00;=;OK
+-s 0:0:0:0:0:0;-s 00:00:00:00:00:00;OK
+-d 00:00:00:00:00:00;=;OK
+-s de:ad:be:ef:0:00 -j RETURN;-s de:ad:be:ef:00:00 -j RETURN;OK
+-d de:ad:be:ef:00:00 -j CONTINUE;=;OK
+-d de:ad:be:ef:0:00/ff:ff:ff:ff:0:0 -j DROP;-d de:ad:be:ef:00:00/ff:ff:ff:ff:00:00 -j DROP;OK
+-p ARP -j ACCEPT;=;OK
+! -p ARP -j ACCEPT;=;OK
+-p 0 -j ACCEPT;=;FAIL
+! -p 0 -j ACCEPT;=;FAIL
diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c
index 25f2735f..33e4c8d9 100644
--- a/extensions/libebt_stp.c
+++ b/extensions/libebt_stp.c
@@ -297,31 +297,6 @@ brstp_parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void ebt_print_mac(const unsigned char *mac)
-{
- int j;
- for (j = 0; j < ETH_ALEN; j++)
- printf("%02x%s", mac[j],
- (j==ETH_ALEN-1) ? "" : ":");
-}
-
-static bool mac_all_ones(const unsigned char *mac)
-{
- static const char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- return memcmp(mac, hlpmsk, sizeof(hlpmsk)) == 0;
-}
-
-static void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
-{
-
- ebt_print_mac(mac);
- if (!mac_all_ones(mask)) {
- printf("/");
- ebt_print_mac(mask);
- }
-}
-
static void brstp_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
@@ -332,8 +307,9 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match,
for (i = 0; i < STP_NUMOPS; i++) {
if (!(stpinfo->bitmask & (1 << i)))
continue;
- printf("--%s %s", brstp_opts[i].name,
- (stpinfo->invflags & (1 << i)) ? "! " : "");
+ if (stpinfo->invflags & (1 << i))
+ printf("! ");
+ printf("--%s ", brstp_opts[i].name);
if (EBT_STP_TYPE == (1 << i)) {
if (stpinfo->type == BPDU_TYPE_CONFIG)
printf("%s", BPDU_TYPE_CONFIG_STRING);
@@ -351,14 +327,14 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match,
} else if (EBT_STP_ROOTPRIO == (1 << i))
print_range(c->root_priol, c->root_priou);
else if (EBT_STP_ROOTADDR == (1 << i))
- ebt_print_mac_and_mask((unsigned char *)c->root_addr,
+ xtables_print_mac_and_mask((unsigned char *)c->root_addr,
(unsigned char*)c->root_addrmsk);
else if (EBT_STP_ROOTCOST == (1 << i))
print_range(c->root_costl, c->root_costu);
else if (EBT_STP_SENDERPRIO == (1 << i))
print_range(c->sender_priol, c->sender_priou);
else if (EBT_STP_SENDERADDR == (1 << i))
- ebt_print_mac_and_mask((unsigned char *)c->sender_addr,
+ xtables_print_mac_and_mask((unsigned char *)c->sender_addr,
(unsigned char *)c->sender_addrmsk);
else if (EBT_STP_PORT == (1 << i))
print_range(c->portl, c->portu);
diff --git a/extensions/libebt_stp.t b/extensions/libebt_stp.t
new file mode 100644
index 00000000..0c6b77b9
--- /dev/null
+++ b/extensions/libebt_stp.t
@@ -0,0 +1,13 @@
+:INPUT,FORWARD,OUTPUT
+--stp-type 1;=;OK
+--stp-flags 0x1;--stp-flags topology-change -j CONTINUE;OK
+--stp-root-prio 1 -j ACCEPT;=;OK
+--stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
+--stp-root-cost 1;=;OK
+--stp-sender-prio 1;=;OK
+--stp-sender-addr de:ad:be:ef:00:00;=;OK
+--stp-port 1;=;OK
+--stp-msg-age 1;=;OK
+--stp-max-age 1;=;OK
+--stp-hello-time 1;=;OK
+--stp-forward-delay 1;=;OK
diff --git a/extensions/libebt_vlan.c b/extensions/libebt_vlan.c
index a2a9dcce..4a2eb712 100644
--- a/extensions/libebt_vlan.c
+++ b/extensions/libebt_vlan.c
@@ -108,14 +108,19 @@ static void brvlan_print(const void *ip, const struct xt_entry_match *match,
struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
if (vlaninfo->bitmask & EBT_VLAN_ID) {
- printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id);
+ if (vlaninfo->invflags & EBT_VLAN_ID)
+ printf("! ");
+ printf("--vlan-id %d ", vlaninfo->id);
}
if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
- printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio);
+ if (vlaninfo->invflags & EBT_VLAN_PRIO)
+ printf("! ");
+ printf("--vlan-prio %d ", vlaninfo->prio);
}
if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
- printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "");
- printf("%4.4X ", ntohs(vlaninfo->encap));
+ if (vlaninfo->invflags & EBT_VLAN_ENCAP)
+ printf("! ");
+ printf("--vlan-encap %4.4X ", ntohs(vlaninfo->encap));
}
}
diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t
new file mode 100644
index 00000000..106374cd
--- /dev/null
+++ b/extensions/libebt_vlan.t
@@ -0,0 +1,13 @@
+:INPUT,FORWARD,OUTPUT
+-p 802_1Q --vlan-id 42;=;OK
+-p 802_1Q ! --vlan-id 42;=;OK
+-p 802_1Q --vlan-prio 1;=;OK
+-p 802_1Q ! --vlan-prio 1;=;OK
+-p 802_1Q --vlan-encap ip;-p 802_1Q --vlan-encap 0800 -j CONTINUE;OK
+-p 802_1Q --vlan-encap 0800 ;=;OK
+-p 802_1Q ! --vlan-encap 0800 ;=;OK
+-p 802_1Q --vlan-encap IPv6 ! --vlan-id 1;-p 802_1Q ! --vlan-id 1 --vlan-encap 86DD -j CONTINUE;OK
+-p 802_1Q ! --vlan-id 1 --vlan-encap 86DD;=;OK
+--vlan-encap ip;=;FAIL
+--vlan-id 2;=;FAIL
+--vlan-prio 1;=;FAIL
diff --git a/extensions/libip6t_standard.t b/extensions/libip6t_standard.t
new file mode 100644
index 00000000..a528af10
--- /dev/null
+++ b/extensions/libip6t_standard.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-s ::/128;=;OK
+! -d ::;! -d ::/128;OK
+! -s ::;! -s ::/128;OK
+-s ::/64;=;OK
diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c
index ba88f758..f90082dc 100644
--- a/extensions/libxt_CLASSIFY.c
+++ b/extensions/libxt_CLASSIFY.c
@@ -73,13 +73,6 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
}
-static void
-arpCLASSIFY_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- CLASSIFY_save(ip, target);
-}
-
static int CLASSIFY_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
@@ -105,35 +98,21 @@ static int CLASSIFY_xlate(struct xt_xlate *xl,
return 1;
}
-static struct xtables_target classify_target[] = {
- {
- .family = NFPROTO_UNSPEC,
- .name = "CLASSIFY",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .help = CLASSIFY_help,
- .print = CLASSIFY_print,
- .save = CLASSIFY_save,
- .x6_parse = CLASSIFY_parse,
- .x6_options = CLASSIFY_opts,
- .xlate = CLASSIFY_xlate,
- },
- {
- .family = NFPROTO_ARP,
- .name = "CLASSIFY",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .help = CLASSIFY_help,
- .print = arpCLASSIFY_print,
- .x6_parse = CLASSIFY_parse,
- .x6_options = CLASSIFY_opts,
- .xlate = CLASSIFY_xlate,
- },
+static struct xtables_target classify_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "CLASSIFY",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .help = CLASSIFY_help,
+ .print = CLASSIFY_print,
+ .save = CLASSIFY_save,
+ .x6_parse = CLASSIFY_parse,
+ .x6_options = CLASSIFY_opts,
+ .xlate = CLASSIFY_xlate,
};
void _init(void)
{
- xtables_register_targets(classify_target, ARRAY_SIZE(classify_target));
+ xtables_register_target(&classify_target);
}
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index 5c6186fe..43aa9779 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -277,13 +277,13 @@ static int MARK_xlate(struct xt_xlate *xl,
switch(markinfo->mode) {
case XT_MARK_SET:
- xt_xlate_add(xl, "0x%x ", markinfo->mark);
+ xt_xlate_add(xl, "0x%x ", (uint32_t)markinfo->mark);
break;
case XT_MARK_AND:
- xt_xlate_add(xl, "mark and 0x%x ", markinfo->mark);
+ xt_xlate_add(xl, "mark and 0x%x ", (uint32_t)markinfo->mark);
break;
case XT_MARK_OR:
- xt_xlate_add(xl, "mark or 0x%x ", markinfo->mark);
+ xt_xlate_add(xl, "mark or 0x%x ", (uint32_t)markinfo->mark);
break;
}
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index daa8c15a..1817d335 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -1271,9 +1271,9 @@ static int _conntrack3_mt_xlate(struct xt_xlate *xl,
sinfo->invert_flags & XT_CONNTRACK_EXPIRES ?
"!= " : "");
if (sinfo->expires_max == sinfo->expires_min)
- xt_xlate_add(xl, "%lu", sinfo->expires_min);
+ xt_xlate_add(xl, "%u", sinfo->expires_min);
else
- xt_xlate_add(xl, "%lu-%lu", sinfo->expires_min,
+ xt_xlate_add(xl, "%u-%u", sinfo->expires_min,
sinfo->expires_max);
space = " ";
}
@@ -1365,7 +1365,7 @@ static int _conntrack3_mt_xlate(struct xt_xlate *xl,
if (sinfo->match_flags & XT_CONNTRACK_REPLDST_PORT) {
xt_xlate_add(xl, "%sct reply proto-dst %s", space,
sinfo->invert_flags & XT_CONNTRACK_REPLDST_PORT ?
- "!= " : "", sinfo->repldst_port);
+ "!= " : "");
if (sinfo->repldst_port == sinfo->repldst_port_high)
xt_xlate_add(xl, "%u", sinfo->repldst_port);
else
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 7d78d852..f3b6e043 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -1221,7 +1221,7 @@ static void print_packets_rate_xlate(struct xt_xlate *xl, uint64_t avg,
_rates[i].mult / avg < _rates[i].mult % avg)
break;
- xt_xlate_add(xl, " %llu/%s ",
+ xt_xlate_add(xl, " %" PRIu64 "/%s ",
_rates[i-1].mult / avg, _rates[i-1].name);
}
@@ -1354,7 +1354,7 @@ static int hashlimit_mt_xlate(struct xt_xlate *xl, const char *name,
else {
print_packets_rate_xlate(xl, cfg->avg, revision);
if (cfg->burst != XT_HASHLIMIT_BURST)
- xt_xlate_add(xl, "burst %lu packets", cfg->burst);
+ xt_xlate_add(xl, "burst %" PRIu64 " packets", (uint64_t)cfg->burst);
}
xt_xlate_add(xl, "}");
@@ -1372,7 +1372,7 @@ static int hashlimit_xlate(struct xt_xlate *xl,
ret = hashlimit_mode_xlate(xl, info->cfg.mode, NFPROTO_IPV4, 32, 32);
xt_xlate_add(xl, " timeout %us limit rate", info->cfg.expire / 1000);
print_packets_rate_xlate(xl, info->cfg.avg, 1);
- xt_xlate_add(xl, " burst %lu packets", info->cfg.burst);
+ xt_xlate_add(xl, " burst %u packets", info->cfg.burst);
xt_xlate_add(xl, "}");
return ret;
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index c7b66295..1b324657 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -15,7 +15,6 @@
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_limit.h>
-#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define XT_LIMIT_AVG "3/hour"
diff --git a/extensions/libxt_rateest.t b/extensions/libxt_rateest.t
index c53b4b62..c5158614 100644
--- a/extensions/libxt_rateest.t
+++ b/extensions/libxt_rateest.t
@@ -1,10 +1,10 @@
:INPUT,FORWARD,OUTPUT
-@iptables -I INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+%iptables -I INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
-m rateest --rateest RE1 --rateest-lt --rateest-bps 8bit;=;OK
-m rateest --rateest RE1 --rateest-eq --rateest-pps 5;=;OK
-m rateest --rateest RE1 --rateest-gt --rateest-bps 5kbit;-m rateest --rateest RE1 --rateest-gt --rateest-bps 5000bit;OK
-m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-lt --rateest-bps2 16bit;=;OK
-@iptables -I INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+%iptables -I INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
-m rateest --rateest1 RE1 --rateest-lt --rateest-bps --rateest2 RE2;=;OK
-m rateest --rateest-delta --rateest1 RE1 --rateest-pps1 0 --rateest-lt --rateest-pps2 42 --rateest2 RE2;=;OK
-m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-eq --rateest-bps2 16bit;=;OK
@@ -12,5 +12,5 @@
-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-lt --rateest-pps2 9;=;OK
-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9;=;OK
-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9;=;OK
-@iptables -D INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
-@iptables -D INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+%iptables -D INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+%iptables -D INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
diff --git a/extensions/libxt_standard.t b/extensions/libxt_standard.t
index 923569c3..4313f7b7 100644
--- a/extensions/libxt_standard.t
+++ b/extensions/libxt_standard.t
@@ -1,4 +1,11 @@
:INPUT,FORWARD,OUTPUT
+-s 127.0.0.1/32 -d 0.0.0.0/8 -j DROP;=;OK
+! -s 0.0.0.0 -j ACCEPT;! -s 0.0.0.0/32 -j ACCEPT;OK
+! -d 0.0.0.0/32 -j ACCEPT;=;OK
+-s 0.0.0.0/24 -j RETURN;=;OK
+-p tcp -j ACCEPT;=;OK
+! -p udp -j ACCEPT;=;OK
-j DROP;=;OK
-j ACCEPT;=;OK
-j RETURN;=;OK
+! -p 0 -j ACCEPT;=;FAIL
diff --git a/include/xtables.h b/include/xtables.h
index 8fb8843a..4aa084a1 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -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);
diff --git a/iptables-test.py b/iptables-test.py
index 5e6bfb7e..532dee7c 100755
--- a/iptables-test.py
+++ b/iptables-test.py
@@ -17,11 +17,13 @@ import argparse
IPTABLES = "iptables"
IP6TABLES = "ip6tables"
-#IPTABLES = "xtables -4"
-#IP6TABLES = "xtables -6"
+ARPTABLES = "arptables"
+EBTABLES = "ebtables"
IPTABLES_SAVE = "iptables-save"
IP6TABLES_SAVE = "ip6tables-save"
+ARPTABLES_SAVE = "arptables-save"
+EBTABLES_SAVE = "ebtables-save"
#IPTABLES_SAVE = ['xtables-save','-4']
#IP6TABLES_SAVE = ['xtables-save','-6']
@@ -111,6 +113,10 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
command = IPTABLES_SAVE
elif splitted[0] == IP6TABLES:
command = IP6TABLES_SAVE
+ elif splitted[0] == ARPTABLES:
+ command = ARPTABLES_SAVE
+ elif splitted[0] == EBTABLES:
+ command = EBTABLES_SAVE
path = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE
command = path + " " + command
@@ -147,12 +153,6 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
return delete_rule(iptables, rule, filename, lineno)
-def run_test_netns(iptables, rule, rule_save, res, filename, lineno):
- execute_cmd("ip netns add ____iptables-container-test", filename, lineno)
- ret = run_test(iptables, rule, rule_save, res, filename, lineno, True)
- execute_cmd("ip netns del ____iptables-container-test", filename, lineno)
- return ret
-
def execute_cmd(cmd, filename, lineno):
'''
Executes a command, checking for segfaults and returning the command exit
@@ -163,7 +163,7 @@ def execute_cmd(cmd, filename, lineno):
:param lineno: line number being tested (used for print_error purposes)
'''
global log_file
- if cmd.startswith('iptables ') or cmd.startswith('ip6tables '):
+ if cmd.startswith('iptables ') or cmd.startswith('ip6tables ') or cmd.startswith('ebtables ') or cmd.startswith('arptables '):
cmd = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE + " " + cmd
print >> log_file, "command: %s" % cmd
@@ -196,6 +196,16 @@ def run_test_file(filename, netns):
iptables = IP6TABLES
elif "libxt_" in filename:
iptables = IPTABLES
+ elif "libarpt_" in filename:
+ # only supported with nf_tables backend
+ if EXECUTEABLE != "xtables-nft-multi":
+ return 0, 0
+ iptables = ARPTABLES
+ elif "libebt_" in filename:
+ # only supported with nf_tables backend
+ if EXECUTEABLE != "xtables-nft-multi":
+ return 0, 0
+ iptables = EBTABLES
else:
# default to iptables if not known prefix
iptables = IPTABLES
@@ -207,6 +217,9 @@ def run_test_file(filename, netns):
table = ""
total_test_passed = True
+ if netns:
+ execute_cmd("ip netns add ____iptables-container-test", filename, 0)
+
for lineno, line in enumerate(f):
if line[0] == "#":
continue
@@ -218,6 +231,16 @@ def run_test_file(filename, netns):
# external non-iptables invocation, executed as is.
if line[0] == "@":
external_cmd = line.rstrip()[1:]
+ if netns:
+ external_cmd = "ip netns exec ____iptables-container-test " + external_cmd
+ execute_cmd(external_cmd, filename, lineno)
+ continue
+
+ # external iptables invocation, executed as is.
+ if line[0] == "%":
+ external_cmd = line.rstrip()[1:]
+ if netns:
+ external_cmd = "ip netns exec ____iptables-container-test " + EXECUTEABLE + " " + external_cmd
execute_cmd(external_cmd, filename, lineno)
continue
@@ -245,13 +268,8 @@ def run_test_file(filename, netns):
rule_save = chain + " " + item[1]
res = item[2].rstrip()
-
- if netns:
- ret = run_test_netns(iptables, rule, rule_save,
- res, filename, lineno + 1)
- else:
- ret = run_test(iptables, rule, rule_save,
- res, filename, lineno + 1, False)
+ ret = run_test(iptables, rule, rule_save,
+ res, filename, lineno + 1, netns)
if ret < 0:
test_passed = False
@@ -261,6 +279,8 @@ def run_test_file(filename, netns):
if test_passed:
passed += 1
+ if netns:
+ execute_cmd("ip netns del ____iptables-container-test", filename, 0)
if total_test_passed:
print filename + ": " + Colors.GREEN + "OK" + Colors.ENDC
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index bd78a866..1a98996f 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -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,25 +627,29 @@ 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))
@@ -596,12 +657,6 @@ __nft_arp_save_rule(const void *data, unsigned int format)
}
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 = {};
@@ -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,
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 35c862cf..ad583a60 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -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));
+ int j;
+
+ for (j = 0; j < ETH_ALEN; j++)
+ 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,
+ if (format & FMT_EBT_SAVE)
+ 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,
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
index 9d49ccbe..de52cd71 100644
--- a/iptables/nft-bridge.h
+++ b/iptables/nft-bridge.h
@@ -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",
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 39e61844..ffb439b4 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -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;
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 1952164e..7bacee4a 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -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)
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 492e4ec1..7b8ca5e4 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -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,
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 1281f080..e3ecdb4d 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -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[],
diff --git a/iptables/nft.c b/iptables/nft.c
index b81f41ab..e8538d38 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -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);
- nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
- nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
+ 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;
diff --git a/iptables/nft.h b/iptables/nft.h
index 7419ec21..9b4ba5f9 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -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);
diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
index 67265c83..73b3b0cf 100755
--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
+++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
@@ -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
'
diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
index b2ed95e8..ee17da00 100755
--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
+++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
@@ -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
diff --git a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
index eeb7d835..b23c1ee1 100755
--- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
+++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
@@ -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
diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
index 34dffeee..5b6e1f6f 100755
--- a/iptables/tests/shell/testcases/iptables/0004-return-codes_0
+++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
@@ -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
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 6939a611..819e7e6c 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -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);
- }*/
- break;
-
+ 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':
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 64f332c1..87189144 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -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);
- cs.jumpto = parse_target(optarg);
- cs.target = ebt_command_jump(cs.jumpto);
+ 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);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index d9faa4d0..f5297740 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -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");
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index 53ce4b87..bed3ee03 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -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;
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index f4c0f9cf..849c53f3 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -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 = {
diff --git a/iptables/xtables.c b/iptables/xtables.c
index e0343dba..24a6e234 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -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");
}
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 34a084f4..ea9bb102 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -2077,6 +2077,28 @@ void xtables_print_num(uint64_t number, unsigned int format)
printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
}
+void xtables_print_mac(const unsigned char *macaddress)
+{
+ unsigned int i;
+
+ printf("%02x", macaddress[0]);
+ for (i = 1; i < 6; ++i)
+ printf(":%02x", macaddress[i]);
+}
+
+void xtables_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
+{
+ static const char hlpmsk[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ xtables_print_mac(mac);
+
+ if (memcmp(mask, hlpmsk, 6) == 0)
+ return;
+
+ printf("/");
+ xtables_print_mac(mask);
+}
+
void xtables_parse_val_mask(struct xt_option_call *cb,
unsigned int *val, unsigned int *mask,
const struct xtables_lmap *lmap)
@@ -2190,6 +2212,7 @@ struct xt_xlate *xt_xlate_alloc(int size)
if (xl->buf.data == NULL)
xtables_error(RESOURCE_PROBLEM, "OOM");
+ xl->buf.data[0] = '\0';
xl->buf.size = size;
xl->buf.rem = size;
xl->buf.off = 0;