diff options
author | Maciej Żenczykowski <maze@google.com> | 2020-04-08 07:13:35 -0700 |
---|---|---|
committer | Maciej Żenczykowski <maze@google.com> | 2020-04-08 07:13:46 -0700 |
commit | ea80eaf31e509bdd4d0e05ccd652b8f9e4896842 (patch) | |
tree | a49ad639f248dbfec523b80a54cd31a5a335539c | |
parent | 65a64d8480b9d2bb78feb93e744756839d713f4e (diff) | |
parent | bba6bc692b0e6137e13881a1f398c134822e9f83 (diff) | |
download | iptables-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
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; |