summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/GNUmakefile.in75
-rw-r--r--extensions/generic.txlate36
-rw-r--r--extensions/iptables.t5
-rw-r--r--extensions/libarpt_mangle.c175
-rw-r--r--extensions/libarpt_mangle.t4
-rw-r--r--extensions/libarpt_mangle.txlate6
-rw-r--r--extensions/libarpt_standard.t9
-rw-r--r--extensions/libebt_802_3.c93
-rw-r--r--extensions/libebt_802_3.t6
-rw-r--r--extensions/libebt_among.c21
-rw-r--r--extensions/libebt_among.t12
-rw-r--r--extensions/libebt_arp.c240
-rw-r--r--extensions/libebt_arp.t21
-rw-r--r--extensions/libebt_arpreply.c52
-rw-r--r--extensions/libebt_arpreply.t4
-rw-r--r--extensions/libebt_dnat.c64
-rw-r--r--extensions/libebt_ip.c245
-rw-r--r--extensions/libebt_ip.t26
-rw-r--r--extensions/libebt_ip.txlate4
-rw-r--r--extensions/libebt_ip6.c241
-rw-r--r--extensions/libebt_ip6.t26
-rw-r--r--extensions/libebt_ip6.txlate2
-rw-r--r--extensions/libebt_log.c121
-rw-r--r--extensions/libebt_mark.c140
-rw-r--r--extensions/libebt_mark_m.c73
-rw-r--r--extensions/libebt_mark_m.t4
-rw-r--r--extensions/libebt_mark_m.txlate2
-rw-r--r--extensions/libebt_nflog.c82
-rw-r--r--extensions/libebt_pkttype.c49
-rw-r--r--extensions/libebt_pkttype.t14
-rw-r--r--extensions/libebt_redirect.c40
-rw-r--r--extensions/libebt_snat.c74
-rw-r--r--extensions/libebt_snat.t2
-rw-r--r--extensions/libebt_standard.t7
-rw-r--r--extensions/libebt_stp.c270
-rw-r--r--extensions/libebt_stp.t61
-rw-r--r--extensions/libebt_vlan.c121
-rw-r--r--extensions/libebt_vlan.t10
-rw-r--r--extensions/libebt_vlan.txlate2
-rw-r--r--extensions/libip6t_DNPT.man4
-rw-r--r--extensions/libip6t_REJECT.man7
-rw-r--r--extensions/libip6t_SNPT.man4
-rw-r--r--extensions/libip6t_ah.c22
-rw-r--r--extensions/libip6t_ah.t6
-rw-r--r--extensions/libip6t_ah.txlate6
-rw-r--r--extensions/libip6t_frag.c27
-rw-r--r--extensions/libip6t_frag.t6
-rw-r--r--extensions/libip6t_frag.txlate6
-rw-r--r--extensions/libip6t_icmp6.t4
-rw-r--r--extensions/libip6t_mh.c18
-rw-r--r--extensions/libip6t_mh.t6
-rw-r--r--extensions/libip6t_mh.txlate13
-rw-r--r--extensions/libip6t_rt.c28
-rw-r--r--extensions/libip6t_rt.t6
-rw-r--r--extensions/libip6t_rt.txlate9
-rw-r--r--extensions/libip6t_standard.t3
-rw-r--r--extensions/libipt_REJECT.man7
-rw-r--r--extensions/libipt_ULOG.man4
-rw-r--r--extensions/libipt_ah.c22
-rw-r--r--extensions/libipt_ah.t6
-rw-r--r--extensions/libipt_ah.txlate6
-rw-r--r--extensions/libipt_icmp.c3
-rw-r--r--extensions/libipt_icmp.t11
-rw-r--r--extensions/libxt_CONNMARK.man4
-rw-r--r--extensions/libxt_CT.man4
-rw-r--r--extensions/libxt_DNAT.man2
-rw-r--r--extensions/libxt_HMARK.c60
-rw-r--r--extensions/libxt_HMARK.man2
-rw-r--r--extensions/libxt_LED.man4
-rw-r--r--extensions/libxt_MARK.c82
-rw-r--r--extensions/libxt_MARK.txlate9
-rw-r--r--extensions/libxt_MASQUERADE.man6
-rw-r--r--extensions/libxt_NFLOG.man4
-rw-r--r--extensions/libxt_NFLOG.t2
-rw-r--r--extensions/libxt_NFQUEUE.man11
-rw-r--r--extensions/libxt_NFQUEUE.t7
-rw-r--r--extensions/libxt_SET.man4
-rw-r--r--extensions/libxt_SNAT.man2
-rw-r--r--extensions/libxt_SYNPROXY.man4
-rw-r--r--extensions/libxt_TCPMSS.t2
-rw-r--r--extensions/libxt_TOS.man2
-rw-r--r--extensions/libxt_TPROXY.c59
-rw-r--r--extensions/libxt_TPROXY.txlate20
-rw-r--r--extensions/libxt_TRACE.man4
-rw-r--r--extensions/libxt_bpf.man8
-rw-r--r--extensions/libxt_cgroup.man2
-rw-r--r--extensions/libxt_cluster.man8
-rw-r--r--extensions/libxt_connbytes.c4
-rw-r--r--extensions/libxt_connbytes.t6
-rw-r--r--extensions/libxt_connlabel.man10
-rw-r--r--extensions/libxt_connlimit.man31
-rw-r--r--extensions/libxt_conntrack.c17
-rw-r--r--extensions/libxt_conntrack.t28
-rw-r--r--extensions/libxt_cpu.man6
-rw-r--r--extensions/libxt_dccp.t10
-rw-r--r--extensions/libxt_dscp.man2
-rw-r--r--extensions/libxt_esp.c26
-rw-r--r--extensions/libxt_esp.t7
-rw-r--r--extensions/libxt_esp.txlate12
-rw-r--r--extensions/libxt_hashlimit.man6
-rw-r--r--extensions/libxt_helper.man10
-rw-r--r--extensions/libxt_icmp.h7
-rw-r--r--extensions/libxt_ipcomp.c7
-rw-r--r--extensions/libxt_ipcomp.t7
-rw-r--r--extensions/libxt_length.t3
-rw-r--r--extensions/libxt_limit.c50
-rw-r--r--extensions/libxt_limit.man2
-rw-r--r--extensions/libxt_multiport.c2
-rw-r--r--extensions/libxt_nfacct.man4
-rw-r--r--extensions/libxt_osf.man40
-rw-r--r--extensions/libxt_owner.man2
-rw-r--r--extensions/libxt_rateest.man16
-rw-r--r--extensions/libxt_set.h12
-rw-r--r--extensions/libxt_socket.c34
-rw-r--r--extensions/libxt_socket.man2
-rw-r--r--extensions/libxt_socket.txlate17
-rw-r--r--extensions/libxt_standard.t5
-rw-r--r--extensions/libxt_string.man20
-rw-r--r--extensions/libxt_tcp.c48
-rw-r--r--extensions/libxt_tcp.t12
-rw-r--r--extensions/libxt_tcp.txlate6
-rw-r--r--extensions/libxt_tcpmss.t4
-rw-r--r--extensions/libxt_time.man2
-rw-r--r--extensions/libxt_u32.man16
-rw-r--r--extensions/libxt_udp.c43
-rw-r--r--extensions/libxt_udp.t12
-rw-r--r--extensions/libxt_udp.txlate6
127 files changed, 1754 insertions, 1785 deletions
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index e289adf0..20c2b7bc 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -22,19 +22,34 @@ regular_CPPFLAGS = @regular_CPPFLAGS@
kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
AM_CFLAGS = ${regular_CFLAGS}
-AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include -I${top_srcdir} ${kinclude_CPPFLAGS} ${CPPFLAGS} @libnetfilter_conntrack_CFLAGS@ @libnftnl_CFLAGS@
+AM_CPPFLAGS = ${regular_CPPFLAGS} \
+ -I${top_builddir}/include \
+ -I${top_builddir} \
+ -I${top_srcdir}/include \
+ -I${top_srcdir} \
+ ${kinclude_CPPFLAGS} \
+ ${CPPFLAGS} \
+ @libnetfilter_conntrack_CFLAGS@ \
+ @libnftnl_CFLAGS@
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
AM_LDFLAGS = @noundef_LDFLAGS@ @regular_LDFLAGS@
-ifeq (${V},)
-AM_LIBTOOL_SILENT = --silent
-AM_VERBOSE_CC = @echo " CC " $@;
-AM_VERBOSE_CCLD = @echo " CCLD " $@;
-AM_VERBOSE_CXX = @echo " CXX " $@;
-AM_VERBOSE_CXXLD = @echo " CXXLD " $@;
-AM_VERBOSE_AR = @echo " AR " $@;
-AM_VERBOSE_GEN = @echo " GEN " $@;
-endif
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+am__v_AR_0 = @echo " AR " $@;
+am__v_CC_0 = @echo " CC " $@;
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_LN_0 = @echo " LN " $@;
+am__v_AR_ = ${am__v_AR_@AM_DEFAULT_V@}
+am__v_CC_ = ${am__v_CC_@AM_DEFAULT_V@}
+am__v_CCLD_ = ${am__v_CCLD_@AM_DEFAULT_V@}
+am__v_GEN_ = ${am__v_GEN_@AM_DEFAULT_V@}
+am__v_LN_ = ${am__v_LN_@AM_DEFAULT_V@}
+AM_V_AR = ${am__v_AR_@AM_V@}
+AM_V_CC = ${am__v_CC_@AM_V@}
+AM_V_CCLD = ${am__v_CCLD_@AM_V@}
+AM_V_GEN = ${am__v_GEN_@AM_V@}
+AM_V_LN = ${am__v_LN_@AM_V@}
#
# Wildcard module list
@@ -113,7 +128,7 @@ clean:
distclean: clean
init%.o: init%.c
- ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
+ ${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
-include .*.d
@@ -122,23 +137,23 @@ init%.o: init%.c
# Shared libraries
#
lib%.so: lib%.oo
- ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -shared -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD};
+ ${AM_V_CCLD} ${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -shared -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD};
lib%.oo: ${srcdir}/lib%.c
- ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
+ ${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
libxt_NOTRACK.so: libxt_CT.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
libxt_state.so: libxt_conntrack.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
libxt_REDIRECT.so: libxt_NAT.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
libxt_MASQUERADE.so: libxt_NAT.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
libxt_SNAT.so: libxt_NAT.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
libxt_DNAT.so: libxt_NAT.so
- ln -fs $< $@
+ ${AM_V_LN} ln -fs $< $@
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
xt_RATEEST_LIBADD = -lm
@@ -153,22 +168,22 @@ xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@
# handling code in the Makefiles.
#
lib%.o: ${srcdir}/lib%.c
- ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
+ ${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
libext.a: initext.o ${libext_objs}
- ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ ${AM_V_AR} ${AR} crs $@ $^;
libext_ebt.a: initextb.o ${libext_ebt_objs}
- ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ ${AM_V_AR} ${AR} crs $@ $^;
libext_arpt.a: initexta.o ${libext_arpt_objs}
- ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ ${AM_V_AR} ${AR} crs $@ $^;
libext4.a: initext4.o ${libext4_objs}
- ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ ${AM_V_AR} ${AR} crs $@ $^;
libext6.a: initext6.o ${libext6_objs}
- ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ ${AM_V_AR} ${AR} crs $@ $^;
initext_func := $(addprefix xt_,${pfx_build_mod})
initextb_func := $(addprefix ebt_,${pfb_build_mod})
@@ -186,7 +201,7 @@ ${initext_depfiles}: FORCE
rm -f $@.tmp;
${initext_sources}: %.c: .%.dd
- ${AM_VERBOSE_GEN}
+ ${AM_V_GEN}
@( \
initext_func="$(value $(basename $@)_func)"; \
funcname="init_extensions$(patsubst initext%.c,%,$@)"; \
@@ -209,23 +224,23 @@ ${initext_sources}: %.c: .%.dd
ex_matches = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:lower:][:digit:]_]+\b')
ex_targets = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:upper:][:digit:]_]+\b')
man_run = \
- ${AM_VERBOSE_GEN} \
+ ${AM_V_GEN} \
for ext in $(sort ${1}); do \
f="${srcdir}/libxt_$$ext.man"; \
if [ -f "$$f" ]; then \
- echo -e "\t+ $$f" >&2; \
+ printf "\t+ $$f\n" >&2; \
echo ".SS $$ext"; \
cat "$$f" || exit $$?; \
fi; \
f="${srcdir}/libip6t_$$ext.man"; \
if [ -f "$$f" ]; then \
- echo -e "\t+ $$f" >&2; \
+ printf "\t+ $$f\n" >&2; \
echo ".SS $$ext (IPv6-specific)"; \
cat "$$f" || exit $$?; \
fi; \
f="${srcdir}/libipt_$$ext.man"; \
if [ -f "$$f" ]; then \
- echo -e "\t+ $$f" >&2; \
+ printf "\t+ $$f\n" >&2; \
echo ".SS $$ext (IPv4-specific)"; \
cat "$$f" || exit $$?; \
fi; \
diff --git a/extensions/generic.txlate b/extensions/generic.txlate
index c24ed156..9ad1266d 100644
--- a/extensions/generic.txlate
+++ b/extensions/generic.txlate
@@ -1,3 +1,9 @@
+arptables-translate -A OUTPUT --proto-type ipv4 -s 1.2.3.4 -j ACCEPT
+nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp ptype 0x800 arp saddr ip 1.2.3.4 counter accept'
+
+arptables-translate -I OUTPUT -o oifname
+nft 'insert rule arp filter OUTPUT oifname "oifname" arp htype 1 arp hlen 6 arp plen 4 counter'
+
iptables-translate -I OUTPUT -p udp -d 8.8.8.8 -j ACCEPT
nft 'insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept'
@@ -58,6 +64,36 @@ nft 'insert rule ip6 filter INPUT counter'
ip6tables-translate -I INPUT ! -s ::/0
nft 'insert rule ip6 filter INPUT ip6 saddr != ::/0 counter'
+iptables-translate -A FORWARD -p 132
+nft 'add rule ip filter FORWARD ip protocol sctp counter'
+
+ip6tables-translate -A FORWARD -p 132
+nft 'add rule ip6 filter FORWARD meta l4proto sctp counter'
+
+iptables-translate -A FORWARD ! -p 132
+nft 'add rule ip filter FORWARD ip protocol != sctp counter'
+
+ip6tables-translate -A FORWARD ! -p 132
+nft 'add rule ip6 filter FORWARD meta l4proto != sctp counter'
+
+iptables-translate -A FORWARD -p 141
+nft 'add rule ip filter FORWARD ip protocol 141 counter'
+
+ip6tables-translate -A FORWARD -p 141
+nft 'add rule ip6 filter FORWARD meta l4proto 141 counter'
+
+iptables-translate -A FORWARD ! -p 141
+nft 'add rule ip filter FORWARD ip protocol != 141 counter'
+
+ip6tables-translate -A FORWARD ! -p 141
+nft 'add rule ip6 filter FORWARD meta l4proto != 141 counter'
+
+iptables-translate -A FORWARD -m tcp --dport 22 -p tcp
+nft 'add rule ip filter FORWARD tcp dport 22 counter'
+
+ip6tables-translate -A FORWARD -m tcp --dport 22 -p tcp
+nft 'add rule ip6 filter FORWARD tcp dport 22 counter'
+
ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0
nft 'insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter'
diff --git a/extensions/iptables.t b/extensions/iptables.t
index b4b6d677..5d6d3d15 100644
--- a/extensions/iptables.t
+++ b/extensions/iptables.t
@@ -4,3 +4,8 @@
-i eth+ -o alongifacename+;=;OK
! -i eth0;=;OK
! -o eth+;=;OK
+-c "";;FAIL
+-c ,3;;FAIL
+-c 3,;;FAIL
+-c ,;;FAIL
+-c 2,3 -j ACCEPT;-j ACCEPT;OK
diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c
index 765edf34..283bb132 100644
--- a/extensions/libarpt_mangle.c
+++ b/extensions/libarpt_mangle.c
@@ -25,19 +25,16 @@ static void arpmangle_print_help(void)
"--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 const 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,
+/* internal use only, explicitly not covered by ARPT_MANGLE_MASK */
+#define ARPT_MANGLE_TARGET 0x10
+
+static const struct xt_option_entry arpmangle_opts[] = {
+{ .name = "mangle-ip-s", .id = ARPT_MANGLE_SIP, .type = XTTYPE_HOSTMASK },
+{ .name = "mangle-ip-d", .id = ARPT_MANGLE_TIP, .type = XTTYPE_HOSTMASK },
+{ .name = "mangle-mac-s", .id = ARPT_MANGLE_SDEV, .type = XTTYPE_ETHERMAC },
+{ .name = "mangle-mac-d", .id = ARPT_MANGLE_TDEV, .type = XTTYPE_ETHERMAC },
+{ .name = "mangle-target", .id = ARPT_MANGLE_TARGET, .type = XTTYPE_STRING },
+XTOPT_TABLEEND,
};
static void arpmangle_init(struct xt_entry_target *target)
@@ -47,86 +44,50 @@ static void arpmangle_init(struct xt_entry_target *target)
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)
+static void assert_hopts(const struct arpt_entry *e, const char *optname)
{
- 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;
+ if (e->arp.arhln_mask == 0)
+ xtables_error(PARAMETER_PROBLEM, "no --h-length defined");
+ if (e->arp.invflags & IPT_INV_ARPHLN)
+ xtables_error(PARAMETER_PROBLEM,
+ "! hln not allowed for --%s", optname);
+ if (e->arp.arhln != 6)
+ xtables_error(PARAMETER_PROBLEM, "only --h-length 6 supported");
+}
+
+static void arpmangle_parse(struct xt_option_call *cb)
+{
+ const struct arpt_entry *e = cb->xt_entry;
+ struct arpt_mangle *mangle = cb->data;
+
+ xtables_option_parse(cb);
+ mangle->flags |= (cb->entry->id & ARPT_MANGLE_MASK);
+ switch (cb->entry->id) {
+ case ARPT_MANGLE_SIP:
+ mangle->u_s.src_ip = cb->val.haddr.in;
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;
+ case ARPT_MANGLE_TIP:
+ mangle->u_t.tgt_ip = cb->val.haddr.in;
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;
+ case ARPT_MANGLE_SDEV:
+ assert_hopts(e, cb->entry->name);
+ memcpy(mangle->src_devaddr, cb->val.ethermac, ETH_ALEN);
+ case ARPT_MANGLE_TDEV:
+ assert_hopts(e, cb->entry->name);
+ memcpy(mangle->tgt_devaddr, cb->val.ethermac, ETH_ALEN);
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"))
+ case ARPT_MANGLE_TARGET:
+ if (!strcmp(cb->arg, "DROP"))
mangle->target = NF_DROP;
- else if (!strcmp(optarg, "ACCEPT"))
+ else if (!strcmp(cb->arg, "ACCEPT"))
mangle->target = NF_ACCEPT;
- else if (!strcmp(optarg, "CONTINUE"))
+ else if (!strcmp(cb->arg, "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 const char *ipaddr_to(const struct in_addr *addrp, int numeric)
@@ -170,6 +131,52 @@ static void arpmangle_save(const void *ip, const struct xt_entry_target *target)
arpmangle_print(ip, target, 0);
}
+static void print_devaddr_xlate(const char *macaddress, struct xt_xlate *xl)
+{
+ unsigned int i;
+
+ xt_xlate_add(xl, "%02x", macaddress[0]);
+ for (i = 1; i < ETH_ALEN; ++i)
+ xt_xlate_add(xl, ":%02x", macaddress[i]);
+}
+
+static int arpmangle_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct arpt_mangle *m = (const void *)params->target->data;
+
+ if (m->flags & ARPT_MANGLE_SIP)
+ xt_xlate_add(xl, "arp saddr ip set %s ",
+ xtables_ipaddr_to_numeric(&m->u_s.src_ip));
+
+ if (m->flags & ARPT_MANGLE_SDEV) {
+ xt_xlate_add(xl, "arp %caddr ether set ", 's');
+ print_devaddr_xlate(m->src_devaddr, xl);
+ }
+
+ if (m->flags & ARPT_MANGLE_TIP)
+ xt_xlate_add(xl, "arp daddr ip set %s ",
+ xtables_ipaddr_to_numeric(&m->u_t.tgt_ip));
+
+ if (m->flags & ARPT_MANGLE_TDEV) {
+ xt_xlate_add(xl, "arp %caddr ether set ", 'd');
+ print_devaddr_xlate(m->tgt_devaddr, xl);
+ }
+
+ switch (m->target) {
+ case NF_ACCEPT:
+ xt_xlate_add(xl, "accept");
+ break;
+ case NF_DROP:
+ xt_xlate_add(xl, "drop");
+ break;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
static struct xtables_target arpmangle_target = {
.name = "mangle",
.revision = 0,
@@ -179,11 +186,11 @@ static struct xtables_target arpmangle_target = {
.userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)),
.help = arpmangle_print_help,
.init = arpmangle_init,
- .parse = arpmangle_parse,
- .final_check = arpmangle_final_check,
+ .x6_parse = arpmangle_parse,
.print = arpmangle_print,
.save = arpmangle_save,
- .extra_opts = arpmangle_opts,
+ .x6_options = arpmangle_opts,
+ .xlate = arpmangle_xlate,
};
void _init(void)
diff --git a/extensions/libarpt_mangle.t b/extensions/libarpt_mangle.t
index da966948..7a639ee1 100644
--- a/extensions/libarpt_mangle.t
+++ b/extensions/libarpt_mangle.t
@@ -3,3 +3,7 @@
-j mangle -d 1.2.3.4 --mangle-ip-d 1.2.3.5;=;OK
-j mangle -d 1.2.3.4 --mangle-mac-d 00:01:02:03:04:05;=;OK
-d 1.2.3.4 --h-length 5 -j mangle --mangle-mac-s 00:01:02:03:04:05;=;FAIL
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target DROP;=;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target ACCEPT;-j mangle --mangle-ip-s 1.2.3.4;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target CONTINUE;=;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target FOO;=;FAIL
diff --git a/extensions/libarpt_mangle.txlate b/extensions/libarpt_mangle.txlate
new file mode 100644
index 00000000..e884d328
--- /dev/null
+++ b/extensions/libarpt_mangle.txlate
@@ -0,0 +1,6 @@
+arptables-translate -A OUTPUT -d 10.21.22.129 -j mangle --mangle-ip-s 10.21.22.161
+nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.21.22.129 counter arp saddr ip set 10.21.22.161 accept'
+arptables-translate -A OUTPUT -d 10.2.22.129/24 -j mangle --mangle-ip-d 10.2.22.1 --mangle-target CONTINUE
+nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.2.22.0/24 counter arp daddr ip set 10.2.22.1'
+arptables-translate -A OUTPUT -d 10.2.22.129/24 -j mangle --mangle-ip-d 10.2.22.1 --mangle-mac-d a:b:c:d:e:f
+nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.2.22.0/24 counter arp daddr ip set 10.2.22.1 arp daddr ether set 0a:0b:0c:0d:0e:0f accept'
diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t
index e84a00b7..15354090 100644
--- a/extensions/libarpt_standard.t
+++ b/extensions/libarpt_standard.t
@@ -12,3 +12,12 @@
-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
+--src-mac=01:02:03:04:05:06 --dst-mac=07:08:09:0A:0B:0C --h-length=6 --opcode=Request --h-type=Ethernet --proto-type=ipv4;--src-mac 01:02:03:04:05:06 --dst-mac 07:08:09:0a:0b:0c --opcode 1 --proto-type 0x800;OK
+--src-mac ! 01:02:03:04:05:06 --dst-mac ! 07:08:09:0A:0B:0C --h-length ! 6 --opcode ! Request --h-type ! Ethernet --proto-type ! ipv4;! --src-mac 01:02:03:04:05:06 ! --dst-mac 07:08:09:0a:0b:0c ! --h-length 6 ! --opcode 1 ! --h-type 0x1 ! --proto-type 0x800;OK
+--h-type 10;--h-type 0x10;OK
+--h-type 0x10;=;OK
+--proto-type 10;--proto-type 0xa;OK
+--proto-type 10/10;--proto-type 0xa/0xa;OK
+--proto-type 0x10;=;OK
+--proto-type 0x10/0x10;=;OK
+--h-length 6/15 --opcode 1/235 --h-type 0x8/0xcf --proto-type 0x800/0xde00;=;OK
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
index f05d02ea..489185e9 100644
--- a/extensions/libebt_802_3.c
+++ b/extensions/libebt_802_3.c
@@ -13,83 +13,40 @@
#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 const struct xt_option_entry br802_3_opts[] =
+{
+ { .name = "802_3-sap", .id = EBT_802_3_SAP,
+ .type = XTTYPE_UINT8, .base = 16,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_802_3_info, sap) },
+ { .name = "802_3-type", .id = EBT_802_3_TYPE,
+ .type = XTTYPE_UINT16, .base = 16,
+ .flags = XTOPT_INVERT | XTOPT_PUT | XTOPT_NBO,
+ XTOPT_POINTER(struct ebt_802_3_info, type) },
+ XTOPT_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"
+"[!] --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"
+"[!] --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)
+static void br802_3_parse(struct xt_option_call *cb)
{
- 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;
- }
+ struct ebt_802_3_info *info = cb->data;
- *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");
+ xtables_option_parse(cb);
+ info->bitmask |= cb->entry->id;
+ if (cb->invert)
+ info->invflags |= cb->entry->id;
}
static void br802_3_print(const void *ip, const struct xt_entry_match *match,
@@ -98,16 +55,14 @@ 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("0x%.2x ", info->sap);
+ printf("--802_3-sap 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));
+ printf("--802_3-type 0x%.4x ", ntohs(info->type));
}
}
@@ -119,12 +74,10 @@ static struct xtables_match br802_3_match =
.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,
+ .x6_parse = br802_3_parse,
.print = br802_3_print,
- .extra_opts = br802_3_opts,
+ .x6_options = br802_3_opts,
};
void _init(void)
diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t
index a138f35d..d1e19795 100644
--- a/extensions/libebt_802_3.t
+++ b/extensions/libebt_802_3.t
@@ -1,5 +1,7 @@
:INPUT,FORWARD,OUTPUT
---802_3-sap ! 0x0a -j CONTINUE;=;FAIL
+! --802_3-sap 0x0a -j CONTINUE;=;FAIL
--802_3-type 0x000a -j RETURN;=;FAIL
--p Length --802_3-sap ! 0x0a -j CONTINUE;=;OK
+-p Length --802_3-sap 0x0a -j CONTINUE;=;OK
+-p Length ! --802_3-sap 0x0a -j CONTINUE;=;OK
-p Length --802_3-type 0x000a -j RETURN;=;OK
+-p Length ! --802_3-type 0x000a -j RETURN;=;OK
diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
index a80fb804..85f9bee4 100644
--- a/extensions/libebt_among.c
+++ b/extensions/libebt_among.c
@@ -43,10 +43,10 @@ static void bramong_print_help(void)
{
printf(
"`among' options:\n"
-"--among-dst [!] list : matches if ether dst is in list\n"
-"--among-src [!] list : matches if ether src is in list\n"
-"--among-dst-file [!] file : obtain dst list from file\n"
-"--among-src-file [!] file : obtain src list from file\n"
+"[!] --among-dst list : matches if ether dst is in list\n"
+"[!] --among-src list : matches if ether src is in list\n"
+"[!] --among-dst-file file : obtain dst list from file\n"
+"[!] --among-src-file file : obtain src list from file\n"
"list has form:\n"
" xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip],yy:yy:yy:yy:yy:yy[=ip.ip.ip.ip]"
",...,zz:zz:zz:zz:zz:zz[=ip.ip.ip.ip][,]\n"
@@ -188,10 +188,10 @@ static int bramong_parse(int c, char **argv, int invert,
}
static void __bramong_print(struct nft_among_pair *pairs,
- int cnt, bool inv, bool have_ip)
+ int cnt, bool have_ip)
{
- const char *isep = inv ? "! " : "";
char abuf[INET_ADDRSTRLEN];
+ const char *isep = "";
int i;
for (i = 0; i < cnt; i++) {
@@ -212,14 +212,13 @@ static void bramong_print(const void *ip, const struct xt_entry_match *match,
struct nft_among_data *data = (struct nft_among_data *)match->data;
if (data->src.cnt) {
- printf("--among-src ");
- __bramong_print(data->pairs,
- data->src.cnt, data->src.inv, data->src.ip);
+ printf("%s--among-src ", data->src.inv ? "! " : "");
+ __bramong_print(data->pairs, data->src.cnt, data->src.ip);
}
if (data->dst.cnt) {
- printf("--among-dst ");
+ printf("%s--among-dst ", data->dst.inv ? "! " : "");
__bramong_print(data->pairs + data->src.cnt,
- data->dst.cnt, data->dst.inv, data->dst.ip);
+ data->dst.cnt, data->dst.ip);
}
}
diff --git a/extensions/libebt_among.t b/extensions/libebt_among.t
index a02206f3..aef07acf 100644
--- a/extensions/libebt_among.t
+++ b/extensions/libebt_among.t
@@ -1,15 +1,15 @@
:INPUT,FORWARD,OUTPUT
--among-dst de:ad:0:be:ee:ff,c0:ff:ee:0:ba:be;--among-dst c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;OK
---among-dst ! c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;=;OK
+! --among-dst c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;=;OK
--among-src be:ef:0:c0:ff:ee,c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;=;OK
--among-src de:ad:0:be:ee:ff=10.0.0.1,c0:ff:ee:0:ba:be=192.168.1.1;--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff=10.0.0.1;OK
---among-src ! c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff=10.0.0.1;=;OK
+! --among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff=10.0.0.1;=;OK
--among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be;=;OK
--among-src de:ad:0:be:ee:ff=10.0.0.1 --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
---among-src ! de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be;=;OK
---among-src de:ad:0:be:ee:ff=10.0.0.1 --among-dst ! c0:ff:ee:0:ba:be=192.168.1.1;=;OK
---among-src ! de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
---among-src de:ad:0:be:ee:ff=10.0.0.1 --among-dst ! c0:ff:ee:0:ba:be=192.168.1.1;=;OK
+! --among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be;=;OK
+--among-src de:ad:0:be:ee:ff=10.0.0.1 ! --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
+! --among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
+--among-src de:ad:0:be:ee:ff=10.0.0.1 ! --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
--among-src;=;FAIL
--among-src 00:11=10.0.0.1;=;FAIL
--among-src de:ad:0:be:ee:ff=10.256.0.1;=;FAIL
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index 63a953d4..50ce32be 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -10,7 +10,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <netinet/ether.h>
@@ -20,26 +19,31 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define ARP_OPCODE '1'
-#define ARP_HTYPE '2'
-#define ARP_PTYPE '3'
-#define ARP_IP_S '4'
-#define ARP_IP_D '5'
-#define ARP_MAC_S '6'
-#define ARP_MAC_D '7'
-#define ARP_GRAT '8'
+/* values must correspond with EBT_ARP_* bit positions */
+enum {
+ O_OPCODE = 0,
+ O_HTYPE,
+ O_PTYPE,
+ O_SRC_IP,
+ O_DST_IP,
+ O_SRC_MAC,
+ O_DST_MAC,
+ O_GRAT,
+};
-static const struct option brarp_opts[] = {
- { "arp-opcode" , required_argument, 0, ARP_OPCODE },
- { "arp-op" , required_argument, 0, ARP_OPCODE },
- { "arp-htype" , required_argument, 0, ARP_HTYPE },
- { "arp-ptype" , required_argument, 0, ARP_PTYPE },
- { "arp-ip-src" , required_argument, 0, ARP_IP_S },
- { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
- { "arp-mac-src" , required_argument, 0, ARP_MAC_S },
- { "arp-mac-dst" , required_argument, 0, ARP_MAC_D },
- { "arp-gratuitous", no_argument, 0, ARP_GRAT },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brarp_opts[] = {
+#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
+ ENTRY("arp-opcode", O_OPCODE, XTTYPE_STRING),
+ ENTRY("arp-op", O_OPCODE, XTTYPE_STRING),
+ ENTRY("arp-htype", O_HTYPE, XTTYPE_STRING),
+ ENTRY("arp-ptype", O_PTYPE, XTTYPE_STRING),
+ ENTRY("arp-ip-src", O_SRC_IP, XTTYPE_HOSTMASK),
+ ENTRY("arp-ip-dst", O_DST_IP, XTTYPE_HOSTMASK),
+ ENTRY("arp-mac-src", O_SRC_MAC, XTTYPE_ETHERMACMASK),
+ ENTRY("arp-mac-dst", O_DST_MAC, XTTYPE_ETHERMACMASK),
+ ENTRY("arp-gratuitous", O_GRAT, XTTYPE_NONE),
+#undef ENTRY
+ XTOPT_TABLEEND
};
/* a few names */
@@ -62,13 +66,13 @@ static void brarp_print_help(void)
printf(
"arp options:\n"
-"--arp-opcode [!] opcode : ARP opcode (integer or string)\n"
-"--arp-htype [!] type : ARP hardware type (integer or string)\n"
-"--arp-ptype [!] type : ARP protocol type (hexadecimal or string)\n"
-"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
-"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
-"--arp-mac-src [!] address[/mask]: ARP MAC source specification\n"
-"--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n"
+"[!] --arp-opcode opcode : ARP opcode (integer or string)\n"
+"[!] --arp-htype type : ARP hardware type (integer or string)\n"
+"[!] --arp-ptype type : ARP protocol type (hexadecimal or string)\n"
+"[!] --arp-ip-src address[/mask]: ARP IP source specification\n"
+"[!] --arp-ip-dst address[/mask]: ARP IP target specification\n"
+"[!] --arp-mac-src address[/mask]: ARP MAC source specification\n"
+"[!] --arp-mac-dst address[/mask]: ARP MAC target specification\n"
"[!] --arp-gratuitous : ARP gratuitous packet\n"
" opcode strings: \n");
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
@@ -78,137 +82,74 @@ static void brarp_print_help(void)
" protocol type string: see "XT_PATH_ETHERTYPES"\n");
}
-#define OPT_OPCODE 0x01
-#define OPT_HTYPE 0x02
-#define OPT_PTYPE 0x04
-#define OPT_IP_S 0x08
-#define OPT_IP_D 0x10
-#define OPT_MAC_S 0x20
-#define OPT_MAC_D 0x40
-#define OPT_GRAT 0x80
-
-static int
-brarp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brarp_parse(struct xt_option_call *cb)
{
- struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
+ struct ebt_arp_info *arpinfo = cb->data;
+ struct xt_ethertypeent *ent;
long int i;
char *end;
- unsigned char *maddr;
- unsigned char *mmask;
- unsigned int ipnr;
- switch (c) {
- case ARP_OPCODE:
- EBT_CHECK_OPTION(flags, OPT_OPCODE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_OPCODE;
- i = strtol(optarg, &end, 10);
+
+ xtables_option_parse(cb);
+
+ arpinfo->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ arpinfo->invflags |= 1 << cb->entry->id;
+
+ switch (cb->entry->id) {
+ case O_OPCODE:
+ i = strtol(cb->arg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
- if (!strcasecmp(opcodes[i], optarg))
+ if (!strcasecmp(opcodes[i], cb->arg))
break;
if (i == ARRAY_SIZE(opcodes))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP opcode");
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP opcode");
i++;
}
arpinfo->opcode = htons(i);
- arpinfo->bitmask |= EBT_ARP_OPCODE;
break;
-
- case ARP_HTYPE:
- EBT_CHECK_OPTION(flags, OPT_HTYPE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_HTYPE;
- i = strtol(optarg, &end, 10);
+ case O_HTYPE:
+ i = strtol(cb->arg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
- if (!strcasecmp("Ethernet", argv[optind - 1]))
+ if (!strcasecmp("Ethernet", cb->arg))
i = 1;
else
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP hardware type");
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP hardware type");
}
arpinfo->htype = htons(i);
- arpinfo->bitmask |= EBT_ARP_HTYPE;
- break;
- case ARP_PTYPE: {
- uint16_t proto;
-
- EBT_CHECK_OPTION(flags, OPT_PTYPE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_PTYPE;
-
- i = strtol(optarg, &end, 16);
- if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
- struct xt_ethertypeent *ent;
-
- ent = xtables_getethertypebyname(argv[optind - 1]);
- if (!ent)
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP "
- "protocol type");
- proto = ent->e_ethertype;
-
- } else
- proto = i;
- arpinfo->ptype = htons(proto);
- arpinfo->bitmask |= EBT_ARP_PTYPE;
break;
- }
-
- case ARP_IP_S:
- case ARP_IP_D:
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- if (c == ARP_IP_S) {
- EBT_CHECK_OPTION(flags, OPT_IP_S);
- arpinfo->saddr = ipaddr->s_addr;
- arpinfo->smsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_SRC_IP;
- } else {
- EBT_CHECK_OPTION(flags, OPT_IP_D);
- arpinfo->daddr = ipaddr->s_addr;
- arpinfo->dmsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_DST_IP;
- }
- free(ipaddr);
- if (invert) {
- if (c == ARP_IP_S)
- arpinfo->invflags |= EBT_ARP_SRC_IP;
- else
- arpinfo->invflags |= EBT_ARP_DST_IP;
+ case O_PTYPE:
+ i = strtol(cb->arg, &end, 16);
+ if (i >= 0 && i < (0x1 << 16) && *end == '\0') {
+ arpinfo->ptype = htons(i);
+ break;
}
+ ent = xtables_getethertypebyname(cb->arg);
+ if (!ent)
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP protocol type");
+ arpinfo->ptype = htons(ent->e_ethertype);
break;
- case ARP_MAC_S:
- case ARP_MAC_D:
- if (c == ARP_MAC_S) {
- EBT_CHECK_OPTION(flags, OPT_MAC_S);
- maddr = arpinfo->smaddr;
- mmask = arpinfo->smmsk;
- arpinfo->bitmask |= EBT_ARP_SRC_MAC;
- } else {
- EBT_CHECK_OPTION(flags, OPT_MAC_D);
- maddr = arpinfo->dmaddr;
- mmask = arpinfo->dmmsk;
- arpinfo->bitmask |= EBT_ARP_DST_MAC;
- }
- if (invert) {
- if (c == ARP_MAC_S)
- arpinfo->invflags |= EBT_ARP_SRC_MAC;
- else
- arpinfo->invflags |= EBT_ARP_DST_MAC;
- }
- if (xtables_parse_mac_and_mask(optarg, maddr, mmask))
- xtables_error(PARAMETER_PROBLEM, "Problem with ARP MAC address argument");
+ case O_SRC_IP:
+ arpinfo->saddr = cb->val.haddr.ip & cb->val.hmask.ip;
+ arpinfo->smsk = cb->val.hmask.ip;
+ break;
+ case O_DST_IP:
+ arpinfo->daddr = cb->val.haddr.ip & cb->val.hmask.ip;
+ arpinfo->dmsk = cb->val.hmask.ip;
+ break;
+ case O_SRC_MAC:
+ memcpy(arpinfo->smaddr, cb->val.ethermac, ETH_ALEN);
+ memcpy(arpinfo->smmsk, cb->val.ethermacmask, ETH_ALEN);
break;
- case ARP_GRAT:
- EBT_CHECK_OPTION(flags, OPT_GRAT);
- arpinfo->bitmask |= EBT_ARP_GRAT;
- if (invert)
- arpinfo->invflags |= EBT_ARP_GRAT;
+ case O_DST_MAC:
+ memcpy(arpinfo->dmaddr, cb->val.ethermac, ETH_ALEN);
+ memcpy(arpinfo->dmmsk, cb->val.ethermacmask, ETH_ALEN);
break;
- default:
- return 0;
}
- return 1;
}
static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric)
@@ -217,51 +158,50 @@ static void brarp_print(const void *ip, const struct xt_entry_match *match, int
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("%d ", ntohs(arpinfo->htype));
+ printf("--arp-htype %d ", ntohs(arpinfo->htype));
}
if (arpinfo->bitmask & EBT_ARP_PTYPE) {
- printf("--arp-ptype ");
if (arpinfo->invflags & EBT_ARP_PTYPE)
printf("! ");
- printf("0x%x ", ntohs(arpinfo->ptype));
+ printf("--arp-ptype 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("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr),
- xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk));
+ printf("--arp-ip-src %s%s ",
+ xtables_ipaddr_to_numeric((void *)&arpinfo->saddr),
+ xtables_ipmask_to_numeric((void *)&arpinfo->smsk));
}
if (arpinfo->bitmask & EBT_ARP_DST_IP) {
- printf("--arp-ip-dst ");
if (arpinfo->invflags & EBT_ARP_DST_IP)
printf("! ");
- printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr),
- xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk));
+ printf("--arp-ip-dst %s%s ",
+ xtables_ipaddr_to_numeric((void *)&arpinfo->daddr),
+ xtables_ipmask_to_numeric((void *)&arpinfo->dmsk));
}
if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
- printf("--arp-mac-src ");
if (arpinfo->invflags & EBT_ARP_SRC_MAC)
printf("! ");
+ 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("! ");
+ printf("--arp-mac-dst ");
xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
printf(" ");
}
@@ -279,9 +219,9 @@ static struct xtables_match brarp_match = {
.size = XT_ALIGN(sizeof(struct ebt_arp_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_arp_info)),
.help = brarp_print_help,
- .parse = brarp_parse,
+ .x6_parse = brarp_parse,
.print = brarp_print,
- .extra_opts = brarp_opts,
+ .x6_options = brarp_opts,
};
void _init(void)
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
index 96fbce90..ea006f25 100644
--- a/extensions/libebt_arp.t
+++ b/extensions/libebt_arp.t
@@ -1,15 +1,22 @@
:INPUT,FORWARD,OUTPUT
-p ARP --arp-op Request;=;OK
--p ARP --arp-htype ! 1;=;OK
+-p ARP ! --arp-op Request;=;OK
+-p ARP --arp-htype Ethernet;-p ARP --arp-htype 1;OK
+-p ARP --arp-htype 1;=;OK
+-p ARP ! --arp-htype 1;=;OK
-p ARP --arp-ptype 0x2;=;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;-p ARP --arp-ip-dst ! 1.2.3.4 -j CONTINUE;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-ip-src ! 1.2.3.4/32;-p ARP --arp-ip-src ! 1.2.3.4;OK
--p ARP --arp-ip-src ! 1.2.3.4/255.255.255.0;-p ARP --arp-ip-src ! 1.2.3.0/24;OK
--p ARP --arp-ip-src ! 1.2.3.4/255.0.255.255;-p ARP --arp-ip-src ! 1.0.3.4/255.0.255.255;OK
+-p ARP --arp-ip-dst ! 1.2.3.4;-p ARP ! --arp-ip-dst 1.2.3.4 -j CONTINUE;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-ip-src 1.2.3.4/32;-p ARP ! --arp-ip-src 1.2.3.4;OK
+-p ARP ! --arp-ip-src 1.2.3.4/255.255.255.0;-p ARP ! --arp-ip-src 1.2.3.0/24;OK
+-p ARP ! --arp-ip-src 1.2.3.4/255.0.255.255;-p ARP ! --arp-ip-src 1.0.3.4/255.0.255.255;OK
-p ARP --arp-mac-src 00:de:ad:be:ef:00;=;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-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
-p ARP --arp-gratuitous;=;OK
+-p ARP ! --arp-gratuitous;=;OK
--arp-htype 1;=;FAIL
diff --git a/extensions/libebt_arpreply.c b/extensions/libebt_arpreply.c
index 80ba2159..1d6ba36a 100644
--- a/extensions/libebt_arpreply.c
+++ b/extensions/libebt_arpreply.c
@@ -10,22 +10,22 @@
#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
+enum {
+ O_MAC,
+ O_TARGET,
+};
-#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 const struct xt_option_entry brarpreply_opts[] = {
+ { .name = "arpreply-mac" , .id = O_MAC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_arpreply_info, mac) },
+ { .name = "arpreply-target" , .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brarpreply_print_help(void)
@@ -44,31 +44,15 @@ static void brarpreply_init(struct xt_entry_target *target)
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)
-
+static void brarpreply_parse(struct xt_option_call *cb)
{
- 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;
+ struct ebt_arpreply_info *replyinfo = cb->data;
- default:
- return 0;
- }
- return 1;
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&replyinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --arpreply-target target");
}
static void brarpreply_print(const void *ip, const struct xt_entry_target *t, int numeric)
@@ -90,9 +74,9 @@ static struct xtables_target arpreply_target = {
.size = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
.help = brarpreply_print_help,
- .parse = brarpreply_parse,
+ .x6_parse = brarpreply_parse,
.print = brarpreply_print,
- .extra_opts = brarpreply_opts,
+ .x6_options = brarpreply_opts,
};
void _init(void)
diff --git a/extensions/libebt_arpreply.t b/extensions/libebt_arpreply.t
index 6734501a..66103e16 100644
--- a/extensions/libebt_arpreply.t
+++ b/extensions/libebt_arpreply.t
@@ -1,4 +1,8 @@
:PREROUTING
*nat
+-j arpreply;=;FAIL
+-p ARP -i foo -j arpreply;-p ARP -i foo -j arpreply --arpreply-mac 00:00:00:00:00:00;OK
-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
+-p ARP -j arpreply ! --arpreply-mac de:ad:00:be:ee:ff;;FAIL
+-p ARP -j arpreply --arpreply-mac de:ad:00:be:ee:ff ! --arpreply-target ACCEPT;;FAIL
diff --git a/extensions/libebt_dnat.c b/extensions/libebt_dnat.c
index 9f5f721e..447ff105 100644
--- a/extensions/libebt_dnat.c
+++ b/extensions/libebt_dnat.c
@@ -9,21 +9,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAT_D '1'
-#define NAT_D_TARGET '2'
-static const struct option brdnat_opts[] =
+enum {
+ O_DST,
+ O_TARGET,
+};
+
+static const struct xt_option_entry brdnat_opts[] =
{
- { "to-destination", required_argument, 0, NAT_D },
- { "to-dst" , required_argument, 0, NAT_D },
- { "dnat-target" , required_argument, 0, NAT_D_TARGET },
- { 0 }
+ { .name = "to-destination", .id = O_DST, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "to-dst" , .id = O_DST, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "dnat-target" , .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brdnat_print_help(void)
@@ -31,7 +35,8 @@ static void brdnat_print_help(void)
printf(
"dnat options:\n"
" --to-dst address : MAC address to map destination to\n"
- " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
+ " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
+ " (standard target is ACCEPT)\n");
}
static void brdnat_init(struct xt_entry_target *target)
@@ -41,35 +46,20 @@ static void brdnat_init(struct xt_entry_target *target)
natinfo->target = EBT_ACCEPT;
}
-#define OPT_DNAT 0x01
-#define OPT_DNAT_TARGET 0x02
-static int brdnat_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brdnat_parse(struct xt_option_call *cb)
{
- struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
- struct ether_addr *addr;
-
- switch (c) {
- case NAT_D:
- EBT_CHECK_OPTION(flags, OPT_DNAT);
- if (!(addr = ether_aton(optarg)))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-destination mac");
- memcpy(natinfo->mac, addr, ETH_ALEN);
- break;
- case NAT_D_TARGET:
- EBT_CHECK_OPTION(flags, OPT_DNAT_TARGET);
- if (ebt_fill_target(optarg, (unsigned int *)&natinfo->target))
- xtables_error(PARAMETER_PROBLEM, "Illegal --dnat-target target");
- break;
- default:
- return 0;
- }
- return 1;
+ struct ebt_nat_info *natinfo = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&natinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --dnat-target target");
}
-static void brdnat_final_check(unsigned int flags)
+static void brdnat_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -116,11 +106,11 @@ static struct xtables_target brdnat_target =
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.help = brdnat_print_help,
.init = brdnat_init,
- .parse = brdnat_parse,
- .final_check = brdnat_final_check,
+ .x6_parse = brdnat_parse,
+ .x6_fcheck = brdnat_final_check,
.print = brdnat_print,
.xlate = brdnat_xlate,
- .extra_opts = brdnat_opts,
+ .x6_options = brdnat_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 68f34bff..3ed852ad 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -16,7 +16,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <inttypes.h>
#include <xtables.h>
@@ -24,44 +23,70 @@
#include "libxt_icmp.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'
-#define IP_EBT_ICMP '7'
-#define IP_EBT_IGMP '8'
-
-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 },
- { .name = "ip-icmp-type", .has_arg = true, .val = IP_EBT_ICMP },
- { .name = "ip-igmp-type", .has_arg = true, .val = IP_EBT_IGMP },
- XT_GETOPT_TABLEEND,
+/* must correspond to the bit position in EBT_IP6_* defines */
+enum {
+ O_SOURCE = 0,
+ O_DEST,
+ O_TOS,
+ O_PROTO,
+ O_SPORT,
+ O_DPORT,
+ O_ICMP,
+ O_IGMP,
+ F_PORT = 1 << O_ICMP | 1 << O_IGMP,
+ F_ICMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_IGMP,
+ F_IGMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_ICMP,
+};
+
+static const struct xt_option_entry brip_opts[] = {
+ { .name = "ip-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-tos", .id = O_TOS, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, tos) },
+ { .name = "ip-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-icmp-type", .id = O_ICMP, .type = XTTYPE_STRING,
+ .excl = F_ICMP, .flags = XTOPT_INVERT },
+ { .name = "ip-igmp-type", .id = O_IGMP, .type = XTTYPE_STRING,
+ .excl = F_IGMP, .flags = XTOPT_INVERT },
+ XTOPT_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"
-"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"
-"--ip-igmp-type [!] type[:type] : igmp type or type range\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"
+"[!] --ip-icmp-type type[[:type]/code[:code]] : icmp type/code or type/code range\n"
+"[!] --ip-igmp-type type[:type] : igmp type or type range\n");
printf("\nValid ICMP Types:\n");
xt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
@@ -69,38 +94,6 @@ static void brip_print_help(void)
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
}
-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 = xtables_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 void print_icmp_code(uint8_t *code)
{
@@ -138,86 +131,38 @@ static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
print_icmp_code(code);
}
-static int
-brip_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brip_parse(struct xt_option_call *cb)
{
- struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
- unsigned int ipnr;
-
- switch (c) {
- case IP_SOURCE:
- if (invert)
- info->invflags |= EBT_IP_SOURCE;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->saddr = ipaddr->s_addr;
- info->smsk = ipmask.s_addr;
- free(ipaddr);
- info->bitmask |= EBT_IP_SOURCE;
- break;
- case IP_DEST:
- if (invert)
- info->invflags |= EBT_IP_DEST;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->daddr = ipaddr->s_addr;
- info->dmsk = ipmask.s_addr;
- free(ipaddr);
- 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_ICMP:
- if (invert)
- info->invflags |= EBT_IP_ICMP;
- ebt_parse_icmp(optarg, info->icmp_type, info->icmp_code);
- info->bitmask |= EBT_IP_ICMP;
+ struct ebt_ip_info *info = cb->data;
+
+ xtables_option_parse(cb);
+
+ info->bitmask |= 1 << cb->entry->id;
+ info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
+
+ switch (cb->entry->id) {
+ case O_SOURCE:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->saddr = cb->val.haddr.ip;
+ info->smsk = cb->val.hmask.ip;
break;
- case IP_EBT_IGMP:
- if (invert)
- info->invflags |= EBT_IP_IGMP;
- ebt_parse_igmp(optarg, info->igmp_type);
- info->bitmask |= EBT_IP_IGMP;
+ case O_DEST:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->daddr = cb->val.haddr.ip;
+ info->dmsk = cb->val.hmask.ip;
break;
- case IP_EBT_TOS: {
- uintmax_t tosvalue;
-
- if (invert)
- info->invflags |= EBT_IP_TOS;
- 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;
- }
+ case O_ICMP:
+ ebt_parse_icmp(cb->arg, info->icmp_type, info->icmp_code);
break;
- case IP_PROTO:
- if (invert)
- info->invflags |= EBT_IP_PROTO;
- info->protocol = xtables_parse_protocol(optarg);
- info->bitmask |= EBT_IP_PROTO;
+ case O_IGMP:
+ ebt_parse_igmp(cb->arg, info->igmp_type);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
}
-static void brip_final_check(unsigned int flags)
+static void brip_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -237,35 +182,34 @@ 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("! ");
addrp = (struct in_addr *)&info->saddr;
maskp = (struct in_addr *)&info->smsk;
- printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
+ printf("--ip-src %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),
+ printf("--ip-dst %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);
+ printf("--ip-tos 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);
@@ -274,28 +218,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);
}
@@ -503,13 +447,12 @@ static struct xtables_match brip_match = {
.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,
+ .x6_parse = brip_parse,
+ .x6_fcheck = brip_final_check,
.print = brip_print,
.xlate = brip_xlate,
- .extra_opts = brip_opts,
+ .x6_options = brip_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t
index 8be5dfbb..a9b5b8b5 100644
--- a/extensions/libebt_ip.t
+++ b/extensions/libebt_ip.t
@@ -1,13 +1,33 @@
: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 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-dst 10.0.0.1;=;OK
-p IPv4 --ip-tos 0xFF;=;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 udp --ip-sport :;-p IPv4 --ip-proto udp --ip-sport 0:65535;OK
+-p IPv4 --ip-proto udp --ip-sport :4;-p IPv4 --ip-proto udp --ip-sport 0:4;OK
+-p IPv4 --ip-proto udp --ip-sport 4:;-p IPv4 --ip-proto udp --ip-sport 4:65535;OK
+-p IPv4 --ip-proto udp --ip-sport 3:4;=;OK
+-p IPv4 --ip-proto udp --ip-sport 4:4;-p IPv4 --ip-proto udp --ip-sport 4;OK
+-p IPv4 --ip-proto udp --ip-sport 4:3;;FAIL
+-p IPv4 --ip-proto udp --ip-dport :;-p IPv4 --ip-proto udp --ip-dport 0:65535;OK
+-p IPv4 --ip-proto udp --ip-dport :4;-p IPv4 --ip-proto udp --ip-dport 0:4;OK
+-p IPv4 --ip-proto udp --ip-dport 4:;-p IPv4 --ip-proto udp --ip-dport 4:65535;OK
+-p IPv4 --ip-proto udp --ip-dport 3:4;=;OK
+-p IPv4 --ip-proto udp --ip-dport 4:4;-p IPv4 --ip-proto udp --ip-dport 4;OK
+-p IPv4 --ip-proto udp --ip-dport 4:3;;FAIL
-p IPv4 --ip-proto 253;=;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
+-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
+! -p ip --ip-proto tcp --ip-sport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-sport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto icmp --ip-icmp-type echo-reply --ip-igmp-type membership-query;;FAIL
+-p IPv4 --ip-proto icmp ! --ip-icmp-type echo-reply;=;OK
diff --git a/extensions/libebt_ip.txlate b/extensions/libebt_ip.txlate
index 44ce9276..712ba3d1 100644
--- a/extensions/libebt_ip.txlate
+++ b/extensions/libebt_ip.txlate
@@ -1,4 +1,4 @@
-ebtables-translate -A FORWARD -p ip --ip-src ! 192.168.0.0/24 -j ACCEPT
+ebtables-translate -A FORWARD -p ip ! --ip-src 192.168.0.0/24 -j ACCEPT
nft 'add rule bridge filter FORWARD ip saddr != 192.168.0.0/24 counter accept'
ebtables-translate -I FORWARD -p ip --ip-dst 10.0.0.1
@@ -22,5 +22,5 @@ nft 'add rule bridge filter FORWARD icmp type 8 counter'
ebtables-translate -A FORWARD -p ip --ip-proto icmp --ip-icmp-type 1/1
nft 'add rule bridge filter FORWARD icmp type 1 icmp code 1 counter'
-ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type ! 1:10
+ebtables-translate -A FORWARD -p ip --ip-protocol icmp ! --ip-icmp-type 1:10
nft 'add rule bridge filter FORWARD icmp type != 1-10 counter'
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index 18bb2720..247a99eb 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -18,59 +18,59 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_ip6.h>
#include "libxt_icmp.h"
-#define IP_SOURCE '1'
-#define IP_DEST '2'
-#define IP_TCLASS '3'
-#define IP_PROTO '4'
-#define IP_SPORT '5'
-#define IP_DPORT '6'
-#define IP_ICMP6 '7'
-
-static const struct option brip6_opts[] = {
- { .name = "ip6-source", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip6-src", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip6-destination", .has_arg = true, .val = IP_DEST },
- { .name = "ip6-dst", .has_arg = true, .val = IP_DEST },
- { .name = "ip6-tclass", .has_arg = true, .val = IP_TCLASS },
- { .name = "ip6-protocol", .has_arg = true, .val = IP_PROTO },
- { .name = "ip6-proto", .has_arg = true, .val = IP_PROTO },
- { .name = "ip6-source-port", .has_arg = true, .val = IP_SPORT },
- { .name = "ip6-sport", .has_arg = true, .val = IP_SPORT },
- { .name = "ip6-destination-port",.has_arg = true,.val = IP_DPORT },
- { .name = "ip6-dport", .has_arg = true, .val = IP_DPORT },
- { .name = "ip6-icmp-type", .has_arg = true, .val = IP_ICMP6 },
- XT_GETOPT_TABLEEND,
+/* must correspond to the bit position in EBT_IP6_* defines */
+enum {
+ O_SOURCE = 0,
+ O_DEST,
+ O_TCLASS,
+ O_PROTO,
+ O_SPORT,
+ O_DPORT,
+ O_ICMP6,
+ F_PORT = 1 << O_ICMP6,
+ F_ICMP6 = 1 << O_SPORT | 1 << O_DPORT,
};
-static void
-parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = xtables_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);
-}
+static const struct xt_option_entry brip6_opts[] = {
+ { .name = "ip6-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-tclass", .id = O_TCLASS, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, tclass) },
+ { .name = "ip6-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, protocol) },
+ { .name = "ip6-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, protocol) },
+ { .name = "ip6-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, sport) },
+ { .name = "ip6-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, sport) },
+ { .name = "ip6-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, dport) },
+ { .name = "ip6-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, dport) },
+ { .name = "ip6-icmp-type", .id = O_ICMP6, .type = XTTYPE_STRING,
+ .excl = F_ICMP6, .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
+};
static void print_port_range(uint16_t *ports)
{
@@ -116,114 +116,53 @@ static void brip6_print_help(void)
{
printf(
"ip6 options:\n"
-"--ip6-src [!] address[/mask]: ipv6 source specification\n"
-"--ip6-dst [!] address[/mask]: ipv6 destination specification\n"
-"--ip6-tclass [!] tclass : ipv6 traffic class specification\n"
-"--ip6-proto [!] protocol : ipv6 protocol specification\n"
-"--ip6-sport [!] port[:port] : tcp/udp source port or port range\n"
-"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n"
-"--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
+"[!] --ip6-src address[/mask]: ipv6 source specification\n"
+"[!] --ip6-dst address[/mask]: ipv6 destination specification\n"
+"[!] --ip6-tclass tclass : ipv6 traffic class specification\n"
+"[!] --ip6-proto protocol : ipv6 protocol specification\n"
+"[!] --ip6-sport port[:port] : tcp/udp source port or port range\n"
+"[!] --ip6-dport port[:port] : tcp/udp destination port or port range\n"
+"[!] --ip6-icmp-type type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
printf("Valid ICMPv6 Types:");
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
}
-static void brip6_init(struct xt_entry_match *match)
-{
- struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
-
- ipinfo->invflags = 0;
- ipinfo->bitmask = 0;
- memset(ipinfo->saddr.s6_addr, 0, sizeof(ipinfo->saddr.s6_addr));
- memset(ipinfo->smsk.s6_addr, 0, sizeof(ipinfo->smsk.s6_addr));
- memset(ipinfo->daddr.s6_addr, 0, sizeof(ipinfo->daddr.s6_addr));
- memset(ipinfo->dmsk.s6_addr, 0, sizeof(ipinfo->dmsk.s6_addr));
-}
-
-/* wrap xtables_ip6parse_any(), ignoring any but the first returned address */
-static void ebt_parse_ip6_address(char *address,
- struct in6_addr *addr, struct in6_addr *msk)
+static void brip6_parse(struct xt_option_call *cb)
{
- struct in6_addr *addrp;
- unsigned int naddrs;
-
- xtables_ip6parse_any(address, &addrp, msk, &naddrs);
- if (naddrs != 1)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid IPv6 Address '%s' specified", address);
- memcpy(addr, addrp, sizeof(*addr));
- free(addrp);
-}
-
-#define OPT_SOURCE 0x01
-#define OPT_DEST 0x02
-#define OPT_TCLASS 0x04
-#define OPT_PROTO 0x08
-#define OPT_SPORT 0x10
-#define OPT_DPORT 0x20
-static int
-brip6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct ebt_ip6_info *info = (struct ebt_ip6_info *)(*match)->data;
+ struct ebt_ip6_info *info = cb->data;
unsigned int i;
- char *end;
-
- switch (c) {
- case IP_SOURCE:
- if (invert)
- info->invflags |= EBT_IP6_SOURCE;
- ebt_parse_ip6_address(optarg, &info->saddr, &info->smsk);
- info->bitmask |= EBT_IP6_SOURCE;
- break;
- case IP_DEST:
- if (invert)
- info->invflags |= EBT_IP6_DEST;
- ebt_parse_ip6_address(optarg, &info->daddr, &info->dmsk);
- info->bitmask |= EBT_IP6_DEST;
- break;
- case IP_SPORT:
- if (invert)
- info->invflags |= EBT_IP6_SPORT;
- parse_port_range(NULL, optarg, info->sport);
- info->bitmask |= EBT_IP6_SPORT;
- break;
- case IP_DPORT:
- if (invert)
- info->invflags |= EBT_IP6_DPORT;
- parse_port_range(NULL, optarg, info->dport);
- info->bitmask |= EBT_IP6_DPORT;
- break;
- case IP_ICMP6:
- if (invert)
- info->invflags |= EBT_IP6_ICMP6;
- ebt_parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code);
- info->bitmask |= EBT_IP6_ICMP6;
+
+ /* XXX: overriding afinfo family is dangerous, but
+ * required for XTTYPE_HOSTMASK parsing */
+ xtables_set_nfproto(NFPROTO_IPV6);
+ xtables_option_parse(cb);
+ xtables_set_nfproto(NFPROTO_BRIDGE);
+
+ info->bitmask |= 1 << cb->entry->id;
+ info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
+
+ switch (cb->entry->id) {
+ case O_SOURCE:
+ for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
+ cb->val.haddr.all[i] &= cb->val.hmask.all[i];
+ info->saddr = cb->val.haddr.in6;
+ info->smsk = cb->val.hmask.in6;
break;
- case IP_TCLASS:
- if (invert)
- info->invflags |= EBT_IP6_TCLASS;
- if (!xtables_strtoui(optarg, &end, &i, 0, 255))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified IPv6 traffic class '%s'", optarg);
- info->tclass = i;
- info->bitmask |= EBT_IP6_TCLASS;
+ case O_DEST:
+ for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
+ cb->val.haddr.all[i] &= cb->val.hmask.all[i];
+ info->daddr = cb->val.haddr.in6;
+ info->dmsk = cb->val.hmask.in6;
break;
- case IP_PROTO:
- if (invert)
- info->invflags |= EBT_IP6_PROTO;
- info->protocol = xtables_parse_protocol(optarg);
- info->bitmask |= EBT_IP6_PROTO;
+ case O_ICMP6:
+ ebt_parse_icmpv6(cb->arg, info->icmpv6_type, info->icmpv6_code);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
}
-static void brip6_final_check(unsigned int flags)
+static void brip6_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -234,31 +173,30 @@ 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("0x%02X ", ipinfo->tclass);
+ printf("--ip6-tclass 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);
@@ -267,21 +205,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);
}
}
@@ -452,13 +390,12 @@ static struct xtables_match brip6_match = {
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
- .init = brip6_init,
.help = brip6_print_help,
- .parse = brip6_parse,
- .final_check = brip6_final_check,
+ .x6_parse = brip6_parse,
+ .x6_fcheck = brip6_final_check,
.print = brip6_print,
.xlate = brip6_xlate,
- .extra_opts = brip6_opts,
+ .x6_options = brip6_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t
index fa1038af..cb1be9e3 100644
--- a/extensions/libebt_ip6.t
+++ b/extensions/libebt_ip6.t
@@ -1,15 +1,35 @@
:INPUT,FORWARD,OUTPUT
--p ip6 --ip6-src ! dead::beef/64 -j ACCEPT;-p IPv6 --ip6-src ! dead::/64 -j ACCEPT;OK
+-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-dst f00:ba::;=;OK
+-p IPv6 --ip6-src 10.0.0.1;;FAIL
-p IPv6 --ip6-tclass 0xFF;=;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 tcp ! --ip6-dport 22;=;OK
+-p IPv6 --ip6-proto tcp ! --ip6-sport 22 --ip6-dport 22;=;OK
-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK
+-p IPv6 --ip6-proto udp --ip6-sport :;-p IPv6 --ip6-proto udp --ip6-sport 0:65535;OK
+-p IPv6 --ip6-proto udp --ip6-sport :4;-p IPv6 --ip6-proto udp --ip6-sport 0:4;OK
+-p IPv6 --ip6-proto udp --ip6-sport 4:;-p IPv6 --ip6-proto udp --ip6-sport 4:65535;OK
+-p IPv6 --ip6-proto udp --ip6-sport 3:4;=;OK
+-p IPv6 --ip6-proto udp --ip6-sport 4:4;-p IPv6 --ip6-proto udp --ip6-sport 4;OK
+-p IPv6 --ip6-proto udp --ip6-sport 4:3;;FAIL
+-p IPv6 --ip6-proto udp --ip6-dport :;-p IPv6 --ip6-proto udp --ip6-dport 0:65535;OK
+-p IPv6 --ip6-proto udp --ip6-dport :4;-p IPv6 --ip6-proto udp --ip6-dport 0:4;OK
+-p IPv6 --ip6-proto udp --ip6-dport 4:;-p IPv6 --ip6-proto udp --ip6-dport 4:65535;OK
+-p IPv6 --ip6-proto udp --ip6-dport 3:4;=;OK
+-p IPv6 --ip6-proto udp --ip6-dport 4:4;-p IPv6 --ip6-proto udp --ip6-dport 4;OK
+-p IPv6 --ip6-proto udp --ip6-dport 4:3;;FAIL
-p IPv6 --ip6-proto 253;=;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 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
+-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
+-p IPv6 --ip6-proto tcp --ip6-sport 22 --ip6-icmp-type echo-request;;FAIL
+-p IPv6 --ip6-proto tcp --ip6-dport 22 --ip6-icmp-type echo-request;;FAIL
diff --git a/extensions/libebt_ip6.txlate b/extensions/libebt_ip6.txlate
index 0debbe12..13d57e3a 100644
--- a/extensions/libebt_ip6.txlate
+++ b/extensions/libebt_ip6.txlate
@@ -25,5 +25,5 @@ nft 'add rule bridge filter FORWARD icmpv6 type 128 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1
nft 'add rule bridge filter FORWARD icmpv6 type 1 icmpv6 code 1 counter'
-ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type ! 1:10
+ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 ! --ip6-icmp-type 1:10
nft 'add rule bridge filter FORWARD icmpv6 type != 1-10 counter'
diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
index 9f8d1589..dc2357c0 100644
--- a/extensions/libebt_log.c
+++ b/extensions/libebt_log.c
@@ -14,19 +14,11 @@
#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'
-
struct code {
char *c_name;
int c_val;
@@ -43,26 +35,26 @@ static struct code eight_priority[] = {
{ "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;
-}
+enum {
+ /* first three must correspond with bit pos in respective EBT_LOG_* */
+ O_LOG_IP = 0,
+ O_LOG_ARP = 1,
+ O_LOG_IP6 = 3,
+ O_LOG_PREFIX,
+ O_LOG_LEVEL,
+ O_LOG_LOG,
+};
-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 const struct xt_option_entry brlog_opts[] = {
+ { .name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, prefix) },
+ { .name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, loglevel) },
+ { .name = "log-arp", .id = O_LOG_ARP, .type = XTTYPE_NONE },
+ { .name = "log-ip", .id = O_LOG_IP, .type = XTTYPE_NONE },
+ { .name = "log", .id = O_LOG_LOG, .type = XTTYPE_NONE },
+ { .name = "log-ip6", .id = O_LOG_IP6, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brlog_help(void)
@@ -87,73 +79,21 @@ 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 unsigned int log_chk_inv(int inv, unsigned int bit, const char *suffix)
-{
- if (inv)
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log%s", suffix);
- return bit;
-}
-
-static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brlog_parse(struct xt_option_call *cb)
{
- 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);
+ struct ebt_log_info *loginfo = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LOG_IP:
+ case O_LOG_ARP:
+ case O_LOG_IP6:
+ loginfo->bitmask |= 1 << cb->entry->id;
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:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP, "-ip");
- break;
- case LOG_ARP:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_ARP, "-arp");
- break;
- case LOG_LOG:
- loginfo->bitmask |= log_chk_inv(invert, 0, "");
- break;
- case LOG_IP6:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP6, "-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,
@@ -204,11 +144,10 @@ static struct xtables_target brlog_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
.init = brlog_init,
.help = brlog_help,
- .parse = brlog_parse,
- .final_check = brlog_final_check,
+ .x6_parse = brlog_parse,
.print = brlog_print,
.xlate = brlog_xlate,
- .extra_opts = brlog_opts,
+ .x6_options = brlog_opts,
};
void _init(void)
diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c
index 40e49618..0dc598fe 100644
--- a/extensions/libebt_mark.c
+++ b/extensions/libebt_mark.c
@@ -12,27 +12,39 @@
#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"
-#define MARK_TARGET '1'
-#define MARK_SETMARK '2'
-#define MARK_ORMARK '3'
-#define MARK_ANDMARK '4'
-#define MARK_XORMARK '5'
-static const struct option brmark_opts[] = {
- { .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
+enum {
+ O_SET_MARK = 0,
+ O_AND_MARK,
+ O_OR_MARK,
+ O_XOR_MARK,
+ O_MARK_TARGET,
+ F_SET_MARK = 1 << O_SET_MARK,
+ F_AND_MARK = 1 << O_AND_MARK,
+ F_OR_MARK = 1 << O_OR_MARK,
+ F_XOR_MARK = 1 << O_XOR_MARK,
+ F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK | F_XOR_MARK,
+};
+
+static const struct xt_option_entry brmark_opts[] = {
+ { .name = "mark-target",.id = O_MARK_TARGET, .type = XTTYPE_STRING },
/* 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,
+ { .name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-set", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-or", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-and", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-xor", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ XTOPT_TABLEEND,
};
static void brmark_print_help(void)
@@ -54,83 +66,39 @@ static void brmark_init(struct xt_entry_target *target)
info->mark = 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)
+static void brmark_parse(struct xt_option_call *cb)
{
- 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))
+ static const unsigned long target_orval[] = {
+ [O_SET_MARK] = MARK_SET_VALUE,
+ [O_AND_MARK] = MARK_AND_VALUE,
+ [O_OR_MARK] = MARK_OR_VALUE,
+ [O_XOR_MARK] = MARK_XOR_VALUE,
+ };
+ struct ebt_mark_t_info *info = cb->data;
+ unsigned int tmp;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_MARK_TARGET:
+ if (ebt_fill_target(cb->arg, &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;
+ return;
+ case O_SET_MARK:
+ case O_OR_MARK:
+ case O_AND_MARK:
+ case O_XOR_MARK:
break;
default:
- return 0;
+ return;
}
/* mutual code */
- info->mark = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'",
- optarg);
-
- return 1;
+ info->mark = cb->val.u32;
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ target_orval[cb->entry->id];
}
static void brmark_print(const void *ip, const struct xt_entry_target *target,
@@ -156,9 +124,9 @@ static void brmark_print(const void *ip, const struct xt_entry_target *target,
printf(" --mark-target %s", ebt_target_name(tmp));
}
-static void brmark_final_check(unsigned int flags)
+static void brmark_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify some option");
}
@@ -215,11 +183,11 @@ static struct xtables_target brmark_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
.help = brmark_print_help,
.init = brmark_init,
- .parse = brmark_parse,
- .final_check = brmark_final_check,
+ .x6_parse = brmark_parse,
+ .x6_fcheck = brmark_final_check,
.print = brmark_print,
.xlate = brmark_xlate,
- .extra_opts = brmark_opts,
+ .x6_options = brmark_opts,
};
void _init(void)
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index 2462d0af..8ee17207 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -12,73 +12,50 @@
#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'
+enum {
+ O_MARK = 0,
+};
-static const struct option brmark_m_opts[] = {
- { .name = "mark", .has_arg = true, .val = MARK },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brmark_m_opts[] = {
+ { .name = "mark", .id = O_MARK, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT | XTOPT_MAND },
+ XTOPT_TABLEEND,
};
static void brmark_m_print_help(void)
{
printf(
"mark option:\n"
-"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
+"[!] --mark [value][/mask]: Match nfmask value (see man page)\n");
}
-static void brmark_m_init(struct xt_entry_match *match)
+static void brmark_m_parse(struct xt_option_call *cb)
{
- 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;
+ struct ebt_mark_m_info *info = cb->data;
char *end;
- switch (c) {
- case MARK:
- if (invert)
- info->invert = 1;
- info->mark = strtoul(optarg, &end, 0);
+ xtables_option_parse(cb);
+
+ switch (cb->entry->id) {
+ case O_MARK:
+ info->invert = cb->invert;
+ info->mark = strtoul(cb->arg, &end, 0);
info->bitmask = EBT_MARK_AND;
if (*end == '/') {
- if (end == optarg)
+ if (end == cb->arg)
info->bitmask = EBT_MARK_OR;
info->mask = strtoul(end+1, &end, 0);
} else {
- info->mask = 0xffffffff;
+ info->mask = UINT32_MAX;
}
- if (*end != '\0' || end == optarg)
+ if (*end != '\0' || end == cb->arg)
xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
- optarg);
+ cb->arg);
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,
@@ -86,9 +63,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)
@@ -111,7 +88,7 @@ static int brmark_m_xlate(struct xt_xlate *xl,
if (info->bitmask == EBT_MARK_OR) {
xt_xlate_add(xl, "and 0x%x %s0 ", (uint32_t)info->mask,
info->invert ? "" : "!= ");
- } else if (info->mask != 0xffffffffU) {
+ } else if (info->mask != UINT32_MAX) {
xt_xlate_add(xl, "and 0x%x %s0x%x ", (uint32_t)info->mask,
op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
} else {
@@ -128,13 +105,11 @@ static struct xtables_match brmark_m_match = {
.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,
+ .x6_parse = brmark_m_parse,
.print = brmark_m_print,
.xlate = brmark_m_xlate,
- .extra_opts = brmark_m_opts,
+ .x6_options = brmark_m_opts,
};
void _init(void)
diff --git a/extensions/libebt_mark_m.t b/extensions/libebt_mark_m.t
index 00035427..4de72bde 100644
--- a/extensions/libebt_mark_m.t
+++ b/extensions/libebt_mark_m.t
@@ -1,6 +1,6 @@
:INPUT,FORWARD,OUTPUT
--mark 42;--mark 0x2a;OK
---mark ! 42;--mark ! 0x2a;OK
+! --mark 42;! --mark 0x2a;OK
--mark 42/0xff;--mark 0x2a/0xff;OK
---mark ! 0x1/0xff;=;OK
+! --mark 0x1/0xff;=;OK
--mark /0x2;=;OK
diff --git a/extensions/libebt_mark_m.txlate b/extensions/libebt_mark_m.txlate
index 2981a564..9061adbf 100644
--- a/extensions/libebt_mark_m.txlate
+++ b/extensions/libebt_mark_m.txlate
@@ -7,7 +7,7 @@ nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
ebtables-translate -A INPUT --mark ! 42
nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
-ebtables-translate -A INPUT --mark ! 0x1/0xff
+ebtables-translate -A INPUT ! --mark 0x1/0xff
nft 'add rule bridge filter INPUT meta mark and 0xff != 0x1 counter'
ebtables-translate -A INPUT --mark /0x02
diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c
index 762d6d5d..48cd5321 100644
--- a/extensions/libebt_nflog.c
+++ b/extensions/libebt_nflog.c
@@ -16,27 +16,30 @@
#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,
+ O_GROUP = 0,
+ O_PREFIX,
+ O_RANGE,
+ O_THRESHOLD,
+ O_NFLOG,
};
-static const 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 const struct xt_option_entry brnflog_opts[] = {
+ { .name = "nflog-group", .id = O_GROUP, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, group) },
+ { .name = "nflog-prefix", .id = O_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, prefix) },
+ { .name = "nflog-range", .id = O_RANGE, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, len) },
+ { .name = "nflog-threshold", .id = O_THRESHOLD, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, threshold) },
+ { .name = "nflog", .id = O_NFLOG, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brnflog_help(void)
@@ -59,55 +62,6 @@ static void brnflog_init(struct xt_entry_target *t)
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)
@@ -153,10 +107,10 @@ static struct xtables_target brnflog_watcher = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
.init = brnflog_init,
.help = brnflog_help,
- .parse = brnflog_parse,
+ .x6_parse = xtables_option_parse,
.print = brnflog_print,
.xlate = brnflog_xlate,
- .extra_opts = brnflog_opts,
+ .x6_options = brnflog_opts,
};
void _init(void)
diff --git a/extensions/libebt_pkttype.c b/extensions/libebt_pkttype.c
index 4e2d19de..579e8fdb 100644
--- a/extensions/libebt_pkttype.c
+++ b/extensions/libebt_pkttype.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/if_packet.h>
@@ -25,57 +24,59 @@ static const char *classes[] = {
"fastroute",
};
-static const struct option brpkttype_opts[] =
-{
- { "pkttype-type" , required_argument, 0, '1' },
- { 0 }
+enum {
+ O_TYPE,
+};
+
+static const struct xt_option_entry brpkttype_opts[] = {
+ { .name = "pkttype-type", .id = O_TYPE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
static void brpkttype_print_help(void)
{
printf(
"pkttype options:\n"
-"--pkttype-type [!] type: class the packet belongs to\n"
+"[!] --pkttype-type type: class the packet belongs to\n"
"Possible values: broadcast, multicast, host, otherhost, or any other byte value (which would be pretty useless).\n");
}
-static int brpkttype_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brpkttype_parse(struct xt_option_call *cb)
{
- struct ebt_pkttype_info *ptinfo = (struct ebt_pkttype_info *)(*match)->data;
- char *end;
+ struct ebt_pkttype_info *ptinfo = cb->data;
long int i;
+ char *end;
+
+ xtables_option_parse(cb);
- switch (c) {
- case '1':
- if (invert)
- ptinfo->invert = 1;
- i = strtol(optarg, &end, 16);
+ switch (cb->entry->id) {
+ case O_TYPE:
+ ptinfo->invert = cb->invert;
+ i = strtol(cb->arg, &end, 16);
if (*end != '\0') {
for (i = 0; i < ARRAY_SIZE(classes); i++) {
- if (!strcasecmp(optarg, classes[i]))
+ if (!strcasecmp(cb->arg, classes[i]))
break;
}
if (i >= ARRAY_SIZE(classes))
- xtables_error(PARAMETER_PROBLEM, "Could not parse class '%s'", optarg);
+ xtables_error(PARAMETER_PROBLEM,
+ "Could not parse class '%s'",
+ cb->arg);
}
if (i < 0 || i > 255)
xtables_error(PARAMETER_PROBLEM, "Problem with specified pkttype class");
ptinfo->pkt_type = (uint8_t)i;
break;
- default:
- return 0;
}
- return 1;
}
-
static void brpkttype_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data;
- printf("--pkttype-type %s", pt->invert ? "! " : "");
+ printf("%s--pkttype-type ", pt->invert ? "! " : "");
if (pt->pkt_type < ARRAY_SIZE(classes))
printf("%s ", classes[pt->pkt_type]);
@@ -107,10 +108,10 @@ static struct xtables_match brpkttype_match = {
.size = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
.help = brpkttype_print_help,
- .parse = brpkttype_parse,
+ .x6_parse = brpkttype_parse,
.print = brpkttype_print,
.xlate = brpkttype_xlate,
- .extra_opts = brpkttype_opts,
+ .x6_options = brpkttype_opts,
};
void _init(void)
diff --git a/extensions/libebt_pkttype.t b/extensions/libebt_pkttype.t
index e3b95ded..f3cdc19d 100644
--- a/extensions/libebt_pkttype.t
+++ b/extensions/libebt_pkttype.t
@@ -1,14 +1,14 @@
:INPUT,FORWARD,OUTPUT
-! --pkttype-type host;--pkttype-type ! host -j CONTINUE;OK
+--pkttype-type ! host;! --pkttype-type host -j CONTINUE;OK
--pkttype-type host;=;OK
---pkttype-type ! host;=;OK
+! --pkttype-type host;=;OK
--pkttype-type broadcast;=;OK
---pkttype-type ! broadcast;=;OK
+! --pkttype-type broadcast;=;OK
--pkttype-type multicast;=;OK
---pkttype-type ! multicast;=;OK
+! --pkttype-type multicast;=;OK
--pkttype-type otherhost;=;OK
---pkttype-type ! otherhost;=;OK
+! --pkttype-type otherhost;=;OK
--pkttype-type outgoing;=;OK
---pkttype-type ! outgoing;=;OK
+! --pkttype-type outgoing;=;OK
--pkttype-type loopback;=;OK
---pkttype-type ! loopback;=;OK
+! --pkttype-type loopback;=;OK
diff --git a/extensions/libebt_redirect.c b/extensions/libebt_redirect.c
index 7821935e..a44dbaec 100644
--- a/extensions/libebt_redirect.c
+++ b/extensions/libebt_redirect.c
@@ -9,17 +9,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_redirect.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define REDIRECT_TARGET '1'
-static const struct option brredir_opts[] =
+enum {
+ O_TARGET,
+};
+
+static const struct xt_option_entry brredir_opts[] =
{
- { "redirect-target", required_argument, 0, REDIRECT_TARGET },
- { 0 }
+ { .name = "redirect-target", .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brredir_print_help(void)
@@ -37,23 +39,15 @@ static void brredir_init(struct xt_entry_target *target)
redirectinfo->target = EBT_ACCEPT;
}
-#define OPT_REDIRECT_TARGET 0x01
-static int brredir_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brredir_parse(struct xt_option_call *cb)
{
- struct ebt_redirect_info *redirectinfo =
- (struct ebt_redirect_info *)(*target)->data;
-
- switch (c) {
- case REDIRECT_TARGET:
- EBT_CHECK_OPTION(flags, OPT_REDIRECT_TARGET);
- if (ebt_fill_target(optarg, (unsigned int *)&redirectinfo->target))
- xtables_error(PARAMETER_PROBLEM, "Illegal --redirect-target target");
- break;
- default:
- return 0;
- }
- return 1;
+ struct ebt_redirect_info *redirectinfo = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&redirectinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --redirect-target target");
}
static void brredir_print(const void *ip, const struct xt_entry_target *target, int numeric)
@@ -97,10 +91,10 @@ static struct xtables_target brredirect_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_redirect_info)),
.help = brredir_print_help,
.init = brredir_init,
- .parse = brredir_parse,
+ .x6_parse = brredir_parse,
.print = brredir_print,
.xlate = brredir_xlate,
- .extra_opts = brredir_opts,
+ .x6_options = brredir_opts,
};
void _init(void)
diff --git a/extensions/libebt_snat.c b/extensions/libebt_snat.c
index c1124bf3..1dc738fa 100644
--- a/extensions/libebt_snat.c
+++ b/extensions/libebt_snat.c
@@ -9,23 +9,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAT_S '1'
-#define NAT_S_TARGET '2'
-#define NAT_S_ARP '3'
-static const struct option brsnat_opts[] =
+enum {
+ O_SRC,
+ O_TARGET,
+ O_ARP,
+};
+
+static const struct xt_option_entry brsnat_opts[] =
{
- { "to-source" , required_argument, 0, NAT_S },
- { "to-src" , required_argument, 0, NAT_S },
- { "snat-target" , required_argument, 0, NAT_S_TARGET },
- { "snat-arp" , no_argument, 0, NAT_S_ARP },
- { 0 }
+ { .name = "to-source", .id = O_SRC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "to-src", .id = O_SRC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "snat-target", .id = O_TARGET, .type = XTTYPE_STRING },
+ { .name = "snat-arp", .id = O_ARP, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brsnat_print_help(void)
@@ -44,43 +48,29 @@ static void brsnat_init(struct xt_entry_target *target)
natinfo->target = EBT_ACCEPT;
}
-#define OPT_SNAT 0x01
-#define OPT_SNAT_TARGET 0x02
-#define OPT_SNAT_ARP 0x04
-static int brsnat_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brsnat_parse(struct xt_option_call *cb)
{
- struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
- struct ether_addr *addr;
-
- switch (c) {
- case NAT_S:
- EBT_CHECK_OPTION(flags, OPT_SNAT);
- if (!(addr = ether_aton(optarg)))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-source mac");
- memcpy(natinfo->mac, addr, ETH_ALEN);
- break;
- case NAT_S_TARGET:
- { unsigned int tmp;
- EBT_CHECK_OPTION(flags, OPT_SNAT_TARGET);
- if (ebt_fill_target(optarg, &tmp))
- xtables_error(PARAMETER_PROBLEM, "Illegal --snat-target target");
- natinfo->target = (natinfo->target & ~EBT_VERDICT_BITS) | (tmp & EBT_VERDICT_BITS);
- }
+ struct ebt_nat_info *natinfo = cb->data;
+ unsigned int tmp;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TARGET:
+ if (ebt_fill_target(cb->arg, &tmp))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --snat-target target");
+ natinfo->target &= ~EBT_VERDICT_BITS;
+ natinfo->target |= tmp & EBT_VERDICT_BITS;
break;
- case NAT_S_ARP:
- EBT_CHECK_OPTION(flags, OPT_SNAT_ARP);
+ case O_ARP:
natinfo->target ^= NAT_ARP_BIT;
break;
- default:
- return 0;
}
- return 1;
}
-static void brsnat_final_check(unsigned int flags)
+static void brsnat_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -133,11 +123,11 @@ static struct xtables_target brsnat_target =
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.help = brsnat_print_help,
.init = brsnat_init,
- .parse = brsnat_parse,
- .final_check = brsnat_final_check,
+ .x6_parse = brsnat_parse,
+ .x6_fcheck = brsnat_final_check,
.print = brsnat_print,
.xlate = brsnat_xlate,
- .extra_opts = brsnat_opts,
+ .x6_options = brsnat_opts,
};
void _init(void)
diff --git a/extensions/libebt_snat.t b/extensions/libebt_snat.t
index 639b13f3..f5d02340 100644
--- a/extensions/libebt_snat.t
+++ b/extensions/libebt_snat.t
@@ -2,3 +2,5 @@
*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
+-j snat;;FAIL
+-j snat --to-src de:ad:00:be:ee:ff;-j snat --to-src de:ad:00:be:ee:ff --snat-target ACCEPT;OK
diff --git a/extensions/libebt_standard.t b/extensions/libebt_standard.t
index 97cb3baa..3f1a459c 100644
--- a/extensions/libebt_standard.t
+++ b/extensions/libebt_standard.t
@@ -6,7 +6,8 @@
-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 ARP -j ACCEPT;=;OK
+-p ! ARP -j ACCEPT;! -p ARP -j ACCEPT;OK
-p 0 -j ACCEPT;=;FAIL
-p ! 0 -j ACCEPT;=;FAIL
:INPUT
@@ -14,6 +15,10 @@
-o foobar;=;FAIL
--logical-in br0;=;OK
--logical-out br1;=;FAIL
+-i + -d 00:0f:ee:d0:ba:be;-d 00:0f:ee:d0:ba:be;OK
+-i + -p ip;-p IPv4;OK
+--logical-in + -d 00:0f:ee:d0:ba:be;-d 00:0f:ee:d0:ba:be;OK
+--logical-in + -p ip;-p IPv4;OK
:FORWARD
-i foobar;=;OK
-o foobar;=;OK
diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c
index 41059baa..189e36a5 100644
--- a/extensions/libebt_stp.c
+++ b/extensions/libebt_stp.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <linux/netfilter_bridge/ebt_stp.h>
#include <xtables.h>
@@ -17,35 +16,37 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define STP_TYPE 'a'
-#define STP_FLAGS 'b'
-#define STP_ROOTPRIO 'c'
-#define STP_ROOTADDR 'd'
-#define STP_ROOTCOST 'e'
-#define STP_SENDERPRIO 'f'
-#define STP_SENDERADDR 'g'
-#define STP_PORT 'h'
-#define STP_MSGAGE 'i'
-#define STP_MAXAGE 'j'
-#define STP_HELLOTIME 'k'
-#define STP_FWDD 'l'
-#define STP_NUMOPS 12
+/* These must correspond to the bit position in EBT_STP_* defines */
+enum {
+ O_TYPE = 0,
+ O_FLAGS,
+ O_RPRIO,
+ O_RADDR,
+ O_RCOST,
+ O_SPRIO,
+ O_SADDR,
+ O_PORT,
+ O_MSGAGE,
+ O_MAXAGE,
+ O_HTIME,
+ O_FWDD,
+};
-static const struct option brstp_opts[] =
-{
- { "stp-type" , required_argument, 0, STP_TYPE},
- { "stp-flags" , required_argument, 0, STP_FLAGS},
- { "stp-root-prio" , required_argument, 0, STP_ROOTPRIO},
- { "stp-root-addr" , required_argument, 0, STP_ROOTADDR},
- { "stp-root-cost" , required_argument, 0, STP_ROOTCOST},
- { "stp-sender-prio" , required_argument, 0, STP_SENDERPRIO},
- { "stp-sender-addr" , required_argument, 0, STP_SENDERADDR},
- { "stp-port" , required_argument, 0, STP_PORT},
- { "stp-msg-age" , required_argument, 0, STP_MSGAGE},
- { "stp-max-age" , required_argument, 0, STP_MAXAGE},
- { "stp-hello-time" , required_argument, 0, STP_HELLOTIME},
- { "stp-forward-delay", required_argument, 0, STP_FWDD},
- { 0 }
+static const struct xt_option_entry brstp_opts[] = {
+#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
+ ENTRY("stp-type", O_TYPE, XTTYPE_STRING),
+ ENTRY("stp-flags", O_FLAGS, XTTYPE_STRING),
+ ENTRY("stp-root-prio", O_RPRIO, XTTYPE_UINT16RC),
+ ENTRY("stp-root-addr", O_RADDR, XTTYPE_ETHERMACMASK),
+ ENTRY("stp-root-cost", O_RCOST, XTTYPE_UINT32RC),
+ ENTRY("stp-sender-prio", O_SPRIO, XTTYPE_UINT16RC),
+ ENTRY("stp-sender-addr", O_SADDR, XTTYPE_ETHERMACMASK),
+ ENTRY("stp-port", O_PORT, XTTYPE_UINT16RC),
+ ENTRY("stp-msg-age", O_MSGAGE, XTTYPE_UINT16RC),
+ ENTRY("stp-max-age", O_MAXAGE, XTTYPE_UINT16RC),
+ ENTRY("stp-hello-time", O_HTIME, XTTYPE_UINT16RC),
+ ENTRY("stp-forward-delay", O_FWDD, XTTYPE_UINT16RC),
+ XTOPT_TABLEEND,
};
#define BPDU_TYPE_CONFIG 0
@@ -62,18 +63,18 @@ static void brstp_print_help(void)
{
printf(
"stp options:\n"
-"--stp-type type : BPDU type\n"
-"--stp-flags flag : control flag\n"
-"--stp-root-prio prio[:prio] : root priority (16-bit) range\n"
-"--stp-root-addr address[/mask] : MAC address of root\n"
-"--stp-root-cost cost[:cost] : root cost (32-bit) range\n"
-"--stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
-"--stp-sender-addr address[/mask] : MAC address of sender\n"
-"--stp-port port[:port] : port id (16-bit) range\n"
-"--stp-msg-age age[:age] : message age timer (16-bit) range\n"
-"--stp-max-age age[:age] : maximum age timer (16-bit) range\n"
-"--stp-hello-time time[:time] : hello time timer (16-bit) range\n"
-"--stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
+"[!] --stp-type type : BPDU type\n"
+"[!] --stp-flags flag : control flag\n"
+"[!] --stp-root-prio prio[:prio] : root priority (16-bit) range\n"
+"[!] --stp-root-addr address[/mask] : MAC address of root\n"
+"[!] --stp-root-cost cost[:cost] : root cost (32-bit) range\n"
+"[!] --stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
+"[!] --stp-sender-addr address[/mask] : MAC address of sender\n"
+"[!] --stp-port port[:port] : port id (16-bit) range\n"
+"[!] --stp-msg-age age[:age] : message age timer (16-bit) range\n"
+"[!] --stp-max-age age[:age] : maximum age timer (16-bit) range\n"
+"[!] --stp-hello-time time[:time] : hello time timer (16-bit) range\n"
+"[!] --stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
" Recognized BPDU type strings:\n"
" \"config\": configuration BPDU (=0)\n"
" \"tcn\" : topology change notification BPDU (=0x80)\n"
@@ -82,67 +83,6 @@ static void brstp_print_help(void)
" \"topology-change-ack\": topology change acknowledgement flag (0x80)");
}
-static int parse_range(const char *portstring, void *lower, void *upper,
- int bits, uint32_t min, uint32_t max)
-{
- char *buffer;
- char *cp, *end;
- uint32_t low_nr, upp_nr;
- int ret = 0;
-
- buffer = xtables_strdup(portstring);
-
- if ((cp = strchr(buffer, ':')) == NULL) {
- low_nr = strtoul(buffer, &end, 10);
- if (*end || low_nr < min || low_nr > max) {
- ret = -1;
- goto out;
- }
- if (bits == 2) {
- *(uint16_t *)lower = low_nr;
- *(uint16_t *)upper = low_nr;
- } else {
- *(uint32_t *)lower = low_nr;
- *(uint32_t *)upper = low_nr;
- }
- } else {
- *cp = '\0';
- cp++;
- if (!*buffer)
- low_nr = min;
- else {
- low_nr = strtoul(buffer, &end, 10);
- if (*end || low_nr < min) {
- ret = -1;
- goto out;
- }
- }
- if (!*cp)
- upp_nr = max;
- else {
- upp_nr = strtoul(cp, &end, 10);
- if (*end || upp_nr > max) {
- ret = -1;
- goto out;
- }
- }
- if (upp_nr < low_nr) {
- ret = -1;
- goto out;
- }
- if (bits == 2) {
- *(uint16_t *)lower = low_nr;
- *(uint16_t *)upper = upp_nr;
- } else {
- *(uint32_t *)lower = low_nr;
- *(uint32_t *)upper = upp_nr;
- }
- }
-out:
- free(buffer);
- return ret;
-}
-
static void print_range(unsigned int l, unsigned int u)
{
if (l == u)
@@ -151,103 +91,84 @@ static void print_range(unsigned int l, unsigned int u)
printf("%u:%u", l, u);
}
-static int
-brstp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brstp_parse(struct xt_option_call *cb)
{
- struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)(*match)->data;
- unsigned int flag;
- long int i;
+ struct ebt_stp_info *stpinfo = cb->data;
char *end = NULL;
+ long int i;
+
+ xtables_option_parse(cb);
- if (c < 'a' || c > ('a' + STP_NUMOPS - 1))
- return 0;
- flag = 1 << (c - 'a');
- EBT_CHECK_OPTION(flags, flag);
- if (invert)
- stpinfo->invflags |= flag;
- stpinfo->bitmask |= flag;
- switch (flag) {
- case EBT_STP_TYPE:
- i = strtol(optarg, &end, 0);
+ stpinfo->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ stpinfo->invflags |= 1 << cb->entry->id;
+
+ switch (cb->entry->id) {
+ case O_TYPE:
+ i = strtol(cb->arg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
- if (!strcasecmp(optarg, BPDU_TYPE_CONFIG_STRING))
+ if (!strcasecmp(cb->arg, BPDU_TYPE_CONFIG_STRING))
stpinfo->type = BPDU_TYPE_CONFIG;
- else if (!strcasecmp(optarg, BPDU_TYPE_TCN_STRING))
+ else if (!strcasecmp(cb->arg, BPDU_TYPE_TCN_STRING))
stpinfo->type = BPDU_TYPE_TCN;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-type argument");
} else
stpinfo->type = i;
break;
- case EBT_STP_FLAGS:
- i = strtol(optarg, &end, 0);
+ case O_FLAGS:
+ i = strtol(cb->arg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
- if (!strcasecmp(optarg, FLAG_TC_STRING))
+ if (!strcasecmp(cb->arg, FLAG_TC_STRING))
stpinfo->config.flags = FLAG_TC;
- else if (!strcasecmp(optarg, FLAG_TC_ACK_STRING))
+ else if (!strcasecmp(cb->arg, FLAG_TC_ACK_STRING))
stpinfo->config.flags = FLAG_TC_ACK;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-flags argument");
} else
stpinfo->config.flags = i;
break;
- case EBT_STP_ROOTPRIO:
- if (parse_range(argv[optind-1], &(stpinfo->config.root_priol),
- &(stpinfo->config.root_priou), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-prio range");
+ case O_RADDR:
+ memcpy(stpinfo->config.root_addr, cb->val.ethermac, ETH_ALEN);
+ memcpy(stpinfo->config.root_addrmsk,
+ cb->val.ethermacmask, ETH_ALEN);
break;
- case EBT_STP_ROOTCOST:
- if (parse_range(argv[optind-1], &(stpinfo->config.root_costl),
- &(stpinfo->config.root_costu), 4, 0, 0xffffffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-cost range");
+ case O_SADDR:
+ memcpy(stpinfo->config.sender_addr, cb->val.ethermac, ETH_ALEN);
+ memcpy(stpinfo->config.sender_addrmsk,
+ cb->val.ethermacmask, ETH_ALEN);
break;
- case EBT_STP_SENDERPRIO:
- if (parse_range(argv[optind-1], &(stpinfo->config.sender_priol),
- &(stpinfo->config.sender_priou), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-prio range");
+
+#define RANGE_ASSIGN(fname, val) { \
+ stpinfo->config.fname##l = val[0]; \
+ stpinfo->config.fname##u = cb->nvals > 1 ? val[1] : val[0]; \
+}
+ case O_RPRIO:
+ RANGE_ASSIGN(root_prio, cb->val.u16_range);
break;
- case EBT_STP_PORT:
- if (parse_range(argv[optind-1], &(stpinfo->config.portl),
- &(stpinfo->config.portu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-port-range");
+ case O_RCOST:
+ RANGE_ASSIGN(root_cost, cb->val.u32_range);
break;
- case EBT_STP_MSGAGE:
- if (parse_range(argv[optind-1], &(stpinfo->config.msg_agel),
- &(stpinfo->config.msg_ageu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-msg-age range");
+ case O_SPRIO:
+ RANGE_ASSIGN(sender_prio, cb->val.u16_range);
break;
- case EBT_STP_MAXAGE:
- if (parse_range(argv[optind-1], &(stpinfo->config.max_agel),
- &(stpinfo->config.max_ageu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-max-age range");
+ case O_PORT:
+ RANGE_ASSIGN(port, cb->val.u16_range);
break;
- case EBT_STP_HELLOTIME:
- if (parse_range(argv[optind-1], &(stpinfo->config.hello_timel),
- &(stpinfo->config.hello_timeu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-hello-time range");
+ case O_MSGAGE:
+ RANGE_ASSIGN(msg_age, cb->val.u16_range);
break;
- case EBT_STP_FWDD:
- if (parse_range(argv[optind-1], &(stpinfo->config.forward_delayl),
- &(stpinfo->config.forward_delayu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-forward-delay range");
+ case O_MAXAGE:
+ RANGE_ASSIGN(max_age, cb->val.u16_range);
break;
- case EBT_STP_ROOTADDR:
- if (xtables_parse_mac_and_mask(argv[optind-1],
- stpinfo->config.root_addr,
- stpinfo->config.root_addrmsk))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-addr address");
+ case O_HTIME:
+ RANGE_ASSIGN(hello_time, cb->val.u16_range);
break;
- case EBT_STP_SENDERADDR:
- if (xtables_parse_mac_and_mask(argv[optind-1],
- stpinfo->config.sender_addr,
- stpinfo->config.sender_addrmsk))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-addr address");
+ case O_FWDD:
+ RANGE_ASSIGN(forward_delay, cb->val.u16_range);
break;
- default:
- xtables_error(PARAMETER_PROBLEM, "Unknown stp option");
+#undef RANGE_ASSIGN
}
- return 1;
}
static void brstp_print(const void *ip, const struct xt_entry_match *match,
@@ -257,11 +178,12 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match,
const struct ebt_stp_config_info *c = &(stpinfo->config);
int i;
- for (i = 0; i < STP_NUMOPS; i++) {
+ for (i = 0; (1 << i) < EBT_STP_MASK; i++) {
if (!(stpinfo->bitmask & (1 << i)))
continue;
- printf("--%s %s", brstp_opts[i].name,
- (stpinfo->invflags & (1 << i)) ? "! " : "");
+ printf("%s--%s ",
+ (stpinfo->invflags & (1 << i)) ? "! " : "",
+ brstp_opts[i].name);
if (EBT_STP_TYPE == (1 << i)) {
if (stpinfo->type == BPDU_TYPE_CONFIG)
printf("%s", BPDU_TYPE_CONFIG_STRING);
@@ -308,9 +230,9 @@ static struct xtables_match brstp_match = {
.family = NFPROTO_BRIDGE,
.size = sizeof(struct ebt_stp_info),
.help = brstp_print_help,
- .parse = brstp_parse,
+ .x6_parse = brstp_parse,
.print = brstp_print,
- .extra_opts = brstp_opts,
+ .x6_options = brstp_opts
};
void _init(void)
diff --git a/extensions/libebt_stp.t b/extensions/libebt_stp.t
index 17d6c1c0..f72051ac 100644
--- a/extensions/libebt_stp.t
+++ b/extensions/libebt_stp.t
@@ -1,13 +1,74 @@
:INPUT,FORWARD,OUTPUT
--stp-type 1;=;OK
+! --stp-type 1;=;OK
--stp-flags 0x1;--stp-flags topology-change -j CONTINUE;OK
+! --stp-flags topology-change;=;OK
--stp-root-prio 1 -j ACCEPT;=;OK
+! --stp-root-prio 1 -j ACCEPT;=;OK
--stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
+! --stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
+--stp-root-addr 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
+! --stp-root-addr 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
--stp-root-cost 1;=;OK
+! --stp-root-cost 1;=;OK
--stp-sender-prio 1;=;OK
+! --stp-sender-prio 1;=;OK
--stp-sender-addr de:ad:be:ef:00:00;=;OK
+! --stp-sender-addr de:ad:be:ef:00:00;=;OK
+--stp-sender-addr de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
+! --stp-sender-addr de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
--stp-port 1;=;OK
+! --stp-port 1;=;OK
--stp-msg-age 1;=;OK
+! --stp-msg-age 1;=;OK
--stp-max-age 1;=;OK
+! --stp-max-age 1;=;OK
--stp-hello-time 1;=;OK
+! --stp-hello-time 1;=;OK
--stp-forward-delay 1;=;OK
+! --stp-forward-delay 1;=;OK
+--stp-root-prio :2;--stp-root-prio 0:2;OK
+--stp-root-prio 2:;--stp-root-prio 2:65535;OK
+--stp-root-prio 1:2;=;OK
+--stp-root-prio 1:1;--stp-root-prio 1;OK
+--stp-root-prio 2:1;;FAIL
+--stp-root-cost :2;--stp-root-cost 0:2;OK
+--stp-root-cost 2:;--stp-root-cost 2:4294967295;OK
+--stp-root-cost 1:2;=;OK
+--stp-root-cost 1:1;--stp-root-cost 1;OK
+--stp-root-cost 2:1;;FAIL
+--stp-sender-prio :2;--stp-sender-prio 0:2;OK
+--stp-sender-prio 2:;--stp-sender-prio 2:65535;OK
+--stp-sender-prio 1:2;=;OK
+--stp-sender-prio 1:1;--stp-sender-prio 1;OK
+--stp-sender-prio 2:1;;FAIL
+--stp-port :;--stp-port 0:65535;OK
+--stp-port :2;--stp-port 0:2;OK
+--stp-port 2:;--stp-port 2:65535;OK
+--stp-port 1:2;=;OK
+--stp-port 1:1;--stp-port 1;OK
+--stp-port 2:1;;FAIL
+--stp-msg-age :;--stp-msg-age 0:65535;OK
+--stp-msg-age :2;--stp-msg-age 0:2;OK
+--stp-msg-age 2:;--stp-msg-age 2:65535;OK
+--stp-msg-age 1:2;=;OK
+--stp-msg-age 1:1;--stp-msg-age 1;OK
+--stp-msg-age 2:1;;FAIL
+--stp-max-age :;--stp-max-age 0:65535;OK
+--stp-max-age :2;--stp-max-age 0:2;OK
+--stp-max-age 2:;--stp-max-age 2:65535;OK
+--stp-max-age 1:2;=;OK
+--stp-max-age 1:1;--stp-max-age 1;OK
+--stp-max-age 2:1;;FAIL
+--stp-hello-time :;--stp-hello-time 0:65535;OK
+--stp-hello-time :2;--stp-hello-time 0:2;OK
+--stp-hello-time 2:;--stp-hello-time 2:65535;OK
+--stp-hello-time 1:2;=;OK
+--stp-hello-time 1:1;--stp-hello-time 1;OK
+--stp-hello-time 2:1;;FAIL
+--stp-forward-delay :;--stp-forward-delay 0:65535;OK
+--stp-forward-delay :2;--stp-forward-delay 0:2;OK
+--stp-forward-delay 2:;--stp-forward-delay 2:65535;OK
+--stp-forward-delay 1:2;=;OK
+--stp-forward-delay 1:1;--stp-forward-delay 1;OK
+--stp-forward-delay 2:1;;FAIL
diff --git a/extensions/libebt_vlan.c b/extensions/libebt_vlan.c
index fa697921..b9f6c519 100644
--- a/extensions/libebt_vlan.c
+++ b/extensions/libebt_vlan.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <ctype.h>
#include <xtables.h>
#include <netinet/if_ether.h>
@@ -18,89 +17,56 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAME_VLAN_ID "id"
-#define NAME_VLAN_PRIO "prio"
-#define NAME_VLAN_ENCAP "encap"
-
-#define VLAN_ID '1'
-#define VLAN_PRIO '2'
-#define VLAN_ENCAP '3'
-
-static const struct option brvlan_opts[] = {
- {"vlan-id" , required_argument, NULL, VLAN_ID},
- {"vlan-prio" , required_argument, NULL, VLAN_PRIO},
- {"vlan-encap", required_argument, NULL, VLAN_ENCAP},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brvlan_opts[] =
+{
+ { .name = "vlan-id", .id = EBT_VLAN_ID, .type = XTTYPE_UINT16,
+ .max = 4094, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_vlan_info, id) },
+ { .name = "vlan-prio", .id = EBT_VLAN_PRIO, .type = XTTYPE_UINT8,
+ .max = 7, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_vlan_info, prio) },
+ { .name = "vlan-encap", .id = EBT_VLAN_ENCAP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
-/*
- * option inverse flags definition
- */
-#define OPT_VLAN_ID 0x01
-#define OPT_VLAN_PRIO 0x02
-#define OPT_VLAN_ENCAP 0x04
-#define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP)
-
static void brvlan_print_help(void)
{
printf(
"vlan options:\n"
-"--vlan-id [!] id : vlan-tagged frame identifier, 0,1-4096 (integer)\n"
-"--vlan-prio [!] prio : Priority-tagged frame's user priority, 0-7 (integer)\n"
-"--vlan-encap [!] encap : Encapsulated frame protocol (hexadecimal or name)\n");
+"[!] --vlan-id id : vlan-tagged frame identifier, 0,1-4096 (integer)\n"
+"[!] --vlan-prio prio : Priority-tagged frame's user priority, 0-7 (integer)\n"
+"[!] --vlan-encap encap : Encapsulated frame protocol (hexadecimal or name)\n");
}
-static int
-brvlan_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brvlan_parse(struct xt_option_call *cb)
{
- struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) (*match)->data;
+ struct ebt_vlan_info *vlaninfo = cb->data;
struct xt_ethertypeent *ethent;
char *end;
- struct ebt_vlan_info local;
-
- switch (c) {
- case VLAN_ID:
- EBT_CHECK_OPTION(flags, OPT_VLAN_ID);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_ID;
- local.id = strtoul(optarg, &end, 10);
- if (local.id > 4094 || *end != '\0')
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-id range ('%s')", optarg);
- vlaninfo->id = local.id;
- vlaninfo->bitmask |= EBT_VLAN_ID;
- break;
- case VLAN_PRIO:
- EBT_CHECK_OPTION(flags, OPT_VLAN_PRIO);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_PRIO;
- local.prio = strtoul(optarg, &end, 10);
- if (local.prio >= 8 || *end != '\0')
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-prio range ('%s')", optarg);
- vlaninfo->prio = local.prio;
- vlaninfo->bitmask |= EBT_VLAN_PRIO;
- break;
- case VLAN_ENCAP:
- EBT_CHECK_OPTION(flags, OPT_VLAN_ENCAP);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_ENCAP;
- local.encap = strtoul(optarg, &end, 16);
+
+ xtables_option_parse(cb);
+
+ vlaninfo->bitmask |= cb->entry->id;
+ if (cb->invert)
+ vlaninfo->invflags |= cb->entry->id;
+
+ if (cb->entry->id == EBT_VLAN_ENCAP) {
+ vlaninfo->encap = strtoul(cb->arg, &end, 16);
if (*end != '\0') {
- ethent = xtables_getethertypebyname(optarg);
+ ethent = xtables_getethertypebyname(cb->arg);
if (ethent == NULL)
- xtables_error(PARAMETER_PROBLEM, "Unknown --vlan-encap value ('%s')", optarg);
- local.encap = ethent->e_ethertype;
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown --vlan-encap value ('%s')",
+ cb->arg);
+ vlaninfo->encap = ethent->e_ethertype;
}
- if (local.encap < ETH_ZLEN)
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-encap range ('%s')", optarg);
- vlaninfo->encap = htons(local.encap);
- vlaninfo->bitmask |= EBT_VLAN_ENCAP;
- break;
- default:
- return 0;
-
+ if (vlaninfo->encap < ETH_ZLEN)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid --vlan-encap range ('%s')",
+ cb->arg);
+ vlaninfo->encap = htons(vlaninfo->encap);
}
- return 1;
}
static void brvlan_print(const void *ip, const struct xt_entry_match *match,
@@ -109,14 +75,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);
+ printf("%s--vlan-id %d ",
+ (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "",
+ vlaninfo->id);
}
if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
- printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio);
+ printf("%s--vlan-prio %d ",
+ (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "",
+ vlaninfo->prio);
}
if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
- printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "");
- printf("%4.4X ", ntohs(vlaninfo->encap));
+ printf("%s--vlan-encap %4.4X ",
+ (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "",
+ ntohs(vlaninfo->encap));
}
}
@@ -144,10 +115,10 @@ static struct xtables_match brvlan_match = {
.size = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.help = brvlan_print_help,
- .parse = brvlan_parse,
+ .x6_parse = brvlan_parse,
.print = brvlan_print,
.xlate = brvlan_xlate,
- .extra_opts = brvlan_opts,
+ .x6_options = brvlan_opts,
};
void _init(void)
diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t
index 3ec05599..e009ad71 100644
--- a/extensions/libebt_vlan.t
+++ b/extensions/libebt_vlan.t
@@ -1,13 +1,13 @@
:INPUT,FORWARD,OUTPUT
-p 802_1Q --vlan-id 42;=;OK
--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-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
+-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/libebt_vlan.txlate b/extensions/libebt_vlan.txlate
index 5d21e3eb..6e12e2d0 100644
--- a/extensions/libebt_vlan.txlate
+++ b/extensions/libebt_vlan.txlate
@@ -1,7 +1,7 @@
ebtables-translate -A INPUT -p 802_1Q --vlan-id 42
nft 'add rule bridge filter INPUT vlan id 42 counter'
-ebtables-translate -A INPUT -p 802_1Q --vlan-prio ! 1
+ebtables-translate -A INPUT -p 802_1Q ! --vlan-prio 1
nft 'add rule bridge filter INPUT vlan pcp != 1 counter'
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ip
diff --git a/extensions/libip6t_DNPT.man b/extensions/libip6t_DNPT.man
index 9b060f5b..2c4ae61b 100644
--- a/extensions/libip6t_DNPT.man
+++ b/extensions/libip6t_DNPT.man
@@ -15,11 +15,11 @@ Set destination prefix that you want to use in the translation and length
.PP
You have to use the SNPT target to undo the translation. Example:
.IP
-ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
+ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 ! \-o vboxnet0
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
.IP
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
-\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
+\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst\-pfx fd00::/64
.PP
You may need to enable IPv6 neighbor proxy:
.IP
diff --git a/extensions/libip6t_REJECT.man b/extensions/libip6t_REJECT.man
index 3c42768e..e68d6f03 100644
--- a/extensions/libip6t_REJECT.man
+++ b/extensions/libip6t_REJECT.man
@@ -44,9 +44,10 @@ response for a packet so classed would then terminate the healthy connection.
.PP
So, instead of:
.PP
--A INPUT ... -j REJECT
+\-A INPUT ... \-j REJECT
.PP
do consider using:
.PP
--A INPUT ... -m conntrack --ctstate INVALID -j DROP
--A INPUT ... -j REJECT
+\-A INPUT ... \-m conntrack \-\-ctstate INVALID \-j DROP
+.br
+\-A INPUT ... \-j REJECT
diff --git a/extensions/libip6t_SNPT.man b/extensions/libip6t_SNPT.man
index 97e0071b..8741c648 100644
--- a/extensions/libip6t_SNPT.man
+++ b/extensions/libip6t_SNPT.man
@@ -15,11 +15,11 @@ Set destination prefix that you want to use in the translation and length
.PP
You have to use the DNPT target to undo the translation. Example:
.IP
-ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
+ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 ! \-o vboxnet0
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
.IP
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
-\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
+\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst\-pfx fd00::/64
.PP
You may need to enable IPv6 neighbor proxy:
.IP
diff --git a/extensions/libip6t_ah.c b/extensions/libip6t_ah.c
index f35982f3..0f95c473 100644
--- a/extensions/libip6t_ah.c
+++ b/extensions/libip6t_ah.c
@@ -58,13 +58,18 @@ static void ah_parse(struct xt_option_call *cb)
}
}
+static bool skip_spi_match(uint32_t min, uint32_t max, bool inv)
+{
+ return min == 0 && max == UINT32_MAX && !inv;
+}
+
static void
print_spis(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (!skip_spi_match(min, max, invert)) {
if (min == max)
printf("%s:%s%u", name, inv, min);
else
@@ -103,11 +108,10 @@ static void ah_print(const void *ip, const struct xt_entry_match *match,
static void ah_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
+ bool inv_spi = ahinfo->invflags & IP6T_AH_INV_SPI;
- if (!(ahinfo->spis[0] == 0
- && ahinfo->spis[1] == 0xFFFFFFFF)) {
- printf("%s --ahspi ",
- (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
+ if (!skip_spi_match(ahinfo->spis[0], ahinfo->spis[1], inv_spi)) {
+ printf("%s --ahspi ", inv_spi ? " !" : "");
if (ahinfo->spis[0]
!= ahinfo->spis[1])
printf("%u:%u",
@@ -132,11 +136,11 @@ static int ah_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ip6t_ah *ahinfo = (struct ip6t_ah *)params->match->data;
+ bool inv_spi = ahinfo->invflags & IP6T_AH_INV_SPI;
char *space = "";
- if (!(ahinfo->spis[0] == 0 && ahinfo->spis[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "ah spi%s ",
- (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !=" : "");
+ if (!skip_spi_match(ahinfo->spis[0], ahinfo->spis[1], inv_spi)) {
+ xt_xlate_add(xl, "ah spi%s ", inv_spi ? " !=" : "");
if (ahinfo->spis[0] != ahinfo->spis[1])
xt_xlate_add(xl, "%u-%u", ahinfo->spis[0],
ahinfo->spis[1]);
@@ -158,7 +162,7 @@ static int ah_xlate(struct xt_xlate *xl,
}
if (!space[0]) /* plain '-m ah' */
- xt_xlate_add(xl, "meta l4proto ah");
+ xt_xlate_add(xl, "exthdr ah exists");
return 1;
}
diff --git a/extensions/libip6t_ah.t b/extensions/libip6t_ah.t
index c1898d44..19aa6f55 100644
--- a/extensions/libip6t_ah.t
+++ b/extensions/libip6t_ah.t
@@ -13,3 +13,9 @@
-m ah --ahspi 0:invalid;;FAIL
-m ah --ahspi;;FAIL
-m ah;=;OK
+-m ah --ahspi :;-m ah;OK
+-m ah ! --ahspi :;-m ah ! --ahspi 0:4294967295;OK
+-m ah --ahspi :3;-m ah --ahspi 0:3;OK
+-m ah --ahspi 3:;-m ah --ahspi 3:4294967295;OK
+-m ah --ahspi 3:3;-m ah --ahspi 3;OK
+-m ah --ahspi 4:3;;FAIL
diff --git a/extensions/libip6t_ah.txlate b/extensions/libip6t_ah.txlate
index cc33ac27..32c6b7de 100644
--- a/extensions/libip6t_ah.txlate
+++ b/extensions/libip6t_ah.txlate
@@ -15,3 +15,9 @@ nft 'add rule ip6 filter INPUT ah spi 500 ah hdrlength != 120 counter drop'
ip6tables-translate -A INPUT -m ah --ahspi 500 --ahlen 120 --ahres -j ACCEPT
nft 'add rule ip6 filter INPUT ah spi 500 ah hdrlength 120 ah reserved 1 counter accept'
+
+ip6tables-translate -A INPUT -m ah --ahspi 0:4294967295
+nft 'add rule ip6 filter INPUT exthdr ah exists counter'
+
+ip6tables-translate -A INPUT -m ah ! --ahspi 0:4294967295
+nft 'add rule ip6 filter INPUT ah spi != 0-4294967295 counter'
diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c
index 49c787e7..ed7fe10a 100644
--- a/extensions/libip6t_frag.c
+++ b/extensions/libip6t_frag.c
@@ -89,13 +89,18 @@ static void frag_parse(struct xt_option_call *cb)
}
}
+static bool skip_ids_match(uint32_t min, uint32_t max, bool inv)
+{
+ return min == 0 && max == UINT32_MAX && !inv;
+}
+
static void
print_ids(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (!skip_ids_match(min, max, invert)) {
printf("%s", name);
if (min == max)
printf(":%s%u", inv, min);
@@ -139,11 +144,10 @@ static void frag_print(const void *ip, const struct xt_entry_match *match,
static void frag_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data;
+ bool inv_ids = fraginfo->invflags & IP6T_FRAG_INV_IDS;
- if (!(fraginfo->ids[0] == 0
- && fraginfo->ids[1] == 0xFFFFFFFF)) {
- printf("%s --fragid ",
- (fraginfo->invflags & IP6T_FRAG_INV_IDS) ? " !" : "");
+ if (!skip_ids_match(fraginfo->ids[0], fraginfo->ids[1], inv_ids)) {
+ printf("%s --fragid ", inv_ids ? " !" : "");
if (fraginfo->ids[0]
!= fraginfo->ids[1])
printf("%u:%u",
@@ -173,22 +177,27 @@ static void frag_save(const void *ip, const struct xt_entry_match *match)
printf(" --fraglast");
}
+#define XLATE_FLAGS (IP6T_FRAG_RES | IP6T_FRAG_FST | \
+ IP6T_FRAG_MF | IP6T_FRAG_NMF)
+
static int frag_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ip6t_frag *fraginfo =
(struct ip6t_frag *)params->match->data;
+ bool inv_ids = fraginfo->invflags & IP6T_FRAG_INV_IDS;
- if (!(fraginfo->ids[0] == 0 && fraginfo->ids[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "frag id %s",
- (fraginfo->invflags & IP6T_FRAG_INV_IDS) ?
- "!= " : "");
+ if (!skip_ids_match(fraginfo->ids[0], fraginfo->ids[1], inv_ids)) {
+ xt_xlate_add(xl, "frag id %s", inv_ids ? "!= " : "");
if (fraginfo->ids[0] != fraginfo->ids[1])
xt_xlate_add(xl, "%u-%u", fraginfo->ids[0],
fraginfo->ids[1]);
else
xt_xlate_add(xl, "%u", fraginfo->ids[0]);
+ } else if (!(fraginfo->flags & XLATE_FLAGS)) {
+ xt_xlate_add(xl, "exthdr frag exists");
+ return 1;
}
/* ignore ineffective IP6T_FRAG_LEN bit */
diff --git a/extensions/libip6t_frag.t b/extensions/libip6t_frag.t
index 299fa03f..ea7ac899 100644
--- a/extensions/libip6t_frag.t
+++ b/extensions/libip6t_frag.t
@@ -1,5 +1,11 @@
:INPUT,FORWARD,OUTPUT
+-m frag --fragid :;-m frag;OK
+-m frag ! --fragid :;-m frag ! --fragid 0:4294967295;OK
+-m frag --fragid :42;-m frag --fragid 0:42;OK
+-m frag --fragid 42:;-m frag --fragid 42:4294967295;OK
-m frag --fragid 1:42;=;OK
+-m frag --fragid 3:3;-m frag --fragid 3;OK
+-m frag --fragid 4:3;;FAIL
-m frag --fraglen 42;=;OK
-m frag --fragres;=;OK
-m frag --fragfirst;=;OK
diff --git a/extensions/libip6t_frag.txlate b/extensions/libip6t_frag.txlate
index 33fc0631..e250587e 100644
--- a/extensions/libip6t_frag.txlate
+++ b/extensions/libip6t_frag.txlate
@@ -15,3 +15,9 @@ nft 'add rule ip6 filter INPUT frag id 100-200 frag frag-off 0 counter accept'
ip6tables-translate -t filter -A INPUT -m frag --fraglast -j ACCEPT
nft 'add rule ip6 filter INPUT frag more-fragments 0 counter accept'
+
+ip6tables-translate -t filter -A INPUT -m frag --fragid 0:4294967295
+nft 'add rule ip6 filter INPUT exthdr frag exists counter'
+
+ip6tables-translate -t filter -A INPUT -m frag ! --fragid 0:4294967295
+nft 'add rule ip6 filter INPUT frag id != 0-4294967295 counter'
diff --git a/extensions/libip6t_icmp6.t b/extensions/libip6t_icmp6.t
index 028cfc16..b9a4dcd3 100644
--- a/extensions/libip6t_icmp6.t
+++ b/extensions/libip6t_icmp6.t
@@ -4,3 +4,7 @@
-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
+-p ipv6-icmp -m icmp6 --icmpv6-type mld-listener-query;-p ipv6-icmp -m icmp6 --icmpv6-type 130;OK
+-p ipv6-icmp -m icmp6 --icmpv6-type mld-listener-report;-p ipv6-icmp -m icmp6 --icmpv6-type 131;OK
+-p ipv6-icmp -m icmp6 --icmpv6-type mld-listener-done;-p ipv6-icmp -m icmp6 --icmpv6-type 132;OK
+-p ipv6-icmp -m icmp6 --icmpv6-type mld-listener-reduction;-p ipv6-icmp -m icmp6 --icmpv6-type 132;OK
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
index 1410d324..1a1cee83 100644
--- a/extensions/libip6t_mh.c
+++ b/extensions/libip6t_mh.c
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_mh.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
enum {
O_MH_TYPE = 0,
@@ -154,11 +155,16 @@ static void print_type(uint8_t type, int numeric)
printf("%s", name);
}
+static bool skip_types_match(uint8_t min, uint8_t max, bool inv)
+{
+ return min == 0 && max == UINT8_MAX && !inv;
+}
+
static void print_types(uint8_t min, uint8_t max, int invert, int numeric)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFF || invert) {
+ if (!skip_types_match(min, max, invert)) {
printf(" ");
if (min == max) {
printf("%s", inv);
@@ -189,11 +195,12 @@ static void mh_print(const void *ip, const struct xt_entry_match *match,
static void mh_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+ bool inv_type = mhinfo->invflags & IP6T_MH_INV_TYPE;
- if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
+ if (skip_types_match(mhinfo->types[0], mhinfo->types[1], inv_type))
return;
- if (mhinfo->invflags & IP6T_MH_INV_TYPE)
+ if (inv_type)
printf(" !");
if (mhinfo->types[0] != mhinfo->types[1])
@@ -206,9 +213,12 @@ static int mh_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ip6t_mh *mhinfo = (struct ip6t_mh *)params->match->data;
+ bool inv_type = mhinfo->invflags & IP6T_MH_INV_TYPE;
- if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xff)
+ if (skip_types_match(mhinfo->types[0], mhinfo->types[1], inv_type)) {
+ xt_xlate_add(xl, "exthdr mh exists");
return 1;
+ }
if (mhinfo->types[0] != mhinfo->types[1])
xt_xlate_add(xl, "mh type %s%u-%u",
diff --git a/extensions/libip6t_mh.t b/extensions/libip6t_mh.t
index 6b76d13d..b628e9e3 100644
--- a/extensions/libip6t_mh.t
+++ b/extensions/libip6t_mh.t
@@ -4,3 +4,9 @@
-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
+-p mobility-header -m mh --mh-type :;-p mobility-header -m mh;OK
+-p mobility-header -m mh ! --mh-type :;-p mobility-header -m mh ! --mh-type 0:255;OK
+-p mobility-header -m mh --mh-type :3;-p mobility-header -m mh --mh-type 0:3;OK
+-p mobility-header -m mh --mh-type 3:;-p mobility-header -m mh --mh-type 3:255;OK
+-p mobility-header -m mh --mh-type 3:3;-p mobility-header -m mh --mh-type 3;OK
+-p mobility-header -m mh --mh-type 4:3;;FAIL
diff --git a/extensions/libip6t_mh.txlate b/extensions/libip6t_mh.txlate
index 4dfaf46a..13b4ba88 100644
--- a/extensions/libip6t_mh.txlate
+++ b/extensions/libip6t_mh.txlate
@@ -1,5 +1,14 @@
ip6tables-translate -A INPUT -p mh --mh-type 1 -j ACCEPT
-nft 'add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept'
+nft 'add rule ip6 filter INPUT mh type 1 counter accept'
ip6tables-translate -A INPUT -p mh --mh-type 1:3 -j ACCEPT
-nft 'add rule ip6 filter INPUT meta l4proto mobility-header mh type 1-3 counter accept'
+nft 'add rule ip6 filter INPUT mh type 1-3 counter accept'
+
+ip6tables-translate -A INPUT -p mh --mh-type 0:255 -j ACCEPT
+nft 'add rule ip6 filter INPUT exthdr mh exists counter accept'
+
+ip6tables-translate -A INPUT -m mh --mh-type 0:255 -j ACCEPT
+nft 'add rule ip6 filter INPUT exthdr mh exists counter accept'
+
+ip6tables-translate -A INPUT -p mh ! --mh-type 0:255 -j ACCEPT
+nft 'add rule ip6 filter INPUT mh type != 0-255 counter accept'
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index d5b0458b..6db09f0b 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -152,13 +152,18 @@ static void rt_parse(struct xt_option_call *cb)
}
}
+static bool skip_segsleft_match(uint32_t min, uint32_t max, bool inv)
+{
+ return min == 0 && max == UINT32_MAX && !inv;
+}
+
static void
print_nums(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (!skip_segsleft_match(min, max, invert)) {
printf(" %s", name);
if (min == max) {
printf(":%s", inv);
@@ -210,6 +215,7 @@ static void rt_print(const void *ip, const struct xt_entry_match *match,
static void rt_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
+ bool inv_sgs = rtinfo->invflags & IP6T_RT_INV_SGS;
if (rtinfo->flags & IP6T_RT_TYP) {
printf("%s --rt-type %u",
@@ -217,10 +223,9 @@ static void rt_save(const void *ip, const struct xt_entry_match *match)
rtinfo->rt_type);
}
- if (!(rtinfo->segsleft[0] == 0
- && rtinfo->segsleft[1] == 0xFFFFFFFF)) {
- printf("%s --rt-segsleft ",
- (rtinfo->invflags & IP6T_RT_INV_SGS) ? " !" : "");
+ if (!skip_segsleft_match(rtinfo->segsleft[0],
+ rtinfo->segsleft[1], inv_sgs)) {
+ printf("%s --rt-segsleft ", inv_sgs ? " !" : "");
if (rtinfo->segsleft[0]
!= rtinfo->segsleft[1])
printf("%u:%u",
@@ -244,10 +249,14 @@ static void rt_save(const void *ip, const struct xt_entry_match *match)
}
+#define XLATE_FLAGS (IP6T_RT_TYP | IP6T_RT_LEN | \
+ IP6T_RT_RES | IP6T_RT_FST | IP6T_RT_FST_NSTRICT)
+
static int rt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)params->match->data;
+ bool inv_sgs = rtinfo->invflags & IP6T_RT_INV_SGS;
if (rtinfo->flags & IP6T_RT_TYP) {
xt_xlate_add(xl, "rt type%s %u",
@@ -255,15 +264,18 @@ static int rt_xlate(struct xt_xlate *xl,
rtinfo->rt_type);
}
- if (!(rtinfo->segsleft[0] == 0 && rtinfo->segsleft[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "rt seg-left%s ",
- (rtinfo->invflags & IP6T_RT_INV_SGS) ? " !=" : "");
+ if (!skip_segsleft_match(rtinfo->segsleft[0],
+ rtinfo->segsleft[1], inv_sgs)) {
+ xt_xlate_add(xl, "rt seg-left%s ", inv_sgs ? " !=" : "");
if (rtinfo->segsleft[0] != rtinfo->segsleft[1])
xt_xlate_add(xl, "%u-%u", rtinfo->segsleft[0],
rtinfo->segsleft[1]);
else
xt_xlate_add(xl, "%u", rtinfo->segsleft[0]);
+ } else if (!(rtinfo->flags & XLATE_FLAGS)) {
+ xt_xlate_add(xl, "exthdr rt exists");
+ return 1;
}
if (rtinfo->flags & IP6T_RT_LEN) {
diff --git a/extensions/libip6t_rt.t b/extensions/libip6t_rt.t
index 3c7b2d98..1c219d66 100644
--- a/extensions/libip6t_rt.t
+++ b/extensions/libip6t_rt.t
@@ -3,3 +3,9 @@
-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
-m rt;=;OK
+-m rt --rt-segsleft :;-m rt;OK
+-m rt ! --rt-segsleft :;-m rt ! --rt-segsleft 0:4294967295;OK
+-m rt --rt-segsleft :3;-m rt --rt-segsleft 0:3;OK
+-m rt --rt-segsleft 3:;-m rt --rt-segsleft 3:4294967295;OK
+-m rt --rt-segsleft 3:3;-m rt --rt-segsleft 3;OK
+-m rt --rt-segsleft 4:3;;FAIL
diff --git a/extensions/libip6t_rt.txlate b/extensions/libip6t_rt.txlate
index 3578bcba..1c2f74a5 100644
--- a/extensions/libip6t_rt.txlate
+++ b/extensions/libip6t_rt.txlate
@@ -12,3 +12,12 @@ nft 'add rule ip6 filter INPUT rt type 0 rt hdrlength 22 counter drop'
ip6tables-translate -A INPUT -m rt --rt-type 0 --rt-len 22 ! --rt-segsleft 26 -j ACCEPT
nft 'add rule ip6 filter INPUT rt type 0 rt seg-left != 26 rt hdrlength 22 counter accept'
+
+ip6tables-translate -A INPUT -m rt --rt-segsleft 13:42 -j ACCEPT
+nft 'add rule ip6 filter INPUT rt seg-left 13-42 counter accept'
+
+ip6tables-translate -A INPUT -m rt --rt-segsleft 0:4294967295 -j ACCEPT
+nft 'add rule ip6 filter INPUT exthdr rt exists counter accept'
+
+ip6tables-translate -A INPUT -m rt ! --rt-segsleft 0:4294967295 -j ACCEPT
+nft 'add rule ip6 filter INPUT rt seg-left != 0-4294967295 counter accept'
diff --git a/extensions/libip6t_standard.t b/extensions/libip6t_standard.t
index a528af10..0c559cc5 100644
--- a/extensions/libip6t_standard.t
+++ b/extensions/libip6t_standard.t
@@ -3,3 +3,6 @@
! -d ::;! -d ::/128;OK
! -s ::;! -s ::/128;OK
-s ::/64;=;OK
+:INPUT
+-i + -d c0::fe;-d c0::fe/128;OK
+-i + -p tcp;-p tcp;OK
diff --git a/extensions/libipt_REJECT.man b/extensions/libipt_REJECT.man
index cc47aead..a7196cdc 100644
--- a/extensions/libipt_REJECT.man
+++ b/extensions/libipt_REJECT.man
@@ -44,9 +44,10 @@ response for a packet so classed would then terminate the healthy connection.
.PP
So, instead of:
.PP
--A INPUT ... -j REJECT
+\-A INPUT ... \-j REJECT
.PP
do consider using:
.PP
--A INPUT ... -m conntrack --ctstate INVALID -j DROP
--A INPUT ... -j REJECT
+\-A INPUT ... \-m conntrack \-\-ctstate INVALID \-j DROP
+.br
+\-A INPUT ... \-j REJECT
diff --git a/extensions/libipt_ULOG.man b/extensions/libipt_ULOG.man
index c91f7764..eb37d4fb 100644
--- a/extensions/libipt_ULOG.man
+++ b/extensions/libipt_ULOG.man
@@ -1,4 +1,4 @@
-This is the deprecated ipv4-only predecessor of the NFLOG target.
+This is the deprecated IPv4-only predecessor of the NFLOG target.
It provides userspace logging of matching packets. When this
target is set for a rule, the Linux kernel will multicast this packet
through a
@@ -9,7 +9,7 @@ Like LOG, this is a "non-terminating target", i.e. rule traversal
continues at the next rule.
.TP
\fB\-\-ulog\-nlgroup\fP \fInlgroup\fP
-This specifies the netlink group (1-32) to which the packet is sent.
+This specifies the netlink group (1\(en32) to which the packet is sent.
Default value is 1.
.TP
\fB\-\-ulog\-prefix\fP \fIprefix\fP
diff --git a/extensions/libipt_ah.c b/extensions/libipt_ah.c
index fec5705c..39e3013d 100644
--- a/extensions/libipt_ah.c
+++ b/extensions/libipt_ah.c
@@ -39,13 +39,18 @@ static void ah_parse(struct xt_option_call *cb)
ahinfo->invflags |= IPT_AH_INV_SPI;
}
+static bool skip_spi_match(uint32_t min, uint32_t max, bool inv)
+{
+ return min == 0 && max == UINT32_MAX && !inv;
+}
+
static void
print_spis(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (!skip_spi_match(min, max, invert)) {
printf("%s", name);
if (min == max) {
printf(":%s", inv);
@@ -75,11 +80,10 @@ static void ah_print(const void *ip, const struct xt_entry_match *match,
static void ah_save(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
+ bool inv_spi = ahinfo->invflags & IPT_AH_INV_SPI;
- if (!(ahinfo->spis[0] == 0
- && ahinfo->spis[1] == 0xFFFFFFFF)) {
- printf("%s --ahspi ",
- (ahinfo->invflags & IPT_AH_INV_SPI) ? " !" : "");
+ if (!skip_spi_match(ahinfo->spis[0], ahinfo->spis[1], inv_spi)) {
+ printf("%s --ahspi ", inv_spi ? " !" : "");
if (ahinfo->spis[0]
!= ahinfo->spis[1])
printf("%u:%u",
@@ -96,15 +100,17 @@ static int ah_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ipt_ah *ahinfo = (struct ipt_ah *)params->match->data;
+ bool inv_spi = ahinfo->invflags & IPT_AH_INV_SPI;
- if (!(ahinfo->spis[0] == 0 && ahinfo->spis[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "ah spi%s ",
- (ahinfo->invflags & IPT_AH_INV_SPI) ? " !=" : "");
+ if (!skip_spi_match(ahinfo->spis[0], ahinfo->spis[1], inv_spi)) {
+ xt_xlate_add(xl, "ah spi%s ", inv_spi ? " !=" : "");
if (ahinfo->spis[0] != ahinfo->spis[1])
xt_xlate_add(xl, "%u-%u", ahinfo->spis[0],
ahinfo->spis[1]);
else
xt_xlate_add(xl, "%u", ahinfo->spis[0]);
+ } else {
+ xt_xlate_add(xl, "meta l4proto ah");
}
return 1;
diff --git a/extensions/libipt_ah.t b/extensions/libipt_ah.t
index cd853865..60593660 100644
--- a/extensions/libipt_ah.t
+++ b/extensions/libipt_ah.t
@@ -11,3 +11,9 @@
-m ah --ahspi;;FAIL
-m ah;;FAIL
-p ah -m ah;=;OK
+-p ah -m ah --ahspi :;-p ah -m ah;OK
+-p ah -m ah ! --ahspi :;-p ah -m ah ! --ahspi 0:4294967295;OK
+-p ah -m ah --ahspi :3;-p ah -m ah --ahspi 0:3;OK
+-p ah -m ah --ahspi 3:;-p ah -m ah --ahspi 3:4294967295;OK
+-p ah -m ah --ahspi 3:3;-p ah -m ah --ahspi 3;OK
+-p ah -m ah --ahspi 4:3;;FAIL
diff --git a/extensions/libipt_ah.txlate b/extensions/libipt_ah.txlate
index 897c82b5..baf5a0ae 100644
--- a/extensions/libipt_ah.txlate
+++ b/extensions/libipt_ah.txlate
@@ -6,3 +6,9 @@ nft 'add rule ip filter INPUT ah spi 500-600 counter drop'
iptables-translate -A INPUT -p 51 -m ah ! --ahspi 50 -j DROP
nft 'add rule ip filter INPUT ah spi != 50 counter drop'
+
+iptables-translate -A INPUT -p 51 -m ah --ahspi 0:4294967295 -j DROP
+nft 'add rule ip filter INPUT meta l4proto ah counter drop'
+
+iptables-translate -A INPUT -p 51 -m ah ! --ahspi 0:4294967295 -j DROP
+nft 'add rule ip filter INPUT ah spi != 0-4294967295 counter drop'
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index b0318aeb..171b3b39 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -108,7 +108,8 @@ static void icmp_save(const void *ip, const struct xt_entry_match *match)
printf(" !");
/* special hack for 'any' case */
- if (icmp->type == 0xFF) {
+ if (icmp->type == 0xFF &&
+ icmp->code[0] == 0 && icmp->code[1] == 0xFF) {
printf(" --icmp-type any");
} else {
printf(" --icmp-type %u", icmp->type);
diff --git a/extensions/libipt_icmp.t b/extensions/libipt_icmp.t
index f4ba65c2..4ea93621 100644
--- a/extensions/libipt_icmp.t
+++ b/extensions/libipt_icmp.t
@@ -1,11 +1,8 @@
:INPUT,FORWARD,OUTPUT
-p icmp -m icmp --icmp-type any;=;OK
-# output uses the number, better use the name?
-# ERROR: cannot find: iptables -I INPUT -p icmp -m icmp --icmp-type echo-reply
-# -p icmp -m icmp --icmp-type echo-reply;=;OK
-# output uses the number, better use the name?
-# ERROR: annot find: iptables -I INPUT -p icmp -m icmp --icmp-type destination-unreachable
-# -p icmp -m icmp --icmp-type destination-unreachable;=;OK
+# XXX: output uses the number, better use the name?
+-p icmp -m icmp --icmp-type echo-reply;-p icmp -m icmp --icmp-type 0;OK
+-p icmp -m icmp --icmp-type destination-unreachable;-p icmp -m icmp --icmp-type 3;OK
# it does not acccept name/name, should we accept this?
# ERROR: cannot load: iptables -A INPUT -p icmp -m icmp --icmp-type destination-unreachable/network-unreachable
# -p icmp -m icmp --icmp-type destination-unreachable/network-unreachable;=;OK
@@ -13,3 +10,5 @@
# we accept "iptables -I INPUT -p tcp -m tcp", why not this below?
# ERROR: cannot load: iptables -A INPUT -p icmp -m icmp
# -p icmp -m icmp;=;OK
+-p icmp -m icmp --icmp-type 255/255;=;OK
+-p icmp -m icmp --icmp-type 255/0:255;-p icmp -m icmp --icmp-type any;OK
diff --git a/extensions/libxt_CONNMARK.man b/extensions/libxt_CONNMARK.man
index 93179239..ccd7da61 100644
--- a/extensions/libxt_CONNMARK.man
+++ b/extensions/libxt_CONNMARK.man
@@ -8,7 +8,7 @@ Zero out the bits given by \fImask\fP and XOR \fIvalue\fP into the ctmark.
Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
masks. The new nfmark value is determined as follows:
.IP
-ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+ctmark = (ctmark & \(tictmask) \(ha (nfmark & nfmask)
.IP
i.e. \fIctmask\fP defines what bits to clear and \fInfmask\fP what bits of the
nfmark to XOR into the ctmark. \fIctmask\fP and \fInfmask\fP default to
@@ -18,7 +18,7 @@ nfmark to XOR into the ctmark. \fIctmask\fP and \fInfmask\fP default to
Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
masks. The new ctmark value is determined as follows:
.IP
-nfmark = (nfmark & ~\fInfmask\fP) ^ (ctmark & \fIctmask\fP);
+nfmark = (nfmark & \(ti\fInfmask\fP) \(ha (ctmark & \fIctmask\fP);
.IP
i.e. \fInfmask\fP defines what bits to clear and \fIctmask\fP what bits of the
ctmark to XOR into the nfmark. \fIctmask\fP and \fInfmask\fP default to
diff --git a/extensions/libxt_CT.man b/extensions/libxt_CT.man
index fc692f9a..7523ead4 100644
--- a/extensions/libxt_CT.man
+++ b/extensions/libxt_CT.man
@@ -20,12 +20,12 @@ the ctmark, not nfmark), \fBnatseqinfo\fP, \fBsecmark\fP (ctsecmark).
Only generate the specified expectation events for this connection.
Possible event types are: \fBnew\fP.
.TP
-\fB\-\-zone-orig\fP {\fIid\fP|\fBmark\fP}
+\fB\-\-zone\-orig\fP {\fIid\fP|\fBmark\fP}
For traffic coming from ORIGINAL direction, assign this packet to zone
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
instead of \fIid\fP, the zone is derived from the packet nfmark.
.TP
-\fB\-\-zone-reply\fP {\fIid\fP|\fBmark\fP}
+\fB\-\-zone\-reply\fP {\fIid\fP|\fBmark\fP}
For traffic coming from REPLY direction, assign this packet to zone
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
instead of \fIid\fP, the zone is derived from the packet nfmark.
diff --git a/extensions/libxt_DNAT.man b/extensions/libxt_DNAT.man
index af9a3f06..090ecb42 100644
--- a/extensions/libxt_DNAT.man
+++ b/extensions/libxt_DNAT.man
@@ -19,7 +19,7 @@ If no port range is specified, then the destination port will never be
modified. If no IP address is specified then only the destination port
will be modified.
If \fBbaseport\fP is given, the difference of the original destination port and
-its value is used as offset into the mapping port range. This allows to create
+its value is used as offset into the mapping port range. This allows one to create
shifted portmap ranges and is available since kernel version 4.18.
For a single port or \fIbaseport\fP, a service name as listed in
\fB/etc/services\fP may be used.
diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
index 94aebe9a..83ce5003 100644
--- a/extensions/libxt_HMARK.c
+++ b/extensions/libxt_HMARK.c
@@ -41,6 +41,7 @@ static void HMARK_help(void)
#define hi struct xt_hmark_info
+/* values must match XT_HMARK_* ones (apart from O_HMARK_TYPE) */
enum {
O_HMARK_SADDR_MASK,
O_HMARK_DADDR_MASK,
@@ -88,32 +89,32 @@ static const struct xt_option_entry HMARK_opts[] = {
{ .name = "hmark-sport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.p16.src)
},
{ .name = "hmark-dport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.p16.dst)
},
{ .name = "hmark-spi-mask",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.v32)
},
{ .name = "hmark-sport",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.p16.src)
},
{ .name = "hmark-dport",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.p16.dst)
},
{ .name = "hmark-spi",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.v32)
},
{ .name = "hmark-proto-mask",
.type = XTTYPE_UINT16,
@@ -211,53 +212,10 @@ static void HMARK_parse(struct xt_option_call *cb, int plen)
case O_HMARK_TYPE:
hmark_parse_type(cb);
break;
- case O_HMARK_SADDR_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
- break;
- case O_HMARK_DADDR_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
- break;
- case O_HMARK_SPI:
- info->port_set.v32 = htonl(cb->val.u32);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI);
- break;
- case O_HMARK_SPORT:
- info->port_set.p16.src = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
- break;
- case O_HMARK_DPORT:
- info->port_set.p16.dst = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
- break;
- case O_HMARK_SPORT_MASK:
- info->port_mask.p16.src = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
- break;
- case O_HMARK_DPORT_MASK:
- info->port_mask.p16.dst = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
- break;
- case O_HMARK_SPI_MASK:
- info->port_mask.v32 = htonl(cb->val.u32);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
- break;
- case O_HMARK_PROTO_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
- break;
- case O_HMARK_RND:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
- break;
- case O_HMARK_MODULUS:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
- break;
- case O_HMARK_OFFSET:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
- break;
- case O_HMARK_CT:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ default:
+ info->flags |= XT_HMARK_FLAG(cb->entry->id);
break;
}
- cb->xflags |= (1 << cb->entry->id);
}
static void HMARK_ip4_parse(struct xt_option_call *cb)
diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man
index cd7ffd54..63d18cb5 100644
--- a/extensions/libxt_HMARK.man
+++ b/extensions/libxt_HMARK.man
@@ -53,7 +53,7 @@ A 32 bit random custom value to feed hash calculation.
\fIExamples:\fP
.PP
iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW
- \-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000
+ \-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark\-offset 10000
\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe
.PP
iptables \-t mangle \-A PREROUTING \-j HMARK \-\-hmark\-offset 10000
diff --git a/extensions/libxt_LED.man b/extensions/libxt_LED.man
index 81c2f296..d92fd940 100644
--- a/extensions/libxt_LED.man
+++ b/extensions/libxt_LED.man
@@ -6,9 +6,9 @@ the trigger behavior:
.TP
\fB\-\-led\-trigger\-id\fP \fIname\fP
This is the name given to the LED trigger. The actual name of the trigger
-will be prefixed with "netfilter-".
+will be prefixed with "netfilter\-".
.TP
-\fB\-\-led-delay\fP \fIms\fP
+\fB\-\-led\-delay\fP \fIms\fP
This indicates how long (in milliseconds) the LED should be left illuminated
when a packet arrives before being switched off again. The default is 0
(blink as fast as possible.) The special value \fIinf\fP can be given to
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index 100f6a38..703d894f 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -1,4 +1,3 @@
-#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <xtables.h>
@@ -69,6 +68,16 @@ static const struct xt_option_entry mark_tg_opts[] = {
XTOPT_TABLEEND,
};
+static const struct xt_option_entry mark_tg_arp_opts[] = {
+ {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .base = 16, .excl = F_ANY},
+ {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .base = 16, .excl = F_ANY},
+ {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .base = 16, .excl = F_ANY},
+ XTOPT_TABLEEND,
+};
+
static void mark_tg_help(void)
{
printf(
@@ -136,6 +145,8 @@ static void mark_tg_parse(struct xt_option_call *cb)
case O_SET_MARK:
info->mark = cb->val.mark;
info->mask = cb->val.mark | cb->val.mask;
+ if (cb->entry->type == XTTYPE_UINT32)
+ info->mask = UINT32_MAX;
break;
case O_AND_MARK:
info->mark = 0;
@@ -263,69 +274,6 @@ static void mark_tg_arp_print(const void *ip,
mark_tg_arp_save(ip, target);
}
-#define MARK_OPT 1
-#define AND_MARK_OPT 2
-#define OR_MARK_OPT 3
-
-static struct option mark_tg_arp_opts[] = {
- { .name = "set-mark", .has_arg = required_argument, .flag = 0, .val = MARK_OPT },
- { .name = "and-mark", .has_arg = required_argument, .flag = 0, .val = AND_MARK_OPT },
- { .name = "or-mark", .has_arg = required_argument, .flag = 0, .val = OR_MARK_OPT },
- { .name = NULL}
-};
-
-static int
-mark_tg_arp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_mark_tginfo2 *info =
- (struct xt_mark_tginfo2 *)(*target)->data;
- int i;
-
- switch (c) {
- case MARK_OPT:
- if (sscanf(argv[optind-1], "%x", &i) != 1) {
- xtables_error(PARAMETER_PROBLEM,
- "Bad mark value `%s'", optarg);
- return 0;
- }
- info->mark = i;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "MARK: Can't specify --set-mark twice");
- *flags = 1;
- break;
- case AND_MARK_OPT:
- if (sscanf(argv[optind-1], "%x", &i) != 1) {
- xtables_error(PARAMETER_PROBLEM,
- "Bad mark value `%s'", optarg);
- return 0;
- }
- info->mark = 0;
- info->mask = ~i;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "MARK: Can't specify --and-mark twice");
- *flags = 1;
- break;
- case OR_MARK_OPT:
- if (sscanf(argv[optind-1], "%x", &i) != 1) {
- xtables_error(PARAMETER_PROBLEM,
- "Bad mark value `%s'", optarg);
- return 0;
- }
- info->mark = info->mask = i;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "MARK: Can't specify --or-mark twice");
- *flags = 1;
- break;
- default:
- return 0;
- }
- return 1;
-}
-
static int mark_tg_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
@@ -428,8 +376,10 @@ static struct xtables_target mark_tg_reg[] = {
.help = mark_tg_help,
.print = mark_tg_arp_print,
.save = mark_tg_arp_save,
- .parse = mark_tg_arp_parse,
- .extra_opts = mark_tg_arp_opts,
+ .x6_parse = mark_tg_parse,
+ .x6_fcheck = mark_tg_check,
+ .x6_options = mark_tg_arp_opts,
+ .xlate = mark_tg_xlate,
},
};
diff --git a/extensions/libxt_MARK.txlate b/extensions/libxt_MARK.txlate
index 36ee7a3b..cef8239a 100644
--- a/extensions/libxt_MARK.txlate
+++ b/extensions/libxt_MARK.txlate
@@ -24,3 +24,12 @@ nft 'add rule ip mangle PREROUTING counter meta mark set mark and 0x64'
iptables-translate -t mangle -A PREROUTING -j MARK --or-mark 0x64
nft 'add rule ip mangle PREROUTING counter meta mark set mark or 0x64'
+
+arptables-translate -A OUTPUT -j MARK --set-mark 0x4
+nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 counter meta mark set 0x4'
+
+arptables-translate -I OUTPUT -o odev -j MARK --and-mark 0x8
+nft 'insert rule arp filter OUTPUT oifname "odev" arp htype 1 arp hlen 6 arp plen 4 counter meta mark set mark and 0x8'
+
+arptables-translate -t mangle -A OUTPUT -o odev -j MARK --or-mark 16
+nft 'add rule arp mangle OUTPUT oifname "odev" arp htype 1 arp hlen 6 arp plen 4 counter meta mark set mark or 0x16'
diff --git a/extensions/libxt_MASQUERADE.man b/extensions/libxt_MASQUERADE.man
index 26d91ddb..5c236447 100644
--- a/extensions/libxt_MASQUERADE.man
+++ b/extensions/libxt_MASQUERADE.man
@@ -15,15 +15,15 @@ any established connections are lost anyway).
\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
This specifies a range of source ports to use, overriding the default
.B SNAT
-source port-selection heuristics (see above). This is only valid
+source port selection heuristics (see above). This is only valid
if the rule also specifies one of the following protocols:
\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP.
.TP
\fB\-\-random\fP
Randomize source port mapping (kernel >= 2.6.21).
-Since kernel 5.0, \fB\-\-random\fP is identical to \fB\-\-random-fully\fP.
+Since kernel 5.0, \fB\-\-random\fP is identical to \fB\-\-random\-fully\fP.
.TP
-\fB\-\-random-fully\fP
+\fB\-\-random\-fully\fP
Fully randomize source port mapping (kernel >= 3.13).
.TP
IPv6 support available since Linux kernels >= 3.7.
diff --git a/extensions/libxt_NFLOG.man b/extensions/libxt_NFLOG.man
index 318e6305..86ebb210 100644
--- a/extensions/libxt_NFLOG.man
+++ b/extensions/libxt_NFLOG.man
@@ -9,7 +9,7 @@ may subscribe to the group to receive the packets. Like LOG, this is a
non-terminating target, i.e. rule traversal continues at the next rule.
.TP
\fB\-\-nflog\-group\fP \fInlgroup\fP
-The netlink group (0 - 2^16\-1) to which packets are (only applicable for
+The netlink group (0\(en2\(ha16\-1) to which packets are (only applicable for
nfnetlink_log). The default value is 0.
.TP
\fB\-\-nflog\-prefix\fP \fIprefix\fP
@@ -17,7 +17,7 @@ A prefix string to include in the log message, up to 64 characters
long, useful for distinguishing messages in the logs.
.TP
\fB\-\-nflog\-range\fP \fIsize\fP
-This option has never worked, use --nflog-size instead
+This option has never worked, use \-\-nflog\-size instead
.TP
\fB\-\-nflog\-size\fP \fIsize\fP
The number of bytes to be copied to userspace (only applicable for
diff --git a/extensions/libxt_NFLOG.t b/extensions/libxt_NFLOG.t
index 25f332ae..0cd81c64 100644
--- a/extensions/libxt_NFLOG.t
+++ b/extensions/libxt_NFLOG.t
@@ -15,7 +15,7 @@
-j NFLOG --nflog-size 4294967296;;FAIL
-j NFLOG --nflog-size -1;;FAIL
-j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK
--j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;-j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;OK
+-j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;-j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;OK;LEGACY;=
-j NFLOG --nflog-threshold 1;=;OK
# ERROR: line 13 (should fail: iptables -A INPUT -j NFLOG --nflog-threshold 0
# -j NFLOG --nflog-threshold 0;;FAIL
diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man
index 950b0d24..cb963bec 100644
--- a/extensions/libxt_NFQUEUE.man
+++ b/extensions/libxt_NFQUEUE.man
@@ -6,8 +6,9 @@ reinject the packet into the kernel. Please see libnetfilter_queue
for details.
.B
nfnetlink_queue
-was added in Linux 2.6.14. The \fBqueue-balance\fP option was added in Linux 2.6.31,
-\fBqueue-bypass\fP in 2.6.39.
+was added in Linux 2.6.14. The \fBqueue\-balance\fP option was added in Linux
+2.6.31,
+\fBqueue\-bypass\fP in 2.6.39.
.TP
\fB\-\-queue\-num\fP \fIvalue\fP
This specifies the QUEUE number to use. Valid queue numbers are 0 to 65535. The default value is 0.
@@ -28,8 +29,8 @@ are dropped. When this option is used, the NFQUEUE rule behaves like ACCEPT ins
will move on to the next table.
.PP
.TP
-\fB\-\-queue\-cpu-fanout\fP
+\fB\-\-queue\-cpu\-fanout\fP
Available starting Linux kernel 3.10. When used together with
-\fB--queue-balance\fP this will use the CPU ID as an index to map packets to
+\fB\-\-queue\-balance\fP this will use the CPU ID as an index to map packets to
the queues. The idea is that you can improve performance if there's a queue
-per CPU. This requires \fB--queue-balance\fP to be specified.
+per CPU. This requires \fB\-\-queue\-balance\fP to be specified.
diff --git a/extensions/libxt_NFQUEUE.t b/extensions/libxt_NFQUEUE.t
index 8fb2b760..94050500 100644
--- a/extensions/libxt_NFQUEUE.t
+++ b/extensions/libxt_NFQUEUE.t
@@ -8,6 +8,13 @@
-j NFQUEUE --queue-balance 0:65535;;FAIL
-j NFQUEUE --queue-balance 0:65536;;FAIL
-j NFQUEUE --queue-balance -1:65535;;FAIL
+-j NFQUEUE --queue-balance 4;;FAIL
+-j NFQUEUE --queue-balance :;-j NFQUEUE --queue-balance 0:65534;OK
+-j NFQUEUE --queue-balance :4;-j NFQUEUE --queue-balance 0:4;OK
+-j NFQUEUE --queue-balance 4:;-j NFQUEUE --queue-balance 4:65534;OK
+-j NFQUEUE --queue-balance 3:4;=;OK
+-j NFQUEUE --queue-balance 4:4;;FAIL
+-j NFQUEUE --queue-balance 4:3;;FAIL
-j NFQUEUE --queue-num 10 --queue-bypass;=;OK
-j NFQUEUE --queue-balance 0:6 --queue-cpu-fanout --queue-bypass;-j NFQUEUE --queue-balance 0:6 --queue-bypass --queue-cpu-fanout;OK
-j NFQUEUE --queue-bypass --queue-balance 0:6 --queue-cpu-fanout;-j NFQUEUE --queue-balance 0:6 --queue-bypass --queue-cpu-fanout;OK
diff --git a/extensions/libxt_SET.man b/extensions/libxt_SET.man
index c4713378..7332acb0 100644
--- a/extensions/libxt_SET.man
+++ b/extensions/libxt_SET.man
@@ -25,8 +25,8 @@ one from the set definition
when adding an entry if it already exists, reset the timeout value
to the specified one or to the default from the set definition
.TP
-\fB\-\-map\-set\fP \fIset\-name\fP
-the set-name should be created with --skbinfo option
+\fB\-\-map\-set\fP \fIset-name\fP
+the set-name should be created with \-\-skbinfo option
\fB\-\-map\-mark\fP
map firewall mark to packet by lookup of value in the set
\fB\-\-map\-prio\fP
diff --git a/extensions/libxt_SNAT.man b/extensions/libxt_SNAT.man
index 80a698a6..d879c871 100644
--- a/extensions/libxt_SNAT.man
+++ b/extensions/libxt_SNAT.man
@@ -23,7 +23,7 @@ will be mapped to ports below 1024, and other ports will be mapped to
\fB\-\-random\fP
Randomize source port mapping through a hash-based algorithm (kernel >= 2.6.21).
.TP
-\fB\-\-random-fully\fP
+\fB\-\-random\-fully\fP
Fully randomize source port mapping through a PRNG (kernel >= 3.14).
.TP
\fB\-\-persistent\fP
diff --git a/extensions/libxt_SYNPROXY.man b/extensions/libxt_SYNPROXY.man
index 30a71ed2..04fffedb 100644
--- a/extensions/libxt_SYNPROXY.man
+++ b/extensions/libxt_SYNPROXY.man
@@ -22,7 +22,7 @@ Example:
.PP
Determine tcp options used by backend, from an external system
.IP
-tcpdump -pni eth0 -c 1 'tcp[tcpflags] == (tcp-syn|tcp-ack)'
+tcpdump \-pni eth0 \-c 1 'tcp[tcpflags] == (tcp\-syn|tcp\-ack)'
.br
port 80 &
.br
@@ -40,7 +40,7 @@ telnet 192.0.2.42 80
.br
length 0
.PP
-Switch tcp_loose mode off, so conntrack will mark out\-of\-flow
+Switch tcp_loose mode off, so conntrack will mark out-of-flow
packets as state INVALID.
.IP
echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
diff --git a/extensions/libxt_TCPMSS.t b/extensions/libxt_TCPMSS.t
index fbfbfcf8..b3639cc1 100644
--- a/extensions/libxt_TCPMSS.t
+++ b/extensions/libxt_TCPMSS.t
@@ -1,6 +1,6 @@
:FORWARD,OUTPUT,POSTROUTING
*mangle
-j TCPMSS;;FAIL
--p tcp -j TCPMSS --set-mss 42;;FAIL;LEGACY
+-p tcp -j TCPMSS --set-mss 42;=;FAIL;LEGACY
-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_TOS.man b/extensions/libxt_TOS.man
index de2d22dc..2c8d4694 100644
--- a/extensions/libxt_TOS.man
+++ b/extensions/libxt_TOS.man
@@ -32,5 +32,5 @@ longterm releases 2.6.32 (>=.42), 2.6.33 (>=.15), and 2.6.35 (>=.14), there is
a bug whereby IPv6 TOS mangling does not behave as documented and differs from
the IPv4 version. The TOS mask indicates the bits one wants to zero out, so it
needs to be inverted before applying it to the original TOS field. However, the
-aformentioned kernels forgo the inversion which breaks \-\-set\-tos and its
+aforementioned kernels forgo the inversion which breaks \-\-set\-tos and its
mnemonics.
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index d13ec85f..ffc9da13 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -147,6 +147,62 @@ static void tproxy_tg1_parse(struct xt_option_call *cb)
}
}
+static int tproxy_tg_xlate(struct xt_xlate *xl,
+ const struct xt_tproxy_target_info_v1 *info)
+{
+ int family = xt_xlate_get_family(xl);
+ uint32_t mask = info->mark_mask;
+ bool port_mandatory = false;
+ char buf[INET6_ADDRSTRLEN];
+
+ xt_xlate_add(xl, "tproxy to");
+
+ inet_ntop(family, &info->laddr, buf, sizeof(buf));
+
+ if (family == AF_INET6 && !IN6_IS_ADDR_UNSPECIFIED(&info->laddr.in6))
+ xt_xlate_add(xl, "[%s]", buf);
+ else if (family == AF_INET && info->laddr.ip)
+ xt_xlate_add(xl, "%s", buf);
+ else
+ port_mandatory = true;
+
+ if (port_mandatory)
+ xt_xlate_add(xl, " :%d", ntohs(info->lport));
+ else if (info->lport)
+ xt_xlate_add(xl, ":%d", ntohs(info->lport));
+
+ /* xt_TPROXY.c does: skb->mark = (skb->mark & ~mark_mask) ^ mark_value */
+ if (mask == 0xffffffff)
+ xt_xlate_add(xl, "meta mark set 0x%x", info->mark_value);
+ else if (mask || info->mark_value)
+ xt_xlate_add(xl, "meta mark set meta mark & 0x%x xor 0x%x",
+ ~mask, info->mark_value);
+
+ return 1;
+}
+
+static int tproxy_tg_xlate_v1(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct xt_tproxy_target_info_v1 *data = (const void *)params->target->data;
+
+ return tproxy_tg_xlate(xl, data);
+}
+
+static int tproxy_tg_xlate_v0(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct xt_tproxy_target_info *info = (const void *)params->target->data;
+ struct xt_tproxy_target_info_v1 t = {
+ .mark_mask = info->mark_mask,
+ .mark_value = info->mark_value,
+ .laddr.ip = info->laddr,
+ .lport = info->lport,
+ };
+
+ return tproxy_tg_xlate(xl, &t);
+}
+
static struct xtables_target tproxy_tg_reg[] = {
{
.name = "TPROXY",
@@ -160,6 +216,7 @@ static struct xtables_target tproxy_tg_reg[] = {
.save = tproxy_tg_save,
.x6_options = tproxy_tg0_opts,
.x6_parse = tproxy_tg0_parse,
+ .xlate = tproxy_tg_xlate_v0,
},
{
.name = "TPROXY",
@@ -173,6 +230,7 @@ static struct xtables_target tproxy_tg_reg[] = {
.save = tproxy_tg_save4,
.x6_options = tproxy_tg1_opts,
.x6_parse = tproxy_tg1_parse,
+ .xlate = tproxy_tg_xlate_v1,
},
{
.name = "TPROXY",
@@ -186,6 +244,7 @@ static struct xtables_target tproxy_tg_reg[] = {
.save = tproxy_tg_save6,
.x6_options = tproxy_tg1_opts,
.x6_parse = tproxy_tg1_parse,
+ .xlate = tproxy_tg_xlate_v1,
},
};
diff --git a/extensions/libxt_TPROXY.txlate b/extensions/libxt_TPROXY.txlate
new file mode 100644
index 00000000..239bbe0d
--- /dev/null
+++ b/extensions/libxt_TPROXY.txlate
@@ -0,0 +1,20 @@
+iptables-translate -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff
+nft 'add rule ip mangle PREROUTING ip protocol tcp counter tproxy to 10.0.0.1:12345 meta mark set meta mark & 0xffffff00 xor 0x23'
+
+iptables-translate -t mangle -A PREROUTING -p udp -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23
+nft 'add rule ip mangle PREROUTING ip protocol udp counter tproxy to 10.0.0.1:12345 meta mark set 0x23'
+
+iptables-translate -t mangle -A PREROUTING -p udp -j TPROXY --on-port 12345 --on-ip 10.0.0.1
+nft 'add rule ip mangle PREROUTING ip protocol udp counter tproxy to 10.0.0.1:12345'
+
+iptables-translate -t mangle -A PREROUTING -p udp -j TPROXY --on-ip 10.0.0.1 --on-port 0
+nft 'add rule ip mangle PREROUTING ip protocol udp counter tproxy to 10.0.0.1'
+
+iptables-translate -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 12345
+nft 'add rule ip mangle PREROUTING ip protocol tcp counter tproxy to :12345'
+
+iptables-translate -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 0
+nft 'add rule ip mangle PREROUTING ip protocol tcp counter tproxy to :0'
+
+ip6tables-translate -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 12345 --on-ip dead::beef --tproxy-mark 0x23/0xffff
+nft 'add rule ip6 mangle PREROUTING meta l4proto tcp counter tproxy to [dead::beef]:12345 meta mark set meta mark & 0xffff0000 xor 0x23'
diff --git a/extensions/libxt_TRACE.man b/extensions/libxt_TRACE.man
index 5187a8d2..9cfa2711 100644
--- a/extensions/libxt_TRACE.man
+++ b/extensions/libxt_TRACE.man
@@ -15,6 +15,6 @@ With iptables-nft, the target is translated into nftables'
.B "meta nftrace"
expression. Hence the kernel sends trace events via netlink to userspace where
they may be displayed using
-.B "xtables-monitor --trace"
+.B "xtables\-monitor \-\-trace"
command. For details, refer to
-.BR xtables-monitor (8).
+.BR xtables\-monitor (8).
diff --git a/extensions/libxt_bpf.man b/extensions/libxt_bpf.man
index d6da2043..b79c21db 100644
--- a/extensions/libxt_bpf.man
+++ b/extensions/libxt_bpf.man
@@ -28,7 +28,7 @@ without the comments or trailing whitespace:
.IP
4 # number of instructions
.br
-48 0 0 9 # load byte ip->proto
+48 0 0 9 # load byte ip\->proto
.br
21 0 1 6 # jump equal IPPROTO_TCP
.br
@@ -44,7 +44,7 @@ Or instead, you can invoke the nfbpf_compile utility.
.IP
iptables \-A OUTPUT \-m bpf \-\-bytecode "`nfbpf_compile RAW 'ip proto 6'`" \-j ACCEPT
.PP
-Or use tcpdump -ddd. In that case, generate BPF targeting a device with the
+Or use tcpdump \-ddd. In that case, generate BPF targeting a device with the
same data link type as the xtables match. Iptables passes packets from the
network layer up, without mac layer. Select a device with data link type RAW,
such as a tun device:
@@ -53,8 +53,8 @@ ip tuntap add tun0 mode tun
.br
ip link set tun0 up
.br
-tcpdump -ddd -i tun0 ip proto 6
+tcpdump \-ddd \-i tun0 ip proto 6
.PP
-See tcpdump -L -i $dev for a list of known data link types for a given device.
+See tcpdump \-L \-i $dev for a list of known data link types for a given device.
.PP
You may want to learn more about BPF from FreeBSD's bpf(4) manpage.
diff --git a/extensions/libxt_cgroup.man b/extensions/libxt_cgroup.man
index 4d5d1d86..140afb48 100644
--- a/extensions/libxt_cgroup.man
+++ b/extensions/libxt_cgroup.man
@@ -15,7 +15,7 @@ option and \-\-path can't be used together.
.PP
Example:
.IP
-iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-path service/http-server \-j DROP
+iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-path service/http\-server \-j DROP
.IP
iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1
\-j DROP
diff --git a/extensions/libxt_cluster.man b/extensions/libxt_cluster.man
index 23448e26..63054471 100644
--- a/extensions/libxt_cluster.man
+++ b/extensions/libxt_cluster.man
@@ -22,7 +22,7 @@ Example:
iptables \-A PREROUTING \-t mangle \-i eth1 \-m cluster
\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
\-\-cluster\-hash\-seed 0xdeadbeef
-\-j MARK \-\-set-mark 0xffff
+\-j MARK \-\-set\-mark 0xffff
.IP
iptables \-A PREROUTING \-t mangle \-i eth2 \-m cluster
\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
@@ -42,10 +42,10 @@ ip maddr add 01:00:5e:00:01:01 dev eth1
ip maddr add 01:00:5e:00:01:02 dev eth2
.IP
arptables \-A OUTPUT \-o eth1 \-\-h\-length 6
-\-j mangle \-\-mangle-mac-s 01:00:5e:00:01:01
+\-j mangle \-\-mangle\-mac\-s 01:00:5e:00:01:01
.IP
-arptables \-A INPUT \-i eth1 \-\-h-length 6
-\-\-destination-mac 01:00:5e:00:01:01
+arptables \-A INPUT \-i eth1 \-\-h\-length 6
+\-\-destination\-mac 01:00:5e:00:01:01
\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
.IP
arptables \-A OUTPUT \-o eth2 \-\-h\-length 6
diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c
index b57f0fc0..2f110857 100644
--- a/extensions/libxt_connbytes.c
+++ b/extensions/libxt_connbytes.c
@@ -41,10 +41,6 @@ static void connbytes_parse(struct xt_option_call *cb)
if (cb->nvals == 2)
sinfo->count.to = cb->val.u64_range[1];
- if (sinfo->count.to < sinfo->count.from)
- xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
- (unsigned long long)sinfo->count.from,
- (unsigned long long)sinfo->count.to);
if (cb->invert) {
i = sinfo->count.from;
sinfo->count.from = sinfo->count.to;
diff --git a/extensions/libxt_connbytes.t b/extensions/libxt_connbytes.t
index 6b24e266..60209c69 100644
--- a/extensions/libxt_connbytes.t
+++ b/extensions/libxt_connbytes.t
@@ -10,6 +10,12 @@
-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir both;=;OK
-m connbytes --connbytes -1:0 --connbytes-mode packets --connbytes-dir original;;FAIL
-m connbytes --connbytes 0:-1 --connbytes-mode packets --connbytes-dir original;;FAIL
+-m connbytes --connbytes : --connbytes-mode packets --connbytes-dir original;-m connbytes --connbytes 0 --connbytes-mode packets --connbytes-dir original;OK
+-m connbytes --connbytes :1000 --connbytes-mode packets --connbytes-dir original;-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir original;OK
+-m connbytes --connbytes 1000 --connbytes-mode packets --connbytes-dir original;=;OK
+-m connbytes --connbytes 1000: --connbytes-mode packets --connbytes-dir original;-m connbytes --connbytes 1000 --connbytes-mode packets --connbytes-dir original;OK
+-m connbytes --connbytes 1000:1000 --connbytes-mode packets --connbytes-dir original;=;OK
+-m connbytes --connbytes 1000:0 --connbytes-mode packets --connbytes-dir original;;FAIL
# ERROR: cannot find: iptables -I INPUT -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both
# -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both;=;OK
-m connbytes --connbytes 0:18446744073709551616 --connbytes-mode avgpkt --connbytes-dir both;;FAIL
diff --git a/extensions/libxt_connlabel.man b/extensions/libxt_connlabel.man
index bdaa51e8..7ce18cf5 100644
--- a/extensions/libxt_connlabel.man
+++ b/extensions/libxt_connlabel.man
@@ -23,11 +23,11 @@ Label translation is done via the \fB/etc/xtables/connlabel.conf\fP configuratio
Example:
.IP
.nf
-0 eth0-in
-1 eth0-out
-2 ppp-in
-3 ppp-out
-4 bulk-traffic
+0 eth0\-in
+1 eth0\-out
+2 ppp\-in
+3 ppp\-out
+4 bulk\-traffic
5 interactive
.fi
.PP
diff --git a/extensions/libxt_connlimit.man b/extensions/libxt_connlimit.man
index ad9f40fa..aa7df2b2 100644
--- a/extensions/libxt_connlimit.man
+++ b/extensions/libxt_connlimit.man
@@ -20,23 +20,28 @@ Apply the limit onto the source group. This is the default if
Apply the limit onto the destination group.
.PP
Examples:
-.TP
-# allow 2 telnet connections per client host
+.IP \(bu 4
+allow 2 telnet connections per client host:
+.br
iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit \-\-connlimit\-above 2 \-j REJECT
-.TP
-# you can also match the other way around:
+.IP \(bu 4
+you can also match the other way around:
+.br
iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit \-\-connlimit\-upto 2 \-j ACCEPT
-.TP
-# limit the number of parallel HTTP requests to 16 per class C sized \
-source network (24 bit netmask)
+.IP \(bu 4
+limit the number of parallel HTTP requests to 16 per class C sized \
+source network (24 bit netmask):
+.br
iptables \-p tcp \-\-syn \-\-dport 80 \-m connlimit \-\-connlimit\-above 16
\-\-connlimit\-mask 24 \-j REJECT
-.TP
-# limit the number of parallel HTTP requests to 16 for the link local network
-(ipv6)
+.IP \(bu 4
+limit the number of parallel HTTP requests to 16 for the link local network
+(IPv6):
+.br
ip6tables \-p tcp \-\-syn \-\-dport 80 \-s fe80::/64 \-m connlimit \-\-connlimit\-above
16 \-\-connlimit\-mask 64 \-j REJECT
-.TP
-# Limit the number of connections to a particular host:
+.IP \(bu 4
+Limit the number of connections to a particular host:
+.br
ip6tables \-p tcp \-\-syn \-\-dport 49152:65535 \-d 2001:db8::1 \-m connlimit
-\-\-connlimit-above 100 \-j REJECT
+\-\-connlimit\-above 100 \-j REJECT
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 09548c29..ffbc7467 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -346,14 +346,13 @@ static void conntrack_parse(struct xt_option_call *cb)
sinfo->invflags |= XT_CONNTRACK_STATE;
break;
case O_CTPROTO:
+ if (cb->val.protocol == 0)
+ xtables_error(PARAMETER_PROBLEM, cb->invert ?
+ "condition would always match protocol" :
+ "rule would never match protocol");
sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol;
if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_PROTO;
- if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
- && (sinfo->invflags & XT_INV_PROTO))
- xtables_error(PARAMETER_PROBLEM,
- "rule would never match protocol");
-
sinfo->flags |= XT_CONNTRACK_PROTO;
break;
case O_CTORIGSRC:
@@ -411,11 +410,11 @@ static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev)
info->invert_flags |= XT_CONNTRACK_STATE;
break;
case O_CTPROTO:
+ if (cb->val.protocol == 0)
+ xtables_error(PARAMETER_PROBLEM, cb->invert ?
+ "conntrack: condition would always match protocol" :
+ "conntrack: rule would never match protocol");
info->l4proto = cb->val.protocol;
- if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
- xtables_error(PARAMETER_PROBLEM, "conntrack: rule would "
- "never match protocol");
-
info->match_flags |= XT_CONNTRACK_PROTO;
if (cb->invert)
info->invert_flags |= XT_CONNTRACK_PROTO;
diff --git a/extensions/libxt_conntrack.t b/extensions/libxt_conntrack.t
index db531475..5e27ddce 100644
--- a/extensions/libxt_conntrack.t
+++ b/extensions/libxt_conntrack.t
@@ -17,6 +17,8 @@
-m conntrack --ctexpire 0:4294967295;=;OK
-m conntrack --ctexpire 42949672956;;FAIL
-m conntrack --ctexpire -1;;FAIL
+-m conntrack --ctexpire 3:3;-m conntrack --ctexpire 3;OK
+-m conntrack --ctexpire 4:3;;FAIL
-m conntrack --ctdir ORIGINAL;=;OK
-m conntrack --ctdir REPLY;=;OK
-m conntrack --ctstatus NONE;=;OK
@@ -25,3 +27,29 @@
-m conntrack --ctstatus EXPECTED;=;OK
-m conntrack --ctstatus SEEN_REPLY;=;OK
-m conntrack;;FAIL
+-m conntrack --ctproto 0;;FAIL
+-m conntrack ! --ctproto 0;;FAIL
+-m conntrack --ctorigsrcport :;-m conntrack --ctorigsrcport 0:65535;OK
+-m conntrack --ctorigsrcport :4;-m conntrack --ctorigsrcport 0:4;OK
+-m conntrack --ctorigsrcport 4:;-m conntrack --ctorigsrcport 4:65535;OK
+-m conntrack --ctorigsrcport 3:4;=;OK
+-m conntrack --ctorigsrcport 4:4;-m conntrack --ctorigsrcport 4;OK
+-m conntrack --ctorigsrcport 4:3;;FAIL
+-m conntrack --ctreplsrcport :;-m conntrack --ctreplsrcport 0:65535;OK
+-m conntrack --ctreplsrcport :4;-m conntrack --ctreplsrcport 0:4;OK
+-m conntrack --ctreplsrcport 4:;-m conntrack --ctreplsrcport 4:65535;OK
+-m conntrack --ctreplsrcport 3:4;=;OK
+-m conntrack --ctreplsrcport 4:4;-m conntrack --ctreplsrcport 4;OK
+-m conntrack --ctreplsrcport 4:3;;FAIL
+-m conntrack --ctorigdstport :;-m conntrack --ctorigdstport 0:65535;OK
+-m conntrack --ctorigdstport :4;-m conntrack --ctorigdstport 0:4;OK
+-m conntrack --ctorigdstport 4:;-m conntrack --ctorigdstport 4:65535;OK
+-m conntrack --ctorigdstport 3:4;=;OK
+-m conntrack --ctorigdstport 4:4;-m conntrack --ctorigdstport 4;OK
+-m conntrack --ctorigdstport 4:3;;FAIL
+-m conntrack --ctrepldstport :;-m conntrack --ctrepldstport 0:65535;OK
+-m conntrack --ctrepldstport :4;-m conntrack --ctrepldstport 0:4;OK
+-m conntrack --ctrepldstport 4:;-m conntrack --ctrepldstport 4:65535;OK
+-m conntrack --ctrepldstport 3:4;=;OK
+-m conntrack --ctrepldstport 4:4;-m conntrack --ctrepldstport 4;OK
+-m conntrack --ctrepldstport 4:3;;FAIL
diff --git a/extensions/libxt_cpu.man b/extensions/libxt_cpu.man
index d9ea5c2f..158d50cb 100644
--- a/extensions/libxt_cpu.man
+++ b/extensions/libxt_cpu.man
@@ -1,15 +1,15 @@
.TP
[\fB!\fP] \fB\-\-cpu\fP \fInumber\fP
-Match cpu handling this packet. cpus are numbered from 0 to NR_CPUS-1
+Match cpu handling this packet. cpus are numbered from 0 to NR_CPUS\-1
Can be used in combination with RPS (Remote Packet Steering) or
multiqueue NICs to spread network traffic on different queues.
.PP
Example:
.PP
iptables \-t nat \-A PREROUTING \-p tcp \-\-dport 80 \-m cpu \-\-cpu 0
-\-j REDIRECT \-\-to\-port 8080
+\-j REDIRECT \-\-to\-ports 8080
.PP
iptables \-t nat \-A PREROUTING \-p tcp \-\-dport 80 \-m cpu \-\-cpu 1
-\-j REDIRECT \-\-to\-port 8081
+\-j REDIRECT \-\-to\-ports 8081
.PP
Available since Linux 2.6.36.
diff --git a/extensions/libxt_dccp.t b/extensions/libxt_dccp.t
index f60b480f..3655ab6f 100644
--- a/extensions/libxt_dccp.t
+++ b/extensions/libxt_dccp.t
@@ -6,6 +6,16 @@
-p dccp -m dccp --sport 1:1023;=;OK
-p dccp -m dccp --sport 1024:65535;=;OK
-p dccp -m dccp --sport 1024:;-p dccp -m dccp --sport 1024:65535;OK
+-p dccp -m dccp --sport :;-p dccp -m dccp --sport 0:65535;OK
+-p dccp -m dccp --sport :4;-p dccp -m dccp --sport 0:4;OK
+-p dccp -m dccp --sport 4:;-p dccp -m dccp --sport 4:65535;OK
+-p dccp -m dccp --sport 4:4;-p dccp -m dccp --sport 4;OK
+-p dccp -m dccp --sport 4:3;;FAIL
+-p dccp -m dccp --dport :;-p dccp -m dccp --dport 0:65535;OK
+-p dccp -m dccp --dport :4;-p dccp -m dccp --dport 0:4;OK
+-p dccp -m dccp --dport 4:;-p dccp -m dccp --dport 4:65535;OK
+-p dccp -m dccp --dport 4:4;-p dccp -m dccp --dport 4;OK
+-p dccp -m dccp --dport 4:3;;FAIL
-p dccp -m dccp ! --sport 1;=;OK
-p dccp -m dccp ! --sport 65535;=;OK
-p dccp -m dccp ! --dport 1;=;OK
diff --git a/extensions/libxt_dscp.man b/extensions/libxt_dscp.man
index 63a17dac..ff4523fd 100644
--- a/extensions/libxt_dscp.man
+++ b/extensions/libxt_dscp.man
@@ -2,7 +2,7 @@ This module matches the 6 bit DSCP field within the TOS field in the
IP header. DSCP has superseded TOS within the IETF.
.TP
[\fB!\fP] \fB\-\-dscp\fP \fIvalue\fP
-Match against a numeric (decimal or hex) value [0-63].
+Match against a numeric (decimal or hex) value in the range 0\(en63.
.TP
[\fB!\fP] \fB\-\-dscp\-class\fP \fIclass\fP
Match the DiffServ class. This value may be any of the
diff --git a/extensions/libxt_esp.c b/extensions/libxt_esp.c
index 2c7ff942..8e9766d7 100644
--- a/extensions/libxt_esp.c
+++ b/extensions/libxt_esp.c
@@ -39,13 +39,18 @@ static void esp_parse(struct xt_option_call *cb)
espinfo->invflags |= XT_ESP_INV_SPI;
}
+static bool skip_spis_match(uint32_t min, uint32_t max, bool inv)
+{
+ return min == 0 && max == UINT32_MAX && !inv;
+}
+
static void
print_spis(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (!skip_spis_match(min, max, invert)) {
if (min == max)
printf(" %s:%s%u", name, inv, min);
else
@@ -69,11 +74,10 @@ esp_print(const void *ip, const struct xt_entry_match *match, int numeric)
static void esp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_esp *espinfo = (struct xt_esp *)match->data;
+ bool inv_spi = espinfo->invflags & XT_ESP_INV_SPI;
- if (!(espinfo->spis[0] == 0
- && espinfo->spis[1] == 0xFFFFFFFF)) {
- printf("%s --espspi ",
- (espinfo->invflags & XT_ESP_INV_SPI) ? " !" : "");
+ if (!skip_spis_match(espinfo->spis[0], espinfo->spis[1], inv_spi)) {
+ printf("%s --espspi ", inv_spi ? " !" : "");
if (espinfo->spis[0]
!= espinfo->spis[1])
printf("%u:%u",
@@ -90,15 +94,21 @@ static int esp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_esp *espinfo = (struct xt_esp *)params->match->data;
+ bool inv_spi = espinfo->invflags & XT_ESP_INV_SPI;
- if (!(espinfo->spis[0] == 0 && espinfo->spis[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "esp spi%s",
- (espinfo->invflags & XT_ESP_INV_SPI) ? " !=" : "");
+ if (!skip_spis_match(espinfo->spis[0], espinfo->spis[1], inv_spi)) {
+ xt_xlate_add(xl, "esp spi%s", inv_spi ? " !=" : "");
if (espinfo->spis[0] != espinfo->spis[1])
xt_xlate_add(xl, " %u-%u", espinfo->spis[0],
espinfo->spis[1]);
else
xt_xlate_add(xl, " %u", espinfo->spis[0]);
+ } else if (afinfo->family == NFPROTO_IPV4) {
+ xt_xlate_add(xl, "meta l4proto esp");
+ } else if (afinfo->family == NFPROTO_IPV6) {
+ xt_xlate_add(xl, "exthdr esp exists");
+ } else {
+ return 0;
}
return 1;
diff --git a/extensions/libxt_esp.t b/extensions/libxt_esp.t
index 92c5779f..ece131c9 100644
--- a/extensions/libxt_esp.t
+++ b/extensions/libxt_esp.t
@@ -4,5 +4,12 @@
-p esp -m esp --espspi 0:4294967295;-p esp -m esp;OK
-p esp -m esp ! --espspi 0:4294967294;=;OK
-p esp -m esp --espspi -1;;FAIL
+-p esp -m esp --espspi :;-p esp -m esp;OK
+-p esp -m esp ! --espspi :;-p esp -m esp ! --espspi 0:4294967295;OK
+-p esp -m esp --espspi :4;-p esp -m esp --espspi 0:4;OK
+-p esp -m esp --espspi 4:;-p esp -m esp --espspi 4:4294967295;OK
+-p esp -m esp --espspi 3:4;=;OK
+-p esp -m esp --espspi 4:4;-p esp -m esp --espspi 4;OK
+-p esp -m esp --espspi 4:3;;FAIL
-p esp -m esp;=;OK
-m esp;;FAIL
diff --git a/extensions/libxt_esp.txlate b/extensions/libxt_esp.txlate
index f6aba52f..5e8fb241 100644
--- a/extensions/libxt_esp.txlate
+++ b/extensions/libxt_esp.txlate
@@ -9,3 +9,15 @@ nft 'add rule ip filter INPUT esp spi 500 counter drop'
iptables-translate -A INPUT -p 50 -m esp --espspi 500:600 -j DROP
nft 'add rule ip filter INPUT esp spi 500-600 counter drop'
+
+iptables-translate -A INPUT -p 50 -m esp --espspi 0:4294967295 -j DROP
+nft 'add rule ip filter INPUT meta l4proto esp counter drop'
+
+iptables-translate -A INPUT -p 50 -m esp ! --espspi 0:4294967295 -j DROP
+nft 'add rule ip filter INPUT esp spi != 0-4294967295 counter drop'
+
+ip6tables-translate -A INPUT -p 50 -m esp --espspi 0:4294967295 -j DROP
+nft 'add rule ip6 filter INPUT exthdr esp exists counter drop'
+
+ip6tables-translate -A INPUT -p 50 -m esp ! --espspi 0:4294967295 -j DROP
+nft 'add rule ip6 filter INPUT esp spi != 0-4294967295 counter drop'
diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man
index 8a35d564..b95a52d2 100644
--- a/extensions/libxt_hashlimit.man
+++ b/extensions/libxt_hashlimit.man
@@ -20,7 +20,7 @@ Maximum initial number of packets to match: this number gets recharged by one
every time the limit specified above is not reached, up to this number; the
default is 5. When byte-based rate matching is requested, this option specifies
the amount of bytes that can exceed the given rate. This option should be used
-with caution -- if the entry expires, the burst value is reset too.
+with caution \(em if the entry expires, the burst value is reset too.
.TP
\fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP...
A comma-separated list of objects to take into consideration. If no
@@ -77,8 +77,8 @@ in 10.0.0.0/8" =>
.TP
matching bytes per second
"flows exceeding 512kbyte/s" =>
-\-\-hashlimit-mode srcip,dstip,srcport,dstport \-\-hashlimit\-above 512kb/s
+\-\-hashlimit\-mode srcip,dstip,srcport,dstport \-\-hashlimit\-above 512kb/s
.TP
matching bytes per second
"hosts that exceed 512kbyte/s, but permit up to 1Megabytes without matching"
-\-\-hashlimit-mode dstip \-\-hashlimit\-above 512kb/s \-\-hashlimit-burst 1mb
+\-\-hashlimit\-mode dstip \-\-hashlimit\-above 512kb/s \-\-hashlimit\-burst 1mb
diff --git a/extensions/libxt_helper.man b/extensions/libxt_helper.man
index 772b1350..fb8a206c 100644
--- a/extensions/libxt_helper.man
+++ b/extensions/libxt_helper.man
@@ -1,11 +1,11 @@
-This module matches packets related to a specific conntrack-helper.
+This module matches packets related to a specific conntrack helper.
.TP
[\fB!\fP] \fB\-\-helper\fP \fIstring\fP
-Matches packets related to the specified conntrack-helper.
+Matches packets related to the specified conntrack helper.
.RS
.PP
-string can be "ftp" for packets related to a ftp-session on default port.
-For other ports append \-portnr to the value, ie. "ftp\-2121".
+string can be "ftp" for packets related to an FTP session on default port.
+For other ports, append \-\-portnr to the value, ie. "ftp\-2121".
.PP
-Same rules apply for other conntrack-helpers.
+Same rules apply for other conntrack helpers.
.RE
diff --git a/extensions/libxt_icmp.h b/extensions/libxt_icmp.h
index a763e50c..7a45b4bd 100644
--- a/extensions/libxt_icmp.h
+++ b/extensions/libxt_icmp.h
@@ -83,6 +83,13 @@ static const struct xt_icmp_names {
{ "echo-reply", 129, 0, 0xFF },
/* Alias */ { "pong", 129, 0, 0xFF },
+ { "mld-listener-query", 130, 0, 0xFF },
+
+ { "mld-listener-report", 131, 0, 0xFF },
+
+ { "mld-listener-done", 132, 0, 0xFF },
+ /* Alias */ { "mld-listener-reduction", 132, 0, 0xFF },
+
{ "router-solicitation", 133, 0, 0xFF },
{ "router-advertisement", 134, 0, 0xFF },
diff --git a/extensions/libxt_ipcomp.c b/extensions/libxt_ipcomp.c
index 4171c4a1..961c17e5 100644
--- a/extensions/libxt_ipcomp.c
+++ b/extensions/libxt_ipcomp.c
@@ -76,11 +76,12 @@ static void comp_print(const void *ip, const struct xt_entry_match *match,
static void comp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_ipcomp *compinfo = (struct xt_ipcomp *)match->data;
+ bool inv_spi = compinfo->invflags & XT_IPCOMP_INV_SPI;
if (!(compinfo->spis[0] == 0
- && compinfo->spis[1] == 0xFFFFFFFF)) {
- printf("%s --ipcompspi ",
- (compinfo->invflags & XT_IPCOMP_INV_SPI) ? " !" : "");
+ && compinfo->spis[1] == UINT32_MAX
+ && !inv_spi)) {
+ printf("%s --ipcompspi ", inv_spi ? " !" : "");
if (compinfo->spis[0]
!= compinfo->spis[1])
printf("%u:%u",
diff --git a/extensions/libxt_ipcomp.t b/extensions/libxt_ipcomp.t
index 8546ba9c..e25695c6 100644
--- a/extensions/libxt_ipcomp.t
+++ b/extensions/libxt_ipcomp.t
@@ -1,3 +1,10 @@
:INPUT,OUTPUT
-p ipcomp -m ipcomp --ipcompspi 18 -j DROP;=;OK
-p ipcomp -m ipcomp ! --ipcompspi 18 -j ACCEPT;=;OK
+-p ipcomp -m ipcomp --ipcompspi :;-p ipcomp -m ipcomp;OK
+-p ipcomp -m ipcomp ! --ipcompspi :;-p ipcomp -m ipcomp ! --ipcompspi 0:4294967295;OK
+-p ipcomp -m ipcomp --ipcompspi :4;-p ipcomp -m ipcomp --ipcompspi 0:4;OK
+-p ipcomp -m ipcomp --ipcompspi 4:;-p ipcomp -m ipcomp --ipcompspi 4:4294967295;OK
+-p ipcomp -m ipcomp --ipcompspi 3:4;=;OK
+-p ipcomp -m ipcomp --ipcompspi 4:4;-p ipcomp -m ipcomp --ipcompspi 4;OK
+-p ipcomp -m ipcomp --ipcompspi 4:3;;FAIL
diff --git a/extensions/libxt_length.t b/extensions/libxt_length.t
index 8b70fc31..bae313b4 100644
--- a/extensions/libxt_length.t
+++ b/extensions/libxt_length.t
@@ -3,8 +3,11 @@
-m length --length :2;-m length --length 0:2;OK
-m length --length 0:3;=;OK
-m length --length 4:;-m length --length 4:65535;OK
+-m length --length :;-m length --length 0:65535;OK
-m length --length 0:65535;=;OK
-m length ! --length 0:65535;=;OK
-m length --length 0:65536;;FAIL
-m length --length -1:65535;;FAIL
+-m length --length 4:4;-m length --length 4;OK
+-m length --length 4:3;;FAIL
-m length;;FAIL
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index e6ec67f3..63f3289d 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -7,7 +7,6 @@
#define _DEFAULT_SOURCE 1
#define _ISOC99_SOURCE 1
#include <errno.h>
-#include <getopt.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -202,44 +201,6 @@ static int limit_xlate_eb(struct xt_xlate *xl,
return 1;
}
-#define FLAG_LIMIT 0x01
-#define FLAG_LIMIT_BURST 0x02
-#define ARG_LIMIT '1'
-#define ARG_LIMIT_BURST '2'
-
-static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct xt_rateinfo *r = (struct xt_rateinfo *)(*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;
-}
-
static void brlimit_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
@@ -250,13 +211,6 @@ static void brlimit_print(const void *ip, const struct xt_entry_match *match,
printf(" --limit-burst %u ", r->burst);
}
-static const 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 struct xtables_match limit_match[] = {
{
.family = NFPROTO_UNSPEC,
@@ -280,9 +234,9 @@ static struct xtables_match limit_match[] = {
.userspacesize = offsetof(struct xt_rateinfo, prev),
.help = limit_help,
.init = limit_init,
- .parse = brlimit_parse,
+ .x6_parse = limit_parse,
.print = brlimit_print,
- .extra_opts = brlimit_opts,
+ .x6_options = limit_opts,
.xlate = limit_xlate_eb,
},
};
diff --git a/extensions/libxt_limit.man b/extensions/libxt_limit.man
index 6fb94ccf..b477dd94 100644
--- a/extensions/libxt_limit.man
+++ b/extensions/libxt_limit.man
@@ -4,7 +4,7 @@ It can be used in combination with the
.B LOG
target to give limited logging, for example.
.PP
-xt_limit has no negation support - you will have to use \-m hashlimit !
+xt_limit has no negation support \(em you will have to use \-m hashlimit !
\-\-hashlimit \fIrate\fP in this case whilst omitting \-\-hashlimit\-mode.
.TP
\fB\-\-limit\fP \fIrate\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
index f3136d8a..813a3555 100644
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -248,7 +248,7 @@ static void multiport_parse6_v1(struct xt_option_call *cb)
static void multiport_check(struct xt_fcheck_call *cb)
{
if (cb->xflags == 0)
- xtables_error(PARAMETER_PROBLEM, "multiport expection an option");
+ xtables_error(PARAMETER_PROBLEM, "no ports specified");
}
static const char *
diff --git a/extensions/libxt_nfacct.man b/extensions/libxt_nfacct.man
index b755f977..4e05891e 100644
--- a/extensions/libxt_nfacct.man
+++ b/extensions/libxt_nfacct.man
@@ -22,9 +22,9 @@ Then, you can check for the amount of traffic that the rules match:
.IP
nfacct get http\-traffic
.IP
-{ pkts = 00000000000000000156, bytes = 00000000000000151786 } = http-traffic;
+{ pkts = 00000000000000000156, bytes = 00000000000000151786 } = http\-traffic;
.PP
You can obtain
.B nfacct(8)
-from http://www.netfilter.org or, alternatively, from the git.netfilter.org
+from https://www.netfilter.org or, alternatively, from the git.netfilter.org
repository.
diff --git a/extensions/libxt_osf.man b/extensions/libxt_osf.man
index 41103f29..85c1a3b4 100644
--- a/extensions/libxt_osf.man
+++ b/extensions/libxt_osf.man
@@ -8,29 +8,39 @@ Match an operating system genre by using a passive fingerprinting.
\fB\-\-ttl\fP \fIlevel\fP
Do additional TTL checks on the packet to determine the operating system.
\fIlevel\fP can be one of the following values:
-.IP \(bu 4
-0 - True IP address and fingerprint TTL comparison. This generally works for
+.RS
+.TP
+\fB0\fP
+True IP address and fingerprint TTL comparison. This generally works for
LANs.
-.IP \(bu 4
-1 - Check if the IP header's TTL is less than the fingerprint one. Works for
+.TP
+\fB1\fP
+Check if the IP header's TTL is less than the fingerprint one. Works for
globally-routable addresses.
-.IP \(bu 4
-2 - Do not compare the TTL at all.
+.TP
+\fB2\fP
+Do not compare the TTL at all.
+.RE
.TP
\fB\-\-log\fP \fIlevel\fP
Log determined genres into dmesg even if they do not match the desired one.
\fIlevel\fP can be one of the following values:
-.IP \(bu 4
-0 - Log all matched or unknown signatures
-.IP \(bu 4
-1 - Log only the first one
-.IP \(bu 4
-2 - Log all known matched signatures
+.RS
+.TP
+\fB0\fP
+Log all matched or unknown signatures
+.TP
+\fB1\fP
+Log only the first one
+.TP
+\fB2\fP
+Log all known matched signatures
+.RE
.PP
You may find something like this in syslog:
.PP
-Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 ->
-11.22.33.44:139 hops=3 Linux [2.5-2.6:] : 1.2.3.4:42624 -> 1.2.3.5:22 hops=4
+Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 \->
+11.22.33.44:139 hops=3 Linux [2.5\-2.6:] : 1.2.3.4:42624 \-> 1.2.3.5:22 hops=4
.PP
OS fingerprints are loadable using the \fBnfnl_osf\fP program. To load
fingerprints from a file, use:
@@ -42,4 +52,4 @@ To remove them again,
\fBnfnl_osf \-f /usr/share/xtables/pf.os \-d\fP
.PP
The fingerprint database can be downloaded from
-http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os .
+http://www.openbsd.org/cgi\-bin/cvsweb/src/etc/pf.os .
diff --git a/extensions/libxt_owner.man b/extensions/libxt_owner.man
index e2479865..fd6fe190 100644
--- a/extensions/libxt_owner.man
+++ b/extensions/libxt_owner.man
@@ -16,7 +16,7 @@ Matches if the packet socket's file structure is owned by the given group.
You may also specify a numerical GID, or a GID range.
.TP
\fB\-\-suppl\-groups\fP
-Causes group(s) specified with \fB\-\-gid-owner\fP to be also checked in the
+Causes group(s) specified with \fB\-\-gid\-owner\fP to be also checked in the
supplementary groups of a process.
.TP
[\fB!\fP] \fB\-\-socket\-exists\fP
diff --git a/extensions/libxt_rateest.man b/extensions/libxt_rateest.man
index 42a82f32..b1779eb3 100644
--- a/extensions/libxt_rateest.man
+++ b/extensions/libxt_rateest.man
@@ -4,22 +4,26 @@ estimators and matching on the difference between two rate estimators.
.PP
For a better understanding of the available options, these are all possible
combinations:
-.\" * Absolute:
+.TP
+Absolute:
.IP \(bu 4
\fBrateest\fP \fIoperator\fP \fBrateest-bps\fP
.IP \(bu 4
\fBrateest\fP \fIoperator\fP \fBrateest-pps\fP
-.\" * Absolute + Delta:
+.TP
+Absolute + Delta:
.IP \(bu 4
(\fBrateest\fP minus \fBrateest-bps1\fP) \fIoperator\fP \fBrateest-bps2\fP
.IP \(bu 4
(\fBrateest\fP minus \fBrateest-pps1\fP) \fIoperator\fP \fBrateest-pps2\fP
-.\" * Relative:
+.TP
+Relative:
.IP \(bu 4
\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-bps\fP(without rate!)
.IP \(bu 4
\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-pps\fP(without rate!)
-.\" * Relative + Delta:
+.TP
+Relative + Delta:
.IP \(bu 4
(\fBrateest1\fP minus \fBrateest-bps1\fP) \fIoperator\fP
(\fBrateest2\fP minus \fBrateest-bps2\fP)
@@ -31,7 +35,7 @@ combinations:
For each estimator (either absolute or relative mode), calculate the difference
between the estimator-determined flow rate and the static value chosen with the
BPS/PPS options. If the flow rate is higher than the specified BPS/PPS, 0 will
-be used instead of a negative value. In other words, "max(0, rateest#_rate -
+be used instead of a negative value. In other words, "max(0, rateest#_rate \-
rateest#_bps)" is used.
.TP
[\fB!\fP] \fB\-\-rateest\-lt\fP
@@ -68,7 +72,7 @@ The names of the two rate estimators for relative mode.
\fB\-\-rateest\-pps2\fP [\fIvalue\fP]
Compare the estimator(s) by bytes or packets per second, and compare against
the chosen value. See the above bullet list for which option is to be used in
-which case. A unit suffix may be used - available ones are: bit, [kmgt]bit,
+which case. A unit suffix may be used \(em available ones are: bit, [kmgt]bit,
[KMGT]ibit, Bps, [KMGT]Bps, [KMGT]iBps.
.PP
Example: This is what can be used to route outgoing data connections from an
diff --git a/extensions/libxt_set.h b/extensions/libxt_set.h
index 597bf7eb..b7de4cc4 100644
--- a/extensions/libxt_set.h
+++ b/extensions/libxt_set.h
@@ -10,7 +10,7 @@
static int
get_version(unsigned *version)
{
- int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ int res, sockfd = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
struct ip_set_req_version req_version;
socklen_t size = sizeof(req_version);
@@ -18,12 +18,6 @@ get_version(unsigned *version)
xtables_error(OTHER_PROBLEM,
"Can't open socket to ipset.\n");
- if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
- xtables_error(OTHER_PROBLEM,
- "Could not set close on exec: %s\n",
- strerror(errno));
- }
-
req_version.op = IP_SET_OP_VERSION;
res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
if (res != 0)
@@ -152,7 +146,7 @@ parse_dirs_v0(const char *opt_arg, struct xt_set_info_v0 *info)
info->u.flags[i++] |= IPSET_DST;
else
xtables_error(PARAMETER_PROBLEM,
- "You must spefify (the comma separated list of) 'src' or 'dst'.");
+ "You must specify (the comma separated list of) 'src' or 'dst'.");
}
if (tmp)
@@ -176,7 +170,7 @@ parse_dirs(const char *opt_arg, struct xt_set_info *info)
info->flags |= (1 << info->dim);
else if (strncmp(ptr, "dst", 3) != 0)
xtables_error(PARAMETER_PROBLEM,
- "You must spefify (the comma separated list of) 'src' or 'dst'.");
+ "You must specify (the comma separated list of) 'src' or 'dst'.");
}
if (tmp)
diff --git a/extensions/libxt_socket.c b/extensions/libxt_socket.c
index a99135cd..2dcfa221 100644
--- a/extensions/libxt_socket.c
+++ b/extensions/libxt_socket.c
@@ -159,6 +159,37 @@ socket_mt_print_v3(const void *ip, const struct xt_entry_match *match,
socket_mt_save_v3(ip, match);
}
+static int socket_mt_xlate(struct xt_xlate *xl, const struct xt_xlate_mt_params *params)
+{
+ const struct xt_socket_mtinfo3 *info = (const void *)params->match->data;
+
+ /* ONLY --nowildcard: match if socket exists. It does not matter
+ * to which address it is bound.
+ */
+ if (info->flags == XT_SOCKET_NOWILDCARD) {
+ xt_xlate_add(xl, "socket wildcard le 1");
+ return 1;
+ }
+
+ /* Without --nowildcard, restrict to sockets NOT bound to
+ * the any address.
+ */
+ if ((info->flags & XT_SOCKET_NOWILDCARD) == 0)
+ xt_xlate_add(xl, "socket wildcard 0");
+
+ if (info->flags & XT_SOCKET_TRANSPARENT)
+ xt_xlate_add(xl, "socket transparent 1");
+
+ /* If --nowildcard was given, -m socket should not test
+ * the bound address. We can simply ignore this; its
+ * equal to "wildcard <= 1".
+ */
+ if (info->flags & XT_SOCKET_RESTORESKMARK)
+ xt_xlate_add(xl, "meta mark set socket mark");
+
+ return 1;
+}
+
static struct xtables_match socket_mt_reg[] = {
{
.name = "socket",
@@ -180,6 +211,7 @@ static struct xtables_match socket_mt_reg[] = {
.save = socket_mt_save,
.x6_parse = socket_mt_parse,
.x6_options = socket_mt_opts,
+ .xlate = socket_mt_xlate,
},
{
.name = "socket",
@@ -193,6 +225,7 @@ static struct xtables_match socket_mt_reg[] = {
.save = socket_mt_save_v2,
.x6_parse = socket_mt_parse_v2,
.x6_options = socket_mt_opts_v2,
+ .xlate = socket_mt_xlate,
},
{
.name = "socket",
@@ -206,6 +239,7 @@ static struct xtables_match socket_mt_reg[] = {
.save = socket_mt_save_v3,
.x6_parse = socket_mt_parse_v3,
.x6_options = socket_mt_opts_v3,
+ .xlate = socket_mt_xlate,
},
};
diff --git a/extensions/libxt_socket.man b/extensions/libxt_socket.man
index f809df69..a268b443 100644
--- a/extensions/libxt_socket.man
+++ b/extensions/libxt_socket.man
@@ -29,7 +29,7 @@ to be matched when restoring the packet mark.
Example: An application opens 2 transparent (\fBIP_TRANSPARENT\fP) sockets and
sets a mark on them with \fBSO_MARK\fP socket option. We can filter matching packets:
.IP
-\-t mangle \-I PREROUTING \-m socket \-\-transparent \-\-restore-skmark \-j action
+\-t mangle \-I PREROUTING \-m socket \-\-transparent \-\-restore\-skmark \-j action
.IP
\-t mangle \-A action \-m mark \-\-mark 10 \-j action2
.IP
diff --git a/extensions/libxt_socket.txlate b/extensions/libxt_socket.txlate
new file mode 100644
index 00000000..7731e42e
--- /dev/null
+++ b/extensions/libxt_socket.txlate
@@ -0,0 +1,17 @@
+# old socket match, no options. Matches if sk can be found and it is not bound to 0.0.0.0/::
+iptables-translate -A INPUT -m socket
+nft 'add rule ip filter INPUT socket wildcard 0 counter'
+
+iptables-translate -A INPUT -m socket --transparent
+nft 'add rule ip filter INPUT socket wildcard 0 socket transparent 1 counter'
+
+# Matches if sk can be found. Doesn't matter as to what addess it is bound to.
+# therefore, emulate "exists".
+iptables-translate -A INPUT -m socket --nowildcard
+nft 'add rule ip filter INPUT socket wildcard le 1 counter'
+
+iptables-translate -A INPUT -m socket --restore-skmark
+nft 'add rule ip filter INPUT socket wildcard 0 meta mark set socket mark counter'
+
+iptables-translate -A INPUT -m socket --transparent --nowildcard --restore-skmark
+nft 'add rule ip filter INPUT socket transparent 1 meta mark set socket mark counter'
diff --git a/extensions/libxt_standard.t b/extensions/libxt_standard.t
index 56d6da2e..7c83cfa3 100644
--- a/extensions/libxt_standard.t
+++ b/extensions/libxt_standard.t
@@ -21,3 +21,8 @@
-s 10.11.12.13/255.128.0.0;-s 10.0.0.0/9;OK
-s 10.11.12.13/255.0.255.0;-s 10.0.12.0/255.0.255.0;OK
-s 10.11.12.13/255.0.12.0;-s 10.0.12.0/255.0.12.0;OK
+:FORWARD
+--protocol=tcp --source=1.2.3.4 --destination=5.6.7.8/32 --in-interface=eth0 --out-interface=eth1 --jump=ACCEPT;-s 1.2.3.4/32 -d 5.6.7.8/32 -i eth0 -o eth1 -p tcp -j ACCEPT;OK
+-ptcp -s1.2.3.4 -d5.6.7.8/32 -ieth0 -oeth1 -jACCEPT;-s 1.2.3.4/32 -d 5.6.7.8/32 -i eth0 -o eth1 -p tcp -j ACCEPT;OK
+-i + -d 1.2.3.4;-d 1.2.3.4/32;OK
+-i + -p tcp;-p tcp;OK
diff --git a/extensions/libxt_string.man b/extensions/libxt_string.man
index 5f1a993c..bdeb0a62 100644
--- a/extensions/libxt_string.man
+++ b/extensions/libxt_string.man
@@ -7,8 +7,9 @@ Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morri
Set the offset from which it starts looking for any matching. If not passed, default is 0.
.TP
\fB\-\-to\fP \fIoffset\fP
-Set the offset up to which should be scanned. That is, byte \fIoffset\fP-1
-(counting from 0) is the last one that is scanned.
+Set the offset up to which should be scanned. That is, byte \fIoffset\fP
+(counting from 0) is the last one that is scanned and the maximum position of
+\fIpattern\fP's last character.
If not passed, default is the packet size.
.TP
[\fB!\fP] \fB\-\-string\fP \fIpattern\fP
@@ -29,3 +30,18 @@ iptables \-A INPUT \-p tcp \-\-dport 80 \-m string \-\-algo bm \-\-string 'GET /
# The hex string pattern can be used for non-printable characters, like |0D 0A| or |0D0A|.
.br
iptables \-p udp \-\-dport 53 \-m string \-\-algo bm \-\-from 40 \-\-to 57 \-\-hex\-string '|03|www|09|netfilter|03|org|00|'
+.P
+Note: Since Boyer-Moore (BM) performs searches for matches from right to left and
+the kernel may store a packet in multiple discontiguous blocks, it's possible
+that a match could be spread over multiple blocks, in which case this algorithm
+won't find it.
+.P
+If you wish to ensure that such thing won't ever happen, use the
+Knuth-Pratt-Morris (KMP) algorithm instead. In conclusion, choose the proper
+string search algorithm depending on your use-case.
+.P
+For example, if you're using the module for filtering, NIDS or any similar
+security-focused purpose, then choose KMP. On the other hand, if you really care
+about performance \(em for example, you're classifying packets to apply Quality
+of Service (QoS) policies \(em and you don't mind about missing possible matches
+spread over multiple fragments, then choose BM.
diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c
index f8257282..32bbd684 100644
--- a/extensions/libxt_tcp.c
+++ b/extensions/libxt_tcp.c
@@ -225,13 +225,18 @@ print_port(uint16_t port, int numeric)
printf("%s", service);
}
+static bool skip_ports_match(uint16_t min, uint16_t max, bool inv)
+{
+ return min == 0 && max == UINT16_MAX && !inv;
+}
+
static void
print_ports(const char *name, uint16_t min, uint16_t max,
int invert, int numeric)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFF || invert) {
+ if (!skip_ports_match(min, max, invert)) {
printf(" %s", name);
if (min == max) {
printf(":%s", inv);
@@ -315,10 +320,11 @@ tcp_print(const void *ip, const struct xt_entry_match *match, int numeric)
static void tcp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_tcp *tcpinfo = (struct xt_tcp *)match->data;
+ bool inv_srcpt = tcpinfo->invflags & XT_TCP_INV_SRCPT;
+ bool inv_dstpt = tcpinfo->invflags & XT_TCP_INV_DSTPT;
- if (tcpinfo->spts[0] != 0
- || tcpinfo->spts[1] != 0xFFFF) {
- if (tcpinfo->invflags & XT_TCP_INV_SRCPT)
+ if (!skip_ports_match(tcpinfo->spts[0], tcpinfo->spts[1], inv_srcpt)) {
+ if (inv_srcpt)
printf(" !");
if (tcpinfo->spts[0]
!= tcpinfo->spts[1])
@@ -330,9 +336,8 @@ static void tcp_save(const void *ip, const struct xt_entry_match *match)
tcpinfo->spts[0]);
}
- if (tcpinfo->dpts[0] != 0
- || tcpinfo->dpts[1] != 0xFFFF) {
- if (tcpinfo->invflags & XT_TCP_INV_DSTPT)
+ if (!skip_ports_match(tcpinfo->dpts[0], tcpinfo->dpts[1], inv_dstpt)) {
+ if (inv_dstpt)
printf(" !");
if (tcpinfo->dpts[0]
!= tcpinfo->dpts[1])
@@ -397,39 +402,42 @@ static int tcp_xlate(struct xt_xlate *xl,
{
const struct xt_tcp *tcpinfo =
(const struct xt_tcp *)params->match->data;
+ bool inv_srcpt = tcpinfo->invflags & XT_TCP_INV_SRCPT;
+ bool inv_dstpt = tcpinfo->invflags & XT_TCP_INV_DSTPT;
+ bool xlated = false;
- if (tcpinfo->spts[0] != 0 || tcpinfo->spts[1] != 0xffff) {
+ if (!skip_ports_match(tcpinfo->spts[0], tcpinfo->spts[1], inv_srcpt)) {
if (tcpinfo->spts[0] != tcpinfo->spts[1]) {
xt_xlate_add(xl, "tcp sport %s%u-%u",
- tcpinfo->invflags & XT_TCP_INV_SRCPT ?
- "!= " : "",
+ inv_srcpt ? "!= " : "",
tcpinfo->spts[0], tcpinfo->spts[1]);
} else {
xt_xlate_add(xl, "tcp sport %s%u",
- tcpinfo->invflags & XT_TCP_INV_SRCPT ?
- "!= " : "",
+ inv_srcpt ? "!= " : "",
tcpinfo->spts[0]);
}
+ xlated = true;
}
- if (tcpinfo->dpts[0] != 0 || tcpinfo->dpts[1] != 0xffff) {
+ if (!skip_ports_match(tcpinfo->dpts[0], tcpinfo->dpts[1], inv_dstpt)) {
if (tcpinfo->dpts[0] != tcpinfo->dpts[1]) {
xt_xlate_add(xl, "tcp dport %s%u-%u",
- tcpinfo->invflags & XT_TCP_INV_DSTPT ?
- "!= " : "",
+ inv_dstpt ? "!= " : "",
tcpinfo->dpts[0], tcpinfo->dpts[1]);
} else {
xt_xlate_add(xl, "tcp dport %s%u",
- tcpinfo->invflags & XT_TCP_INV_DSTPT ?
- "!= " : "",
+ inv_dstpt ? "!= " : "",
tcpinfo->dpts[0]);
}
+ xlated = true;
}
- if (tcpinfo->option)
+ if (tcpinfo->option) {
xt_xlate_add(xl, "tcp option %u %s", tcpinfo->option,
tcpinfo->invflags & XT_TCP_INV_OPTION ?
"missing" : "exists");
+ xlated = true;
+ }
if (tcpinfo->flg_mask || (tcpinfo->invflags & XT_TCP_INV_FLAGS)) {
xt_xlate_add(xl, "tcp flags %s",
@@ -437,8 +445,12 @@ static int tcp_xlate(struct xt_xlate *xl,
print_tcp_xlate(xl, tcpinfo->flg_cmp);
xt_xlate_add(xl, " / ");
print_tcp_xlate(xl, tcpinfo->flg_mask);
+ xlated = true;
}
+ if (!xlated)
+ xt_xlate_add(xl, "meta l4proto tcp");
+
return 1;
}
diff --git a/extensions/libxt_tcp.t b/extensions/libxt_tcp.t
index 7a3bbd08..75d5b1ed 100644
--- a/extensions/libxt_tcp.t
+++ b/extensions/libxt_tcp.t
@@ -6,6 +6,18 @@
-p tcp -m tcp --sport 1:1023;=;OK
-p tcp -m tcp --sport 1024:65535;=;OK
-p tcp -m tcp --sport 1024:;-p tcp -m tcp --sport 1024:65535;OK
+-p tcp -m tcp --sport :;-p tcp -m tcp;OK
+-p tcp -m tcp ! --sport :;-p tcp -m tcp ! --sport 0:65535;OK
+-p tcp -m tcp --sport :4;-p tcp -m tcp --sport 0:4;OK
+-p tcp -m tcp --sport 4:;-p tcp -m tcp --sport 4:65535;OK
+-p tcp -m tcp --sport 4:4;-p tcp -m tcp --sport 4;OK
+-p tcp -m tcp --sport 4:3;;FAIL
+-p tcp -m tcp --dport :;-p tcp -m tcp;OK
+-p tcp -m tcp ! --dport :;-p tcp -m tcp ! --dport 0:65535;OK
+-p tcp -m tcp --dport :4;-p tcp -m tcp --dport 0:4;OK
+-p tcp -m tcp --dport 4:;-p tcp -m tcp --dport 4:65535;OK
+-p tcp -m tcp --dport 4:4;-p tcp -m tcp --dport 4;OK
+-p tcp -m tcp --dport 4:3;;FAIL
-p tcp -m tcp ! --sport 1;=;OK
-p tcp -m tcp ! --sport 65535;=;OK
-p tcp -m tcp ! --dport 1;=;OK
diff --git a/extensions/libxt_tcp.txlate b/extensions/libxt_tcp.txlate
index 9802ddfe..b3ddcc15 100644
--- a/extensions/libxt_tcp.txlate
+++ b/extensions/libxt_tcp.txlate
@@ -30,3 +30,9 @@ nft 'add rule ip filter INPUT tcp option 23 exists counter'
iptables-translate -A INPUT -p tcp ! --tcp-option 23
nft 'add rule ip filter INPUT tcp option 23 missing counter'
+
+iptables-translate -I OUTPUT -p tcp --sport 0:65535 -j ACCEPT
+nft 'insert rule ip filter OUTPUT meta l4proto tcp counter accept'
+
+iptables-translate -I OUTPUT -p tcp ! --sport 0:65535 -j ACCEPT
+nft 'insert rule ip filter OUTPUT tcp sport != 0-65535 counter accept'
diff --git a/extensions/libxt_tcpmss.t b/extensions/libxt_tcpmss.t
index 2b415957..d0fb52fa 100644
--- a/extensions/libxt_tcpmss.t
+++ b/extensions/libxt_tcpmss.t
@@ -1,6 +1,10 @@
:INPUT,FORWARD,OUTPUT
-m tcpmss --mss 42;;FAIL
-p tcp -m tcpmss --mss 42;=;OK
+-p tcp -m tcpmss --mss :;-p tcp -m tcpmss --mss 0:65535;OK
+-p tcp -m tcpmss --mss :42;-p tcp -m tcpmss --mss 0:42;OK
+-p tcp -m tcpmss --mss 42:;-p tcp -m tcpmss --mss 42:65535;OK
+-p tcp -m tcpmss --mss 42:42;-p tcp -m tcpmss --mss 42;OK
-p tcp -m tcpmss --mss 42:12345;=;OK
-p tcp -m tcpmss --mss 42:65536;;FAIL
-p tcp -m tcpmss --mss 65535:1000;;FAIL
diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man
index 4c0cae06..5b749a48 100644
--- a/extensions/libxt_time.man
+++ b/extensions/libxt_time.man
@@ -58,7 +58,7 @@ rest of the system uses).
The caveat with the kernel timezone is that Linux distributions may ignore to
set the kernel timezone, and instead only set the system time. Even if a
particular distribution does set the timezone at boot, it is usually does not
-keep the kernel timezone offset - which is what changes on DST - up to date.
+keep the kernel timezone offset \(em which is what changes on DST \(em up to date.
ntpd will not touch the kernel timezone, so running it will not resolve the
issue. As such, one may encounter a timezone that is always +0000, or one that
is wrong half of the time of the year. As such, \fBusing \-\-kerneltz is highly
diff --git a/extensions/libxt_u32.man b/extensions/libxt_u32.man
index 40a69f8e..183a63f7 100644
--- a/extensions/libxt_u32.man
+++ b/extensions/libxt_u32.man
@@ -69,13 +69,13 @@ Example:
.IP
match IP packets with total length >= 256
.IP
-The IP header contains a total length field in bytes 2-3.
+The IP header contains a total length field in bytes 2\(en3.
.IP
\-\-u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fP"
.IP
-read bytes 0-3
+read bytes 0\(en3
.IP
-AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range
+AND that with 0xFFFF (giving bytes 2\(en3), and test whether that is in the range
[0x100:0xFFFF]
.PP
Example: (more realistic, hence more complicated)
@@ -86,7 +86,7 @@ First test that it is an ICMP packet, true iff byte 9 (protocol) = 1
.IP
\-\-u32 "\fB6 & 0xFF = 1 &&\fP ...
.IP
-read bytes 6-9, use \fB&\fP to throw away bytes 6-8 and compare the result to
+read bytes 6\(en9, use \fB&\fP to throw away bytes 6\(en8 and compare the result to
1. Next test that it is not a fragment. (If so, it might be part of such a
packet but we cannot always tell.) N.B.: This test is generally needed if you
want to match anything beyond the IP header. The last 6 bits of byte 6 and all
@@ -101,11 +101,11 @@ stored in the right half of byte 0 of the IP header itself.
.IP
... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fP"
.IP
-The first 0 means read bytes 0-3, \fB>>22\fP means shift that 22 bits to the
+The first 0 means read bytes 0\(en3, \fB>>22\fP means shift that 22 bits to the
right. Shifting 24 bits would give the first byte, so only 22 bits is four
times that plus a few more bits. \fB&3C\fP then eliminates the two extra bits
on the right and the first four bits of the first byte. For instance, if IHL=5,
-then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in
+then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0\(en1 are (in
binary) xxxx0101 yyzzzzzz, \fB>>22\fP gives the 10 bit value xxxx0101yy and
\fB&3C\fP gives 010100. \fB@\fP means to use this number as a new offset into
the packet, and read four bytes starting from there. This is the first 4 bytes
@@ -115,7 +115,7 @@ the result with 0.
.PP
Example:
.IP
-TCP payload bytes 8-12 is any of 1, 2, 5 or 8
+TCP payload bytes 8\(en12 is any of 1, 2, 5 or 8
.IP
First we test that the packet is a tcp packet (similar to ICMP).
.IP
@@ -130,5 +130,5 @@ makes this the new offset into the packet, which is the start of the TCP
header. The length of the TCP header (again in 32 bit words) is the left half
of byte 12 of the TCP header. The \fB12>>26&3C\fP computes this length in bytes
(similar to the IP header before). "@" makes this the new offset, which is the
-start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and
+start of the TCP payload. Finally, 8 reads bytes 8\(en12 of the payload and
\fB=\fP checks whether the result is any of 1, 2, 5 or 8.
diff --git a/extensions/libxt_udp.c b/extensions/libxt_udp.c
index ba1c3eb7..748d4180 100644
--- a/extensions/libxt_udp.c
+++ b/extensions/libxt_udp.c
@@ -82,13 +82,18 @@ print_port(uint16_t port, int numeric)
printf("%s", service);
}
+static bool skip_ports_match(uint16_t min, uint16_t max, bool inv)
+{
+ return min == 0 && max == UINT16_MAX && !inv;
+}
+
static void
print_ports(const char *name, uint16_t min, uint16_t max,
int invert, int numeric)
{
const char *inv = invert ? "!" : "";
- if (min != 0 || max != 0xFFFF || invert) {
+ if (!skip_ports_match(min, max, invert)) {
printf(" %s", name);
if (min == max) {
printf(":%s", inv);
@@ -122,10 +127,11 @@ udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
static void udp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
+ bool inv_srcpt = udpinfo->invflags & XT_UDP_INV_SRCPT;
+ bool inv_dstpt = udpinfo->invflags & XT_UDP_INV_DSTPT;
- if (udpinfo->spts[0] != 0
- || udpinfo->spts[1] != 0xFFFF) {
- if (udpinfo->invflags & XT_UDP_INV_SRCPT)
+ if (!skip_ports_match(udpinfo->spts[0], udpinfo->spts[1], inv_srcpt)) {
+ if (inv_srcpt)
printf(" !");
if (udpinfo->spts[0]
!= udpinfo->spts[1])
@@ -137,9 +143,8 @@ static void udp_save(const void *ip, const struct xt_entry_match *match)
udpinfo->spts[0]);
}
- if (udpinfo->dpts[0] != 0
- || udpinfo->dpts[1] != 0xFFFF) {
- if (udpinfo->invflags & XT_UDP_INV_DSTPT)
+ if (!skip_ports_match(udpinfo->dpts[0], udpinfo->dpts[1], inv_dstpt)) {
+ if (inv_dstpt)
printf(" !");
if (udpinfo->dpts[0]
!= udpinfo->dpts[1])
@@ -156,35 +161,39 @@ static int udp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_udp *udpinfo = (struct xt_udp *)params->match->data;
+ bool inv_srcpt = udpinfo->invflags & XT_UDP_INV_SRCPT;
+ bool inv_dstpt = udpinfo->invflags & XT_UDP_INV_DSTPT;
+ bool xlated = false;
- if (udpinfo->spts[0] != 0 || udpinfo->spts[1] != 0xFFFF) {
+ if (!skip_ports_match(udpinfo->spts[0], udpinfo->spts[1], inv_srcpt)) {
if (udpinfo->spts[0] != udpinfo->spts[1]) {
xt_xlate_add(xl,"udp sport %s%u-%u",
- udpinfo->invflags & XT_UDP_INV_SRCPT ?
- "!= ": "",
+ inv_srcpt ? "!= ": "",
udpinfo->spts[0], udpinfo->spts[1]);
} else {
xt_xlate_add(xl, "udp sport %s%u",
- udpinfo->invflags & XT_UDP_INV_SRCPT ?
- "!= ": "",
+ inv_srcpt ? "!= ": "",
udpinfo->spts[0]);
}
+ xlated = true;
}
- if (udpinfo->dpts[0] != 0 || udpinfo->dpts[1] != 0xFFFF) {
+ if (!skip_ports_match(udpinfo->dpts[0], udpinfo->dpts[1], inv_dstpt)) {
if (udpinfo->dpts[0] != udpinfo->dpts[1]) {
xt_xlate_add(xl,"udp dport %s%u-%u",
- udpinfo->invflags & XT_UDP_INV_SRCPT ?
- "!= ": "",
+ inv_dstpt ? "!= ": "",
udpinfo->dpts[0], udpinfo->dpts[1]);
} else {
xt_xlate_add(xl,"udp dport %s%u",
- udpinfo->invflags & XT_UDP_INV_SRCPT ?
- "!= ": "",
+ inv_dstpt ? "!= ": "",
udpinfo->dpts[0]);
}
+ xlated = true;
}
+ if (!xlated)
+ xt_xlate_add(xl, "meta l4proto udp");
+
return 1;
}
diff --git a/extensions/libxt_udp.t b/extensions/libxt_udp.t
index f5347701..6a2c9d07 100644
--- a/extensions/libxt_udp.t
+++ b/extensions/libxt_udp.t
@@ -6,6 +6,18 @@
-p udp -m udp --sport 1:1023;=;OK
-p udp -m udp --sport 1024:65535;=;OK
-p udp -m udp --sport 1024:;-p udp -m udp --sport 1024:65535;OK
+-p udp -m udp --sport :;-p udp -m udp;OK
+-p udp -m udp ! --sport :;-p udp -m udp ! --sport 0:65535;OK
+-p udp -m udp --sport :4;-p udp -m udp --sport 0:4;OK
+-p udp -m udp --sport 4:;-p udp -m udp --sport 4:65535;OK
+-p udp -m udp --sport 4:4;-p udp -m udp --sport 4;OK
+-p udp -m udp --sport 4:3;;FAIL
+-p udp -m udp --dport :;-p udp -m udp;OK
+-p udp -m udp ! --dport :;-p udp -m udp ! --dport 0:65535;OK
+-p udp -m udp --dport :4;-p udp -m udp --dport 0:4;OK
+-p udp -m udp --dport 4:;-p udp -m udp --dport 4:65535;OK
+-p udp -m udp --dport 4:4;-p udp -m udp --dport 4;OK
+-p udp -m udp --dport 4:3;;FAIL
-p udp -m udp ! --sport 1;=;OK
-p udp -m udp ! --sport 65535;=;OK
-p udp -m udp ! --dport 1;=;OK
diff --git a/extensions/libxt_udp.txlate b/extensions/libxt_udp.txlate
index 28e7ca20..d6bbb96f 100644
--- a/extensions/libxt_udp.txlate
+++ b/extensions/libxt_udp.txlate
@@ -9,3 +9,9 @@ nft 'insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accep
iptables-translate -I OUTPUT -p udp --dport 1020:1023 --sport 53 -j ACCEPT
nft 'insert rule ip filter OUTPUT udp sport 53 udp dport 1020-1023 counter accept'
+
+iptables-translate -I OUTPUT -p udp --sport 0:65535 -j ACCEPT
+nft 'insert rule ip filter OUTPUT meta l4proto udp counter accept'
+
+iptables-translate -I OUTPUT -p udp ! --sport 0:65535 -j ACCEPT
+nft 'insert rule ip filter OUTPUT udp sport != 0-65535 counter accept'