summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/GNUmakefile.in76
-rw-r--r--extensions/libarpt_mangle.c204
-rw-r--r--extensions/libebt_802_3.c133
-rw-r--r--extensions/libebt_ip.c312
-rw-r--r--extensions/libebt_limit.c179
-rw-r--r--extensions/libebt_log.c197
-rw-r--r--extensions/libebt_mark.c191
-rw-r--r--extensions/libebt_mark_m.c118
-rw-r--r--extensions/libebt_nflog.c144
-rw-r--r--extensions/libip6t_DNAT.t8
-rw-r--r--extensions/libip6t_DNPT.c8
-rw-r--r--extensions/libip6t_DNPT.t7
-rw-r--r--extensions/libip6t_HL.t10
-rw-r--r--extensions/libip6t_MASQUERADE.t8
-rw-r--r--extensions/libip6t_NETMAP.t4
-rw-r--r--extensions/libip6t_REDIRECT.t6
-rw-r--r--extensions/libip6t_SNAT.t8
-rw-r--r--extensions/libip6t_SNPT.c8
-rw-r--r--extensions/libip6t_SNPT.t7
-rw-r--r--extensions/libip6t_dst.c2
-rw-r--r--extensions/libip6t_dst.t5
-rw-r--r--extensions/libip6t_frag.t11
-rw-r--r--extensions/libip6t_hbh.t5
-rw-r--r--extensions/libip6t_hl.t8
-rw-r--r--extensions/libip6t_icmp6.t6
-rw-r--r--extensions/libip6t_ipv6header.t4
-rw-r--r--extensions/libip6t_mh.t6
-rw-r--r--extensions/libip6t_rt.t4
-rw-r--r--extensions/libipt_MIRROR.c15
-rw-r--r--extensions/libipt_MIRROR.man12
-rw-r--r--extensions/libipt_NETMAP.t4
-rw-r--r--extensions/libipt_REDIRECT.t6
-rw-r--r--extensions/libipt_SAME.c186
-rw-r--r--extensions/libipt_SAME.man17
-rw-r--r--extensions/libipt_TTL.t10
-rw-r--r--extensions/libipt_realm.t4
-rw-r--r--extensions/libipt_unclean.c15
-rw-r--r--extensions/libipt_unclean.man2
-rw-r--r--extensions/libxt_CLASSIFY.c44
-rw-r--r--extensions/libxt_CONNSECMARK.t5
-rw-r--r--extensions/libxt_HMARK.t8
-rw-r--r--extensions/libxt_IDLETIMER.t4
-rw-r--r--extensions/libxt_LED.t4
-rw-r--r--extensions/libxt_RATEEST.t2
-rw-r--r--extensions/libxt_SET.t3
-rw-r--r--extensions/libxt_SYNPROXY.t3
-rw-r--r--extensions/libxt_TCPMSS.t6
-rw-r--r--extensions/libxt_TCPOPTSTRIP.t8
-rw-r--r--extensions/libxt_TEE.c4
-rw-r--r--extensions/libxt_TPROXY.t5
-rw-r--r--extensions/libxt_bpf.t2
-rw-r--r--extensions/libxt_cgroup.man18
-rw-r--r--extensions/libxt_ecn.t5
-rw-r--r--extensions/libxt_mac.t5
-rw-r--r--extensions/libxt_osf.t4
-rw-r--r--extensions/libxt_physdev.man14
-rw-r--r--extensions/libxt_policy.t5
-rw-r--r--extensions/libxt_quota.c2
-rw-r--r--extensions/libxt_quota.t7
-rw-r--r--extensions/libxt_recent.t11
-rw-r--r--extensions/libxt_rpfilter.t4
-rw-r--r--extensions/libxt_set.t4
-rw-r--r--extensions/libxt_socket.t4
-rw-r--r--extensions/libxt_statistic.t8
-rw-r--r--extensions/libxt_string.man3
-rw-r--r--extensions/libxt_tcp.man1
-rw-r--r--extensions/libxt_tcpmss.t5
-rw-r--r--extensions/libxt_u32.t2
68 files changed, 1850 insertions, 300 deletions
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 52915725..4e94bd01 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -39,16 +39,24 @@ endif
# Wildcard module list
#
pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
+pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c)))
+pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c)))
pfx_symlinks := NOTRACK state
@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod})
+pfb_build_mod := $(filter-out @blacklist_modules@,${pfb_build_mod})
+pfa_build_mod := $(filter-out @blacklist_modules@,${pfa_build_mod})
pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod})
pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod})
pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
+pfb_objs := $(patsubst %,libebt_%.o,${pfb_build_mod})
+pfa_objs := $(patsubst %,libarpt_%.o,${pfa_build_mod})
pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks})
+pfb_solibs := $(patsubst %,libebt_%.so,${pfb_build_mod})
+pfa_solibs := $(patsubst %,libarpt_%.so,${pfa_build_mod})
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
@@ -56,13 +64,15 @@ pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
#
# Building blocks
#
-targets := libext.a libext4.a libext6.a matches.man targets.man
+targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man
targets_install :=
@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
+@ENABLE_STATIC_TRUE@ libext_ebt_objs := ${pfb_objs}
+@ENABLE_STATIC_TRUE@ libext_arpt_objs := ${pfa_objs}
@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
@ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs}
-@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
-@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
+@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
.SECONDARY:
@@ -75,7 +85,7 @@ install: ${targets_install}
if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
clean:
- rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c;
+ rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c initextb.c initexta.c;
rm -f .*.d .*.dd;
distclean: clean
@@ -118,6 +128,12 @@ lib%.o: ${srcdir}/lib%.c
libext.a: initext.o ${libext_objs}
${AM_VERBOSE_AR} ${AR} crs $@ $^;
+libext_ebt.a: initextb.o ${libext_ebt_objs}
+ ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+
+libext_arpt.a: initexta.o ${libext_arpt_objs}
+ ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+
libext4.a: initext4.o ${libext4_objs}
${AM_VERBOSE_AR} ${AR} crs $@ $^;
@@ -125,6 +141,8 @@ libext6.a: initext6.o ${libext6_objs}
${AM_VERBOSE_AR} ${AR} crs $@ $^;
initext_func := $(addprefix xt_,${pfx_build_mod})
+initextb_func := $(addprefix ebt_,${pfb_build_mod})
+initexta_func := $(addprefix arpt_,${pfa_build_mod})
initext4_func := $(addprefix ipt_,${pf4_build_mod})
initext6_func := $(addprefix ip6t_,${pf6_build_mod})
@@ -133,6 +151,16 @@ initext6_func := $(addprefix ip6t_,${pf6_build_mod})
cmp -s $@ $@.tmp || mv $@.tmp $@; \
rm -f $@.tmp;
+.initextb.dd: FORCE
+ @echo "${initextb_func}" >$@.tmp; \
+ cmp -s $@ $@.tmp || mv $@.tmp $@; \
+ rm -f $@.tmp;
+
+.initexta.dd: FORCE
+ @echo "${initexta_func}" >$@.tmp; \
+ cmp -s $@ $@.tmp || mv $@.tmp $@; \
+ rm -f $@.tmp;
+
.initext4.dd: FORCE
@echo "${initext4_func}" >$@.tmp; \
cmp -s $@ $@.tmp || mv $@.tmp $@; \
@@ -159,6 +187,38 @@ initext.c: .initext.dd
echo "}" >>$@; \
);
+initextb.c: .initextb.dd
+ ${AM_VERBOSE_GEN}
+ @( \
+ echo "" >$@; \
+ for i in ${initextb_func}; do \
+ echo "extern void lib$${i}_init(void);" >>$@; \
+ done; \
+ echo "void init_extensionsb(void);" >>$@; \
+ echo "void init_extensionsb(void)" >>$@; \
+ echo "{" >>$@; \
+ for i in ${initextb_func}; do \
+ echo " ""lib$${i}_init();" >>$@; \
+ done; \
+ echo "}" >>$@; \
+ );
+
+initexta.c: .initexta.dd
+ ${AM_VERBOSE_GEN}
+ @( \
+ echo "" >$@; \
+ for i in ${initexta_func}; do \
+ echo "extern void lib$${i}_init(void);" >>$@; \
+ done; \
+ echo "void init_extensionsa(void);" >>$@; \
+ echo "void init_extensionsa(void)" >>$@; \
+ echo "{" >>$@; \
+ for i in ${initexta_func}; do \
+ echo " ""lib$${i}_init();" >>$@; \
+ done; \
+ echo "}" >>$@; \
+ );
+
initext4.c: .initext4.dd
${AM_VERBOSE_GEN}
@( \
@@ -219,8 +279,8 @@ man_run = \
fi; \
done >$@;
-matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
+matches.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_matches,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
-targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
+targets.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_targets,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c
new file mode 100644
index 00000000..03c31a94
--- /dev/null
+++ b/extensions/libarpt_mangle.c
@@ -0,0 +1,204 @@
+/*
+ * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> adapted
+ * this code to libxtables for arptables-compat in 2015
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <getopt.h>
+#include <netinet/ether.h>
+#include <xtables.h>
+#include <linux/netfilter_arp/arpt_mangle.h>
+#include "iptables/nft.h"
+#include "iptables/nft-arp.h"
+
+static void arpmangle_print_help(void)
+{
+ printf(
+ "mangle target options:\n"
+ "--mangle-ip-s IP address\n"
+ "--mangle-ip-d IP address\n"
+ "--mangle-mac-s MAC address\n"
+ "--mangle-mac-d MAC address\n"
+ "--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n");
+}
+
+#define MANGLE_IPS '1'
+#define MANGLE_IPT '2'
+#define MANGLE_DEVS '3'
+#define MANGLE_DEVT '4'
+#define MANGLE_TARGET '5'
+
+static struct option arpmangle_opts[] = {
+ { .name = "mangle-ip-s", .has_arg = true, .val = MANGLE_IPS },
+ { .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT },
+ { .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS },
+ { .name = "mangle-mac-d", .has_arg = true, .val = MANGLE_DEVT },
+ { .name = "mangle-target", .has_arg = true, .val = MANGLE_TARGET },
+ XT_GETOPT_TABLEEND,
+};
+
+static void arpmangle_init(struct xt_entry_target *target)
+{
+ struct arpt_mangle *mangle = (struct arpt_mangle *)target->data;
+
+ mangle->target = NF_ACCEPT;
+}
+
+static int
+arpmangle_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data;
+ struct in_addr *ipaddr, mask;
+ struct ether_addr *macaddr;
+ const struct arpt_entry *e = (const struct arpt_entry *)entry;
+ unsigned int nr;
+ int ret = 1;
+
+ memset(&mask, 0, sizeof(mask));
+
+ switch (c) {
+ case MANGLE_IPS:
+ xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
+ mangle->u_s.src_ip.s_addr = ipaddr->s_addr;
+ free(ipaddr);
+ mangle->flags |= ARPT_MANGLE_SIP;
+ break;
+ case MANGLE_IPT:
+ xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
+ mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr;
+ free(ipaddr);
+ mangle->flags |= ARPT_MANGLE_TIP;
+ break;
+ case MANGLE_DEVS:
+ if (e->arp.arhln_mask == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "no --h-length defined");
+ if (e->arp.invflags & ARPT_INV_ARPHLN)
+ xtables_error(PARAMETER_PROBLEM,
+ "! --h-length not allowed for "
+ "--mangle-mac-s");
+ if (e->arp.arhln != 6)
+ xtables_error(PARAMETER_PROBLEM,
+ "only --h-length 6 supported");
+ macaddr = ether_aton(optarg);
+ if (macaddr == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "invalid source MAC");
+ memcpy(mangle->src_devaddr, macaddr, e->arp.arhln);
+ mangle->flags |= ARPT_MANGLE_SDEV;
+ break;
+ case MANGLE_DEVT:
+ if (e->arp.arhln_mask == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "no --h-length defined");
+ if (e->arp.invflags & ARPT_INV_ARPHLN)
+ xtables_error(PARAMETER_PROBLEM,
+ "! hln not allowed for --mangle-mac-d");
+ if (e->arp.arhln != 6)
+ xtables_error(PARAMETER_PROBLEM,
+ "only --h-length 6 supported");
+ macaddr = ether_aton(optarg);
+ if (macaddr == NULL)
+ xtables_error(PARAMETER_PROBLEM, "invalid target MAC");
+ memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln);
+ mangle->flags |= ARPT_MANGLE_TDEV;
+ break;
+ case MANGLE_TARGET:
+ if (!strcmp(optarg, "DROP"))
+ mangle->target = NF_DROP;
+ else if (!strcmp(optarg, "ACCEPT"))
+ mangle->target = NF_ACCEPT;
+ else if (!strcmp(optarg, "CONTINUE"))
+ mangle->target = XT_CONTINUE;
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "bad target for --mangle-target");
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void arpmangle_final_check(unsigned int flags)
+{
+}
+
+static void print_mac(const unsigned char *mac, int l)
+{
+ int j;
+
+ for (j = 0; j < l; j++)
+ printf("%02x%s", mac[j],
+ (j==l-1) ? "" : ":");
+}
+
+static void
+arpmangle_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ struct arpt_mangle *m = (struct arpt_mangle *)(target->data);
+ char buf[100];
+
+ if (m->flags & ARPT_MANGLE_SIP) {
+ if (numeric)
+ sprintf(buf, "%s",
+ xtables_ipaddr_to_numeric(&(m->u_s.src_ip)));
+ else
+ sprintf(buf, "%s",
+ xtables_ipaddr_to_anyname(&(m->u_s.src_ip)));
+ printf("--mangle-ip-s %s ", buf);
+ }
+ if (m->flags & ARPT_MANGLE_SDEV) {
+ printf("--mangle-mac-s ");
+ print_mac((unsigned char *)m->src_devaddr, 6);
+ printf(" ");
+ }
+ if (m->flags & ARPT_MANGLE_TIP) {
+ if (numeric)
+ sprintf(buf, "%s",
+ xtables_ipaddr_to_numeric(&(m->u_t.tgt_ip)));
+ else
+ sprintf(buf, "%s",
+ xtables_ipaddr_to_anyname(&(m->u_t.tgt_ip)));
+ printf("--mangle-ip-d %s ", buf);
+ }
+ if (m->flags & ARPT_MANGLE_TDEV) {
+ printf("--mangle-mac-d ");
+ print_mac((unsigned char *)m->tgt_devaddr, 6);
+ printf(" ");
+ }
+ if (m->target != NF_ACCEPT) {
+ printf("--mangle-target ");
+ if (m->target == NF_DROP)
+ printf("DROP ");
+ else
+ printf("CONTINUE ");
+ }
+}
+
+static struct xtables_target arpmangle_target = {
+ .name = "mangle",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_ARP,
+ .size = XT_ALIGN(sizeof(struct arpt_mangle)),
+ .userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)),
+ .help = arpmangle_print_help,
+ .init = arpmangle_init,
+ .parse = arpmangle_parse,
+ .final_check = arpmangle_final_check,
+ .print = arpmangle_print,
+ .extra_opts = arpmangle_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&arpmangle_target);
+}
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
new file mode 100644
index 00000000..3c4a1c3c
--- /dev/null
+++ b/extensions/libebt_802_3.c
@@ -0,0 +1,133 @@
+/* 802_3
+ *
+ * Author:
+ * Chris Vitale <csv@bluetail.com>
+ *
+ * May 2003
+ *
+ * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * to use libxtables for ebtables-compat
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_802_3.h>
+
+#define _802_3_SAP '1'
+#define _802_3_TYPE '2'
+
+static const struct option br802_3_opts[] = {
+ { .name = "802_3-sap", .has_arg = true, .val = _802_3_SAP },
+ { .name = "802_3-type", .has_arg = true, .val = _802_3_TYPE },
+ XT_GETOPT_TABLEEND,
+};
+
+static void br802_3_print_help(void)
+{
+ printf(
+"802_3 options:\n"
+"--802_3-sap [!] protocol : 802.3 DSAP/SSAP- 1 byte value (hex)\n"
+" DSAP and SSAP are always the same. One SAP applies to both fields\n"
+"--802_3-type [!] protocol : 802.3 SNAP Type- 2 byte value (hex)\n"
+" Type implies SAP value 0xaa\n");
+}
+
+static void br802_3_init(struct xt_entry_match *match)
+{
+ struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
+
+ info->invflags = 0;
+ info->bitmask = 0;
+}
+
+static int
+br802_3_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ebt_802_3_info *info = (struct ebt_802_3_info *) (*match)->data;
+ unsigned int i;
+ char *end;
+
+ switch (c) {
+ case _802_3_SAP:
+ if (invert)
+ info->invflags |= EBT_802_3_SAP;
+ i = strtoul(optarg, &end, 16);
+ if (i > 255 || *end != '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified "
+ "sap hex value, %x",i);
+ info->sap = i; /* one byte, so no byte order worries */
+ info->bitmask |= EBT_802_3_SAP;
+ break;
+ case _802_3_TYPE:
+ if (invert)
+ info->invflags |= EBT_802_3_TYPE;
+ i = strtoul(optarg, &end, 16);
+ if (i > 65535 || *end != '\0') {
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the specified "
+ "type hex value, %x",i);
+ }
+ info->type = htons(i);
+ info->bitmask |= EBT_802_3_TYPE;
+ break;
+ default:
+ return 0;
+ }
+
+ *flags |= info->bitmask;
+ return 1;
+}
+
+static void
+br802_3_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify proper arguments");
+}
+
+static void br802_3_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ 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("0x%.2x ", info->sap);
+ }
+ if (info->bitmask & EBT_802_3_TYPE) {
+ printf("--802_3-type ");
+ if (info->invflags & EBT_802_3_TYPE)
+ printf("! ");
+ printf("0x%.4x ", ntohs(info->type));
+ }
+}
+
+static struct xtables_match br802_3_match =
+{
+ .name = "802_3",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_802_3_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
+ .init = br802_3_init,
+ .help = br802_3_print_help,
+ .parse = br802_3_parse,
+ .final_check = br802_3_final_check,
+ .print = br802_3_print,
+ .extra_opts = br802_3_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&br802_3_match);
+}
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
new file mode 100644
index 00000000..8b628760
--- /dev/null
+++ b/extensions/libebt_ip.c
@@ -0,0 +1,312 @@
+/* ebt_ip
+ *
+ * Authors:
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * Changes:
+ * added ip-sport and ip-dport; parsing of port arguments is
+ * based on code from iptables-1.2.7a
+ * Innominate Security Technologies AG <mhopf@innominate.com>
+ * September, 2002
+ *
+ * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * to use libxtables for ebtables-compat in 2015.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_ip.h>
+
+#define IP_SOURCE '1'
+#define IP_DEST '2'
+#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
+#define IP_PROTO '4'
+#define IP_SPORT '5'
+#define IP_DPORT '6'
+
+static const struct option brip_opts[] = {
+ { .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
+ { .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
+ { .name = "ip-destination", .has_arg = true, .val = IP_DEST },
+ { .name = "ip-dst", .has_arg = true, .val = IP_DEST },
+ { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
+ { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
+ { .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
+ { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
+ { .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
+ { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
+ { .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brip_print_help(void)
+{
+ printf(
+"ip options:\n"
+"--ip-src [!] address[/mask]: ip source specification\n"
+"--ip-dst [!] address[/mask]: ip destination specification\n"
+"--ip-tos [!] tos : ip tos specification\n"
+"--ip-proto [!] protocol : ip protocol specification\n"
+"--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
+"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
+}
+
+static void brip_init(struct xt_entry_match *match)
+{
+ struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
+
+ info->invflags = 0;
+ info->bitmask = 0;
+}
+
+static void
+parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(portstring);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
+ else {
+ *cp = '\0';
+ cp++;
+
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
+ ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
+
+ if (ports[0] > ports[1])
+ xtables_error(PARAMETER_PROBLEM,
+ "invalid portrange (min > max)");
+ }
+ free(buffer);
+}
+
+/* original code from ebtables: useful_functions.c */
+static int undot_ip(char *ip, unsigned char *ip2)
+{
+ char *p, *q, *end;
+ long int onebyte;
+ int i;
+ char buf[20];
+
+ strncpy(buf, ip, sizeof(buf) - 1);
+
+ p = buf;
+ for (i = 0; i < 3; i++) {
+ if ((q = strchr(p, '.')) == NULL)
+ return -1;
+ *q = '\0';
+ onebyte = strtol(p, &end, 10);
+ if (*end != '\0' || onebyte > 255 || onebyte < 0)
+ return -1;
+ ip2[i] = (unsigned char)onebyte;
+ p = q + 1;
+ }
+
+ onebyte = strtol(p, &end, 10);
+ if (*end != '\0' || onebyte > 255 || onebyte < 0)
+ return -1;
+ ip2[3] = (unsigned char)onebyte;
+
+ return 0;
+}
+
+static int ip_mask(char *mask, unsigned char *mask2)
+{
+ char *end;
+ long int bits;
+ uint32_t mask22;
+
+ if (undot_ip(mask, mask2)) {
+ /* not the /a.b.c.e format, maybe the /x format */
+ bits = strtol(mask, &end, 10);
+ if (*end != '\0' || bits > 32 || bits < 0)
+ return -1;
+ if (bits != 0) {
+ mask22 = htonl(0xFFFFFFFF << (32 - bits));
+ memcpy(mask2, &mask22, 4);
+ } else {
+ mask22 = 0xFFFFFFFF;
+ memcpy(mask2, &mask22, 4);
+ }
+ }
+ return 0;
+}
+
+static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
+{
+ char *p;
+
+ /* first the mask */
+ if ((p = strrchr(address, '/')) != NULL) {
+ *p = '\0';
+ if (ip_mask(p + 1, (unsigned char *)msk)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the IP mask '%s'", p + 1);
+ return;
+ }
+ } else
+ *msk = 0xFFFFFFFF;
+
+ if (undot_ip(address, (unsigned char *)addr)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the IP address '%s'", address);
+ return;
+ }
+ *addr = *addr & *msk;
+}
+
+static int
+brip_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
+
+ switch (c) {
+ case IP_SOURCE:
+ if (invert)
+ info->invflags |= EBT_IP_SOURCE;
+ ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
+ info->bitmask |= EBT_IP_SOURCE;
+ break;
+ case IP_DEST:
+ if (invert)
+ info->invflags |= EBT_IP_DEST;
+ ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
+ info->bitmask |= EBT_IP_DEST;
+ break;
+ case IP_SPORT:
+ if (invert)
+ info->invflags |= EBT_IP_SPORT;
+ parse_port_range(NULL, optarg, info->sport);
+ info->bitmask |= EBT_IP_SPORT;
+ break;
+ case IP_DPORT:
+ if (invert)
+ info->invflags |= EBT_IP_DPORT;
+ parse_port_range(NULL, optarg, info->dport);
+ info->bitmask |= EBT_IP_DPORT;
+ break;
+ case IP_EBT_TOS:
+ if (invert)
+ info->invflags |= EBT_IP_TOS;
+ if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos,
+ 0, 255))
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified IP tos");
+ info->bitmask |= EBT_IP_TOS;
+ break;
+ case IP_PROTO:
+ if (invert)
+ info->invflags |= EBT_IP_PROTO;
+ info->protocol = xtables_parse_protocol(optarg);
+ if (info->protocol == -1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown specified IP protocol - %s",
+ optarg);
+ info->bitmask |= EBT_IP_PROTO;
+ break;
+ default:
+ return 0;
+ }
+
+ *flags |= info->bitmask;
+ return 1;
+}
+
+static void brip_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify proper arguments");
+}
+
+static void print_port_range(uint16_t *ports)
+{
+ if (ports[0] == ports[1])
+ printf("%d ", ports[0]);
+ else
+ printf("%d:%d ", ports[0], ports[1]);
+}
+
+static void brip_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
+ struct in_addr *addrp, *maskp;
+
+ if (info->bitmask & EBT_IP_SOURCE) {
+ printf("--ip-src ");
+ if (info->invflags & EBT_IP_SOURCE)
+ printf("! ");
+ 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("! ");
+ 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("0x%02X ", info->tos);
+ }
+ if (info->bitmask & EBT_IP_PROTO) {
+ struct protoent *pe;
+
+ printf("--ip-proto ");
+ if (info->invflags & EBT_IP_PROTO)
+ printf("! ");
+ pe = getprotobynumber(info->protocol);
+ if (pe == NULL) {
+ printf("%d ", info->protocol);
+ } else {
+ printf("%s ", pe->p_name);
+ }
+ }
+ if (info->bitmask & EBT_IP_SPORT) {
+ printf("--ip-sport ");
+ if (info->invflags & EBT_IP_SPORT)
+ printf("! ");
+ print_port_range(info->sport);
+ }
+ if (info->bitmask & EBT_IP_DPORT) {
+ printf("--ip-dport ");
+ if (info->invflags & EBT_IP_DPORT)
+ printf("! ");
+ print_port_range(info->dport);
+ }
+}
+
+static struct xtables_match brip_match = {
+ .name = "ip",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_ip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
+ .init = brip_init,
+ .help = brip_print_help,
+ .parse = brip_parse,
+ .final_check = brip_final_check,
+ .print = brip_print,
+ .extra_opts = brip_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&brip_match);
+}
diff --git a/extensions/libebt_limit.c b/extensions/libebt_limit.c
new file mode 100644
index 00000000..c71561c1
--- /dev/null
+++ b/extensions/libebt_limit.c
@@ -0,0 +1,179 @@
+/* ebt_limit
+ *
+ * Authors:
+ * Tom Marshall <tommy@home.tig-grr.com>
+ *
+ * Mostly copied from iptables' limit match.
+ *
+ * September, 2003
+ *
+ * Translated to use libxtables for ebtables-compat in 2015 by
+ * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_limit.h>
+#include "iptables/nft.h"
+#include "iptables/nft-bridge.h"
+
+#define EBT_LIMIT_AVG "3/hour"
+#define EBT_LIMIT_BURST 5
+
+#define FLAG_LIMIT 0x01
+#define FLAG_LIMIT_BURST 0x02
+#define ARG_LIMIT '1'
+#define ARG_LIMIT_BURST '2'
+
+static struct option brlimit_opts[] =
+{
+ { .name = "limit", .has_arg = true, .val = ARG_LIMIT },
+ { .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brlimit_print_help(void)
+{
+ printf(
+"limit options:\n"
+"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+"--limit-burst number : number to match in a burst, -1 < number < 10001,\n"
+" default %u\n", EBT_LIMIT_BURST);
+}
+
+static int parse_rate(const char *rate, uint32_t *val)
+{
+ const char *delim;
+ uint32_t r;
+ uint32_t mult = 1; /* Seconds by default. */
+
+ delim = strchr(rate, '/');
+ if (delim) {
+ if (strlen(delim+1) == 0)
+ return 0;
+
+ if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
+ mult = 1;
+ else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
+ mult = 60;
+ else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
+ mult = 60*60;
+ else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
+ mult = 24*60*60;
+ else
+ return 0;
+ }
+ r = atoi(rate);
+ if (!r)
+ return 0;
+
+ /* This would get mapped to infinite (1/day is minimum they
+ can specify, so we're ok at that end). */
+ if (r / mult > EBT_LIMIT_SCALE)
+ return 0;
+
+ *val = EBT_LIMIT_SCALE * mult / r;
+ return 1;
+}
+
+static void brlimit_init(struct xt_entry_match *match)
+{
+ struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
+
+ parse_rate(EBT_LIMIT_AVG, &r->avg);
+ r->burst = EBT_LIMIT_BURST;
+}
+
+static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data;
+ uintmax_t num;
+
+ switch (c) {
+ case ARG_LIMIT:
+ EBT_CHECK_OPTION(flags, FLAG_LIMIT);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --limit");
+ if (!parse_rate(optarg, &r->avg))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad rate `%s'", optarg);
+ break;
+ case ARG_LIMIT_BURST:
+ EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --limit-burst");
+ if (!xtables_strtoul(optarg, NULL, &num, 0, 10000))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --limit-burst `%s'", optarg);
+ r->burst = num;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+struct rates
+{
+ const char *name;
+ uint32_t mult;
+};
+
+static struct rates g_rates[] =
+{
+ { "day", EBT_LIMIT_SCALE*24*60*60 },
+ { "hour", EBT_LIMIT_SCALE*60*60 },
+ { "min", EBT_LIMIT_SCALE*60 },
+ { "sec", EBT_LIMIT_SCALE }
+};
+
+static void print_rate(uint32_t period)
+{
+ unsigned int i;
+
+ for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++)
+ if (period > g_rates[i].mult ||
+ g_rates[i].mult/period < g_rates[i].mult%period)
+ break;
+
+ printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name);
+}
+
+static void brlimit_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
+
+ printf("--limit ");
+ print_rate(r->avg);
+ printf("--limit-burst %u ", r->burst);
+}
+
+static struct xtables_match brlimit_match = {
+ .name = "limit",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_limit_info)),
+ .userspacesize = offsetof(struct ebt_limit_info, prev),
+ .init = brlimit_init,
+ .help = brlimit_print_help,
+ .parse = brlimit_parse,
+ .print = brlimit_print,
+ .extra_opts = brlimit_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&brlimit_match);
+}
diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
new file mode 100644
index 00000000..0799185d
--- /dev/null
+++ b/extensions/libebt_log.c
@@ -0,0 +1,197 @@
+/*
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the
+ * xtables-compat environment in 2015.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_log.h>
+
+#define LOG_DEFAULT_LEVEL LOG_INFO
+
+#define LOG_PREFIX '1'
+#define LOG_LEVEL '2'
+#define LOG_ARP '3'
+#define LOG_IP '4'
+#define LOG_LOG '5'
+#define LOG_IP6 '6'
+
+typedef struct _code {
+ char *c_name;
+ int c_val;
+} CODE;
+
+static CODE eight_priority[] = {
+ { "emerg", LOG_EMERG },
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "error", LOG_ERR },
+ { "warning", LOG_WARNING },
+ { "notice", LOG_NOTICE },
+ { "info", LOG_INFO },
+ { "debug", LOG_DEBUG }
+};
+
+static int name_to_loglevel(const char *arg)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (!strcmp(arg, eight_priority[i].c_name))
+ return eight_priority[i].c_val;
+
+ /* return bad loglevel */
+ return 9;
+}
+
+static const struct option brlog_opts[] = {
+ { .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX },
+ { .name = "log-level", .has_arg = true, .val = LOG_LEVEL },
+ { .name = "log-arp", .has_arg = false, .val = LOG_ARP },
+ { .name = "log-ip", .has_arg = false, .val = LOG_IP },
+ { .name = "log", .has_arg = false, .val = LOG_LOG },
+ { .name = "log-ip6", .has_arg = false, .val = LOG_IP6 },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brlog_help(void)
+{
+ int i;
+
+ printf(
+"log options:\n"
+"--log : use this if you're not specifying anything\n"
+"--log-level level : level = [1-8] or a string\n"
+"--log-prefix prefix : max. %d chars.\n"
+"--log-ip : put ip info. in the log for ip packets\n"
+"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
+"--log-ip6 : put ip6 info. in the log for ip6 packets\n"
+ , EBT_LOG_PREFIX_SIZE - 1);
+ for (i = 0; i < 8; i++)
+ printf("%d = %s\n", eight_priority[i].c_val,
+ eight_priority[i].c_name);
+}
+
+static void brlog_init(struct xt_entry_target *t)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
+
+ loginfo->bitmask = 0;
+ loginfo->prefix[0] = '\0';
+ loginfo->loglevel = LOG_NOTICE;
+}
+
+static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
+ long int i;
+ char *end;
+
+ switch (c) {
+ case LOG_PREFIX:
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!` after --log-prefix");
+ if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Prefix too long");
+ if (strchr(optarg, '\"'))
+ xtables_error(PARAMETER_PROBLEM,
+ "Use of \\\" is not allowed"
+ " in the prefix");
+ strcpy((char *)loginfo->prefix, (char *)optarg);
+ break;
+ case LOG_LEVEL:
+ i = strtol(optarg, &end, 16);
+ if (*end != '\0' || i < 0 || i > 7)
+ loginfo->loglevel = name_to_loglevel(optarg);
+ else
+ loginfo->loglevel = i;
+
+ if (loginfo->loglevel == 9)
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the log-level");
+ break;
+ case LOG_IP:
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --log-ip");
+ loginfo->bitmask |= EBT_LOG_IP;
+ break;
+ case LOG_ARP:
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --log-arp");
+ loginfo->bitmask |= EBT_LOG_ARP;
+ case LOG_LOG:
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --log");
+ break;
+ case LOG_IP6:
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --log-ip6");
+ loginfo->bitmask |= EBT_LOG_IP6;
+ break;
+ default:
+ return 0;
+ }
+
+ *flags |= loginfo->bitmask;
+ return 1;
+}
+
+static void brlog_final_check(unsigned int flags)
+{
+}
+
+static void brlog_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
+
+ printf("--log-level %s --log-prefix \"%s\"",
+ eight_priority[loginfo->loglevel].c_name,
+ loginfo->prefix);
+
+ if (loginfo->bitmask & EBT_LOG_IP)
+ printf(" --log-ip");
+ if (loginfo->bitmask & EBT_LOG_ARP)
+ printf(" --log-arp");
+ if (loginfo->bitmask & EBT_LOG_IP6)
+ printf(" --log-ip6");
+ printf(" ");
+}
+
+static struct xtables_target brlog_target = {
+ .name = "log",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_log_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
+ .init = brlog_init,
+ .help = brlog_help,
+ .parse = brlog_parse,
+ .final_check = brlog_final_check,
+ .print = brlog_print,
+ .extra_opts = brlog_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&brlog_target);
+}
diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c
new file mode 100644
index 00000000..587b4a63
--- /dev/null
+++ b/extensions/libebt_mark.c
@@ -0,0 +1,191 @@
+/* ebt_mark
+ *
+ * Authors:
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * July, 2002, September 2006
+ *
+ * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * to use libxtables for ebtables-compat in 2015.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_mark_t.h>
+#include "iptables/nft.h"
+#include "iptables/nft-bridge.h"
+
+static int mark_supplied;
+
+#define MARK_TARGET '1'
+#define MARK_SETMARK '2'
+#define MARK_ORMARK '3'
+#define MARK_ANDMARK '4'
+#define MARK_XORMARK '5'
+static struct option brmark_opts[] = {
+ { .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
+ /* an oldtime messup, we should have always used the scheme
+ * <extension-name>-<option> */
+ { .name = "set-mark", .has_arg = true, .val = MARK_SETMARK },
+ { .name = "mark-set", .has_arg = true, .val = MARK_SETMARK },
+ { .name = "mark-or", .has_arg = true, .val = MARK_ORMARK },
+ { .name = "mark-and", .has_arg = true, .val = MARK_ANDMARK },
+ { .name = "mark-xor", .has_arg = true, .val = MARK_XORMARK },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brmark_print_help(void)
+{
+ printf(
+ "mark target options:\n"
+ " --mark-set value : Set nfmark value\n"
+ " --mark-or value : Or nfmark with value (nfmark |= value)\n"
+ " --mark-and value : And nfmark with value (nfmark &= value)\n"
+ " --mark-xor value : Xor nfmark with value (nfmark ^= value)\n"
+ " --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
+}
+
+static void brmark_init(struct xt_entry_target *target)
+{
+ struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
+
+ info->target = EBT_ACCEPT;
+ info->mark = 0;
+ mark_supplied = 0;
+}
+
+#define OPT_MARK_TARGET 0x01
+#define OPT_MARK_SETMARK 0x02
+#define OPT_MARK_ORMARK 0x04
+#define OPT_MARK_ANDMARK 0x08
+#define OPT_MARK_XORMARK 0x10
+
+static int
+brmark_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)
+ (*target)->data;
+ char *end;
+ uint32_t mask;
+
+ switch (c) {
+ case MARK_TARGET:
+ { unsigned int tmp;
+ EBT_CHECK_OPTION(flags, OPT_MARK_TARGET);
+ if (ebt_fill_target(optarg, &tmp))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --mark-target target");
+ /* the 4 lsb are left to designate the target */
+ info->target = (info->target & ~EBT_VERDICT_BITS) |
+ (tmp & EBT_VERDICT_BITS);
+ }
+ return 1;
+ case MARK_SETMARK:
+ EBT_CHECK_OPTION(flags, OPT_MARK_SETMARK);
+ mask = (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
+ if (*flags & mask)
+ xtables_error(PARAMETER_PROBLEM,
+ "--mark-set cannot be used together with"
+ " specific --mark option");
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ MARK_SET_VALUE;
+ break;
+ case MARK_ORMARK:
+ EBT_CHECK_OPTION(flags, OPT_MARK_ORMARK);
+ mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
+ if (*flags & mask)
+ xtables_error(PARAMETER_PROBLEM,
+ "--mark-or cannot be used together with"
+ " specific --mark option");
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ MARK_OR_VALUE;
+ break;
+ case MARK_ANDMARK:
+ EBT_CHECK_OPTION(flags, OPT_MARK_ANDMARK);
+ mask = (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK);
+ if (*flags & mask)
+ xtables_error(PARAMETER_PROBLEM,
+ "--mark-and cannot be used together with"
+ " specific --mark option");
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ MARK_AND_VALUE;
+ break;
+ case MARK_XORMARK:
+ EBT_CHECK_OPTION(flags, OPT_MARK_XORMARK);
+ mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK);
+ if (*flags & mask)
+ xtables_error(PARAMETER_PROBLEM,
+ "--mark-xor cannot be used together with"
+ " specific --mark option");
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ MARK_XOR_VALUE;
+ break;
+ default:
+ return 0;
+ }
+ /* mutual code */
+ info->mark = strtoul(optarg, &end, 0);
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'",
+ optarg);
+
+ mark_supplied = 1;
+ return 1;
+}
+
+static void brmark_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
+ int tmp;
+
+ tmp = info->target & ~EBT_VERDICT_BITS;
+ if (tmp == MARK_SET_VALUE)
+ printf("--mark-set");
+ else if (tmp == MARK_OR_VALUE)
+ printf("--mark-or");
+ else if (tmp == MARK_XOR_VALUE)
+ printf("--mark-xor");
+ else if (tmp == MARK_AND_VALUE)
+ printf("--mark-and");
+ else
+ xtables_error(PARAMETER_PROBLEM, "Unknown mark action");
+
+ printf(" 0x%lx", info->mark);
+ tmp = info->target | ~EBT_VERDICT_BITS;
+ printf(" --mark-target %s", ebt_target_name(tmp));
+}
+
+static void brmark_final_check(unsigned int flags)
+{
+ if (mark_supplied == 0)
+ xtables_error(PARAMETER_PROBLEM, "No mark value supplied");
+
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify some option");
+}
+
+static struct xtables_target brmark_target = {
+ .name = "mark",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
+ .help = brmark_print_help,
+ .init = brmark_init,
+ .parse = brmark_parse,
+ .final_check = brmark_final_check,
+ .print = brmark_print,
+ .extra_opts = brmark_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&brmark_target);
+}
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
new file mode 100644
index 00000000..ef9eb6a6
--- /dev/null
+++ b/extensions/libebt_mark_m.c
@@ -0,0 +1,118 @@
+/* ebt_mark_m
+ *
+ * Authors:
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * July, 2002
+ *
+ * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * to use libxtables for ebtables-compat in 2015.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_mark_m.h>
+
+#define MARK '1'
+
+static struct option brmark_m_opts[] = {
+ { .name = "mark", .has_arg = true, .val = MARK },
+ XT_GETOPT_TABLEEND,
+};
+
+static void brmark_m_print_help(void)
+{
+ printf(
+"mark option:\n"
+"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
+}
+
+static void brmark_m_init(struct xt_entry_match *match)
+{
+ struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
+
+ info->mark = 0;
+ info->mask = 0;
+ info->invert = 0;
+ info->bitmask = 0;
+}
+
+#define OPT_MARK 0x01
+static int
+brmark_m_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)
+ (*match)->data;
+ char *end;
+
+ switch (c) {
+ case MARK:
+ if (invert)
+ info->invert = 1;
+ info->mark = strtoul(optarg, &end, 0);
+ info->bitmask = EBT_MARK_AND;
+ if (*end == '/') {
+ if (end == optarg)
+ info->bitmask = EBT_MARK_OR;
+ info->mask = strtoul(end+1, &end, 0);
+ } else {
+ info->mask = 0xffffffff;
+ }
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
+ optarg);
+ break;
+ default:
+ return 0;
+ }
+
+ *flags |= info->bitmask;
+ return 1;
+}
+
+static void brmark_m_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify proper arguments");
+}
+
+static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
+
+ printf("--mark ");
+ if (info->invert)
+ printf("! ");
+ if (info->bitmask == EBT_MARK_OR)
+ printf("/0x%lx ", info->mask);
+ else if (info->mask != 0xffffffff)
+ printf("0x%lx/0x%lx ", info->mark, info->mask);
+ else
+ printf("0x%lx ", info->mark);
+}
+
+static struct xtables_match brmark_m_match = {
+ .name = "mark_m",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
+ .init = brmark_m_init,
+ .help = brmark_m_print_help,
+ .parse = brmark_m_parse,
+ .final_check = brmark_m_final_check,
+ .print = brmark_m_print,
+ .extra_opts = brmark_m_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&brmark_m_match);
+}
diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c
new file mode 100644
index 00000000..72bf3724
--- /dev/null
+++ b/extensions/libebt_nflog.c
@@ -0,0 +1,144 @@
+/* ebt_nflog
+ *
+ * Authors:
+ * Peter Warasin <peter@endian.com>
+ *
+ * February, 2008
+ *
+ * Based on:
+ * ebt_ulog.c, (C) 2004, Bart De Schuymer <bdschuym@pandora.be>
+ * libxt_NFLOG.c
+ *
+ * Adapted to libxtables for ebtables-compat in 2015 by
+ * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <xtables.h>
+#include "iptables/nft.h"
+#include "iptables/nft-bridge.h"
+#include <linux/netfilter_bridge/ebt_nflog.h>
+
+enum {
+ NFLOG_GROUP = 0x1,
+ NFLOG_PREFIX = 0x2,
+ NFLOG_RANGE = 0x4,
+ NFLOG_THRESHOLD = 0x8,
+ NFLOG_NFLOG = 0x16,
+};
+
+static struct option brnflog_opts[] = {
+ { .name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP},
+ { .name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX},
+ { .name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE},
+ { .name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD},
+ { .name = "nflog", .has_arg = false, .val = NFLOG_NFLOG},
+ XT_GETOPT_TABLEEND,
+};
+
+static void brnflog_help(void)
+{
+ printf("nflog options:\n"
+ "--nflog : use the default nflog parameters\n"
+ "--nflog-prefix prefix : Prefix string for log message\n"
+ "--nflog-group group : NETLINK group used for logging\n"
+ "--nflog-range range : Number of byte to copy\n"
+ "--nflog-threshold : Message threshold of"
+ "in-kernel queue\n");
+}
+
+static void brnflog_init(struct xt_entry_target *t)
+{
+ struct ebt_nflog_info *info = (struct ebt_nflog_info *)t->data;
+
+ info->prefix[0] = '\0';
+ info->group = EBT_NFLOG_DEFAULT_GROUP;
+ info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD;
+}
+
+static int brnflog_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct ebt_nflog_info *info = (struct ebt_nflog_info *)(*target)->data;
+ unsigned int i;
+
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "The use of '!' makes no sense for the"
+ " nflog watcher");
+
+ switch (c) {
+ case NFLOG_PREFIX:
+ EBT_CHECK_OPTION(flags, NFLOG_PREFIX);
+ if (strlen(optarg) > EBT_NFLOG_PREFIX_SIZE - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Prefix too long for nflog-prefix");
+ strncpy(info->prefix, optarg, EBT_NFLOG_PREFIX_SIZE);
+ break;
+ case NFLOG_GROUP:
+ EBT_CHECK_OPTION(flags, NFLOG_GROUP);
+ if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "--nflog-group must be a number!");
+ info->group = i;
+ break;
+ case NFLOG_RANGE:
+ EBT_CHECK_OPTION(flags, NFLOG_RANGE);
+ if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "--nflog-range must be a number!");
+ info->len = i;
+ break;
+ case NFLOG_THRESHOLD:
+ EBT_CHECK_OPTION(flags, NFLOG_THRESHOLD);
+ if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "--nflog-threshold must be a number!");
+ info->threshold = i;
+ break;
+ case NFLOG_NFLOG:
+ EBT_CHECK_OPTION(flags, NFLOG_NFLOG);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void
+brnflog_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ struct ebt_nflog_info *info = (struct ebt_nflog_info *)target->data;
+
+ if (info->prefix[0] != '\0')
+ printf("--nflog-prefix \"%s\" ", info->prefix);
+ if (info->group)
+ printf("--nflog-group %d ", info->group);
+ if (info->len)
+ printf("--nflog-range %d ", info->len);
+ if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD)
+ printf("--nflog-threshold %d ", info->threshold);
+}
+
+static struct xtables_target brnflog_watcher = {
+ .name = "nflog",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_BRIDGE,
+ .size = XT_ALIGN(sizeof(struct ebt_nflog_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
+ .init = brnflog_init,
+ .help = brnflog_help,
+ .parse = brnflog_parse,
+ .print = brnflog_print,
+ .extra_opts = brnflog_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&brnflog_watcher);
+}
diff --git a/extensions/libip6t_DNAT.t b/extensions/libip6t_DNAT.t
new file mode 100644
index 00000000..3141c299
--- /dev/null
+++ b/extensions/libip6t_DNAT.t
@@ -0,0 +1,8 @@
+:PREROUTING
+*nat
+-j DNAT --to-destination dead::beef;=;OK
+-j DNAT --to-destination dead::beef-dead::fee7;=;OK
+-p tcp -j DNAT --to-destination [dead::beef]:1025-65535;=;OK
+-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535;=;OK
+-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65536;;FAIL
+-j DNAT;;FAIL
diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c
index a442de6d..d045e44c 100644
--- a/extensions/libip6t_DNPT.c
+++ b/extensions/libip6t_DNPT.c
@@ -52,9 +52,9 @@ static void DNPT_print(const void *ip, const struct xt_entry_target *target,
{
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
- printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ printf(" DNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
npt->src_pfx_len);
- printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
npt->dst_pfx_len);
}
@@ -65,12 +65,12 @@ static void DNPT_save(const void *ip, const struct xt_entry_target *target)
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->src_pfx_len != 0)
- printf("--src-pfx %s/%u ",
+ printf(" --src-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
info->src_pfx_len);
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->dst_pfx_len != 0)
- printf("--dst-pfx %s/%u ",
+ printf(" --dst-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
info->dst_pfx_len);
}
diff --git a/extensions/libip6t_DNPT.t b/extensions/libip6t_DNPT.t
new file mode 100644
index 00000000..0406dc90
--- /dev/null
+++ b/extensions/libip6t_DNPT.t
@@ -0,0 +1,7 @@
+:PREROUTING
+*mangle
+-j DNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK
+-j DNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL
+-j DNPT --src-pfx dead::/64;;FAIL
+-j DNPT --dst-pfx dead::/64;;FAIL
+-j DNPT;;FAIL
diff --git a/extensions/libip6t_HL.t b/extensions/libip6t_HL.t
new file mode 100644
index 00000000..4e529f88
--- /dev/null
+++ b/extensions/libip6t_HL.t
@@ -0,0 +1,10 @@
+:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j HL --hl-set 42;=;OK
+-j HL --hl-inc 1;=;OK
+-j HL --hl-dec 1;=;OK
+-j HL --hl-set 256;;FAIL
+-j HL --hl-inc 0;;FAIL
+-j HL --hl-dec 0;;FAIL
+-j HL --hl-dec 1 --hl-inc 1;;FAIL
+-j HL --hl-set --hl-inc 1;;FAIL
diff --git a/extensions/libip6t_MASQUERADE.t b/extensions/libip6t_MASQUERADE.t
new file mode 100644
index 00000000..46502040
--- /dev/null
+++ b/extensions/libip6t_MASQUERADE.t
@@ -0,0 +1,8 @@
+:POSTROUTING
+*nat
+-j MASQUERADE;=;OK
+-j MASQUERADE --random;=;OK
+-p tcp -j MASQUERADE --to-ports 1024;=;OK
+-p udp -j MASQUERADE --to-ports 1024-65535;=;OK
+-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL
+-p udp -j MASQUERADE --to-ports -1;;FAIL
diff --git a/extensions/libip6t_NETMAP.t b/extensions/libip6t_NETMAP.t
new file mode 100644
index 00000000..043562d2
--- /dev/null
+++ b/extensions/libip6t_NETMAP.t
@@ -0,0 +1,4 @@
+:PREROUTING,INPUT,OUTPUT,POSTROUTING
+*nat
+-j NETMAP --to dead::/64;=;OK
+-j NETMAP --to dead::beef;=;OK
diff --git a/extensions/libip6t_REDIRECT.t b/extensions/libip6t_REDIRECT.t
new file mode 100644
index 00000000..a0fb0ed1
--- /dev/null
+++ b/extensions/libip6t_REDIRECT.t
@@ -0,0 +1,6 @@
+:PREROUTING,OUTPUT
+*nat
+-p tcp -j REDIRECT --to-ports 42;=;OK
+-p udp -j REDIRECT --to-ports 42-1234;=;OK
+-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK
+-j REDIRECT --to-ports 42;;FAIL
diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t
new file mode 100644
index 00000000..bb080497
--- /dev/null
+++ b/extensions/libip6t_SNAT.t
@@ -0,0 +1,8 @@
+:POSTROUTING
+*nat
+-j SNAT --to-source dead::beef;=;OK
+-j SNAT --to-source dead::beef-dead::fee7;=;OK
+-p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK
+-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK
+-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL
+-j SNAT;;FAIL
diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c
index 4f10de03..65f787d9 100644
--- a/extensions/libip6t_SNPT.c
+++ b/extensions/libip6t_SNPT.c
@@ -52,9 +52,9 @@ static void SNPT_print(const void *ip, const struct xt_entry_target *target,
{
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
- printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ printf(" SNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
npt->src_pfx_len);
- printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
npt->dst_pfx_len);
}
@@ -65,12 +65,12 @@ static void SNPT_save(const void *ip, const struct xt_entry_target *target)
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->src_pfx_len != 0)
- printf("--src-pfx %s/%u ",
+ printf(" --src-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
info->src_pfx_len);
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->dst_pfx_len != 0)
- printf("--dst-pfx %s/%u ",
+ printf(" --dst-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
info->dst_pfx_len);
}
diff --git a/extensions/libip6t_SNPT.t b/extensions/libip6t_SNPT.t
new file mode 100644
index 00000000..7ed6d0c9
--- /dev/null
+++ b/extensions/libip6t_SNPT.t
@@ -0,0 +1,7 @@
+:INPUT,POSTROUTING
+*mangle
+-j SNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK
+-j SNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL
+-j SNPT --src-pfx dead::/64;;FAIL
+-j SNPT --dst-pfx dead::/64;;FAIL
+-j SNPT;;FAIL
diff --git a/extensions/libip6t_dst.c b/extensions/libip6t_dst.c
index 3fd4c019..fe7e3403 100644
--- a/extensions/libip6t_dst.c
+++ b/extensions/libip6t_dst.c
@@ -112,6 +112,8 @@ static void dst_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_DSTLEN:
+ if (cb->invert)
+ optinfo->invflags |= IP6T_OPTS_INV_LEN;
optinfo->flags |= IP6T_OPTS_LEN;
break;
case O_DSTOPTS:
diff --git a/extensions/libip6t_dst.t b/extensions/libip6t_dst.t
new file mode 100644
index 00000000..0b0013b5
--- /dev/null
+++ b/extensions/libip6t_dst.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-m dst --dst-len 0;=;OK
+-m dst --dst-opts 149:92,12:12,123:12;=;OK
+-m dst ! --dst-len 42;=;OK
+-m dst --dst-len 42 --dst-opts 149:92,12:12,123:12;=;OK
diff --git a/extensions/libip6t_frag.t b/extensions/libip6t_frag.t
new file mode 100644
index 00000000..dab49894
--- /dev/null
+++ b/extensions/libip6t_frag.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-m frag --fragid 1:42;=;OK
+-m frag --fraglen 42;=;OK
+-m frag --fragres;=;OK
+-m frag --fragfirst;=;OK
+-m frag --fragmore;=;OK
+-m frag --fraglast;=;OK
+-m frag ! --fragid 1 ! --fraglen 42 --fragres --fragfirst;=;OK
+-m frag --fragfirst --fragmore;=;OK
+-m frag --fragfirst --fraglast;=;OK
+-m frag --fraglast --fragmore;;FAIL
diff --git a/extensions/libip6t_hbh.t b/extensions/libip6t_hbh.t
new file mode 100644
index 00000000..4b58f25a
--- /dev/null
+++ b/extensions/libip6t_hbh.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-m hbh;=;OK
+-m hbh --hbh-len 42;=;OK
+-m hbh ! --hbh-len 42;=;OK
+-m hbh --hbh-len 42 --hbh-opts 1:2,23:42,4:6,8:10,42,23,4:5;=;OK
diff --git a/extensions/libip6t_hl.t b/extensions/libip6t_hl.t
new file mode 100644
index 00000000..b02816af
--- /dev/null
+++ b/extensions/libip6t_hl.t
@@ -0,0 +1,8 @@
+:INPUT,FORWARD,OUTPUT
+-m hl;;FAIL
+-m hl --hl-eq 42;=;OK
+-m hl ! --hl-eq 42;=;OK
+-m hl --hl-lt 42;=;OK
+-m hl --hl-gt 42;=;OK
+-m hl --hl-gt 42 --hl-eq 42;;FAIL
+-m hl --hl-gt;;FAIL
diff --git a/extensions/libip6t_icmp6.t b/extensions/libip6t_icmp6.t
new file mode 100644
index 00000000..028cfc16
--- /dev/null
+++ b/extensions/libip6t_icmp6.t
@@ -0,0 +1,6 @@
+:INPUT,FORWARD,OUTPUT
+-m icmpv6;;FAIL
+-p ipv6-icmp -m icmp6 --icmpv6-type 1/0;=;OK
+-p ipv6-icmp -m icmp6 --icmpv6-type 2;=;OK
+# cannot use option twice:
+-p ipv6-icmp -m icmp6 --icmpv6-type no-route --icmpv6-type packet-too-big;;FAIL
diff --git a/extensions/libip6t_ipv6header.t b/extensions/libip6t_ipv6header.t
new file mode 100644
index 00000000..67fa4799
--- /dev/null
+++ b/extensions/libip6t_ipv6header.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-m ipv6header --header hop-by-hop;=;OK
+-m ipv6header --header hop-by-hop --soft;=;OK
+-m ipv6header --header ipv6-nonxt;=;OK
diff --git a/extensions/libip6t_mh.t b/extensions/libip6t_mh.t
new file mode 100644
index 00000000..6b76d13d
--- /dev/null
+++ b/extensions/libip6t_mh.t
@@ -0,0 +1,6 @@
+:INPUT,FORWARD,OUTPUT
+-m mh;;FAIL
+-p mobility-header -m mh;=;OK
+-p mobility-header -m mh --mh-type 1;=;OK
+-p mobility-header -m mh ! --mh-type 4;=;OK
+-p mobility-header -m mh --mh-type 4:123;=;OK
diff --git a/extensions/libip6t_rt.t b/extensions/libip6t_rt.t
new file mode 100644
index 00000000..71701388
--- /dev/null
+++ b/extensions/libip6t_rt.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-m rt --rt-type 0 --rt-segsleft 1:23 --rt-len 42 --rt-0-res;=;OK
+-m rt --rt-type 0 ! --rt-segsleft 1:23 ! --rt-len 42 --rt-0-res;=;OK
+-m rt ! --rt-type 1 ! --rt-segsleft 12:23 ! --rt-len 42;=;OK
diff --git a/extensions/libipt_MIRROR.c b/extensions/libipt_MIRROR.c
deleted file mode 100644
index fb78751d..00000000
--- a/extensions/libipt_MIRROR.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Shared library add-on to iptables to add MIRROR target support. */
-#include <xtables.h>
-
-static struct xtables_target mirror_tg_reg = {
- .name = "MIRROR",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(0),
- .userspacesize = XT_ALIGN(0),
-};
-
-void _init(void)
-{
- xtables_register_target(&mirror_tg_reg);
-}
diff --git a/extensions/libipt_MIRROR.man b/extensions/libipt_MIRROR.man
deleted file mode 100644
index 7b720bcb..00000000
--- a/extensions/libipt_MIRROR.man
+++ /dev/null
@@ -1,12 +0,0 @@
-This is an experimental demonstration target which inverts the source
-and destination fields in the IP header and retransmits the packet.
-It is only valid in the
-.BR INPUT ,
-.B FORWARD
-and
-.B PREROUTING
-chains, and user-defined chains which are only called from those
-chains. Note that the outgoing packets are
-.B NOT
-seen by any packet filtering chains, connection tracking or NAT, to
-avoid loops and other problems.
diff --git a/extensions/libipt_NETMAP.t b/extensions/libipt_NETMAP.t
new file mode 100644
index 00000000..31924b98
--- /dev/null
+++ b/extensions/libipt_NETMAP.t
@@ -0,0 +1,4 @@
+:PREROUTING,INPUT,OUTPUT,POSTROUTING
+*nat
+-j NETMAP --to 1.2.3.0/24;=;OK
+-j NETMAP --to 1.2.3.4;=;OK
diff --git a/extensions/libipt_REDIRECT.t b/extensions/libipt_REDIRECT.t
new file mode 100644
index 00000000..a0fb0ed1
--- /dev/null
+++ b/extensions/libipt_REDIRECT.t
@@ -0,0 +1,6 @@
+:PREROUTING,OUTPUT
+*nat
+-p tcp -j REDIRECT --to-ports 42;=;OK
+-p udp -j REDIRECT --to-ports 42-1234;=;OK
+-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK
+-j REDIRECT --to-ports 42;;FAIL
diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c
deleted file mode 100644
index 5d5bf630..00000000
--- a/extensions/libipt_SAME.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <xtables.h>
-#include <linux/netfilter/nf_nat.h>
-#include <linux/netfilter_ipv4/ipt_SAME.h>
-
-enum {
- O_TO_ADDR = 0,
- O_NODST,
- O_RANDOM,
- F_TO_ADDR = 1 << O_TO_ADDR,
- F_RANDOM = 1 << O_RANDOM,
-};
-
-static void SAME_help(void)
-{
- printf(
-"SAME target options:\n"
-" --to <ipaddr>-<ipaddr>\n"
-" Addresses to map source to.\n"
-" May be specified more than\n"
-" once for multiple ranges.\n"
-" --nodst\n"
-" Don't use destination-ip in\n"
-" source selection\n"
-" --random\n"
-" Randomize source port\n");
-}
-
-static const struct xt_option_entry SAME_opts[] = {
- {.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND},
- {.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE},
- {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-
-/* Parses range of IPs */
-static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range)
-{
- char *dash, *arg;
- const struct in_addr *ip;
-
- arg = strdup(orig_arg);
- if (arg == NULL)
- xtables_error(RESOURCE_PROBLEM, "strdup");
- range->flags |= NF_NAT_RANGE_MAP_IPS;
- dash = strchr(arg, '-');
-
- if (dash)
- *dash = '\0';
-
- ip = xtables_numeric_to_ipaddr(arg);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- arg);
- range->min_ip = ip->s_addr;
-
- if (dash) {
- ip = xtables_numeric_to_ipaddr(dash+1);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- dash+1);
- }
- range->max_ip = ip->s_addr;
- if (dash)
- if (range->min_ip > range->max_ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
- arg, dash+1);
- free(arg);
-}
-
-static void SAME_parse(struct xt_option_call *cb)
-{
- struct ipt_same_info *mr = cb->data;
- unsigned int count;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_TO_ADDR:
- if (mr->rangesize == IPT_SAME_MAX_RANGE)
- xtables_error(PARAMETER_PROBLEM,
- "Too many ranges specified, maximum "
- "is %i ranges.\n",
- IPT_SAME_MAX_RANGE);
- parse_to(cb->arg, &mr->range[mr->rangesize]);
- mr->rangesize++;
- break;
- case O_NODST:
- mr->info |= IPT_SAME_NODST;
- break;
- case O_RANDOM:
- for (count=0; count < mr->rangesize; count++)
- mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
- break;
- }
-}
-
-static void SAME_fcheck(struct xt_fcheck_call *cb)
-{
- static const unsigned int f = F_TO_ADDR | F_RANDOM;
- struct ipt_same_info *mr = cb->data;
- unsigned int count;
-
- if ((cb->xflags & f) == f)
- for (count = 0; count < mr->rangesize; ++count)
- mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
-}
-
-static void SAME_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- unsigned int count;
- const struct ipt_same_info *mr = (const void *)target->data;
- int random_selection = 0;
-
- printf(" same:");
-
- for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_ipv4_range *r = &mr->range[count];
- struct in_addr a;
-
- a.s_addr = r->min_ip;
-
- printf("%s", xtables_ipaddr_to_numeric(&a));
- a.s_addr = r->max_ip;
-
- if (r->min_ip != r->max_ip)
- printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- random_selection = 1;
- }
-
- if (mr->info & IPT_SAME_NODST)
- printf(" nodst");
-
- if (random_selection)
- printf(" random");
-}
-
-static void SAME_save(const void *ip, const struct xt_entry_target *target)
-{
- unsigned int count;
- const struct ipt_same_info *mr = (const void *)target->data;
- int random_selection = 0;
-
- for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_ipv4_range *r = &mr->range[count];
- struct in_addr a;
-
- a.s_addr = r->min_ip;
- printf(" --to %s", xtables_ipaddr_to_numeric(&a));
- a.s_addr = r->max_ip;
-
- if (r->min_ip != r->max_ip)
- printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- random_selection = 1;
- }
-
- if (mr->info & IPT_SAME_NODST)
- printf(" --nodst");
-
- if (random_selection)
- printf(" --random");
-}
-
-static struct xtables_target same_tg_reg = {
- .name = "SAME",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_same_info)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)),
- .help = SAME_help,
- .x6_parse = SAME_parse,
- .x6_fcheck = SAME_fcheck,
- .print = SAME_print,
- .save = SAME_save,
- .x6_options = SAME_opts,
-};
-
-void _init(void)
-{
- xtables_register_target(&same_tg_reg);
-}
diff --git a/extensions/libipt_SAME.man b/extensions/libipt_SAME.man
deleted file mode 100644
index a99dc73f..00000000
--- a/extensions/libipt_SAME.man
+++ /dev/null
@@ -1,17 +0,0 @@
-Similar to SNAT/DNAT depending on chain: it takes a range of addresses
-(`\-\-to 1.2.3.4\-1.2.3.7') and gives a client the same
-source-/destination-address for each connection.
-.PP
-N.B.: The DNAT target's \fB\-\-persistent\fP option replaced the SAME target.
-.TP
-\fB\-\-to\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP]
-Addresses to map source to. May be specified more than once for
-multiple ranges.
-.TP
-\fB\-\-nodst\fP
-Don't use the destination-ip in the calculations when selecting the
-new source-ip
-.TP
-\fB\-\-random\fP
-Port mapping will be forcibly randomized to avoid attacks based on
-port prediction (kernel >= 2.6.21).
diff --git a/extensions/libipt_TTL.t b/extensions/libipt_TTL.t
new file mode 100644
index 00000000..36809792
--- /dev/null
+++ b/extensions/libipt_TTL.t
@@ -0,0 +1,10 @@
+:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j TTL --ttl-set 42;=;OK
+-j TTL --ttl-inc 1;=;OK
+-j TTL --ttl-dec 1;=;OK
+-j TTL --ttl-set 256;;FAIL
+-j TTL --ttl-inc 0;;FAIL
+-j TTL --ttl-dec 0;;FAIL
+-j TTL --ttl-dec 1 --ttl-inc 1;;FAIL
+-j TTL --ttl-set --ttl-inc 1;;FAIL
diff --git a/extensions/libipt_realm.t b/extensions/libipt_realm.t
new file mode 100644
index 00000000..ca666407
--- /dev/null
+++ b/extensions/libipt_realm.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-m realm --realm 0x1/0x2a;=;OK
+-m realm --realm 0x2a;=;OK
+-m realm;;FAIL
diff --git a/extensions/libipt_unclean.c b/extensions/libipt_unclean.c
deleted file mode 100644
index bc4a4a08..00000000
--- a/extensions/libipt_unclean.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Shared library add-on to iptables for unclean. */
-#include <xtables.h>
-
-static struct xtables_match unclean_mt_reg = {
- .name = "unclean",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(0),
- .userspacesize = XT_ALIGN(0),
-};
-
-void _init(void)
-{
- xtables_register_match(&unclean_mt_reg);
-}
diff --git a/extensions/libipt_unclean.man b/extensions/libipt_unclean.man
deleted file mode 100644
index 3fecd554..00000000
--- a/extensions/libipt_unclean.man
+++ /dev/null
@@ -1,2 +0,0 @@
-This module takes no options, but attempts to match packets which seem
-malformed or unusual. This is regarded as experimental.
diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c
index e04657ae..cd016d8f 100644
--- a/extensions/libxt_CLASSIFY.c
+++ b/extensions/libxt_CLASSIFY.c
@@ -73,20 +73,40 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
}
-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,
+static void
+arpCLASSIFY_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ CLASSIFY_save(ip, target);
+}
+
+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,
+ },
+ {
+ .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,
+ },
};
void _init(void)
{
- xtables_register_target(&classify_target);
+ xtables_register_targets(classify_target, ARRAY_SIZE(classify_target));
}
diff --git a/extensions/libxt_CONNSECMARK.t b/extensions/libxt_CONNSECMARK.t
new file mode 100644
index 00000000..2751b255
--- /dev/null
+++ b/extensions/libxt_CONNSECMARK.t
@@ -0,0 +1,5 @@
+:PREROUTING,FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j CONNSECMARK --restore;=;OK
+-j CONNSECMARK --save;=;OK
+-j CONNSECMARK;;FAIL
diff --git a/extensions/libxt_HMARK.t b/extensions/libxt_HMARK.t
new file mode 100644
index 00000000..3bcf1dad
--- /dev/null
+++ b/extensions/libxt_HMARK.t
@@ -0,0 +1,8 @@
+:INPUT,FORWARD,OUTPUT
+-j HMARK;;FAIL
+-j HMARK --hmark-src-prefix 32 --hmark-rnd 0x00000004 --hmark-mod 42;=;OK
+-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK
+-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-spi-mask 0x00000004 --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK
+-j HMARK --hmark-src-prefix 1 --hmark-dst-prefix 2 --hmark-sport-mask 0x0003 --hmark-dport-mask 0x0004 --hmark-proto-mask 0x05 --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK
+# cannot mix in spi mask:
+-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct --hmark-spi-mask 4;;FAIL
diff --git a/extensions/libxt_IDLETIMER.t b/extensions/libxt_IDLETIMER.t
new file mode 100644
index 00000000..6afd92c1
--- /dev/null
+++ b/extensions/libxt_IDLETIMER.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-j IDLETIMER --timeout;;FAIL
+-j IDLETIMER --timeout 42;;FAIL
+-j IDLETIMER --timeout 42 --label foo;=;OK
diff --git a/extensions/libxt_LED.t b/extensions/libxt_LED.t
new file mode 100644
index 00000000..1f6705f4
--- /dev/null
+++ b/extensions/libxt_LED.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-j LED;;FAIL
+-j LED --led-trigger-id "foo";=;OK
+-j LED --led-trigger-id "foo" --led-delay 42 --led-always-blink;=;OK
diff --git a/extensions/libxt_RATEEST.t b/extensions/libxt_RATEEST.t
new file mode 100644
index 00000000..c2b6bb34
--- /dev/null
+++ b/extensions/libxt_RATEEST.t
@@ -0,0 +1,2 @@
+:INPUT,FORWARD,OUTPUT
+-j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms;=;OK
diff --git a/extensions/libxt_SET.t b/extensions/libxt_SET.t
new file mode 100644
index 00000000..30c27ca3
--- /dev/null
+++ b/extensions/libxt_SET.t
@@ -0,0 +1,3 @@
+:INPUT,FORWARD,OUTPUT
+# fails: foo does not exist
+-j SET --add-set foo src,dst;;FAIL
diff --git a/extensions/libxt_SYNPROXY.t b/extensions/libxt_SYNPROXY.t
new file mode 100644
index 00000000..dd8b0e76
--- /dev/null
+++ b/extensions/libxt_SYNPROXY.t
@@ -0,0 +1,3 @@
+:INPUT,FORWARD
+-j SYNPROXY --sack-perm --timestamp --mss 1460 --wscale 9;;FAIL
+-p tcp -m tcp --dport 42 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 9 --mss 1460;=;OK
diff --git a/extensions/libxt_TCPMSS.t b/extensions/libxt_TCPMSS.t
new file mode 100644
index 00000000..553a3452
--- /dev/null
+++ b/extensions/libxt_TCPMSS.t
@@ -0,0 +1,6 @@
+:FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j TCPMSS;;FAIL
+-p tcp -j TCPMSS --set-mss 42;;FAIL
+-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --set-mss 42;=;OK
+-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --clamp-mss-to-pmtu;=;OK
diff --git a/extensions/libxt_TCPOPTSTRIP.t b/extensions/libxt_TCPOPTSTRIP.t
new file mode 100644
index 00000000..b5c7a109
--- /dev/null
+++ b/extensions/libxt_TCPOPTSTRIP.t
@@ -0,0 +1,8 @@
+:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j TCPOPTSTRIP;;FAIL
+-p tcp -j TCPOPTSTRIP;=;OK
+-p tcp -j TCPOPTSTRIP --strip-options 2,3,4,5,6,7;=;OK
+-p tcp -j TCPOPTSTRIP --strip-options 0;;FAIL
+-p tcp -j TCPOPTSTRIP --strip-options 1;;FAIL
+-p tcp -j TCPOPTSTRIP --strip-options 1,2;;FAIL
diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c
index 92c7601c..66c060d3 100644
--- a/extensions/libxt_TEE.c
+++ b/extensions/libxt_TEE.c
@@ -99,7 +99,7 @@ static struct xtables_target tee_tg_reg[] = {
.revision = 1,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
+ .userspacesize = offsetof(struct xt_tee_tginfo, priv),
.help = tee_tg_help,
.print = tee_tg_print,
.save = tee_tg_save,
@@ -112,7 +112,7 @@ static struct xtables_target tee_tg_reg[] = {
.revision = 1,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
+ .userspacesize = offsetof(struct xt_tee_tginfo, priv),
.help = tee_tg_help,
.print = tee_tg6_print,
.save = tee_tg6_save,
diff --git a/extensions/libxt_TPROXY.t b/extensions/libxt_TPROXY.t
new file mode 100644
index 00000000..12f82b1f
--- /dev/null
+++ b/extensions/libxt_TPROXY.t
@@ -0,0 +1,5 @@
+:PREROUTING
+*mangle
+-j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;;FAIL
+-p udp -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK
+-p tcp -m tcp --dport 2342 -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK
diff --git a/extensions/libxt_bpf.t b/extensions/libxt_bpf.t
new file mode 100644
index 00000000..80361ad5
--- /dev/null
+++ b/extensions/libxt_bpf.t
@@ -0,0 +1,2 @@
+:INPUT,FORWARD,OUTPUT
+-m bpf --bytecode "4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0";=;OK
diff --git a/extensions/libxt_cgroup.man b/extensions/libxt_cgroup.man
index 456a0311..d0eb09b2 100644
--- a/extensions/libxt_cgroup.man
+++ b/extensions/libxt_cgroup.man
@@ -2,13 +2,21 @@
[\fB!\fP] \fB\-\-cgroup\fP \fIfwid\fP
Match corresponding cgroup for this packet.
-Can be used to assign particular firewall policies for aggregated
-task/jobs on the system. This allows for more fine-grained firewall
-policies that only match for a subset of the system's processes.
-fwid is the maker set through the net_cls cgroup's id.
+Can be used in the OUTPUT chain to assign particular firewall
+policies for aggregated task/jobs on the system. This allows
+for more fine-grained firewall policies that only match for a
+subset of the system's processes. fwid is the maker set through
+the net_cls cgroup's id.
+
+\fBIMPORTANT\fP: when being used in the INPUT chain, the cgroup
+matcher is currently only of limited functionality, meaning it
+will only match on packets that are processed for local sockets
+through early socket demuxing. Therefore, general usage on the
+INPUT chain is disadviced unless the implications are well
+understood.
.PP
Example:
-.PP
+.IP
iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1
\-j DROP
.PP
diff --git a/extensions/libxt_ecn.t b/extensions/libxt_ecn.t
new file mode 100644
index 00000000..b32aea30
--- /dev/null
+++ b/extensions/libxt_ecn.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-m ecn --ecn-tcp-cwr;;FAIL
+-p tcp -m ecn --ecn-tcp-cwr;=;OK
+-p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 2;=;OK
+-p tcp -m ecn ! --ecn-tcp-ece ! --ecn-tcp-cwr ! --ecn-ip-ect 2;=;OK
diff --git a/extensions/libxt_mac.t b/extensions/libxt_mac.t
new file mode 100644
index 00000000..a5ec81d8
--- /dev/null
+++ b/extensions/libxt_mac.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD
+-m mac --mac-source 42:01:02:03:04:05;=;OK
+-m mac --mac-source 42:01:02:03:04;=;FAIL
+-m mac --mac-source 42:01:02:03:04:05:06;=;FAIL
+-m mac;;FAIL
diff --git a/extensions/libxt_osf.t b/extensions/libxt_osf.t
new file mode 100644
index 00000000..ede6d32c
--- /dev/null
+++ b/extensions/libxt_osf.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD
+-m osf --genre linux --ttl 0 --log 0;;FAIL
+-p tcp -m osf --genre linux --ttl 0 --log 0;=;OK
+-p tcp -m osf --genre linux --ttl 3 --log 0;;FAIL
diff --git a/extensions/libxt_physdev.man b/extensions/libxt_physdev.man
index 53beb2e5..06b778af 100644
--- a/extensions/libxt_physdev.man
+++ b/extensions/libxt_physdev.man
@@ -15,21 +15,13 @@ interface which begins with this name will match. If the packet didn't arrive
through a bridge device, this packet won't match this option, unless '!' is used.
.TP
[\fB!\fP] \fB\-\-physdev\-out\fP \fIname\fP
-Name of a bridge port via which a packet is going to be sent (for packets
+Name of a bridge port via which a packet is going to be sent (for bridged packets
entering the
-.BR FORWARD ,
-.B OUTPUT
+.BR FORWARD
and
.B POSTROUTING
chains). If the interface name ends in a "+", then any
-interface which begins with this name will match. Note that in the
-.BR nat " and " mangle
-.B OUTPUT
-chains one cannot match on the bridge output port, however one can in the
-.B "filter OUTPUT"
-chain. If the packet won't leave by a bridge device or if it is yet unknown what
-the output device will be, then the packet won't match this option,
-unless '!' is used.
+interface which begins with this name will match.
.TP
[\fB!\fP] \fB\-\-physdev\-is\-in\fP
Matches if the packet has entered through a bridge interface.
diff --git a/extensions/libxt_policy.t b/extensions/libxt_policy.t
new file mode 100644
index 00000000..24a3e2f4
--- /dev/null
+++ b/extensions/libxt_policy.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD
+-m policy --dir in --pol ipsec;=;OK
+-m policy --dir in --pol ipsec --strict;;FAIL
+-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --mode tunnel --tunnel-dst 10.0.0.0/8 --tunnel-src 10.0.0.0/8 --next --reqid 2;=;OK
+-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --tunnel-dst 10.0.0.0/8;;FAIL
diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c
index ff498da7..ff7dd2a3 100644
--- a/extensions/libxt_quota.c
+++ b/extensions/libxt_quota.c
@@ -37,7 +37,7 @@ quota_save(const void *ip, const struct xt_entry_match *match)
const struct xt_quota_info *q = (const void *)match->data;
if (q->flags & XT_QUOTA_INVERT)
- printf("! ");
+ printf(" !");
printf(" --quota %llu", (unsigned long long) q->quota);
}
diff --git a/extensions/libxt_quota.t b/extensions/libxt_quota.t
index 76f0ee95..c5684279 100644
--- a/extensions/libxt_quota.t
+++ b/extensions/libxt_quota.t
@@ -1,10 +1,7 @@
:INPUT,FORWARD,OUTPUT
-m quota --quota 0;=;OK
-# iptables-save shows wrong output
-# ERROR: cannot find: iptables -I INPUT -m quota ! --quota 0)
-#-m quota ! --quota 0;=;OK
+-m quota ! --quota 0;=;OK
-m quota --quota 18446744073709551615;=;OK
-# ERROR: cannot find: iptables -I INPUT -m quota ! --quota 18446744073709551615
-#-m quota ! --quota 18446744073709551615;=;OK
+-m quota ! --quota 18446744073709551615;=;OK
-m quota --quota 18446744073709551616;;FAIL
-m quota;;FAIL
diff --git a/extensions/libxt_recent.t b/extensions/libxt_recent.t
new file mode 100644
index 00000000..9a83918e
--- /dev/null
+++ b/extensions/libxt_recent.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-m recent --set;=;OK
+-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource;=;OK
+-m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK
+-m recent --update --rttl;=;OK
+-m recent --set --rttl;;FAIL
+-m recent --rcheck --hitcount 999 --name foo --mask 255.255.255.255 --rsource;;FAIL
+# nonsensical, but all should load successfully:
+-m recent --rcheck --hitcount 3 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK
+-m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK
+-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK
diff --git a/extensions/libxt_rpfilter.t b/extensions/libxt_rpfilter.t
new file mode 100644
index 00000000..390268f3
--- /dev/null
+++ b/extensions/libxt_rpfilter.t
@@ -0,0 +1,4 @@
+:PREROUTING
+*mangle
+-m rpfilter;=;OK
+-m rpfilter --loose --validmark --accept-local --invert;=;OK
diff --git a/extensions/libxt_set.t b/extensions/libxt_set.t
new file mode 100644
index 00000000..dd9e9f17
--- /dev/null
+++ b/extensions/libxt_set.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-m set --match-set foo;;FAIL
+# fails: foo does not exist
+-m set --match-set foo src,dst;;FAIL
diff --git a/extensions/libxt_socket.t b/extensions/libxt_socket.t
new file mode 100644
index 00000000..8c0036e2
--- /dev/null
+++ b/extensions/libxt_socket.t
@@ -0,0 +1,4 @@
+:PREROUTING,INPUT
+*mangle
+-m socket;=;OK
+-m socket --transparent --nowildcard;=;OK
diff --git a/extensions/libxt_statistic.t b/extensions/libxt_statistic.t
new file mode 100644
index 00000000..bb6673da
--- /dev/null
+++ b/extensions/libxt_statistic.t
@@ -0,0 +1,8 @@
+:INPUT,FORWARD,OUTPUT
+-m statistic;;FAIL
+-m statistic --mode random ! --probability 0.50000000000;=;OK
+-m statistic --mode random ! --probability 1.1;;FAIL
+-m statistic --probability 1;;FAIL
+-m statistic --mode nth ! --every 5 --packet 2;=;OK
+-m statistic --mode nth ! --every 5;;FAIL
+-m statistic --mode nth ! --every 5 --packet 5;;FAIL
diff --git a/extensions/libxt_string.man b/extensions/libxt_string.man
index adc9c180..54c03a3a 100644
--- a/extensions/libxt_string.man
+++ b/extensions/libxt_string.man
@@ -17,6 +17,9 @@ Matches the given pattern.
[\fB!\fP] \fB\-\-hex\-string\fP \fIpattern\fP
Matches the given pattern in hex notation.
.TP
+\fB\-\-icase\fP
+Ignore case when searching.
+.TP
Examples:
.IP
# The string pattern can be used for simple text characters.
diff --git a/extensions/libxt_tcp.man b/extensions/libxt_tcp.man
index 7a16118b..80194617 100644
--- a/extensions/libxt_tcp.man
+++ b/extensions/libxt_tcp.man
@@ -7,7 +7,6 @@ name or a port number. An inclusive range can also be specified,
using the format \fIfirst\fP\fB:\fP\fIlast\fP.
If the first port is omitted, "0" is assumed; if the last is omitted,
"65535" is assumed.
-If the first port is greater than the second one they will be swapped.
The flag
\fB\-\-sport\fP
is a convenient alias for this option.
diff --git a/extensions/libxt_tcpmss.t b/extensions/libxt_tcpmss.t
new file mode 100644
index 00000000..3181e49d
--- /dev/null
+++ b/extensions/libxt_tcpmss.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-m tcpmss --mss 42;;FAIL
+-p tcp -m tcpmss --mss 42;=;OK
+-p tcp -m tcpmss --mss 42:12345;=;OK
+-p tcp -m tcpmss --mss 42:65536;;FAIL
diff --git a/extensions/libxt_u32.t b/extensions/libxt_u32.t
new file mode 100644
index 00000000..0d9be47a
--- /dev/null
+++ b/extensions/libxt_u32.t
@@ -0,0 +1,2 @@
+:INPUT,FORWARD,OUTPUT
+-m u32 --u32 "0x0=0x0&&0x0=0x1";=;OK