aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2020-01-23 18:45:42 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-01-23 18:45:42 +0000
commit1c8a667d69c01c38bbd20877da9ae003f358e7df (patch)
tree362b9c3f4002a826623c6e1c5aed22117f71a838
parentc70f7ac0238cbe801ba4ce7148a1bb2d8d9ade36 (diff)
parent1197ed225c226c6d735af09d2cbd119e41610d69 (diff)
downloadiptables-1c8a667d69c01c38bbd20877da9ae003f358e7df.tar.gz
Merge changes from topic "b143044679"
* changes: iptables 1.6.2 - make it build Merge tag 'v1.6.2' of git://git.netfilter.org/iptables
-rw-r--r--.gitignore4
-rw-r--r--README.version2
-rw-r--r--config.h6
-rw-r--r--configure.ac10
-rw-r--r--extensions/GNUmakefile.in2
-rw-r--r--extensions/generic.txlate5
-rw-r--r--extensions/libebt_limit.c2
-rw-r--r--extensions/libebt_log.c6
-rw-r--r--extensions/libebt_mark.c2
-rw-r--r--extensions/libebt_mark_m.c2
-rw-r--r--extensions/libebt_nflog.c2
-rw-r--r--extensions/libip6t_DNAT.c12
-rw-r--r--extensions/libip6t_DNAT.t3
-rw-r--r--extensions/libip6t_DNAT.txlate11
-rw-r--r--extensions/libip6t_LOG.txlate8
-rw-r--r--extensions/libip6t_MASQUERADE.c19
-rw-r--r--extensions/libip6t_MASQUERADE.t1
-rw-r--r--extensions/libip6t_MASQUERADE.txlate8
-rw-r--r--extensions/libip6t_REDIRECT.txlate5
-rw-r--r--extensions/libip6t_REJECT.txlate8
-rw-r--r--extensions/libip6t_SNAT.c8
-rw-r--r--extensions/libip6t_SNAT.t3
-rw-r--r--extensions/libip6t_SNAT.txlate11
-rw-r--r--extensions/libip6t_ah.txlate17
-rw-r--r--extensions/libip6t_frag.txlate17
-rw-r--r--extensions/libip6t_hbh.txlate5
-rw-r--r--extensions/libip6t_hl.txlate5
-rw-r--r--extensions/libip6t_icmp6.c2
-rw-r--r--extensions/libip6t_icmp6.txlate8
-rw-r--r--extensions/libip6t_mh.txlate5
-rw-r--r--extensions/libip6t_rt.txlate14
-rw-r--r--extensions/libip6t_srh.c242
-rw-r--r--extensions/libip6t_srh.t26
-rw-r--r--extensions/libipt_DNAT.t3
-rw-r--r--extensions/libipt_DNAT.txlate14
-rw-r--r--extensions/libipt_LOG.txlate5
-rw-r--r--extensions/libipt_MASQUERADE.c15
-rw-r--r--extensions/libipt_MASQUERADE.t1
-rw-r--r--extensions/libipt_MASQUERADE.txlate8
-rw-r--r--extensions/libipt_REDIRECT.txlate5
-rw-r--r--extensions/libipt_REJECT.txlate8
-rw-r--r--extensions/libipt_SNAT.t3
-rw-r--r--extensions/libipt_SNAT.txlate14
-rw-r--r--extensions/libipt_ah.txlate8
-rw-r--r--extensions/libipt_icmp.txlate8
-rw-r--r--extensions/libipt_realm.txlate11
-rw-r--r--extensions/libipt_ttl.txlate5
-rw-r--r--extensions/libxt_CLASSIFY.txlate8
-rw-r--r--extensions/libxt_CONNMARK.txlate23
-rw-r--r--extensions/libxt_DSCP.txlate5
-rw-r--r--extensions/libxt_MARK.c2
-rw-r--r--extensions/libxt_MARK.txlate23
-rw-r--r--extensions/libxt_MASQUERADE.man6
-rw-r--r--extensions/libxt_NFLOG.txlate14
-rw-r--r--extensions/libxt_NFQUEUE.txlate8
-rw-r--r--extensions/libxt_TCPMSS.c14
-rw-r--r--extensions/libxt_TCPMSS.txlate5
-rw-r--r--extensions/libxt_TEE.txlate11
-rw-r--r--extensions/libxt_TOS.c26
-rw-r--r--extensions/libxt_TOS.txlate23
-rw-r--r--extensions/libxt_TRACE.txlate2
-rw-r--r--extensions/libxt_addrtype.c70
-rw-r--r--extensions/libxt_addrtype.txlate11
-rw-r--r--extensions/libxt_cgroup.txlate5
-rw-r--r--extensions/libxt_cluster.c51
-rw-r--r--extensions/libxt_cluster.txlate26
-rw-r--r--extensions/libxt_comment.txlate8
-rw-r--r--extensions/libxt_connbytes.txlate14
-rw-r--r--extensions/libxt_connlabel.txlate5
-rw-r--r--extensions/libxt_connmark.txlate14
-rw-r--r--extensions/libxt_conntrack.txlate41
-rw-r--r--extensions/libxt_cpu.txlate5
-rw-r--r--extensions/libxt_dccp.txlate14
-rw-r--r--extensions/libxt_devgroup.txlate17
-rw-r--r--extensions/libxt_dscp.txlate5
-rw-r--r--extensions/libxt_ecn.txlate23
-rw-r--r--extensions/libxt_esp.txlate11
-rw-r--r--extensions/libxt_hashlimit.c638
-rw-r--r--extensions/libxt_hashlimit.man8
-rw-r--r--extensions/libxt_hashlimit.t5
-rw-r--r--extensions/libxt_hashlimit.txlate5
-rw-r--r--extensions/libxt_helper.txlate5
-rw-r--r--extensions/libxt_ipcomp.t5
-rw-r--r--extensions/libxt_ipcomp.txlate5
-rw-r--r--extensions/libxt_iprange.txlate14
-rw-r--r--extensions/libxt_length.txlate11
-rw-r--r--extensions/libxt_limit.c1
-rw-r--r--extensions/libxt_limit.txlate8
-rw-r--r--extensions/libxt_mac.txlate5
-rw-r--r--extensions/libxt_mark.txlate5
-rw-r--r--extensions/libxt_multiport.txlate11
-rw-r--r--extensions/libxt_owner.txlate8
-rw-r--r--extensions/libxt_pkttype.txlate8
-rw-r--r--extensions/libxt_policy.c27
-rw-r--r--extensions/libxt_policy.txlate5
-rw-r--r--extensions/libxt_quota.txlate5
-rw-r--r--extensions/libxt_recent.c4
-rw-r--r--extensions/libxt_rpfilter.txlate8
-rw-r--r--extensions/libxt_sctp.c2
-rw-r--r--extensions/libxt_sctp.t9
-rw-r--r--extensions/libxt_sctp.txlate38
-rw-r--r--extensions/libxt_statistic.txlate8
-rw-r--r--extensions/libxt_tcp.txlate20
-rw-r--r--extensions/libxt_tcpmss.c6
-rw-r--r--extensions/libxt_tcpmss.man2
-rw-r--r--extensions/libxt_tcpmss.t1
-rw-r--r--extensions/libxt_udp.txlate11
-rw-r--r--include/iptables/internal.h2
-rw-r--r--include/linux/netfilter/xt_hashlimit.h36
-rw-r--r--include/linux/netfilter_ipv6/ip6t_srh.h56
-rw-r--r--include/xtables-version.h4
-rw-r--r--iptables/ip6tables-restore.c37
-rw-r--r--iptables/ip6tables-save.c28
-rw-r--r--iptables/iptables-restore.8.in28
-rw-r--r--iptables/iptables-restore.c34
-rw-r--r--iptables/iptables-save.8.in14
-rw-r--r--iptables/iptables-save.c28
-rw-r--r--iptables/iptables-standalone.c3
-rw-r--r--iptables/iptables-xml.c27
-rw-r--r--iptables/iptables.c3
-rw-r--r--iptables/nft-ipv4.c4
-rw-r--r--iptables/nft-ipv6.c4
-rw-r--r--iptables/nft.c20
-rw-r--r--iptables/xshared.c2
-rw-r--r--iptables/xtables-arp.c2
-rw-r--r--iptables/xtables-restore.c27
-rw-r--r--iptables/xtables-save.c26
-rw-r--r--iptables/xtables-standalone.c3
-rw-r--r--iptables/xtables-translate.c31
-rw-r--r--iptables/xtables.c2
-rw-r--r--libiptc/libiptc.c14
-rw-r--r--libxtables/xtables.c74
-rw-r--r--utils/.gitignore1
-rw-r--r--utils/Makefile.am4
-rw-r--r--utils/nfnl_osf.8.in67
-rw-r--r--utils/nfnl_osf.c2
-rw-r--r--utils/nfsynproxy.c1
-rw-r--r--utils/pf.os5
-rwxr-xr-xxlate-test.py104
139 files changed, 2439 insertions, 221 deletions
diff --git a/.gitignore b/.gitignore
index 80eeb987..f5ffafb8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,7 @@ Makefile.in
/configure
/libtool
/stamp-h1
+/iptables/iptables-apply.8
+
+/iptables/xtables-multi
+/iptables/xtables-compat-multi
diff --git a/README.version b/README.version
index 74c158a5..f8bff18b 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
URL: git://git.netfilter.org/iptables
-Version: 1.6.1
+Version: 1.6.2
BugComponent: 31808
diff --git a/config.h b/config.h
index 7bff59c2..21ae69c9 100644
--- a/config.h
+++ b/config.h
@@ -63,7 +63,7 @@
#define PACKAGE_NAME "iptables"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "iptables 1.6.1"
+#define PACKAGE_STRING "iptables 1.6.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "iptables"
@@ -72,7 +72,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.6.1"
+#define PACKAGE_VERSION "1.6.2"
/* The size of `struct ip6_hdr', as computed by sizeof. */
#define SIZEOF_STRUCT_IP6_HDR 40
@@ -81,7 +81,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "1.6.1"
+#define VERSION "1.6.2"
/* Location of the iptables lock file */
#define XT_LOCK_NAME "/system/etc/xtables.lock"
diff --git a/configure.ac b/configure.ac
index 221812a8..b814ef08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_INIT([iptables], [1.6.1])
+AC_INIT([iptables], [1.6.2])
# See libtool.info "Libtool's versioning system"
libxtables_vcurrent=12
@@ -42,8 +42,9 @@ AC_ARG_ENABLE([ipv6],
AC_ARG_ENABLE([largefile],
AS_HELP_STRING([--disable-largefile], [Do not build largefile support]),
[enable_largefile="$enableval"],
- [enable_largefile="yes";
- largefile_cppflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
+ [enable_largefile="yes"])
+AS_IF([test "$enable_largefile" = "yes"], [largefile_cppflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
+
AC_ARG_ENABLE([devel],
AS_HELP_STRING([--enable-devel],
[Install Xtables development headers]),
@@ -248,7 +249,8 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
libiptc/Makefile libiptc/libiptc.pc
libiptc/libip4tc.pc libiptc/libip6tc.pc
libxtables/Makefile utils/Makefile
- include/xtables-version.h include/iptables/internal.h])
+ include/xtables-version.h include/iptables/internal.h
+ utils/nfnl_osf.8])
AC_OUTPUT
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index b7a8a836..bee666e8 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -101,7 +101,7 @@ init%.o: init%.c
# Shared libraries
#
lib%.so: lib%.oo
- ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD};
+ ${AM_VERBOSE_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 $<;
diff --git a/extensions/generic.txlate b/extensions/generic.txlate
new file mode 100644
index 00000000..1140bb89
--- /dev/null
+++ b/extensions/generic.txlate
@@ -0,0 +1,5 @@
+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
+
+iptables-translate -F -t nat
+nft flush table ip nat
diff --git a/extensions/libebt_limit.c b/extensions/libebt_limit.c
index 6b9bb16f..988f678a 100644
--- a/extensions/libebt_limit.c
+++ b/extensions/libebt_limit.c
@@ -29,7 +29,7 @@
#define ARG_LIMIT '1'
#define ARG_LIMIT_BURST '2'
-static struct option brlimit_opts[] =
+static const struct option brlimit_opts[] =
{
{ .name = "limit", .has_arg = true, .val = ARG_LIMIT },
{ .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST },
diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
index 0799185d..f170af03 100644
--- a/extensions/libebt_log.c
+++ b/extensions/libebt_log.c
@@ -27,12 +27,12 @@
#define LOG_LOG '5'
#define LOG_IP6 '6'
-typedef struct _code {
+struct code {
char *c_name;
int c_val;
-} CODE;
+};
-static CODE eight_priority[] = {
+static struct code eight_priority[] = {
{ "emerg", LOG_EMERG },
{ "alert", LOG_ALERT },
{ "crit", LOG_CRIT },
diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c
index a1a208c3..7b80b22e 100644
--- a/extensions/libebt_mark.c
+++ b/extensions/libebt_mark.c
@@ -25,7 +25,7 @@ static int mark_supplied;
#define MARK_ORMARK '3'
#define MARK_ANDMARK '4'
#define MARK_XORMARK '5'
-static struct option brmark_opts[] = {
+static const struct option brmark_opts[] = {
{ .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
/* an oldtime messup, we should have always used the scheme
* <extension-name>-<option> */
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index ab9d2344..eb08dbab 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -18,7 +18,7 @@
#define MARK '1'
-static struct option brmark_m_opts[] = {
+static const struct option brmark_m_opts[] = {
{ .name = "mark", .has_arg = true, .val = MARK },
XT_GETOPT_TABLEEND,
};
diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c
index fef71960..5f1d13b1 100644
--- a/extensions/libebt_nflog.c
+++ b/extensions/libebt_nflog.c
@@ -30,7 +30,7 @@ enum {
NFLOG_NFLOG = 0x16,
};
-static struct option brnflog_opts[] = {
+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},
diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c
index 08d920db..8e478b21 100644
--- a/extensions/libip6t_DNAT.c
+++ b/extensions/libip6t_DNAT.c
@@ -163,13 +163,11 @@ static void DNAT_parse(struct xt_option_call *cb)
switch (cb->entry->id) {
case O_TO_DEST:
if (cb->xflags & F_X_TO_DEST) {
- if (!kernel_version)
- get_kernel_version();
- if (kernel_version > LINUX_VERSION(2, 6, 10))
- xtables_error(PARAMETER_PROBLEM,
- "DNAT: Multiple --to-destination not supported");
+ xtables_error(PARAMETER_PROBLEM,
+ "DNAT: Multiple --to-destination not supported");
}
parse_to(cb->arg, portok, range);
+ cb->xflags |= F_X_TO_DEST;
break;
case O_PERSISTENT:
range->flags |= NF_NAT_RANGE_PERSISTENT;
@@ -281,7 +279,7 @@ static int DNAT_xlate(struct xt_xlate *xl,
return 1;
}
-static struct xtables_target snat_tg_reg = {
+static struct xtables_target dnat_tg_reg = {
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV6,
@@ -299,5 +297,5 @@ static struct xtables_target snat_tg_reg = {
void _init(void)
{
- xtables_register_target(&snat_tg_reg);
+ xtables_register_target(&dnat_tg_reg);
}
diff --git a/extensions/libip6t_DNAT.t b/extensions/libip6t_DNAT.t
index 3141c299..6d8f1dab 100644
--- a/extensions/libip6t_DNAT.t
+++ b/extensions/libip6t_DNAT.t
@@ -2,7 +2,10 @@
*nat
-j DNAT --to-destination dead::beef;=;OK
-j DNAT --to-destination dead::beef-dead::fee7;=;OK
+-j DNAT --to-destination [dead::beef]:1025-65535;;FAIL
+-j DNAT --to-destination [dead::beef] --to-destination [dead::fee7];;FAIL
-p tcp -j DNAT --to-destination [dead::beef]:1025-65535;=;OK
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535;=;OK
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65536;;FAIL
+-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535 --to-destination [dead::beef-dead::fee8]:1025-65535;;FAIL
-j DNAT;;FAIL
diff --git a/extensions/libip6t_DNAT.txlate b/extensions/libip6t_DNAT.txlate
new file mode 100644
index 00000000..fe26075d
--- /dev/null
+++ b/extensions/libip6t_DNAT.txlate
@@ -0,0 +1,11 @@
+ip6tables-translate -t nat -A prerouting -i eth1 -p tcp --dport 8080 -j DNAT --to-destination [fec0::1234]:80
+nft add rule ip6 nat prerouting iifname eth1 tcp dport 8080 counter dnat to [fec0::1234]:80
+
+ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:1-20
+nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:1-20
+
+ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --persistent
+nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 persistent
+
+ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --random --persistent
+nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 random,persistent
diff --git a/extensions/libip6t_LOG.txlate b/extensions/libip6t_LOG.txlate
new file mode 100644
index 00000000..2820a82c
--- /dev/null
+++ b/extensions/libip6t_LOG.txlate
@@ -0,0 +1,8 @@
+iptables-translate -I INPUT -j LOG
+nft insert rule ip filter INPUT counter log
+
+ip6tables-translate -A FORWARD -p tcp -j LOG --log-level debug
+nft add rule ip6 filter FORWARD meta l4proto tcp counter log level debug
+
+ip6tables-translate -A FORWARD -p tcp -j LOG --log-prefix "Checking log"
+nft add rule ip6 filter FORWARD meta l4proto tcp counter log prefix \"Checking log\"
diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c
index 3b59e43e..f92760fa 100644
--- a/extensions/libip6t_MASQUERADE.c
+++ b/extensions/libip6t_MASQUERADE.c
@@ -18,6 +18,7 @@
enum {
O_TO_PORTS = 0,
O_RANDOM,
+ O_RANDOM_FULLY,
};
static void MASQUERADE_help(void)
@@ -27,12 +28,15 @@ static void MASQUERADE_help(void)
" --to-ports <port>[-<port>]\n"
" Port (range) to map to.\n"
" --random\n"
-" Randomize source port.\n");
+" Randomize source port.\n"
+" --random-fully\n"
+" Fully randomize source port.\n");
}
static const struct xt_option_entry MASQUERADE_opts[] = {
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
@@ -96,6 +100,9 @@ static void MASQUERADE_parse(struct xt_option_call *cb)
case O_RANDOM:
r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
+ case O_RANDOM_FULLY:
+ r->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+ break;
}
}
@@ -114,6 +121,9 @@ MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ printf(" random-fully");
}
static void
@@ -129,6 +139,9 @@ MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ printf(" --random-fully");
}
static int MASQUERADE_xlate(struct xt_xlate *xl,
@@ -148,6 +161,10 @@ static int MASQUERADE_xlate(struct xt_xlate *xl,
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
xt_xlate_add(xl, "random ");
+ xt_xlate_add(xl, " ");
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ xt_xlate_add(xl, "random-fully ");
+
return 1;
}
diff --git a/extensions/libip6t_MASQUERADE.t b/extensions/libip6t_MASQUERADE.t
index 46502040..e25d2a04 100644
--- a/extensions/libip6t_MASQUERADE.t
+++ b/extensions/libip6t_MASQUERADE.t
@@ -2,6 +2,7 @@
*nat
-j MASQUERADE;=;OK
-j MASQUERADE --random;=;OK
+-j MASQUERADE --random-fully;=;OK
-p tcp -j MASQUERADE --to-ports 1024;=;OK
-p udp -j MASQUERADE --to-ports 1024-65535;=;OK
-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL
diff --git a/extensions/libip6t_MASQUERADE.txlate b/extensions/libip6t_MASQUERADE.txlate
new file mode 100644
index 00000000..6c289c2b
--- /dev/null
+++ b/extensions/libip6t_MASQUERADE.txlate
@@ -0,0 +1,8 @@
+ip6tables-translate -t nat -A POSTROUTING -j MASQUERADE
+nft add rule ip6 nat POSTROUTING counter masquerade
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
+nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
+nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random
diff --git a/extensions/libip6t_REDIRECT.txlate b/extensions/libip6t_REDIRECT.txlate
new file mode 100644
index 00000000..209f67a4
--- /dev/null
+++ b/extensions/libip6t_REDIRECT.txlate
@@ -0,0 +1,5 @@
+ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080
+nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080
+
+ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
+nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080 random
diff --git a/extensions/libip6t_REJECT.txlate b/extensions/libip6t_REJECT.txlate
new file mode 100644
index 00000000..cfa35ebf
--- /dev/null
+++ b/extensions/libip6t_REJECT.txlate
@@ -0,0 +1,8 @@
+ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT
+nft add rule ip6 filter FORWARD tcp dport 22 counter reject
+
+ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp6-reject-route
+nft add rule ip6 filter FORWARD tcp dport 22 counter reject with icmpv6 type reject-route
+
+ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
+nft add rule ip6 filter FORWARD tcp dport 22 counter reject with tcp reset
diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
index 671ac61a..7d74b3d7 100644
--- a/extensions/libip6t_SNAT.c
+++ b/extensions/libip6t_SNAT.c
@@ -166,13 +166,11 @@ static void SNAT_parse(struct xt_option_call *cb)
switch (cb->entry->id) {
case O_TO_SRC:
if (cb->xflags & F_X_TO_SRC) {
- if (!kernel_version)
- get_kernel_version();
- if (kernel_version > LINUX_VERSION(2, 6, 10))
- xtables_error(PARAMETER_PROBLEM,
- "SNAT: Multiple --to-source not supported");
+ xtables_error(PARAMETER_PROBLEM,
+ "SNAT: Multiple --to-source not supported");
}
parse_to(cb->arg, portok, range);
+ cb->xflags |= F_X_TO_SRC;
break;
case O_PERSISTENT:
range->flags |= NF_NAT_RANGE_PERSISTENT;
diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t
index bb080497..d188a6bb 100644
--- a/extensions/libip6t_SNAT.t
+++ b/extensions/libip6t_SNAT.t
@@ -2,7 +2,10 @@
*nat
-j SNAT --to-source dead::beef;=;OK
-j SNAT --to-source dead::beef-dead::fee7;=;OK
+-j SNAT --to-source [dead::beef]:1025-65535;;FAIL
+-j SNAT --to-source [dead::beef] --to-source [dead::fee7];;FAIL
-p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL
+-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535 --to-source [dead::beef-dead::fee8]:1025-65535;;FAIL
-j SNAT;;FAIL
diff --git a/extensions/libip6t_SNAT.txlate b/extensions/libip6t_SNAT.txlate
new file mode 100644
index 00000000..9793f8d5
--- /dev/null
+++ b/extensions/libip6t_SNAT.txlate
@@ -0,0 +1,11 @@
+ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:80
+nft add rule ip6 nat postrouting oifname eth0 meta l4proto tcp counter snat to [fec0::1234]:80
+
+ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:1-20
+nft add rule ip6 nat postrouting oifname eth0 meta l4proto tcp counter snat to [fec0::1234]:1-20
+
+ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random
+nft add rule ip6 nat postrouting oifname eth0 meta l4proto tcp counter snat to [fec0::1234]:123 random
+
+ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random-fully --persistent
+nft add rule ip6 nat postrouting oifname eth0 meta l4proto tcp counter snat to [fec0::1234]:123 fully-random,persistent
diff --git a/extensions/libip6t_ah.txlate b/extensions/libip6t_ah.txlate
new file mode 100644
index 00000000..c6b09a2e
--- /dev/null
+++ b/extensions/libip6t_ah.txlate
@@ -0,0 +1,17 @@
+ip6tables-translate -A INPUT -m ah --ahspi 500 -j DROP
+nft add rule ip6 filter INPUT ah spi 500 counter drop
+
+ip6tables-translate -A INPUT -m ah --ahspi 500:550 -j DROP
+nft add rule ip6 filter INPUT ah spi 500-550 counter drop
+
+ip6tables-translate -A INPUT -m ah ! --ahlen 120
+nft add rule ip6 filter INPUT ah hdrlength != 120 counter
+
+ip6tables-translate -A INPUT -m ah --ahres
+nft add rule ip6 filter INPUT ah reserved 1 counter
+
+ip6tables-translate -A INPUT -m ah --ahspi 500 ! --ahlen 120 -j DROP
+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
diff --git a/extensions/libip6t_frag.txlate b/extensions/libip6t_frag.txlate
new file mode 100644
index 00000000..e8bd9d4b
--- /dev/null
+++ b/extensions/libip6t_frag.txlate
@@ -0,0 +1,17 @@
+ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 -j ACCEPT
+nft add rule ip6 filter INPUT frag id 100-200 counter accept
+
+ip6tables-translate -t filter -A INPUT -m frag --fragid 100 --fragres --fragmore -j ACCEPT
+nft add rule ip6 filter INPUT frag id 100 frag reserved 1 frag more-fragments 1 counter accept
+
+ip6tables-translate -t filter -A INPUT -m frag ! --fragid 100:200 -j ACCEPT
+nft add rule ip6 filter INPUT frag id != 100-200 counter accept
+
+ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fraglast -j ACCEPT
+nft add rule ip6 filter INPUT frag id 100-200 frag more-fragments 0 counter accept
+
+ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fragfirst -j ACCEPT
+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
diff --git a/extensions/libip6t_hbh.txlate b/extensions/libip6t_hbh.txlate
new file mode 100644
index 00000000..28101fd7
--- /dev/null
+++ b/extensions/libip6t_hbh.txlate
@@ -0,0 +1,5 @@
+ip6tables-translate -t filter -A INPUT -m hbh --hbh-len 22
+nft add rule ip6 filter INPUT hbh hdrlength 22 counter
+
+ip6tables-translate -t filter -A INPUT -m hbh ! --hbh-len 22
+nft add rule ip6 filter INPUT hbh hdrlength != 22 counter
diff --git a/extensions/libip6t_hl.txlate b/extensions/libip6t_hl.txlate
new file mode 100644
index 00000000..17563938
--- /dev/null
+++ b/extensions/libip6t_hl.txlate
@@ -0,0 +1,5 @@
+ip6tables-translate -t nat -A postrouting -m hl --hl-gt 3
+nft add rule ip6 nat postrouting ip6 hoplimit gt 3 counter
+
+ip6tables-translate -t nat -A postrouting -m hl ! --hl-eq 3
+nft add rule ip6 nat postrouting ip6 hoplimit != 3 counter
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index b49a241d..37c2bcb8 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -282,8 +282,6 @@ static int icmp6_xlate(struct xt_xlate *xl,
if (!type_xlate_print(xl, info->type, info->code[0], info->code[1]))
return 0;
- xt_xlate_add(xl, " ");
-
return 1;
}
diff --git a/extensions/libip6t_icmp6.txlate b/extensions/libip6t_icmp6.txlate
new file mode 100644
index 00000000..15481ad6
--- /dev/null
+++ b/extensions/libip6t_icmp6.txlate
@@ -0,0 +1,8 @@
+ip6tables-translate -t filter -A INPUT -m icmp6 --icmpv6-type 1 -j LOG
+nft add rule ip6 filter INPUT icmpv6 type destination-unreachable counter log
+
+ip6tables-translate -t filter -A INPUT -m icmp6 --icmpv6-type neighbour-advertisement -j LOG
+nft add rule ip6 filter INPUT icmpv6 type nd-neighbor-advert counter log
+
+ip6tables-translate -t filter -A INPUT -m icmp6 ! --icmpv6-type packet-too-big -j LOG
+nft add rule ip6 filter INPUT icmpv6 type != packet-too-big counter log
diff --git a/extensions/libip6t_mh.txlate b/extensions/libip6t_mh.txlate
new file mode 100644
index 00000000..f5d638c0
--- /dev/null
+++ b/extensions/libip6t_mh.txlate
@@ -0,0 +1,5 @@
+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
+
+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
diff --git a/extensions/libip6t_rt.txlate b/extensions/libip6t_rt.txlate
new file mode 100644
index 00000000..6464cf9e
--- /dev/null
+++ b/extensions/libip6t_rt.txlate
@@ -0,0 +1,14 @@
+ip6tables-translate -A INPUT -m rt --rt-type 0 -j DROP
+nft add rule ip6 filter INPUT rt type 0 counter drop
+
+ip6tables-translate -A INPUT -m rt ! --rt-len 22 -j DROP
+nft add rule ip6 filter INPUT rt hdrlength != 22 counter drop
+
+ip6tables-translate -A INPUT -m rt --rt-segsleft 26 -j ACCEPT
+nft add rule ip6 filter INPUT rt seg-left 26 counter accept
+
+ip6tables-translate -A INPUT -m rt --rt-type 0 --rt-len 22 -j DROP
+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
diff --git a/extensions/libip6t_srh.c b/extensions/libip6t_srh.c
new file mode 100644
index 00000000..ac0ae084
--- /dev/null
+++ b/extensions/libip6t_srh.c
@@ -0,0 +1,242 @@
+/* Shared library to add Segment Routing Header (SRH) matching support.
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ */
+
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6t_srh.h>
+#include <string.h>
+
+/* srh command-line options */
+enum {
+ O_SRH_NEXTHDR,
+ O_SRH_LEN_EQ,
+ O_SRH_LEN_GT,
+ O_SRH_LEN_LT,
+ O_SRH_SEGS_EQ,
+ O_SRH_SEGS_GT,
+ O_SRH_SEGS_LT,
+ O_SRH_LAST_EQ,
+ O_SRH_LAST_GT,
+ O_SRH_LAST_LT,
+ O_SRH_TAG,
+};
+
+static void srh_help(void)
+{
+ printf(
+"srh match options:\n"
+"[!] --srh-next-hdr next-hdr Next Header value of SRH\n"
+"[!] --srh-hdr-len-eq hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-hdr-len-gt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-hdr-len-lt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-segs-left-eq segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-left-gt segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-left-lt segs_left Segments Left value of SRH\n"
+"[!] --srh-last-entry-eq last_entry Last Entry value of SRH\n"
+"[!] --srh-last-entry-gt last_entry Last Entry value of SRH\n"
+"[!] --srh-last-entry-lt last_entry Last Entry value of SRH\n"
+"[!] --srh-tag tag Tag value of SRH\n");
+}
+
+#define s struct ip6t_srh
+static const struct xt_option_entry srh_opts[] = {
+ { .name = "srh-next-hdr", .id = O_SRH_NEXTHDR, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, next_hdr)},
+ { .name = "srh-hdr-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-hdr-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-hdr-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-segs-left-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-left-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-left-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-last-entry-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-entry-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-entry-lt", .id = O_SRH_LAST_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-tag", .id = O_SRH_TAG, .type = XTTYPE_UINT16,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, tag)},
+ { }
+};
+#undef s
+
+static void srh_init(struct xt_entry_match *m)
+{
+ struct ip6t_srh *srhinfo = (void *)m->data;
+
+ srhinfo->mt_flags = 0;
+ srhinfo->mt_invflags = 0;
+}
+
+static void srh_parse(struct xt_option_call *cb)
+{
+ struct ip6t_srh *srhinfo = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRH_NEXTHDR:
+ srhinfo->mt_flags |= IP6T_SRH_NEXTHDR;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_NEXTHDR;
+ break;
+ case O_SRH_LEN_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_EQ;
+ break;
+ case O_SRH_LEN_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_GT;
+ break;
+ case O_SRH_LEN_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_LT;
+ break;
+ case O_SRH_SEGS_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_EQ;
+ break;
+ case O_SRH_SEGS_GT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_GT;
+ break;
+ case O_SRH_SEGS_LT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_LT;
+ break;
+ case O_SRH_LAST_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_EQ;
+ break;
+ case O_SRH_LAST_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_GT;
+ break;
+ case O_SRH_LAST_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_LT;
+ break;
+ case O_SRH_TAG:
+ srhinfo->mt_flags |= IP6T_SRH_TAG;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_TAG;
+ break;
+ }
+}
+
+static void srh_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ printf(" srh");
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf(" next-hdr:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR ? "!" : "",
+ srhinfo->next_hdr);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf(" hdr-len-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf(" hdr-len-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf(" hdr-len-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf(" segs-left-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf(" segs-left-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf(" segs-left-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf(" last-entry-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf(" last-entry-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf(" last-entry-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf(" tag:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_TAG ? "!" : "",
+ srhinfo->tag);
+}
+
+static void srh_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf("%s --srh-next-hdr %u", (srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR) ? " !" : "",
+ srhinfo->next_hdr);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf("%s --srh-hdr-len-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf("%s --srh-hdr-len-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf("%s --srh-hdr-len-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf("%s --srh-segs-left-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf("%s --srh-segs-left-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf("%s --srh-segs-left-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf("%s --srh-last-entry-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf("%s --srh-last-entry-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf("%s --srh-last-entry-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf("%s --srh-tag %u", (srhinfo->mt_invflags & IP6T_SRH_INV_TAG) ? " !" : "",
+ srhinfo->tag);
+}
+
+static struct xtables_match srh_mt6_reg = {
+ .name = "srh",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .help = srh_help,
+ .init = srh_init,
+ .print = srh_print,
+ .save = srh_save,
+ .x6_parse = srh_parse,
+ .x6_options = srh_opts,
+};
+
+void
+_init(void)
+{
+ xtables_register_match(&srh_mt6_reg);
+}
diff --git a/extensions/libip6t_srh.t b/extensions/libip6t_srh.t
new file mode 100644
index 00000000..08897d5c
--- /dev/null
+++ b/extensions/libip6t_srh.t
@@ -0,0 +1,26 @@
+:INPUT,FORWARD,OUTPUT
+-m srh --srh-next-hdr 17;=;OK
+-m srh --srh-hdr-len-eq 8;=;OK
+-m srh --srh-hdr-len-gt 8;=;OK
+-m srh --srh-hdr-len-lt 8;=;OK
+-m srh --srh-segs-left-eq 1;=;OK
+-m srh --srh-segs-left-gt 1;=;OK
+-m srh --srh-segs-left-lt 1;=;OK
+-m srh --srh-last-entry-eq 4;=;OK
+-m srh --srh-last-entry-gt 4;=;OK
+-m srh --srh-last-entry-lt 4;=;OK
+-m srh --srh-tag 0;=;OK
+-m srh ! --srh-next-hdr 17;=;OK
+-m srh ! --srh-hdr-len-eq 8;=;OK
+-m srh ! --srh-hdr-len-gt 8;=;OK
+-m srh ! --srh-hdr-len-lt 8;=;OK
+-m srh ! --srh-segs-left-eq 1;=;OK
+-m srh ! --srh-segs-left-gt 1;=;OK
+-m srh ! --srh-segs-left-lt 1;=;OK
+-m srh ! --srh-last-entry-eq 4;=;OK
+-m srh ! --srh-last-entry-gt 4;=;OK
+-m srh ! --srh-last-entry-lt 4;=;OK
+-m srh ! --srh-tag 0;=;OK
+-m srh --srh-next-hdr 17 --srh-segs-left-eq 1 --srh-last-entry-eq 4 --srh-tag 0;=;OK
+-m srh ! --srh-next-hdr 17 ! --srh-segs-left-eq 0 --srh-tag 0;=;OK
+-m srh;=;OK
diff --git a/extensions/libipt_DNAT.t b/extensions/libipt_DNAT.t
index e3fd5632..1959801d 100644
--- a/extensions/libipt_DNAT.t
+++ b/extensions/libipt_DNAT.t
@@ -2,7 +2,10 @@
*nat
-j DNAT --to-destination 1.1.1.1;=;OK
-j DNAT --to-destination 1.1.1.1-1.1.1.10;=;OK
+-j DNAT --to-destination 1.1.1.1:1025-65535;;FAIL
+-j DNAT --to-destination 1.1.1.1 --to-destination 2.2.2.2;;FAIL
-p tcp -j DNAT --to-destination 1.1.1.1:1025-65535;=;OK
-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65535;=;OK
-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65536;;FAIL
+-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65535 --to-destination 2.2.2.2-2.2.2.20:1025-65535;;FAIL
-j DNAT;;FAIL
diff --git a/extensions/libipt_DNAT.txlate b/extensions/libipt_DNAT.txlate
new file mode 100644
index 00000000..692358e2
--- /dev/null
+++ b/extensions/libipt_DNAT.txlate
@@ -0,0 +1,14 @@
+iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4
+nft add rule ip nat prerouting oifname eth0 ip protocol tcp counter dnat to 1.2.3.4
+
+iptables-translate -t nat -A prerouting -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10
+nft add rule ip nat prerouting ip daddr 15.45.23.67 tcp dport 80 counter dnat to 192.168.1.1-192.168.1.10
+
+iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4:1-1023
+nft add rule ip nat prerouting oifname eth0 ip protocol tcp counter dnat to 1.2.3.4:1-1023
+
+iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4 --random
+nft add rule ip nat prerouting oifname eth0 ip protocol tcp counter dnat to 1.2.3.4 random
+
+iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4 --random --persistent
+nft add rule ip nat prerouting oifname eth0 ip protocol tcp counter dnat to 1.2.3.4 random,persistent
diff --git a/extensions/libipt_LOG.txlate b/extensions/libipt_LOG.txlate
new file mode 100644
index 00000000..81f64fb2
--- /dev/null
+++ b/extensions/libipt_LOG.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A FORWARD -p tcp -j LOG --log-level error
+nft add rule ip filter FORWARD ip protocol tcp counter log level err
+
+iptables-translate -A FORWARD -p tcp -j LOG --log-prefix "Random prefix"
+nft add rule ip filter FORWARD ip protocol tcp counter log prefix \"Random prefix\"
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
index b7b5fc74..90bf6065 100644
--- a/extensions/libipt_MASQUERADE.c
+++ b/extensions/libipt_MASQUERADE.c
@@ -11,6 +11,7 @@
enum {
O_TO_PORTS = 0,
O_RANDOM,
+ O_RANDOM_FULLY,
};
static void MASQUERADE_help(void)
@@ -20,12 +21,15 @@ static void MASQUERADE_help(void)
" --to-ports <port>[-<port>]\n"
" Port (range) to map to.\n"
" --random\n"
-" Randomize source port.\n");
+" Randomize source port.\n"
+" --random-fully\n"
+" Fully randomize source port.\n");
}
static const struct xt_option_entry MASQUERADE_opts[] = {
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
@@ -97,6 +101,9 @@ static void MASQUERADE_parse(struct xt_option_call *cb)
case O_RANDOM:
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
+ case O_RANDOM_FULLY:
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+ break;
}
}
@@ -116,6 +123,9 @@ MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ printf(" random-fully");
}
static void
@@ -132,6 +142,9 @@ MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ printf(" --random-fully");
}
static int MASQUERADE_xlate(struct xt_xlate *xl,
diff --git a/extensions/libipt_MASQUERADE.t b/extensions/libipt_MASQUERADE.t
index 46502040..e25d2a04 100644
--- a/extensions/libipt_MASQUERADE.t
+++ b/extensions/libipt_MASQUERADE.t
@@ -2,6 +2,7 @@
*nat
-j MASQUERADE;=;OK
-j MASQUERADE --random;=;OK
+-j MASQUERADE --random-fully;=;OK
-p tcp -j MASQUERADE --to-ports 1024;=;OK
-p udp -j MASQUERADE --to-ports 1024-65535;=;OK
-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL
diff --git a/extensions/libipt_MASQUERADE.txlate b/extensions/libipt_MASQUERADE.txlate
new file mode 100644
index 00000000..40b6958a
--- /dev/null
+++ b/extensions/libipt_MASQUERADE.txlate
@@ -0,0 +1,8 @@
+iptables-translate -t nat -A POSTROUTING -j MASQUERADE
+nft add rule ip nat POSTROUTING counter masquerade
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
+nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
+nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10-20 random
diff --git a/extensions/libipt_REDIRECT.txlate b/extensions/libipt_REDIRECT.txlate
new file mode 100644
index 00000000..815bb771
--- /dev/null
+++ b/extensions/libipt_REDIRECT.txlate
@@ -0,0 +1,5 @@
+iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080
+nft add rule ip nat prerouting tcp dport 80 counter redirect to :8080
+
+iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
+nft add rule ip nat prerouting tcp dport 80 counter redirect to :8080 random
diff --git a/extensions/libipt_REJECT.txlate b/extensions/libipt_REJECT.txlate
new file mode 100644
index 00000000..a1bfb5f4
--- /dev/null
+++ b/extensions/libipt_REJECT.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT
+nft add rule ip filter FORWARD tcp dport 22 counter reject
+
+iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp-net-unreachable
+nft add rule ip filter FORWARD tcp dport 22 counter reject with icmp type net-unreachable
+
+iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
+nft add rule ip filter FORWARD tcp dport 22 counter reject with tcp reset
diff --git a/extensions/libipt_SNAT.t b/extensions/libipt_SNAT.t
index 73071bb0..186e1cb8 100644
--- a/extensions/libipt_SNAT.t
+++ b/extensions/libipt_SNAT.t
@@ -2,7 +2,10 @@
*nat
-j SNAT --to-source 1.1.1.1;=;OK
-j SNAT --to-source 1.1.1.1-1.1.1.10;=;OK
+-j SNAT --to-source 1.1.1.1:1025-65535;;FAIL
+-j SNAT --to-source 1.1.1.1 --to-source 2.2.2.2;;FAIL
-p tcp -j SNAT --to-source 1.1.1.1:1025-65535;=;OK
-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535;=;OK
-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65536;;FAIL
+-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535 --to-source 2.2.2.2-2.2.2.20:1025-65535;;FAIL
-j SNAT;;FAIL
diff --git a/extensions/libipt_SNAT.txlate b/extensions/libipt_SNAT.txlate
new file mode 100644
index 00000000..4efd3ad0
--- /dev/null
+++ b/extensions/libipt_SNAT.txlate
@@ -0,0 +1,14 @@
+iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4
+nft add rule ip nat postrouting oifname eth0 counter snat to 1.2.3.4
+
+iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6
+nft add rule ip nat postrouting oifname eth0 counter snat to 1.2.3.4-1.2.3.6
+
+iptables-translate -t nat -A postrouting -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023
+nft add rule ip nat postrouting oifname eth0 ip protocol tcp counter snat to 1.2.3.4:1-1023
+
+iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4 --random
+nft add rule ip nat postrouting oifname eth0 counter snat to 1.2.3.4 random
+
+iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4 --random --persistent
+nft add rule ip nat postrouting oifname eth0 counter snat to 1.2.3.4 random,persistent
diff --git a/extensions/libipt_ah.txlate b/extensions/libipt_ah.txlate
new file mode 100644
index 00000000..ea3ef3e9
--- /dev/null
+++ b/extensions/libipt_ah.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A INPUT -p 51 -m ah --ahspi 500 -j DROP
+nft add rule ip filter INPUT ah spi 500 counter drop
+
+iptables-translate -A INPUT -p 51 -m ah --ahspi 500:600 -j DROP
+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
diff --git a/extensions/libipt_icmp.txlate b/extensions/libipt_icmp.txlate
new file mode 100644
index 00000000..434f8cc4
--- /dev/null
+++ b/extensions/libipt_icmp.txlate
@@ -0,0 +1,8 @@
+iptables-translate -t filter -A INPUT -m icmp --icmp-type echo-reply -j ACCEPT
+nft add rule ip filter INPUT icmp type echo-reply counter accept
+
+iptables-translate -t filter -A INPUT -m icmp --icmp-type 3 -j ACCEPT
+nft add rule ip filter INPUT icmp type destination-unreachable counter accept
+
+iptables-translate -t filter -A INPUT -m icmp ! --icmp-type 3 -j ACCEPT
+nft add rule ip filter INPUT icmp type != destination-unreachable counter accept
diff --git a/extensions/libipt_realm.txlate b/extensions/libipt_realm.txlate
new file mode 100644
index 00000000..7d710294
--- /dev/null
+++ b/extensions/libipt_realm.txlate
@@ -0,0 +1,11 @@
+iptables-translate -A PREROUTING -m realm --realm 4
+nft add rule ip filter PREROUTING rtclassid 0x4 counter
+
+iptables-translate -A PREROUTING -m realm --realm 5/5
+nft add rule ip filter PREROUTING rtclassid and 0x5 == 0x5 counter
+
+iptables-translate -A PREROUTING -m realm ! --realm 50
+nft add rule ip filter PREROUTING rtclassid != 0x32 counter
+
+iptables-translate -A INPUT -m realm --realm 1/0xf
+nft add rule ip filter INPUT rtclassid and 0xf == 0x1 counter
diff --git a/extensions/libipt_ttl.txlate b/extensions/libipt_ttl.txlate
new file mode 100644
index 00000000..3d5d6a70
--- /dev/null
+++ b/extensions/libipt_ttl.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A INPUT -m ttl --ttl-eq 3 -j ACCEPT
+nft add rule ip filter INPUT ip ttl 3 counter accept
+
+iptables-translate -A INPUT -m ttl --ttl-gt 5 -j ACCEPT
+nft add rule ip filter INPUT ip ttl gt 5 counter accept
diff --git a/extensions/libxt_CLASSIFY.txlate b/extensions/libxt_CLASSIFY.txlate
new file mode 100644
index 00000000..3b349237
--- /dev/null
+++ b/extensions/libxt_CLASSIFY.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A OUTPUT -j CLASSIFY --set-class 0:0
+nft add rule ip filter OUTPUT counter meta priority set none
+
+iptables-translate -A OUTPUT -j CLASSIFY --set-class ffff:ffff
+nft add rule ip filter OUTPUT counter meta priority set root
+
+iptables-translate -A OUTPUT -j CLASSIFY --set-class 1:234
+nft add rule ip filter OUTPUT counter meta priority set 1:234
diff --git a/extensions/libxt_CONNMARK.txlate b/extensions/libxt_CONNMARK.txlate
new file mode 100644
index 00000000..62321be1
--- /dev/null
+++ b/extensions/libxt_CONNMARK.txlate
@@ -0,0 +1,23 @@
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-mark 0x16
+nft add rule ip mangle PREROUTING counter ct mark set 0x16
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-xmark 0x16/0x12
+nft add rule ip mangle PREROUTING counter ct mark set ct mark xor 0x16 and 0xffffffed
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --and-mark 0x16
+nft add rule ip mangle PREROUTING counter ct mark set ct mark and 0x16
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --or-mark 0x16
+nft add rule ip mangle PREROUTING counter ct mark set ct mark or 0x16
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --save-mark
+nft add rule ip mangle PREROUTING counter ct mark set mark
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --save-mark --mask 0x12
+nft add rule ip mangle PREROUTING counter ct mark set mark and 0x12
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --restore-mark
+nft add rule ip mangle PREROUTING counter meta mark set ct mark
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --restore-mark --mask 0x12
+nft add rule ip mangle PREROUTING counter meta mark set ct mark and 0x12
diff --git a/extensions/libxt_DSCP.txlate b/extensions/libxt_DSCP.txlate
new file mode 100644
index 00000000..442742ef
--- /dev/null
+++ b/extensions/libxt_DSCP.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A OUTPUT -j DSCP --set-dscp 1
+nft add rule ip filter OUTPUT counter ip dscp set 0x01
+
+ip6tables-translate -A OUTPUT -j DSCP --set-dscp 6
+nft add rule ip6 filter OUTPUT counter ip6 dscp set 0x06
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index c2f15e3b..12b1695e 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -76,7 +76,7 @@ static void mark_tg_help(void)
" --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n"
" --and-mark bits Binary AND the nfmark with bits\n"
" --or-mark bits Binary OR the nfmark with bits\n"
-" --xor-mask bits Binary XOR the nfmark with bits\n"
+" --xor-mark bits Binary XOR the nfmark with bits\n"
"\n");
}
diff --git a/extensions/libxt_MARK.txlate b/extensions/libxt_MARK.txlate
new file mode 100644
index 00000000..ab5977e9
--- /dev/null
+++ b/extensions/libxt_MARK.txlate
@@ -0,0 +1,23 @@
+iptables-translate -t mangle -A OUTPUT -j MARK --set-mark 64
+nft add rule ip mangle OUTPUT counter meta mark set 0x40
+
+iptables-translate -t mangle -A OUTPUT -j MARK --set-xmark 0x40/0x32
+nft add rule ip mangle OUTPUT counter meta mark set mark and 0xffffffcd xor 0x40
+
+iptables-translate -t mangle -A OUTPUT -j MARK --or-mark 64
+nft add rule ip mangle OUTPUT counter meta mark set mark or 0x40
+
+iptables-translate -t mangle -A OUTPUT -j MARK --and-mark 64
+nft add rule ip mangle OUTPUT counter meta mark set mark and 0x40
+
+iptables-translate -t mangle -A OUTPUT -j MARK --xor-mark 64
+nft add rule ip mangle OUTPUT counter meta mark set mark xor 0x40
+
+iptables-translate -t mangle -A PREROUTING -j MARK --set-mark 0x64
+nft add rule ip mangle PREROUTING counter meta mark set 0x64
+
+iptables-translate -t mangle -A PREROUTING -j MARK --and-mark 0x64
+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
diff --git a/extensions/libxt_MASQUERADE.man b/extensions/libxt_MASQUERADE.man
index c9e39501..cc1e7690 100644
--- a/extensions/libxt_MASQUERADE.man
+++ b/extensions/libxt_MASQUERADE.man
@@ -25,4 +25,10 @@ If option
\fB\-\-random\fP
is used then port mapping will be randomized (kernel >= 2.6.21).
.TP
+\fB\-\-random-fully\fP
+Full randomize source port mapping
+If option
+\fB\-\-random-fully\fP
+is used then port mapping will be fully randomized (kernel >= 3.13).
+.TP
IPv6 support available since Linux kernels >= 3.7.
diff --git a/extensions/libxt_NFLOG.txlate b/extensions/libxt_NFLOG.txlate
new file mode 100644
index 00000000..a0872c9e
--- /dev/null
+++ b/extensions/libxt_NFLOG.txlate
@@ -0,0 +1,14 @@
+iptables-translate -A FORWARD -j NFLOG --nflog-group 32 --nflog-prefix "Prefix 1.0"
+nft add rule ip filter FORWARD counter log prefix \"Prefix 1.0\" group 32
+
+iptables-translate -A OUTPUT -j NFLOG --nflog-group 30
+nft add rule ip filter OUTPUT counter log group 30
+
+iptables-translate -I INPUT -j NFLOG --nflog-threshold 2
+nft insert rule ip filter INPUT counter log queue-threshold 2 group 0
+
+iptables-translate -I INPUT -j NFLOG --nflog-size 256
+nft insert rule ip filter INPUT counter log snaplen 256 group 0
+
+iptables-translate -I INPUT -j NFLOG --nflog-threshold 25
+nft insert rule ip filter INPUT counter log queue-threshold 25 group 0
diff --git a/extensions/libxt_NFQUEUE.txlate b/extensions/libxt_NFQUEUE.txlate
new file mode 100644
index 00000000..3d188a7a
--- /dev/null
+++ b/extensions/libxt_NFQUEUE.txlate
@@ -0,0 +1,8 @@
+iptables-translate -t nat -A PREROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 30
+nft add rule ip nat PREROUTING tcp dport 80 counter queue num 30
+
+iptables-translate -A FORWARD -j NFQUEUE --queue-num 0 --queue-bypass -p TCP --sport 80
+nft add rule ip filter FORWARD tcp sport 80 counter queue num 0 bypass
+
+iptables-translate -A FORWARD -j NFQUEUE --queue-bypass -p TCP --sport 80 --queue-balance 0:3 --queue-cpu-fanout
+nft add rule ip filter FORWARD tcp sport 80 counter queue num 0-3 bypass,fanout
diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c
index 4b71e44a..0d9b200e 100644
--- a/extensions/libxt_TCPMSS.c
+++ b/extensions/libxt_TCPMSS.c
@@ -91,6 +91,19 @@ static void TCPMSS_save(const void *ip, const struct xt_entry_target *target)
printf(" --set-mss %u", mssinfo->mss);
}
+static int TCPMSS_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct xt_tcpmss_info *mssinfo =
+ (const struct xt_tcpmss_info *)params->target->data;
+ if (mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
+ xt_xlate_add(xl, "tcp option maxseg size set rt mtu");
+ else
+ xt_xlate_add(xl, "tcp option maxseg size set %d", mssinfo->mss);
+
+ return 1;
+}
+
static struct xtables_target tcpmss_tg_reg[] = {
{
.family = NFPROTO_IPV4,
@@ -104,6 +117,7 @@ static struct xtables_target tcpmss_tg_reg[] = {
.x6_parse = TCPMSS_parse,
.x6_fcheck = TCPMSS_check,
.x6_options = TCPMSS4_opts,
+ .xlate = TCPMSS_xlate,
},
{
.family = NFPROTO_IPV6,
diff --git a/extensions/libxt_TCPMSS.txlate b/extensions/libxt_TCPMSS.txlate
new file mode 100644
index 00000000..6a64d2ce
--- /dev/null
+++ b/extensions/libxt_TCPMSS.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
+nft add rule ip filter FORWARD tcp flags & (syn|rst) == syn counter tcp option maxseg size set rt mtu
+
+iptables-translate -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 90
+nft add rule ip filter FORWARD tcp flags & (syn|rst) == syn counter tcp option maxseg size set 90
diff --git a/extensions/libxt_TEE.txlate b/extensions/libxt_TEE.txlate
new file mode 100644
index 00000000..9fcee254
--- /dev/null
+++ b/extensions/libxt_TEE.txlate
@@ -0,0 +1,11 @@
+# iptables-translate -t mangle -A PREROUTING -j TEE --gateway 192.168.0.2 --oif eth0
+# nft add rule ip mangle PREROUTING counter dup to 192.168.0.2 device eth0
+#
+# iptables-translate -t mangle -A PREROUTING -j TEE --gateway 192.168.0.2
+# nft add rule ip mangle PREROUTING counter dup to 192.168.0.2
+
+ip6tables-translate -t mangle -A PREROUTING -j TEE --gateway ab12:00a1:1112:acba::
+nft add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba::
+
+ip6tables-translate -t mangle -A PREROUTING -j TEE --gateway ab12:00a1:1112:acba:: --oif eth0
+nft add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba:: device eth0
diff --git a/extensions/libxt_TOS.c b/extensions/libxt_TOS.c
index cef58765..b66fa329 100644
--- a/extensions/libxt_TOS.c
+++ b/extensions/libxt_TOS.c
@@ -183,6 +183,30 @@ static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
printf(" --set-tos 0x%02x/0x%02x", info->tos_value, info->tos_mask);
}
+static int tos_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct ipt_tos_target_info *info =
+ (struct ipt_tos_target_info *) params->target->data;
+ uint8_t dscp = info->tos >> 2;
+
+ xt_xlate_add(xl, "ip dscp set 0x%02x", dscp);
+
+ return 1;
+}
+
+static int tos_xlate6(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct ipt_tos_target_info *info =
+ (struct ipt_tos_target_info *) params->target->data;
+ uint8_t dscp = info->tos >> 2;
+
+ xt_xlate_add(xl, "ip6 dscp set 0x%02x", dscp);
+
+ return 1;
+}
+
static struct xtables_target tos_tg_reg[] = {
{
.version = XTABLES_VERSION,
@@ -197,6 +221,7 @@ static struct xtables_target tos_tg_reg[] = {
.x6_parse = tos_tg_parse_v0,
.x6_fcheck = tos_tg_check,
.x6_options = tos_tg_opts_v0,
+ .xlate = tos_xlate,
},
{
.version = XTABLES_VERSION,
@@ -211,6 +236,7 @@ static struct xtables_target tos_tg_reg[] = {
.x6_parse = tos_tg_parse,
.x6_fcheck = tos_tg_check,
.x6_options = tos_tg_opts,
+ .xlate = tos_xlate6,
},
};
diff --git a/extensions/libxt_TOS.txlate b/extensions/libxt_TOS.txlate
new file mode 100644
index 00000000..0952310e
--- /dev/null
+++ b/extensions/libxt_TOS.txlate
@@ -0,0 +1,23 @@
+ip6tables-translate -A INPUT -j TOS --set-tos 0x1f
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x07
+
+ip6tables-translate -A INPUT -j TOS --set-tos 0xff
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x3f
+
+ip6tables-translate -A INPUT -j TOS --set-tos Minimize-Delay
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
+
+ip6tables-translate -A INPUT -j TOS --set-tos Minimize-Cost
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+
+ip6tables-translate -A INPUT -j TOS --set-tos Normal-Service
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+
+ip6tables-translate -A INPUT -j TOS --and-tos 0x12
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+
+ip6tables-translate -A INPUT -j TOS --or-tos 0x12
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
+
+ip6tables-translate -A INPUT -j TOS --xor-tos 0x12
+nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
diff --git a/extensions/libxt_TRACE.txlate b/extensions/libxt_TRACE.txlate
new file mode 100644
index 00000000..8e3d2a7a
--- /dev/null
+++ b/extensions/libxt_TRACE.txlate
@@ -0,0 +1,2 @@
+iptables-translate -t raw -A PREROUTING -j TRACE
+nft add rule ip raw PREROUTING counter nftrace set 1
diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c
index e5d3033c..5cafa219 100644
--- a/extensions/libxt_addrtype.c
+++ b/extensions/libxt_addrtype.c
@@ -5,6 +5,7 @@
* This program is released under the terms of GNU GPL */
#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <xtables.h>
#include <linux/netfilter/xt_addrtype.h>
@@ -245,6 +246,74 @@ static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
printf(" --limit-iface-out");
}
+static const char *const rtn_lnames[] = {
+ "unspec",
+ "unicast",
+ "local",
+ "broadcast",
+ "anycast",
+ "multicast",
+ "blackhole",
+ "unreachable",
+ "prohibit",
+ NULL,
+};
+
+static bool multiple_bits_set(uint16_t val)
+{
+ int first = ffs(val);
+
+ return first && (val >> first) > 0;
+}
+
+static int addrtype_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_addrtype_info_v1 *info =
+ (const void *)params->match->data;
+ const char *sep = "";
+ bool need_braces;
+ uint16_t val;
+ int i;
+
+ xt_xlate_add(xl, "fib ");
+
+ if (info->source) {
+ xt_xlate_add(xl, "saddr ");
+ val = info->source;
+ } else {
+ xt_xlate_add(xl, "daddr ");
+ val = info->dest;
+ }
+
+ if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
+ xt_xlate_add(xl, ". iif ");
+ else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
+ xt_xlate_add(xl, ". oif ");
+
+ xt_xlate_add(xl, "type ");
+
+ if (info->flags & (XT_ADDRTYPE_INVERT_SOURCE | XT_ADDRTYPE_INVERT_DEST))
+ xt_xlate_add(xl, "!= ");
+
+ need_braces = multiple_bits_set(val);
+
+ if (need_braces)
+ xt_xlate_add(xl, "{ ");
+
+ for (i = 0; rtn_lnames[i]; i++) {
+ if (val & (1 << i)) {
+ xt_xlate_add(xl, "%s%s", sep, rtn_lnames[i]);
+ sep = ", ";
+ }
+ }
+
+ if (need_braces)
+ xt_xlate_add(xl, " }");
+
+ return 1;
+}
+
static const struct xt_option_entry addrtype_opts_v0[] = {
{.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING,
.flags = XTOPT_INVERT},
@@ -292,6 +361,7 @@ static struct xtables_match addrtype_mt_reg[] = {
.x6_parse = addrtype_parse_v1,
.x6_fcheck = addrtype_check,
.x6_options = addrtype_opts_v1,
+ .xlate = addrtype_xlate,
},
};
diff --git a/extensions/libxt_addrtype.txlate b/extensions/libxt_addrtype.txlate
new file mode 100644
index 00000000..a719b2c9
--- /dev/null
+++ b/extensions/libxt_addrtype.txlate
@@ -0,0 +1,11 @@
+iptables-translate -A INPUT -m addrtype --src-type LOCAL
+nft add rule ip filter INPUT fib saddr type local counter
+
+iptables-translate -A INPUT -m addrtype --dst-type LOCAL
+nft add rule ip filter INPUT fib daddr type local counter
+
+iptables-translate -A INPUT -m addrtype ! --dst-type ANYCAST,LOCAL
+nft add rule ip filter INPUT fib daddr type != { local, anycast } counter
+
+iptables-translate -A INPUT -m addrtype --limit-iface-in --dst-type ANYCAST,LOCAL
+nft add rule ip filter INPUT fib daddr . iif type { local, anycast } counter
diff --git a/extensions/libxt_cgroup.txlate b/extensions/libxt_cgroup.txlate
new file mode 100644
index 00000000..75f2e6ae
--- /dev/null
+++ b/extensions/libxt_cgroup.txlate
@@ -0,0 +1,5 @@
+iptables-translate -t filter -A INPUT -m cgroup --cgroup 0 -j ACCEPT
+nft add rule ip filter INPUT meta cgroup 0 counter accept
+
+iptables-translate -t filter -A INPUT -m cgroup ! --cgroup 0 -j ACCEPT
+nft add rule ip filter INPUT meta cgroup != 0 counter accept
diff --git a/extensions/libxt_cluster.c b/extensions/libxt_cluster.c
index 3adff12c..c9c35ee2 100644
--- a/extensions/libxt_cluster.c
+++ b/extensions/libxt_cluster.c
@@ -126,6 +126,56 @@ cluster_save(const void *ip, const struct xt_entry_match *match)
info->total_nodes, info->hash_seed);
}
+static int cluster_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ int node, shift_value = 1, comma_needed = 0;
+ uint32_t temp_node_mask, node_id = 0, needs_set = 0;
+ const struct xt_cluster_match_info *info = (void *)params->match->data;
+ const char *jhash_st = "jhash ct original saddr mod";
+ const char *pkttype_st = "meta pkttype set host";
+
+ if (!(info->node_mask & (info->node_mask - 1))) {
+ if (info->node_mask <= 2)
+ xt_xlate_add(xl, "%s %u seed 0x%08x eq %u %s", jhash_st,
+ info->total_nodes, info->hash_seed,
+ info->node_mask, pkttype_st);
+ else {
+ temp_node_mask = info->node_mask;
+ while (1) {
+ temp_node_mask = temp_node_mask >> shift_value;
+ node_id++;
+ if (temp_node_mask == 0)
+ break;
+ }
+ xt_xlate_add(xl, "%s %u seed 0x%08x eq %u %s", jhash_st,
+ info->total_nodes, info->hash_seed,
+ node_id, pkttype_st);
+ }
+ } else {
+ xt_xlate_add(xl, "%s %u seed 0x%08x ", jhash_st,
+ info->total_nodes, info->hash_seed);
+ for (node = 0; node < 32; node++) {
+ if (info->node_mask & (1 << node)) {
+ if (needs_set == 0) {
+ xt_xlate_add(xl, "{ ");
+ needs_set = 1;
+ }
+
+ if (comma_needed)
+ xt_xlate_add(xl, ", ");
+ xt_xlate_add(xl, "%u", node);
+ comma_needed++;
+ }
+ }
+ if (needs_set)
+ xt_xlate_add(xl, " }");
+ xt_xlate_add(xl, " %s", pkttype_st);
+ }
+
+ return 1;
+}
+
static struct xtables_match cluster_mt_reg = {
.family = NFPROTO_UNSPEC,
.name = "cluster",
@@ -138,6 +188,7 @@ static struct xtables_match cluster_mt_reg = {
.x6_parse = cluster_parse,
.x6_fcheck = cluster_check,
.x6_options = cluster_opts,
+ .xlate = cluster_xlate,
};
void _init(void)
diff --git a/extensions/libxt_cluster.txlate b/extensions/libxt_cluster.txlate
new file mode 100644
index 00000000..a9d3b51a
--- /dev/null
+++ b/extensions/libxt_cluster.txlate
@@ -0,0 +1,26 @@
+iptables-translate -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
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 1 --cluster-local-node 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 2 --cluster-local-nodemask 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 1 --cluster-local-nodemask 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-node 32 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 32 seed 0xdeadbeef eq 32 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-nodemask 32 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 32 seed 0xdeadbeef eq 6 meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-nodemask 5 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 32 seed 0xdeadbeef { 0, 2 } meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 7 --cluster-local-nodemask 9 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 7 seed 0xdeadbeef { 0, 3 } meta pkttype set host counter meta mark set 0xffff
+
+iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 7 --cluster-local-node 5 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
+nft add rule ip mangle PREROUTING iifname eth1 jhash ct original saddr mod 7 seed 0xdeadbeef eq 5 meta pkttype set host counter meta mark set 0xffff
diff --git a/extensions/libxt_comment.txlate b/extensions/libxt_comment.txlate
new file mode 100644
index 00000000..c610b0e5
--- /dev/null
+++ b/extensions/libxt_comment.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A INPUT -s 192.168.0.0 -m comment --comment "A privatized IP block"
+nft add rule ip filter INPUT ip saddr 192.168.0.0 counter comment \"A privatized IP block\"
+
+iptables-translate -A INPUT -p tcp -m tcp --sport http -s 192.168.0.0/16 -d 192.168.0.0/16 -j LONGNACCEPT -m comment --comment "foobar"
+nft add rule ip filter INPUT ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter jump LONGNACCEPT comment \"foobar\"
+
+iptables-translate -A FORWARD -p tcp -m tcp --sport http -s 192.168.0.0/16 -d 192.168.0.0/16 -j DROP -m comment --comment singlecomment
+nft add rule ip filter FORWARD ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter drop comment \"singlecomment\"
diff --git a/extensions/libxt_connbytes.txlate b/extensions/libxt_connbytes.txlate
new file mode 100644
index 00000000..f78958d2
--- /dev/null
+++ b/extensions/libxt_connbytes.txlate
@@ -0,0 +1,14 @@
+iptables-translate -A OUTPUT -m connbytes --connbytes 200 --connbytes-dir original --connbytes-mode packets
+nft add rule ip filter OUTPUT ct original packets ge 200 counter
+
+iptables-translate -A OUTPUT -m connbytes ! --connbytes 200 --connbytes-dir reply --connbytes-mode packets
+nft add rule ip filter OUTPUT ct reply packets lt 200 counter
+
+iptables-translate -A OUTPUT -m connbytes --connbytes 200:600 --connbytes-dir both --connbytes-mode bytes
+nft add rule ip filter OUTPUT ct bytes 200-600 counter
+
+iptables-translate -A OUTPUT -m connbytes ! --connbytes 200:600 --connbytes-dir both --connbytes-mode bytes
+nft add rule ip filter OUTPUT ct bytes != 200-600 counter
+
+iptables-translate -A OUTPUT -m connbytes --connbytes 200:200 --connbytes-dir both --connbytes-mode avgpkt
+nft add rule ip filter OUTPUT ct avgpkt 200 counter
diff --git a/extensions/libxt_connlabel.txlate b/extensions/libxt_connlabel.txlate
new file mode 100644
index 00000000..5be42204
--- /dev/null
+++ b/extensions/libxt_connlabel.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A INPUT -m connlabel --label bit40
+nft add rule ip filter INPUT ct label bit40 counter
+
+iptables-translate -A INPUT -m connlabel ! --label bit40 --set
+nft add rule ip filter INPUT ct label set bit40 ct label and bit40 != bit40 counter
diff --git a/extensions/libxt_connmark.txlate b/extensions/libxt_connmark.txlate
new file mode 100644
index 00000000..89423259
--- /dev/null
+++ b/extensions/libxt_connmark.txlate
@@ -0,0 +1,14 @@
+iptables-translate -A INPUT -m connmark --mark 2 -j ACCEPT
+nft add rule ip filter INPUT ct mark 0x2 counter accept
+
+iptables-translate -A INPUT -m connmark ! --mark 2 -j ACCEPT
+nft add rule ip filter INPUT ct mark != 0x2 counter accept
+
+iptables-translate -A INPUT -m connmark --mark 10/10 -j ACCEPT
+nft add rule ip filter INPUT ct mark and 0xa == 0xa counter accept
+
+iptables-translate -A INPUT -m connmark ! --mark 10/10 -j ACCEPT
+nft add rule ip filter INPUT ct mark and 0xa != 0xa counter accept
+
+iptables-translate -t mangle -A PREROUTING -p tcp --dport 40 -m connmark --mark 0x40
+nft add rule ip mangle PREROUTING tcp dport 40 ct mark 0x40 counter
diff --git a/extensions/libxt_conntrack.txlate b/extensions/libxt_conntrack.txlate
new file mode 100644
index 00000000..e35d5ce8
--- /dev/null
+++ b/extensions/libxt_conntrack.txlate
@@ -0,0 +1,41 @@
+iptables-translate -t filter -A INPUT -m conntrack --ctstate NEW,RELATED -j ACCEPT
+nft add rule ip filter INPUT ct state new,related counter accept
+
+ip6tables-translate -t filter -A INPUT -m conntrack ! --ctstate NEW,RELATED -j ACCEPT
+nft add rule ip6 filter INPUT ct state != new,related counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctproto UDP -j ACCEPT
+nft add rule ip filter INPUT ct original protocol 17 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack ! --ctproto UDP -j ACCEPT
+nft add rule ip filter INPUT ct original protocol != 17 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctorigsrc 10.100.2.131 -j ACCEPT
+nft add rule ip filter INPUT ct original saddr 10.100.2.131 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctorigsrc 10.100.0.0/255.255.0.0 -j ACCEPT
+nft add rule ip filter INPUT ct original saddr 10.100.0.0/16 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctorigdst 10.100.2.131 -j ACCEPT
+nft add rule ip filter INPUT ct original daddr 10.100.2.131 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctreplsrc 10.100.2.131 -j ACCEPT
+nft add rule ip filter INPUT ct reply saddr 10.100.2.131 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctrepldst 10.100.2.131 -j ACCEPT
+nft add rule ip filter INPUT ct reply daddr 10.100.2.131 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctproto tcp --ctorigsrcport 443:444 -j ACCEPT
+nft add rule ip filter INPUT ct original protocol 6 ct original proto-src 443-444 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack ! --ctstatus CONFIRMED -j ACCEPT
+nft add rule ip filter INPUT ct status != confirmed counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctexpire 3 -j ACCEPT
+nft add rule ip filter INPUT ct expiration 3 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctdir ORIGINAL -j ACCEPT
+nft add rule ip filter INPUT ct direction original counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctstate NEW --ctproto tcp --ctorigsrc 192.168.0.1 --ctorigdst 192.168.0.1 --ctreplsrc 192.168.0.1 --ctrepldst 192.168.0.1 --ctorigsrcport 12 --ctorigdstport 14 --ctreplsrcport 16 --ctrepldstport 18 --ctexpire 10 --ctstatus SEEN_REPLY --ctdir ORIGINAL -j ACCEPT
+nft add rule ip filter INPUT ct direction original ct original protocol 6 ct state new ct status seen-reply ct expiration 10 ct original saddr 192.168.0.1 ct original daddr 192.168.0.1 ct reply saddr 192.168.0.1 ct reply daddr 192.168.0.1 ct original proto-src 12 ct original proto-dst 14 ct reply proto-src 16 ct reply proto-dst 18 counter accept
diff --git a/extensions/libxt_cpu.txlate b/extensions/libxt_cpu.txlate
new file mode 100644
index 00000000..c59b0e02
--- /dev/null
+++ b/extensions/libxt_cpu.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A INPUT -p tcp --dport 80 -m cpu --cpu 0 -j ACCEPT
+nft add rule ip filter INPUT tcp dport 80 cpu 0 counter accept
+
+iptables-translate -A INPUT -p tcp --dport 80 -m cpu ! --cpu 1 -j ACCEPT
+nft add rule ip filter INPUT tcp dport 80 cpu != 1 counter accept
diff --git a/extensions/libxt_dccp.txlate b/extensions/libxt_dccp.txlate
new file mode 100644
index 00000000..b47dc65f
--- /dev/null
+++ b/extensions/libxt_dccp.txlate
@@ -0,0 +1,14 @@
+iptables-translate -A INPUT -p dccp -m dccp --sport 100
+nft add rule ip filter INPUT dccp sport 100 counter
+
+iptables-translate -A INPUT -p dccp -m dccp --dport 100:200
+nft add rule ip filter INPUT dccp dport 100-200 counter
+
+iptables-translate -A INPUT -p dccp -m dccp ! --dport 100
+nft add rule ip filter INPUT dccp dport != 100 counter
+
+iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK
+nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack} counter
+
+iptables-translate -A INPUT -p dccp -m dccp --sport 200 --dport 100
+nft add rule ip filter INPUT dccp sport 200 dport 100 counter
diff --git a/extensions/libxt_devgroup.txlate b/extensions/libxt_devgroup.txlate
new file mode 100644
index 00000000..aeb597bd
--- /dev/null
+++ b/extensions/libxt_devgroup.txlate
@@ -0,0 +1,17 @@
+iptables-translate -A FORWARD -m devgroup --src-group 0x2 -j ACCEPT
+nft add rule ip filter FORWARD iifgroup 0x2 counter accept
+
+iptables-translate -A FORWARD -m devgroup --dst-group 0xc/0xc -j ACCEPT
+nft add rule ip filter FORWARD oifgroup and 0xc == 0xc counter accept
+
+iptables-translate -t mangle -A PREROUTING -p tcp --dport 46000 -m devgroup --src-group 23 -j ACCEPT
+nft add rule ip mangle PREROUTING tcp dport 46000 iifgroup 0x17 counter accept
+
+iptables-translate -A FORWARD -m devgroup ! --dst-group 0xc/0xc -j ACCEPT
+nft add rule ip filter FORWARD oifgroup and 0xc != 0xc counter accept
+
+iptables-translate -A FORWARD -m devgroup ! --src-group 0x2 -j ACCEPT
+nft add rule ip filter FORWARD iifgroup != 0x2 counter accept
+
+iptables-translate -A FORWARD -m devgroup ! --src-group 0x2 --dst-group 0xc/0xc -j ACCEPT
+nft add rule ip filter FORWARD iifgroup != 0x2 oifgroup and 0xc != 0xc counter accept
diff --git a/extensions/libxt_dscp.txlate b/extensions/libxt_dscp.txlate
new file mode 100644
index 00000000..2cccc3b4
--- /dev/null
+++ b/extensions/libxt_dscp.txlate
@@ -0,0 +1,5 @@
+iptables-translate -t filter -A INPUT -m dscp --dscp 0x32 -j ACCEPT
+nft add rule ip filter INPUT ip dscp 0x32 counter accept
+
+ip6tables-translate -t filter -A INPUT -m dscp ! --dscp 0x32 -j ACCEPT
+nft add rule ip6 filter INPUT ip6 dscp != 0x32 counter accept
diff --git a/extensions/libxt_ecn.txlate b/extensions/libxt_ecn.txlate
new file mode 100644
index 00000000..9e3bd310
--- /dev/null
+++ b/extensions/libxt_ecn.txlate
@@ -0,0 +1,23 @@
+iptables-translate -A INPUT -m ecn --ecn-ip-ect 0
+nft add rule ip filter INPUT ip ecn not-ect counter
+
+iptables-translate -A INPUT -m ecn --ecn-ip-ect 1
+nft add rule ip filter INPUT ip ecn ect1 counter
+
+iptables-translate -A INPUT -m ecn --ecn-ip-ect 2
+nft add rule ip filter INPUT ip ecn ect0 counter
+
+iptables-translate -A INPUT -m ecn --ecn-ip-ect 3
+nft add rule ip filter INPUT ip ecn ce counter
+
+iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 0
+nft add rule ip filter INPUT ip ecn != not-ect counter
+
+iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 1
+nft add rule ip filter INPUT ip ecn != ect1 counter
+
+iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 2
+nft add rule ip filter INPUT ip ecn != ect0 counter
+
+iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 3
+nft add rule ip filter INPUT ip ecn != ce counter
diff --git a/extensions/libxt_esp.txlate b/extensions/libxt_esp.txlate
new file mode 100644
index 00000000..a67c6f0e
--- /dev/null
+++ b/extensions/libxt_esp.txlate
@@ -0,0 +1,11 @@
+iptables-translate -A FORWARD -p esp -j ACCEPT
+nft add rule ip filter FORWARD ip protocol esp counter accept
+
+iptables-translate -A INPUT --in-interface wan --protocol esp -j ACCEPT
+nft add rule ip filter INPUT iifname wan ip protocol esp counter accept
+
+iptables-translate -A INPUT -p 50 -m esp --espspi 500 -j DROP
+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
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 7a1b37a9..70bc615b 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -7,14 +7,15 @@
* Based on ipt_limit.c by
* Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
* Hervé Eychenne <rv@wallfire.org>
- *
+ *
* Error corections by nmalykh@bilim.com (22.01.2005)
*/
#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
#define _ISOC99_SOURCE 1
+#include <inttypes.h>
#include <math.h>
#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -68,10 +69,13 @@ enum {
O_HTABLE_MAX,
O_HTABLE_GCINT,
O_HTABLE_EXPIRE,
+ O_RATEMATCH,
+ O_INTERVAL,
F_BURST = 1 << O_BURST,
F_UPTO = 1 << O_UPTO,
F_ABOVE = 1 << O_ABOVE,
F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE,
+ F_RATEMATCH = 1 << O_RATEMATCH,
};
static void hashlimit_mt_help(void)
@@ -95,6 +99,29 @@ static void hashlimit_mt_help(void)
"\n", XT_HASHLIMIT_BURST);
}
+static void hashlimit_mt_help_v3(void)
+{
+ printf(
+"hashlimit match options:\n"
+" --hashlimit-upto <avg> max average match rate\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+" --hashlimit-above <avg> min average match rate\n"
+" --hashlimit-mode <mode> mode is a comma-separated list of\n"
+" dstip,srcip,dstport,srcport (or none)\n"
+" --hashlimit-srcmask <length> source address grouping prefix length\n"
+" --hashlimit-dstmask <length> destination address grouping prefix length\n"
+" --hashlimit-name <name> name for /proc/net/ipt_hashlimit\n"
+" --hashlimit-burst <num> number to match in a burst, default %u\n"
+" --hashlimit-htable-size <num> number of hashtable buckets\n"
+" --hashlimit-htable-max <num> number of hashtable entries\n"
+" --hashlimit-htable-gcinterval interval between garbage collection runs\n"
+" --hashlimit-htable-expire after which time are idle entries expired?\n"
+" --hashlimit-rate-match rate match the flow without rate-limiting it\n"
+" --hashlimit-rate-interval interval in seconds for hashlimit-rate-match\n"
+"\n", XT_HASHLIMIT_BURST);
+}
+
#define s struct xt_hashlimit_info
static const struct xt_option_entry hashlimit_opts[] = {
{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
@@ -153,6 +180,35 @@ static const struct xt_option_entry hashlimit_mt_opts_v1[] = {
#undef s
#define s struct xt_hashlimit_mtinfo2
+static const struct xt_option_entry hashlimit_mt_opts_v2[] = {
+ {.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
+ {.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
+ {.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
+ {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
+ {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.size)},
+ {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.max)},
+ {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.gc_interval)},
+ {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.expire)},
+ {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
+ {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+};
+#undef s
+
+#define s struct xt_hashlimit_mtinfo3
static const struct xt_option_entry hashlimit_mt_opts[] = {
{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT},
@@ -178,12 +234,14 @@ static const struct xt_option_entry hashlimit_mt_opts[] = {
{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+ {.name = "hashlimit-rate-match", .id = O_RATEMATCH, .type = XTTYPE_NONE},
+ {.name = "hashlimit-rate-interval", .id = O_INTERVAL, .type = XTTYPE_STRING},
XTOPT_TABLEEND,
};
#undef s
static int
-cfg_copy(struct hashlimit_cfg2 *to, const void *from, int revision)
+cfg_copy(struct hashlimit_cfg3 *to, const void *from, int revision)
{
if (revision == 1) {
struct hashlimit_cfg1 *cfg = (struct hashlimit_cfg1 *)from;
@@ -198,7 +256,19 @@ cfg_copy(struct hashlimit_cfg2 *to, const void *from, int revision)
to->srcmask = cfg->srcmask;
to->dstmask = cfg->dstmask;
} else if (revision == 2) {
- memcpy(to, from, sizeof(struct hashlimit_cfg2));
+ struct hashlimit_cfg2 *cfg = (struct hashlimit_cfg2 *)from;
+
+ to->mode = cfg->mode;
+ to->avg = cfg->avg;
+ to->burst = cfg->burst;
+ to->size = cfg->size;
+ to->max = cfg->max;
+ to->gc_interval = cfg->gc_interval;
+ to->expire = cfg->expire;
+ to->srcmask = cfg->srcmask;
+ to->dstmask = cfg->dstmask;
+ } else if (revision == 3) {
+ memcpy(to, from, sizeof(struct hashlimit_cfg3));
} else {
return -EINVAL;
}
@@ -262,7 +332,7 @@ static uint64_t parse_burst(const char *burst, int revision)
if (v > max)
xtables_error(PARAMETER_PROBLEM, "bad value for option "
"\"--hashlimit-burst\", value \"%s\" too large "
- "(max %lumb).", burst, max/1024/1024);
+ "(max %"PRIu64"mb).", burst, max/1024/1024);
return v;
}
@@ -285,8 +355,8 @@ static bool parse_bytes(const char *rate, void *val, struct hashlimit_mt_udata *
tmp = (uint64_t) r * factor;
if (tmp > max)
xtables_error(PARAMETER_PROBLEM,
- "Rate value too large \"%llu\" (max %lu)\n",
- (unsigned long long)tmp, max);
+ "Rate value too large \"%"PRIu64"\" (max %"PRIu64")\n",
+ tmp, max);
tmp = bytes_to_cost(tmp);
if (tmp == 0)
@@ -346,6 +416,16 @@ int parse_rate(const char *rate, void *val, struct hashlimit_mt_udata *ud, int r
return 1;
}
+static int parse_interval(const char *rate, uint32_t *val)
+{
+ int r = atoi(rate);
+ if (r <= 0)
+ return 0;
+
+ *val = r;
+ return 1;
+}
+
static void hashlimit_init(struct xt_entry_match *m)
{
struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
@@ -377,7 +457,7 @@ static void hashlimit_mt6_init_v1(struct xt_entry_match *match)
info->cfg.dstmask = 128;
}
-static void hashlimit_mt4_init(struct xt_entry_match *match)
+static void hashlimit_mt4_init_v2(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
@@ -388,7 +468,7 @@ static void hashlimit_mt4_init(struct xt_entry_match *match)
info->cfg.dstmask = 32;
}
-static void hashlimit_mt6_init(struct xt_entry_match *match)
+static void hashlimit_mt6_init_v2(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
@@ -399,6 +479,30 @@ static void hashlimit_mt6_init(struct xt_entry_match *match)
info->cfg.dstmask = 128;
}
+static void hashlimit_mt4_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo3 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.srcmask = 32;
+ info->cfg.dstmask = 32;
+ info->cfg.interval = 0;
+}
+
+static void hashlimit_mt6_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo3 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.srcmask = 128;
+ info->cfg.dstmask = 128;
+ info->cfg.interval = 0;
+}
+
/* Parse a 'mode' parameter into the required bitmask */
static int parse_mode(uint32_t *mode, const char *option_arg)
{
@@ -488,7 +592,7 @@ static void hashlimit_mt_parse_v1(struct xt_option_call *cb)
}
}
-static void hashlimit_mt_parse(struct xt_option_call *cb)
+static void hashlimit_mt_parse_v2(struct xt_option_call *cb)
{
struct xt_hashlimit_mtinfo2 *info = cb->data;
@@ -529,6 +633,54 @@ static void hashlimit_mt_parse(struct xt_option_call *cb)
}
}
+static void hashlimit_mt_parse(struct xt_option_call *cb)
+{
+ struct xt_hashlimit_mtinfo3 *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_BURST:
+ info->cfg.burst = parse_burst(cb->arg, 2);
+ break;
+ case O_UPTO:
+ if (cb->invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
+ info->cfg.mode |= XT_HASHLIMIT_BYTES;
+ else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-upto", cb->arg);
+ break;
+ case O_ABOVE:
+ if (!cb->invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
+ info->cfg.mode |= XT_HASHLIMIT_BYTES;
+ else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-above", cb->arg);
+ break;
+ case O_MODE:
+ if (parse_mode(&info->cfg.mode, cb->arg) < 0)
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-mode", cb->arg);
+ break;
+ case O_SRCMASK:
+ info->cfg.srcmask = cb->val.hlen;
+ break;
+ case O_DSTMASK:
+ info->cfg.dstmask = cb->val.hlen;
+ break;
+ case O_RATEMATCH:
+ info->cfg.mode |= XT_HASHLIMIT_RATE_MATCH;
+ break;
+ case O_INTERVAL:
+ if (!parse_interval(cb->arg, &info->cfg.interval))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-rate-interval", cb->arg);
+ }
+}
+
static void hashlimit_check(struct xt_fcheck_call *cb)
{
const struct hashlimit_mt_udata *udata = cb->udata;
@@ -557,7 +709,8 @@ static void hashlimit_mt_check_v1(struct xt_fcheck_call *cb)
if (cb->xflags & F_BURST) {
if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
xtables_error(PARAMETER_PROBLEM,
- "burst cannot be smaller than %lub", cost_to_bytes(info->cfg.avg));
+ "burst cannot be smaller than %"PRIu64"b",
+ cost_to_bytes(info->cfg.avg));
burst = info->cfg.burst;
burst /= cost_to_bytes(info->cfg.avg);
@@ -571,7 +724,7 @@ static void hashlimit_mt_check_v1(struct xt_fcheck_call *cb)
burst_error_v1();
}
-static void hashlimit_mt_check(struct xt_fcheck_call *cb)
+static void hashlimit_mt_check_v2(struct xt_fcheck_call *cb)
{
const struct hashlimit_mt_udata *udata = cb->udata;
struct xt_hashlimit_mtinfo2 *info = cb->data;
@@ -587,6 +740,37 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb)
if (cb->xflags & F_BURST) {
if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
xtables_error(PARAMETER_PROBLEM,
+ "burst cannot be smaller than %"PRIu64"b",
+ cost_to_bytes(info->cfg.avg));
+
+ burst = info->cfg.burst;
+ burst /= cost_to_bytes(info->cfg.avg);
+ if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
+ burst++;
+ if (!(cb->xflags & F_HTABLE_EXPIRE))
+ info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
+ }
+ info->cfg.burst = burst;
+ } else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
+ burst_error();
+}
+
+static void hashlimit_mt_check(struct xt_fcheck_call *cb)
+{
+ const struct hashlimit_mt_udata *udata = cb->udata;
+ struct xt_hashlimit_mtinfo3 *info = cb->data;
+
+ if (!(cb->xflags & (F_UPTO | F_ABOVE)))
+ xtables_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit");
+ if (!(cb->xflags & F_HTABLE_EXPIRE))
+ info->cfg.expire = udata->mult * 1000; /* from s to msec */
+
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
+ uint32_t burst = 0;
+ if (cb->xflags & F_BURST) {
+ if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
+ xtables_error(PARAMETER_PROBLEM,
"burst cannot be smaller than %lub", cost_to_bytes(info->cfg.avg));
burst = info->cfg.burst;
@@ -599,6 +783,18 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb)
info->cfg.burst = burst;
} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
burst_error();
+
+ if (cb->xflags & F_RATEMATCH) {
+ if (!(info->cfg.mode & XT_HASHLIMIT_BYTES))
+ info->cfg.avg /= udata->mult;
+
+ if (info->cfg.interval == 0) {
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES)
+ info->cfg.interval = 1;
+ else
+ info->cfg.interval = udata->mult;
+ }
+ }
}
struct rates {
@@ -615,7 +811,7 @@ static const struct rates rates[] = {
{ "min", XT_HASHLIMIT_SCALE_v2*60 },
{ "sec", XT_HASHLIMIT_SCALE_v2 } };
-static uint32_t print_rate(uint32_t period, int revision)
+static uint32_t print_rate(uint64_t period, int revision)
{
unsigned int i;
const struct rates *_rates = (revision == 1) ? rates_v1 : rates;
@@ -631,7 +827,7 @@ static uint32_t print_rate(uint32_t period, int revision)
|| _rates[i].mult/period < _rates[i].mult%period)
break;
- printf(" %lu/%s", _rates[i-1].mult / period, _rates[i-1].name);
+ printf(" %"PRIu64"/%s", _rates[i-1].mult / period, _rates[i-1].name);
/* return in msec */
return _rates[i-1].mult / scale * 1000;
}
@@ -721,9 +917,10 @@ static void hashlimit_print(const void *ip,
}
static void
-hashlimit_mt_print(const struct hashlimit_cfg2 *cfg, unsigned int dmask, int revision)
+hashlimit_mt_print(const struct hashlimit_cfg3 *cfg, unsigned int dmask, int revision)
{
- uint32_t quantum;
+ uint64_t quantum;
+ uint64_t period;
if (cfg->mode & XT_HASHLIMIT_INVERT)
fputs(" limit: above", stdout);
@@ -733,7 +930,15 @@ hashlimit_mt_print(const struct hashlimit_cfg2 *cfg, unsigned int dmask, int rev
if (cfg->mode & XT_HASHLIMIT_BYTES) {
quantum = print_bytes(cfg->avg, cfg->burst, "");
} else {
- quantum = print_rate(cfg->avg, revision);
+ if (revision == 3) {
+ period = cfg->avg;
+ if (cfg->interval != 0)
+ period *= cfg->interval;
+
+ quantum = print_rate(period, revision);
+ } else {
+ quantum = print_rate(cfg->avg, revision);
+ }
printf(" burst %llu", cfg->burst);
}
if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
@@ -754,6 +959,13 @@ hashlimit_mt_print(const struct hashlimit_cfg2 *cfg, unsigned int dmask, int rev
printf(" srcmask %u", cfg->srcmask);
if (cfg->dstmask != dmask)
printf(" dstmask %u", cfg->dstmask);
+
+ if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
+ printf(" rate-match");
+
+ if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
+ if (cfg->interval != 1)
+ printf(" rate-interval %u", cfg->interval);
}
static void
@@ -761,7 +973,7 @@ hashlimit_mt4_print_v1(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
- struct hashlimit_cfg2 cfg;
+ struct hashlimit_cfg3 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
@@ -777,7 +989,7 @@ hashlimit_mt6_print_v1(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
- struct hashlimit_cfg2 cfg;
+ struct hashlimit_cfg3 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
@@ -789,21 +1001,52 @@ hashlimit_mt6_print_v1(const void *ip, const struct xt_entry_match *match,
}
static void
-hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
+hashlimit_mt4_print_v2(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
+ struct hashlimit_cfg3 cfg;
+ int ret;
+
+ ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
+
+ if (ret)
+ xtables_error(OTHER_PROBLEM, "unknown revision");
- hashlimit_mt_print(&info->cfg, 32, 2);
+ hashlimit_mt_print(&cfg, 32, 2);
}
static void
-hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
+hashlimit_mt6_print_v2(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
+ struct hashlimit_cfg3 cfg;
+ int ret;
+
+ ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
+
+ if (ret)
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ hashlimit_mt_print(&cfg, 128, 2);
+}
+static void
+hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
+
+ hashlimit_mt_print(&info->cfg, 32, 3);
+}
+
+static void
+hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
- hashlimit_mt_print(&info->cfg, 128, 2);
+ hashlimit_mt_print(&info->cfg, 128, 3);
}
static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
@@ -831,7 +1074,7 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
}
static void
-hashlimit_mt_save(const struct hashlimit_cfg2 *cfg, const char* name, unsigned int dmask, int revision)
+hashlimit_mt_save(const struct hashlimit_cfg3 *cfg, const char* name, unsigned int dmask, int revision)
{
uint32_t quantum;
@@ -868,13 +1111,20 @@ hashlimit_mt_save(const struct hashlimit_cfg2 *cfg, const char* name, unsigned i
printf(" --hashlimit-srcmask %u", cfg->srcmask);
if (cfg->dstmask != dmask)
printf(" --hashlimit-dstmask %u", cfg->dstmask);
+
+ if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
+ printf(" --hashlimit-rate-match");
+
+ if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
+ if (cfg->interval != 1)
+ printf(" --hashlimit-rate-interval %u", cfg->interval);
}
static void
hashlimit_mt4_save_v1(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
- struct hashlimit_cfg2 cfg;
+ struct hashlimit_cfg3 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
@@ -889,7 +1139,7 @@ static void
hashlimit_mt6_save_v1(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
- struct hashlimit_cfg2 cfg;
+ struct hashlimit_cfg3 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
@@ -901,19 +1151,300 @@ hashlimit_mt6_save_v1(const void *ip, const struct xt_entry_match *match)
}
static void
-hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
+hashlimit_mt4_save_v2(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
+ struct hashlimit_cfg3 cfg;
+ int ret;
+
+ ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
- hashlimit_mt_save(&info->cfg, info->name, 32, 2);
+ if (ret)
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ hashlimit_mt_save(&cfg, info->name, 32, 2);
}
static void
-hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
+hashlimit_mt6_save_v2(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
+ struct hashlimit_cfg3 cfg;
+ int ret;
+
+ ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
+
+ if (ret)
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ hashlimit_mt_save(&cfg, info->name, 128, 2);
+}
+
+static void
+hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
+
+ hashlimit_mt_save(&info->cfg, info->name, 32, 3);
+}
+
+static void
+hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
+
+ hashlimit_mt_save(&info->cfg, info->name, 128, 3);
+}
+
+static const struct rates rates_v1_xlate[] = {
+ { "day", XT_HASHLIMIT_SCALE * 24 * 60 * 60 },
+ { "hour", XT_HASHLIMIT_SCALE * 60 * 60 },
+ { "minute", XT_HASHLIMIT_SCALE * 60 },
+ { "second", XT_HASHLIMIT_SCALE } };
+
+static const struct rates rates_xlate[] = {
+ { "day", XT_HASHLIMIT_SCALE_v2 * 24 * 60 * 60 },
+ { "hour", XT_HASHLIMIT_SCALE_v2 * 60 * 60 },
+ { "minute", XT_HASHLIMIT_SCALE_v2 * 60 },
+ { "second", XT_HASHLIMIT_SCALE_v2 } };
+
+static void print_packets_rate_xlate(struct xt_xlate *xl, uint64_t avg,
+ int revision)
+{
+ unsigned int i;
+ const struct rates *_rates = (revision == 1) ?
+ rates_v1_xlate : rates_xlate;
+
+ for (i = 1; i < ARRAY_SIZE(rates); ++i)
+ if (avg > _rates[i].mult ||
+ _rates[i].mult / avg < _rates[i].mult % avg)
+ break;
+
+ xt_xlate_add(xl, " %llu/%s ",
+ _rates[i-1].mult / avg, _rates[i-1].name);
+}
+
+static void print_bytes_rate_xlate(struct xt_xlate *xl,
+ const struct hashlimit_cfg3 *cfg)
+{
+ unsigned int i;
+ unsigned long long r;
+
+ r = cost_to_bytes(cfg->avg);
+
+ for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
+ if (r >= units[i].thresh &&
+ bytes_to_cost(r & ~(units[i].thresh - 1)) == cfg->avg)
+ break;
+
+ xt_xlate_add(xl, " %llu %sbytes/second", r / units[i].thresh,
+ units[i].name);
+
+ r *= cfg->burst;
+ for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
+ if (r >= units[i].thresh)
+ break;
+
+ if (cfg->burst > 0)
+ xt_xlate_add(xl, " burst %llu %sbytes", r / units[i].thresh,
+ units[i].name);
+}
+
+static void hashlimit_print_subnet_xlate(struct xt_xlate *xl,
+ uint32_t nsub, int family)
+{
+ char sep = (family == NFPROTO_IPV4) ? '.' : ':';
+ char *fmt = (family == NFPROTO_IPV4) ? "%u" : "%04x";
+ unsigned int nblocks = (family == NFPROTO_IPV4) ? 4 : 8;
+ unsigned int nbits = (family == NFPROTO_IPV4) ? 8 : 16;
+ unsigned int acm, i;
+
+ xt_xlate_add(xl, " and ");
+ while (nblocks--) {
+ acm = 0;
+
+ for (i = 0; i < nbits; i++) {
+ acm <<= 1;
+
+ if (nsub > 0) {
+ acm++;
+ nsub--;
+ }
+ }
+
+ xt_xlate_add(xl, fmt, acm);
+ if (nblocks > 0)
+ xt_xlate_add(xl, "%c", sep);
+ }
+}
+
+static const char *const hashlimit_modes4_xlate[] = {
+ [XT_HASHLIMIT_HASH_DIP] = "ip daddr",
+ [XT_HASHLIMIT_HASH_DPT] = "tcp dport",
+ [XT_HASHLIMIT_HASH_SIP] = "ip saddr",
+ [XT_HASHLIMIT_HASH_SPT] = "tcp sport",
+};
+
+static const char *const hashlimit_modes6_xlate[] = {
+ [XT_HASHLIMIT_HASH_DIP] = "ip6 daddr",
+ [XT_HASHLIMIT_HASH_DPT] = "tcp dport",
+ [XT_HASHLIMIT_HASH_SIP] = "ip6 saddr",
+ [XT_HASHLIMIT_HASH_SPT] = "tcp sport",
+};
+
+static int hashlimit_mode_xlate(struct xt_xlate *xl,
+ uint32_t mode, int family,
+ unsigned int nsrc, unsigned int ndst)
+{
+ const char * const *_modes = (family == NFPROTO_IPV4) ?
+ hashlimit_modes4_xlate : hashlimit_modes6_xlate;
+ bool prevopt = false;
+ unsigned int mask;
+
+ mode &= ~XT_HASHLIMIT_INVERT & ~XT_HASHLIMIT_BYTES;
+
+ for (mask = 1; mode > 0; mask <<= 1) {
+ if (!(mode & mask))
+ continue;
+
+ if (!prevopt) {
+ xt_xlate_add(xl, " ");
+ prevopt = true;
+ }
+ else {
+ xt_xlate_add(xl, " . ");
+ }
+
+ xt_xlate_add(xl, "%s", _modes[mask]);
+
+ if (mask == XT_HASHLIMIT_HASH_DIP &&
+ ((family == NFPROTO_IPV4 && ndst != 32) ||
+ (family == NFPROTO_IPV6 && ndst != 128)))
+ hashlimit_print_subnet_xlate(xl, ndst, family);
+ else if (mask == XT_HASHLIMIT_HASH_SIP &&
+ ((family == NFPROTO_IPV4 && nsrc != 32) ||
+ (family == NFPROTO_IPV6 && nsrc != 128)))
+ hashlimit_print_subnet_xlate(xl, nsrc, family);
+
+ mode &= ~mask;
+ }
+
+ return prevopt;
+}
+
+static int hashlimit_mt_xlate(struct xt_xlate *xl, const char *name,
+ const struct hashlimit_cfg3 *cfg,
+ int revision, int family)
+{
+ int ret = 1;
+
+ xt_xlate_add(xl, "meter %s {", name);
+ ret = hashlimit_mode_xlate(xl, cfg->mode, family,
+ cfg->srcmask, cfg->dstmask);
+ if (cfg->expire != 1000)
+ xt_xlate_add(xl, " timeout %us", cfg->expire / 1000);
+ xt_xlate_add(xl, " limit rate");
+
+ if (cfg->mode & XT_HASHLIMIT_INVERT)
+ xt_xlate_add(xl, " over");
+
+ if (cfg->mode & XT_HASHLIMIT_BYTES)
+ print_bytes_rate_xlate(xl, cfg);
+ else {
+ print_packets_rate_xlate(xl, cfg->avg, revision);
+ if (cfg->burst != XT_HASHLIMIT_BURST)
+ xt_xlate_add(xl, "burst %lu packets", cfg->burst);
+
+ }
+ xt_xlate_add(xl, "}");
+
+ return ret;
+}
+
+static int hashlimit_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_info *info = (const void *)params->match->data;
+ int ret = 1;
+
+ xt_xlate_add(xl, "meter %s {", info->name);
+ ret = hashlimit_mode_xlate(xl, info->cfg.mode, NFPROTO_IPV4, 32, 32);
+ xt_xlate_add(xl, " timeout %us limit rate", info->cfg.expire / 1000);
+ print_packets_rate_xlate(xl, info->cfg.avg, 1);
+ xt_xlate_add(xl, " burst %lu packets", info->cfg.burst);
+ xt_xlate_add(xl, "}");
+
+ return ret;
+}
+
+static int hashlimit_mt4_xlate_v1(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo1 *info =
+ (const void *)params->match->data;
+ struct hashlimit_cfg3 cfg;
+
+ if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV4);
+}
+
+static int hashlimit_mt6_xlate_v1(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo1 *info =
+ (const void *)params->match->data;
+ struct hashlimit_cfg3 cfg;
- hashlimit_mt_save(&info->cfg, info->name, 128, 2);
+ if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV6);
+}
+
+static int hashlimit_mt4_xlate_v2(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo2 *info =
+ (const void *)params->match->data;
+ struct hashlimit_cfg3 cfg;
+
+ if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV4);
+}
+
+static int hashlimit_mt6_xlate_v2(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo2 *info =
+ (const void *)params->match->data;
+ struct hashlimit_cfg3 cfg;
+
+ if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
+ xtables_error(OTHER_PROBLEM, "unknown revision");
+
+ return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV6);
+}
+
+static int hashlimit_mt4_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo3 *info =
+ (const void *)params->match->data;
+
+ return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV4);
+}
+
+static int hashlimit_mt6_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ const struct xt_hashlimit_mtinfo3 *info =
+ (const void *)params->match->data;
+
+ return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV6);
}
static struct xtables_match hashlimit_mt_reg[] = {
@@ -932,6 +1463,7 @@ static struct xtables_match hashlimit_mt_reg[] = {
.save = hashlimit_save,
.x6_options = hashlimit_opts,
.udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_xlate,
},
{
.version = XTABLES_VERSION,
@@ -948,6 +1480,7 @@ static struct xtables_match hashlimit_mt_reg[] = {
.save = hashlimit_mt4_save_v1,
.x6_options = hashlimit_mt_opts_v1,
.udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt4_xlate_v1,
},
{
.version = XTABLES_VERSION,
@@ -964,6 +1497,7 @@ static struct xtables_match hashlimit_mt_reg[] = {
.save = hashlimit_mt6_save_v1,
.x6_options = hashlimit_mt_opts_v1,
.udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt6_xlate_v1,
},
{
.version = XTABLES_VERSION,
@@ -973,6 +1507,40 @@ static struct xtables_match hashlimit_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
.help = hashlimit_mt_help,
+ .init = hashlimit_mt4_init_v2,
+ .x6_parse = hashlimit_mt_parse_v2,
+ .x6_fcheck = hashlimit_mt_check_v2,
+ .print = hashlimit_mt4_print_v2,
+ .save = hashlimit_mt4_save_v2,
+ .x6_options = hashlimit_mt_opts_v2,
+ .udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt4_xlate_v2,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 2,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
+ .help = hashlimit_mt_help,
+ .init = hashlimit_mt6_init_v2,
+ .x6_parse = hashlimit_mt_parse_v2,
+ .x6_fcheck = hashlimit_mt_check_v2,
+ .print = hashlimit_mt6_print_v2,
+ .save = hashlimit_mt6_save_v2,
+ .x6_options = hashlimit_mt_opts_v2,
+ .udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt6_xlate_v2,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 3,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
+ .help = hashlimit_mt_help_v3,
.init = hashlimit_mt4_init,
.x6_parse = hashlimit_mt_parse,
.x6_fcheck = hashlimit_mt_check,
@@ -980,15 +1548,16 @@ static struct xtables_match hashlimit_mt_reg[] = {
.save = hashlimit_mt4_save,
.x6_options = hashlimit_mt_opts,
.udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt4_xlate,
},
{
.version = XTABLES_VERSION,
.name = "hashlimit",
- .revision = 2,
+ .revision = 3,
.family = NFPROTO_IPV6,
- .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
- .userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
- .help = hashlimit_mt_help,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
+ .help = hashlimit_mt_help_v3,
.init = hashlimit_mt6_init,
.x6_parse = hashlimit_mt_parse,
.x6_fcheck = hashlimit_mt_check,
@@ -996,6 +1565,7 @@ static struct xtables_match hashlimit_mt_reg[] = {
.save = hashlimit_mt6_save,
.x6_options = hashlimit_mt_opts,
.udata_size = sizeof(struct hashlimit_mt_udata),
+ .xlate = hashlimit_mt6_xlate,
},
};
diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man
index 6aac3f28..5dbb3273 100644
--- a/extensions/libxt_hashlimit.man
+++ b/extensions/libxt_hashlimit.man
@@ -51,6 +51,14 @@ After how many milliseconds do hash entries expire.
.TP
\fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
How many milliseconds between garbage collection intervals.
+.TP
+\fB\-\-hashlimit\-rate\-match\fP
+Classify the flow instead of rate-limiting it. This acts like a
+true/flase match on whether the rate is above/below a certain number
+.TP
+\fB\-\-hashlimit\-rate\-interval\fP \fIsec\fP
+Can be used with \-\-hashlimit\-rate\-match to specify the interval
+at which the rate should be sampled
.PP
Examples:
.TP
diff --git a/extensions/libxt_hashlimit.t b/extensions/libxt_hashlimit.t
index d27c8616..ccd0d1e6 100644
--- a/extensions/libxt_hashlimit.t
+++ b/extensions/libxt_hashlimit.t
@@ -26,3 +26,8 @@
-m hashlimit --hashlimit-name mini1;;FAIL
-m hashlimit --hashlimit-upto 1/sec;;FAIL
-m hashlimit;;FAIL
+-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name syn-flood;=;OK
+-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name rate1 --hashlimit-rate-match;=;OK
+-m hashlimit --hashlimit-upto 40mb/s --hashlimit-mode srcip --hashlimit-name rate2 --hashlimit-rate-match;=;OK
+-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name rate3 --hashlimit-rate-match --hashlimit-rate-interval 10;=;OK
+-m hashlimit --hashlimit-upto 40mb/s --hashlimit-mode srcip --hashlimit-name rate4 --hashlimit-rate-match --hashlimit-rate-interval 10;=;OK
diff --git a/extensions/libxt_hashlimit.txlate b/extensions/libxt_hashlimit.txlate
new file mode 100644
index 00000000..6c8d07f1
--- /dev/null
+++ b/extensions/libxt_hashlimit.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A OUTPUT -m tcp -p tcp --dport 443 -m hashlimit --hashlimit-above 20kb/s --hashlimit-burst 1mb --hashlimit-mode dstip --hashlimit-name https --hashlimit-dstmask 24 -m state --state NEW -j DROP
+nft add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr and 255.255.255.0 timeout 60s limit rate over 20 kbytes/second burst 1 mbytes} ct state new counter drop
+
+iptables-translate -A OUTPUT -m tcp -p tcp --dport 443 -m hashlimit --hashlimit-upto 300 --hashlimit-burst 15 --hashlimit-mode srcip,dstip --hashlimit-name https --hashlimit-htable-expire 300000 -m state --state NEW -j DROP
+nft add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr . ip saddr timeout 300s limit rate 300/second burst 15 packets} ct state new counter drop
diff --git a/extensions/libxt_helper.txlate b/extensions/libxt_helper.txlate
new file mode 100644
index 00000000..8259aba3
--- /dev/null
+++ b/extensions/libxt_helper.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A FORWARD -m helper --helper sip
+nft add rule ip filter FORWARD ct helper \"sip\" counter
+
+iptables-translate -A FORWARD -m helper ! --helper ftp
+nft add rule ip filter FORWARD ct helper != \"ftp\" counter
diff --git a/extensions/libxt_ipcomp.t b/extensions/libxt_ipcomp.t
new file mode 100644
index 00000000..ce111142
--- /dev/null
+++ b/extensions/libxt_ipcomp.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD
+-m policy --dir in --pol ipsec --proto ipcomp;=;OK
+-m policy --dir in --pol none --proto ipcomp;;FAIL
+-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto ipcomp;=;OK
+-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto ipcomp --mode tunnel --tunnel-dst 10.0.0.0/8 --tunnel-src 10.0.0.0/8 --next --reqid 2;=;OK
diff --git a/extensions/libxt_ipcomp.txlate b/extensions/libxt_ipcomp.txlate
new file mode 100644
index 00000000..f9efe53c
--- /dev/null
+++ b/extensions/libxt_ipcomp.txlate
@@ -0,0 +1,5 @@
+iptables-translate -t filter -A INPUT -m ipcomp --ipcompspi 0x12 -j ACCEPT
+nft add rule ip filter INPUT comp cpi 18 counter accept
+
+iptables-translate -t filter -A INPUT -m ipcomp ! --ipcompspi 0x12 -j ACCEPT
+nft add rule ip filter INPUT comp cpi != 18 counter accept
diff --git a/extensions/libxt_iprange.txlate b/extensions/libxt_iprange.txlate
new file mode 100644
index 00000000..999f4b72
--- /dev/null
+++ b/extensions/libxt_iprange.txlate
@@ -0,0 +1,14 @@
+iptables-translate -A INPUT -m iprange --src-range 192.168.25.149-192.168.25.151 -j ACCEPT
+nft add rule ip filter INPUT ip saddr 192.168.25.149-192.168.25.151 counter accept
+
+iptables-translate -A INPUT -m iprange --dst-range 192.168.25.149-192.168.25.151 -j ACCEPT
+nft add rule ip filter INPUT ip daddr 192.168.25.149-192.168.25.151 counter accept
+
+iptables-translate -A INPUT -m iprange --dst-range 3.3.3.3-6.6.6.6 --src-range 4.4.4.4-7.7.7.7 -j ACCEPT
+nft add rule ip filter INPUT ip saddr 4.4.4.4-7.7.7.7 ip daddr 3.3.3.3-6.6.6.6 counter accept
+
+ip6tables-translate -A INPUT -m iprange ! --dst-range ::2d01-::2d03 -j ACCEPT
+nft add rule ip6 filter INPUT ip6 daddr != ::2d01-::2d03 counter accept
+
+ip6tables-translate -A INPUT -m iprange ! --dst-range ::2d01-::2d03 --src-range ::2d01-::2d03 -j ACCEPT
+nft add rule ip6 filter INPUT ip6 saddr ::2d01-::2d03 ip6 daddr != ::2d01-::2d03 counter accept
diff --git a/extensions/libxt_length.txlate b/extensions/libxt_length.txlate
new file mode 100644
index 00000000..e777c265
--- /dev/null
+++ b/extensions/libxt_length.txlate
@@ -0,0 +1,11 @@
+iptables-translate -A INPUT -p icmp -m length --length 86:0xffff -j DROP
+nft add rule ip filter INPUT ip protocol icmp meta length 86-65535 counter drop
+
+iptables-translate -A INPUT -p udp -m length --length :400
+nft add rule ip filter INPUT ip protocol udp meta length 0-400 counter
+
+iptables-translate -A INPUT -p udp -m length --length 40
+nft add rule ip filter INPUT ip protocol udp meta length 40 counter
+
+iptables-translate -A INPUT -p udp -m length ! --length 40
+nft add rule ip filter INPUT ip protocol udp meta length != 40 counter
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index 5cc95c2e..c8ddca87 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -4,6 +4,7 @@
* Hervé Eychenne <rv@wallfire.org>
*/
#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
#define _ISOC99_SOURCE 1
#include <math.h>
#include <stdio.h>
diff --git a/extensions/libxt_limit.txlate b/extensions/libxt_limit.txlate
new file mode 100644
index 00000000..df9ed2d5
--- /dev/null
+++ b/extensions/libxt_limit.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A INPUT -m limit --limit 3/m --limit-burst 3
+nft add rule ip filter INPUT limit rate 3/minute burst 3 packets counter
+
+iptables-translate -A INPUT -m limit --limit 10/s --limit-burst 5
+nft add rule ip filter INPUT limit rate 10/second burst 5 packets counter
+
+iptables-translate -A INPUT -m limit --limit 10/s --limit-burst 0
+nft add rule ip filter INPUT limit rate 10/second counter
diff --git a/extensions/libxt_mac.txlate b/extensions/libxt_mac.txlate
new file mode 100644
index 00000000..08696f3d
--- /dev/null
+++ b/extensions/libxt_mac.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A INPUT -m mac --mac-source 0a:12:3e:4f:b2:c6 -j DROP
+nft add rule ip filter INPUT ether saddr 0a:12:3e:4f:b2:c6 counter drop
+
+iptables-translate -A INPUT -p tcp --dport 80 -m mac --mac-source 0a:12:3e:4f:b2:c6 -j ACCEPT
+nft add rule ip filter INPUT tcp dport 80 ether saddr 0a:12:3e:4f:b2:c6 counter accept
diff --git a/extensions/libxt_mark.txlate b/extensions/libxt_mark.txlate
new file mode 100644
index 00000000..6bfb5243
--- /dev/null
+++ b/extensions/libxt_mark.txlate
@@ -0,0 +1,5 @@
+iptables-translate -I INPUT -p tcp -m mark ! --mark 0xa/0xa
+nft insert rule ip filter INPUT ip protocol tcp mark and 0xa != 0xa counter
+
+iptables-translate -I INPUT -p tcp -m mark ! --mark 0x1
+nft insert rule ip filter INPUT ip protocol tcp mark != 0x1 counter
diff --git a/extensions/libxt_multiport.txlate b/extensions/libxt_multiport.txlate
new file mode 100644
index 00000000..752e7148
--- /dev/null
+++ b/extensions/libxt_multiport.txlate
@@ -0,0 +1,11 @@
+iptables-translate -t filter -A INPUT -p tcp -m multiport --dports 80,81 -j ACCEPT
+nft add rule ip filter INPUT ip protocol tcp tcp dport { 80,81} counter accept
+
+iptables-translate -t filter -A INPUT -p tcp -m multiport --dports 80:88 -j ACCEPT
+nft add rule ip filter INPUT ip protocol tcp tcp dport 80-88 counter accept
+
+iptables-translate -t filter -A INPUT -p tcp -m multiport ! --dports 80:88 -j ACCEPT
+nft add rule ip filter INPUT ip protocol tcp tcp dport != 80-88 counter accept
+
+iptables-translate -t filter -A INPUT -p tcp -m multiport --sports 50 -j ACCEPT
+nft add rule ip filter INPUT ip protocol tcp tcp sport 50 counter accept
diff --git a/extensions/libxt_owner.txlate b/extensions/libxt_owner.txlate
new file mode 100644
index 00000000..86fb0585
--- /dev/null
+++ b/extensions/libxt_owner.txlate
@@ -0,0 +1,8 @@
+iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner root -j ACCEPT
+nft add rule ip nat OUTPUT tcp dport 80 skuid 0 counter accept
+
+iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner --gid-owner 0-10 -j ACCEPT
+nft add rule ip nat OUTPUT tcp dport 80 skgid 0-10 counter accept
+
+iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner ! --uid-owner 1000 -j ACCEPT
+nft add rule ip nat OUTPUT tcp dport 80 skuid != 1000 counter accept
diff --git a/extensions/libxt_pkttype.txlate b/extensions/libxt_pkttype.txlate
new file mode 100644
index 00000000..6506a380
--- /dev/null
+++ b/extensions/libxt_pkttype.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A INPUT -m pkttype --pkt-type broadcast -j DROP
+nft add rule ip filter INPUT pkttype broadcast counter drop
+
+iptables-translate -A INPUT -m pkttype ! --pkt-type unicast -j DROP
+nft add rule ip filter INPUT pkttype != unicast counter drop
+
+iptables-translate -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
+nft add rule ip filter INPUT pkttype multicast counter accept
diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c
index 0a64a80c..f9a4819c 100644
--- a/extensions/libxt_policy.c
+++ b/extensions/libxt_policy.c
@@ -376,6 +376,31 @@ static void policy6_save(const void *ip, const struct xt_entry_match *match)
}
}
+static int policy_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params)
+{
+ static const unsigned int allowed = XT_POLICY_MATCH_STRICT |
+ XT_POLICY_MATCH_NONE |
+ XT_POLICY_MATCH_IN;
+ static const struct xt_policy_elem empty;
+ const struct xt_policy_info *info = (const void *)params->match->data;
+
+ if ((info->flags & ~allowed) || info->len > 1)
+ return 0;
+
+ if (memcmp(&info->pol[0], &empty, sizeof(empty)))
+ return 0;
+
+ xt_xlate_add(xl, "meta secpath ");
+
+ if (info->flags & XT_POLICY_MATCH_NONE)
+ xt_xlate_add(xl, "missing");
+ else
+ xt_xlate_add(xl, "exists");
+
+ return 1;
+}
+
static struct xtables_match policy_mt_reg[] = {
{
.name = "policy",
@@ -389,6 +414,7 @@ static struct xtables_match policy_mt_reg[] = {
.print = policy4_print,
.save = policy4_save,
.x6_options = policy_opts,
+ .xlate = policy_xlate,
},
{
.name = "policy",
@@ -402,6 +428,7 @@ static struct xtables_match policy_mt_reg[] = {
.print = policy6_print,
.save = policy6_save,
.x6_options = policy_opts,
+ .xlate = policy_xlate,
},
};
diff --git a/extensions/libxt_policy.txlate b/extensions/libxt_policy.txlate
new file mode 100644
index 00000000..66788a76
--- /dev/null
+++ b/extensions/libxt_policy.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A INPUT -m policy --pol ipsec --dir in
+nft add rule ip filter INPUT meta secpath exists counter
+
+iptables-translate -A INPUT -m policy --pol none --dir in
+nft add rule ip filter INPUT meta secpath missing counter
diff --git a/extensions/libxt_quota.txlate b/extensions/libxt_quota.txlate
new file mode 100644
index 00000000..91142141
--- /dev/null
+++ b/extensions/libxt_quota.txlate
@@ -0,0 +1,5 @@
+iptables-translate -A OUTPUT -m quota --quota 111
+nft add rule ip filter OUTPUT quota 111 bytes counter
+
+iptables-translate -A OUTPUT -m quota ! --quota 111
+nft add rule ip filter OUTPUT quota over 111 bytes counter
diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c
index e1801f1c..055ae350 100644
--- a/extensions/libxt_recent.c
+++ b/extensions/libxt_recent.c
@@ -199,7 +199,7 @@ static void recent_print(const void *ip, const struct xt_entry_match *match,
if(info->hit_count) printf(" hit_count: %d", info->hit_count);
if (info->check_set & XT_RECENT_TTL)
printf(" TTL-Match");
- if(info->name) printf(" name: %s", info->name);
+ printf(" name: %s", info->name);
if (info->side == XT_RECENT_SOURCE)
printf(" side: source");
if (info->side == XT_RECENT_DEST)
@@ -239,7 +239,7 @@ static void recent_save(const void *ip, const struct xt_entry_match *match,
if(info->hit_count) printf(" --hitcount %d", info->hit_count);
if (info->check_set & XT_RECENT_TTL)
printf(" --rttl");
- if(info->name) printf(" --name %s",info->name);
+ printf(" --name %s",info->name);
switch(family) {
case NFPROTO_IPV4:
diff --git a/extensions/libxt_rpfilter.txlate b/extensions/libxt_rpfilter.txlate
new file mode 100644
index 00000000..8d7733ba
--- /dev/null
+++ b/extensions/libxt_rpfilter.txlate
@@ -0,0 +1,8 @@
+iptables-translate -t mangle -A PREROUTING -m rpfilter
+nft add rule ip mangle PREROUTING fib saddr . iif oif != 0 counter
+
+iptables-translate -t mangle -A PREROUTING -m rpfilter --validmark --loose
+nft add rule ip mangle PREROUTING fib saddr . mark oif != 0 counter
+
+ip6tables-translate -t mangle -A PREROUTING -m rpfilter --validmark --invert
+nft add rule ip6 mangle PREROUTING fib saddr . mark . iif oif 0 counter
diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c
index df1936be..140de265 100644
--- a/extensions/libxt_sctp.c
+++ b/extensions/libxt_sctp.c
@@ -370,7 +370,7 @@ print_chunk(uint32_t chunknum, int numeric)
for (i = 0; i < ARRAY_SIZE(sctp_chunk_names); ++i)
if (sctp_chunk_names[i].chunk_type == chunknum)
- printf("%s", sctp_chunk_names[chunknum].name);
+ printf("%s", sctp_chunk_names[i].name);
}
}
diff --git a/extensions/libxt_sctp.t b/extensions/libxt_sctp.t
index 2f75e2a6..4016e4fb 100644
--- a/extensions/libxt_sctp.t
+++ b/extensions/libxt_sctp.t
@@ -23,10 +23,7 @@
-p sctp -m sctp --chunk-types all COOKIE_ACK;=;OK
-p sctp -m sctp --chunk-types all ECN_ECNE;=;OK
-p sctp -m sctp --chunk-types all ECN_CWR;=;OK
-# ERROR: iptables-save segfaults: iptables -A INPUT -p sctp -m sctp --chunk-types all ASCONF
-# -p sctp -m sctp --chunk-types all ASCONF;=;OK
-# ERROR: iptables-save segfaults: iptables -A INPUT -p sctp -m sctp --chunk-types all ASCONF_ACK
-# -p sctp -m sctp --chunk-types all ASCONF_ACK;=;OK
-# ERROR: iptables-save segfaults: iptables -A INPUT -p sctp -m sctp --chunk-types all FORWARD_TSN
-# -p sctp -m sctp --chunk-types all FORWARD_TSN;=;OK
+-p sctp -m sctp --chunk-types all ASCONF;=;OK
+-p sctp -m sctp --chunk-types all ASCONF_ACK;=;OK
+-p sctp -m sctp --chunk-types all FORWARD_TSN;=;OK
-p sctp -m sctp --chunk-types all SHUTDOWN_COMPLETE;=;OK
diff --git a/extensions/libxt_sctp.txlate b/extensions/libxt_sctp.txlate
new file mode 100644
index 00000000..72f4641a
--- /dev/null
+++ b/extensions/libxt_sctp.txlate
@@ -0,0 +1,38 @@
+iptables-translate -A INPUT -p sctp --dport 80 -j DROP
+nft add rule ip filter INPUT sctp dport 80 counter drop
+
+iptables-translate -A INPUT -p sctp --sport 50 -j DROP
+nft add rule ip filter INPUT sctp sport 50 counter drop
+
+iptables-translate -A INPUT -p sctp ! --dport 80 -j DROP
+nft add rule ip filter INPUT sctp dport != 80 counter drop
+
+iptables-translate -A INPUT -p sctp ! --sport 50 -j DROP
+nft add rule ip filter INPUT sctp sport != 50 counter drop
+
+iptables-translate -A INPUT -p sctp --sport 80:100 -j ACCEPT
+nft add rule ip filter INPUT sctp sport 80-100 counter accept
+
+iptables-translate -A INPUT -p sctp --dport 50:56 -j ACCEPT
+nft add rule ip filter INPUT sctp dport 50-56 counter accept
+
+iptables-translate -A INPUT -p sctp ! --sport 80:100 -j ACCEPT
+nft add rule ip filter INPUT sctp sport != 80-100 counter accept
+
+iptables-translate -A INPUT -p sctp ! --dport 50:56 -j ACCEPT
+nft add rule ip filter INPUT sctp dport != 50-56 counter accept
+
+iptables-translate -A INPUT -p sctp --dport 80 --sport 50 -j ACCEPT
+nft add rule ip filter INPUT sctp sport 50 dport 80 counter accept
+
+iptables-translate -A INPUT -p sctp --dport 80:100 --sport 50 -j ACCEPT
+nft add rule ip filter INPUT sctp sport 50 dport 80-100 counter accept
+
+iptables-translate -A INPUT -p sctp --dport 80 --sport 50:55 -j ACCEPT
+nft add rule ip filter INPUT sctp sport 50-55 dport 80 counter accept
+
+iptables-translate -A INPUT -p sctp ! --dport 80:100 --sport 50 -j ACCEPT
+nft add rule ip filter INPUT sctp sport 50 dport != 80-100 counter accept
+
+iptables-translate -A INPUT -p sctp --dport 80 ! --sport 50:55 -j ACCEPT
+nft add rule ip filter INPUT sctp sport != 50-55 dport 80 counter accept
diff --git a/extensions/libxt_statistic.txlate b/extensions/libxt_statistic.txlate
new file mode 100644
index 00000000..4c3dea43
--- /dev/null
+++ b/extensions/libxt_statistic.txlate
@@ -0,0 +1,8 @@
+iptables-translate -A OUTPUT -m statistic --mode nth --every 10 --packet 1
+nft add rule ip filter OUTPUT numgen inc mod 10 1 counter
+
+iptables-translate -A OUTPUT -m statistic --mode nth ! --every 10 --packet 5
+nft add rule ip filter OUTPUT numgen inc mod 10 != 5 counter
+
+iptables-translate -A OUTPUT -m statistic --mode random --probability 0.1
+nft # -A OUTPUT -m statistic --mode random --probability 0.1
diff --git a/extensions/libxt_tcp.txlate b/extensions/libxt_tcp.txlate
new file mode 100644
index 00000000..db099037
--- /dev/null
+++ b/extensions/libxt_tcp.txlate
@@ -0,0 +1,20 @@
+iptables-translate -A INPUT -p tcp -i eth0 --sport 53 -j ACCEPT
+nft add rule ip filter INPUT iifname eth0 tcp sport 53 counter accept
+
+iptables-translate -A OUTPUT -p tcp -o eth0 --dport 53:66 -j DROP
+nft add rule ip filter OUTPUT oifname eth0 tcp dport 53-66 counter drop
+
+iptables-translate -I OUTPUT -p tcp -d 8.8.8.8 -j ACCEPT
+nft insert rule ip filter OUTPUT ip protocol tcp ip daddr 8.8.8.8 counter accept
+
+iptables-translate -I OUTPUT -p tcp --dport 1020:1023 --sport 53 -j ACCEPT
+nft insert rule ip filter OUTPUT tcp sport 53 tcp dport 1020-1023 counter accept
+
+iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
+nft add rule ip filter INPUT tcp flags & fin|ack == fin counter drop
+
+iptables-translate -A INPUT -p tcp --syn -j ACCEPT
+nft add rule ip filter INPUT tcp flags & (fin|syn|rst|ack) == syn counter accept
+
+iptables-translate -A INPUT -p tcp --syn --dport 80 -j ACCEPT
+nft add rule ip filter INPUT tcp dport 80 tcp flags & (fin|syn|rst|ack) == syn counter accept
diff --git a/extensions/libxt_tcpmss.c b/extensions/libxt_tcpmss.c
index c7c59717..bcd357aa 100644
--- a/extensions/libxt_tcpmss.c
+++ b/extensions/libxt_tcpmss.c
@@ -27,8 +27,12 @@ static void tcpmss_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
mssinfo->mss_min = cb->val.u16_range[0];
mssinfo->mss_max = mssinfo->mss_min;
- if (cb->nvals == 2)
+ if (cb->nvals == 2) {
mssinfo->mss_max = cb->val.u16_range[1];
+ if (mssinfo->mss_max < mssinfo->mss_min)
+ xtables_error(PARAMETER_PROBLEM,
+ "tcpmss: invalid range given");
+ }
if (cb->invert)
mssinfo->invert = 1;
}
diff --git a/extensions/libxt_tcpmss.man b/extensions/libxt_tcpmss.man
index 8ee715cd..8253c363 100644
--- a/extensions/libxt_tcpmss.man
+++ b/extensions/libxt_tcpmss.man
@@ -1,4 +1,4 @@
This matches the TCP MSS (maximum segment size) field of the TCP header. You can only use this on TCP SYN or SYN/ACK packets, since the MSS is only negotiated during the TCP handshake at connection startup time.
.TP
[\fB!\fP] \fB\-\-mss\fP \fIvalue\fP[\fB:\fP\fIvalue\fP]
-Match a given TCP MSS value or range.
+Match a given TCP MSS value or range. If a range is given, the second \fIvalue\fP must be greater than or equal to the first \fIvalue\fP.
diff --git a/extensions/libxt_tcpmss.t b/extensions/libxt_tcpmss.t
index 3181e49d..2b415957 100644
--- a/extensions/libxt_tcpmss.t
+++ b/extensions/libxt_tcpmss.t
@@ -3,3 +3,4 @@
-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_udp.txlate b/extensions/libxt_udp.txlate
new file mode 100644
index 00000000..a9adfcda
--- /dev/null
+++ b/extensions/libxt_udp.txlate
@@ -0,0 +1,11 @@
+iptables-translate -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
+nft add rule ip filter INPUT iifname eth0 udp sport 53 counter accept
+
+iptables-translate -A OUTPUT -p udp -o eth0 --dport 53:66 -j DROP
+nft add rule ip filter OUTPUT oifname eth0 udp dport 53-66 counter drop
+
+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
+
+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
diff --git a/include/iptables/internal.h b/include/iptables/internal.h
index 3b9013ab..bf5aa64c 100644
--- a/include/iptables/internal.h
+++ b/include/iptables/internal.h
@@ -1,7 +1,7 @@
#ifndef IPTABLES_INTERNAL_H
#define IPTABLES_INTERNAL_H 1
-#define IPTABLES_VERSION "1.6.1"
+#define IPTABLES_VERSION "1.6.2"
/**
* Program's own name and version.
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
index d9808b5d..ade33f6c 100644
--- a/include/linux/netfilter/xt_hashlimit.h
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -17,12 +17,13 @@
struct xt_hashlimit_htable;
enum {
- XT_HASHLIMIT_HASH_DIP = 1 << 0,
- XT_HASHLIMIT_HASH_DPT = 1 << 1,
- XT_HASHLIMIT_HASH_SIP = 1 << 2,
- XT_HASHLIMIT_HASH_SPT = 1 << 3,
- XT_HASHLIMIT_INVERT = 1 << 4,
- XT_HASHLIMIT_BYTES = 1 << 5,
+ XT_HASHLIMIT_HASH_DIP = 1 << 0,
+ XT_HASHLIMIT_HASH_DPT = 1 << 1,
+ XT_HASHLIMIT_HASH_SIP = 1 << 2,
+ XT_HASHLIMIT_HASH_SPT = 1 << 3,
+ XT_HASHLIMIT_INVERT = 1 << 4,
+ XT_HASHLIMIT_BYTES = 1 << 5,
+ XT_HASHLIMIT_RATE_MATCH = 1 << 6,
};
struct hashlimit_cfg {
@@ -77,6 +78,21 @@ struct hashlimit_cfg2 {
__u8 srcmask, dstmask;
};
+struct hashlimit_cfg3 {
+ __u64 avg; /* Average secs between packets * scale */
+ __u64 burst; /* Period multiplier for upper limit. */
+ __u32 mode; /* bitmask of XT_HASHLIMIT_HASH_* */
+
+ /* user specified */
+ __u32 size; /* how many buckets */
+ __u32 max; /* max number of entries */
+ __u32 gc_interval; /* gc interval */
+ __u32 expire; /* when do entries expire? */
+
+ __u32 interval; /* in seconds*/
+ __u8 srcmask, dstmask;
+};
+
struct xt_hashlimit_mtinfo1 {
char name[IFNAMSIZ];
struct hashlimit_cfg1 cfg;
@@ -93,4 +109,12 @@ struct xt_hashlimit_mtinfo2 {
struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
};
+struct xt_hashlimit_mtinfo3 {
+ char name[NAME_MAX];
+ struct hashlimit_cfg3 cfg;
+
+ /* Used internally by the kernel */
+ struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
+};
+
#endif /*_XT_HASHLIMIT_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_srh.h b/include/linux/netfilter_ipv6/ip6t_srh.h
new file mode 100644
index 00000000..087efa1a
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_srh.h
@@ -0,0 +1,56 @@
+#ifndef _IP6T_SRH_H
+#define _IP6T_SRH_H
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+/* Values for "mt_flags" field in struct ip6t_srh */
+#define IP6T_SRH_NEXTHDR 0x0001
+#define IP6T_SRH_LEN_EQ 0x0002
+#define IP6T_SRH_LEN_GT 0x0004
+#define IP6T_SRH_LEN_LT 0x0008
+#define IP6T_SRH_SEGS_EQ 0x0010
+#define IP6T_SRH_SEGS_GT 0x0020
+#define IP6T_SRH_SEGS_LT 0x0040
+#define IP6T_SRH_LAST_EQ 0x0080
+#define IP6T_SRH_LAST_GT 0x0100
+#define IP6T_SRH_LAST_LT 0x0200
+#define IP6T_SRH_TAG 0x0400
+#define IP6T_SRH_MASK 0x07FF
+
+/* Values for "mt_invflags" field in struct ip6t_srh */
+#define IP6T_SRH_INV_NEXTHDR 0x0001
+#define IP6T_SRH_INV_LEN_EQ 0x0002
+#define IP6T_SRH_INV_LEN_GT 0x0004
+#define IP6T_SRH_INV_LEN_LT 0x0008
+#define IP6T_SRH_INV_SEGS_EQ 0x0010
+#define IP6T_SRH_INV_SEGS_GT 0x0020
+#define IP6T_SRH_INV_SEGS_LT 0x0040
+#define IP6T_SRH_INV_LAST_EQ 0x0080
+#define IP6T_SRH_INV_LAST_GT 0x0100
+#define IP6T_SRH_INV_LAST_LT 0x0200
+#define IP6T_SRH_INV_TAG 0x0400
+#define IP6T_SRH_INV_MASK 0x07FF
+
+/**
+ * struct ip6t_srh - SRH match options
+ * @ next_hdr: Next header field of SRH
+ * @ hdr_len: Extension header length field of SRH
+ * @ segs_left: Segments left field of SRH
+ * @ last_entry: Last entry field of SRH
+ * @ tag: Tag field of SRH
+ * @ mt_flags: match options
+ * @ mt_invflags: Invert the sense of match options
+ */
+
+struct ip6t_srh {
+ __u8 next_hdr;
+ __u8 hdr_len;
+ __u8 segs_left;
+ __u8 last_entry;
+ __u16 tag;
+ __u16 mt_flags;
+ __u16 mt_invflags;
+};
+
+#endif /*_IP6T_SRH_H*/
diff --git a/include/xtables-version.h b/include/xtables-version.h
index 65327656..ed31ad85 100644
--- a/include/xtables-version.h
+++ b/include/xtables-version.h
@@ -1,2 +1,2 @@
-#define XTABLES_VERSION "libxtables.so.10"
-#define XTABLES_VERSION_CODE 10
+#define XTABLES_VERSION "libxtables.so.12"
+#define XTABLES_VERSION_CODE 12
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
index 0db8d849..181e29f7 100644
--- a/iptables/ip6tables-restore.c
+++ b/iptables/ip6tables-restore.c
@@ -26,7 +26,7 @@
#define DEBUGP(x, args...)
#endif
-static int counters = 0, verbose = 0, noflush = 0, wait = 0;
+static int counters, verbose, noflush, wait;
static struct timeval wait_interval = {
.tv_sec = 1,
@@ -36,6 +36,7 @@ static struct timeval wait_interval = {
static const struct option options[] = {
{.name = "counters", .has_arg = 0, .val = 'c'},
{.name = "verbose", .has_arg = 0, .val = 'v'},
+ {.name = "version", .has_arg = 0, .val = 'V'},
{.name = "test", .has_arg = 0, .val = 't'},
{.name = "help", .has_arg = 0, .val = 'h'},
{.name = "noflush", .has_arg = 0, .val = 'n'},
@@ -46,13 +47,15 @@ static const struct option options[] = {
{NULL},
};
-static void print_usage(const char *name, const char *version) __attribute__((noreturn));
+#define prog_name ip6tables_globals.program_name
+#define prog_vers ip6tables_globals.program_version
static void print_usage(const char *name, const char *version)
{
- fprintf(stderr, "Usage: %s [-c] [-v] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
+ fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
+ " [ --version]\n"
" [ --test ]\n"
" [ --help ]\n"
" [ --noflush ]\n"
@@ -60,8 +63,6 @@ static void print_usage(const char *name, const char *version)
" [ --wait-interval=<usecs>\n"
" [ --table=<TABLE> ]\n"
" [ --modprobe=<command> ]\n", name);
-
- exit(1);
}
static struct xtc_handle *create_handle(const char *tablename)
@@ -78,8 +79,7 @@ static struct xtc_handle *create_handle(const char *tablename)
if (!handle) {
xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
- "table '%s'\n", ip6tables_globals.program_name,
- tablename);
+ "table '%s'\n", prog_name, tablename);
exit(1);
}
return handle;
@@ -165,8 +165,11 @@ static void add_param_to_argv(char *parsestart)
param_buffer[param_len] = '\0';
/* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
+ if ((param_buffer[0] == '-' &&
+ param_buffer[1] != '-' &&
+ strchr(param_buffer, 't')) ||
+ (!strncmp(param_buffer, "--t", 3) &&
+ !strncmp(param_buffer, "--table", strlen(param_buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be "
"used in ip6tables-restore.\n", line);
@@ -213,7 +216,7 @@ int ip6tables_restore_main(int argc, char *argv[])
init_extensions6();
#endif
- while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcvVthnwWM:T:", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -224,13 +227,16 @@ int ip6tables_restore_main(int argc, char *argv[])
case 'v':
verbose = 1;
break;
+ case 'V':
+ printf("%s v%s\n", prog_name, prog_vers);
+ exit(0);
case 't':
testing = 1;
break;
case 'h':
print_usage("ip6tables-restore",
IPTABLES_VERSION);
- break;
+ exit(0);
case 'n':
noflush = 1;
break;
@@ -246,6 +252,10 @@ int ip6tables_restore_main(int argc, char *argv[])
case 'T':
tablename = optarg;
break;
+ default:
+ fprintf(stderr,
+ "Try `ip6tables-restore -h' for more information.\n");
+ exit(1);
}
}
@@ -263,6 +273,11 @@ int ip6tables_restore_main(int argc, char *argv[])
}
else in = stdin;
+ if (!wait_interval.tv_sec && !wait) {
+ fprintf(stderr, "Option --wait-interval requires option --wait\n");
+ exit(1);
+ }
+
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret = 0;
diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c
index 053413a9..8e3a6afd 100644
--- a/iptables/ip6tables-save.c
+++ b/iptables/ip6tables-save.c
@@ -14,17 +14,19 @@
#include <time.h>
#include <netdb.h>
#include <arpa/inet.h>
+#include <unistd.h>
#include "libiptc/libip6tc.h"
#include "ip6tables.h"
#include "ip6tables-multi.h"
-static int show_counters = 0;
+static int show_counters;
static const struct option options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "dump", .has_arg = false, .val = 'd'},
{.name = "table", .has_arg = true, .val = 't'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
+ {.name = "file", .has_arg = true, .val = 'f'},
{NULL},
};
@@ -128,7 +130,8 @@ static int do_output(const char *tablename)
int ip6tables_save_main(int argc, char *argv[])
{
const char *tablename = NULL;
- int c;
+ FILE *file = NULL;
+ int ret, c;
ip6tables_globals.program_name = "ip6tables-save";
c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
@@ -143,7 +146,7 @@ int ip6tables_save_main(int argc, char *argv[])
init_extensions6();
#endif
- while ((c = getopt_long(argc, argv, "bcdt:M:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcdt:M:f:", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -159,9 +162,28 @@ int ip6tables_save_main(int argc, char *argv[])
case 'M':
xtables_modprobe_program = optarg;
break;
+ case 'f':
+ file = fopen(optarg, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ ret = dup2(fileno(file), STDOUT_FILENO);
+ if (ret == -1) {
+ fprintf(stderr, "Failed to redirect stdout, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ fclose(file);
+ break;
case 'd':
do_output(tablename);
exit(0);
+ default:
+ fprintf(stderr,
+ "Look at manual page `ip6tables-save.8' for more information.\n");
+ exit(1);
}
}
diff --git a/iptables/iptables-restore.8.in b/iptables/iptables-restore.8.in
index 7a286b91..f751492d 100644
--- a/iptables/iptables-restore.8.in
+++ b/iptables/iptables-restore.8.in
@@ -23,11 +23,13 @@ iptables-restore \(em Restore IP Tables
.P
ip6tables-restore \(em Restore IPv6 Tables
.SH SYNOPSIS
-\fBiptables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
-[\fB\-T\fP \fIname\fP] [\fBfile\fP]
+\fBiptables\-restore\fP [\fB\-chntvV\fP] [\fB\-w\fP \fIsecs\fP]
+[\fB\-W\fP \fIusecs\fP] [\fB\-M\fP \fImodprobe\fP] [\fB\-T\fP \fIname\fP]
+[\fBfile\fP]
.P
-\fBip6tables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
-[\fB\-T\fP \fIname\fP] [\fBfile\fP]
+\fBip6tables\-restore\fP [\fB\-chntvV\fP] [\fB\-w\fP \fIsecs\fP]
+[\fB\-W\fP \fIusecs\fP] [\fB\-M\fP \fImodprobe\fP] [\fB\-T\fP \fIname\fP]
+[\fBfile\fP]
.SH DESCRIPTION
.PP
.B iptables-restore
@@ -53,6 +55,24 @@ Only parse and construct the ruleset, but do not commit it.
\fB\-v\fP, \fB\-\-verbose\fP
Print additional debug info during ruleset processing.
.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version number.
+.TP
+\fB\-w\fP, \fB\-\-wait\fP [\fIseconds\fP]
+Wait for the xtables lock.
+To prevent multiple instances of the program from running concurrently,
+an attempt will be made to obtain an exclusive lock at launch. By default,
+the program will exit if the lock cannot be obtained. This option will
+make the program wait (indefinitely or for optional \fIseconds\fP) until
+the exclusive lock can be obtained.
+.TP
+\fB\-W\fP, \fB\-\-wait-interval\fP \fImicroseconds\fP
+Interval to wait per each iteration.
+When running latency sensitive applications, waiting for the xtables lock
+for extended durations may not be acceptable. This option will make each
+iteration take the amount of time specified. The default interval is
+1 second. This option only works with \fB\-w\fP.
+.TP
\fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP
Specify the path to the modprobe program. By default, iptables-restore will
inspect /proc/sys/kernel/modprobe to determine the executable's path.
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 078d1d46..e63a3e50 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -23,7 +23,7 @@
#define DEBUGP(x, args...)
#endif
-static int counters = 0, verbose = 0, noflush = 0, wait = 0;
+static int counters, verbose, noflush, wait;
static struct timeval wait_interval = {
.tv_sec = 1,
@@ -33,6 +33,7 @@ static struct timeval wait_interval = {
static const struct option options[] = {
{.name = "counters", .has_arg = 0, .val = 'c'},
{.name = "verbose", .has_arg = 0, .val = 'v'},
+ {.name = "version", .has_arg = 0, .val = 'V'},
{.name = "test", .has_arg = 0, .val = 't'},
{.name = "help", .has_arg = 0, .val = 'h'},
{.name = "noflush", .has_arg = 0, .val = 'n'},
@@ -43,15 +44,15 @@ static const struct option options[] = {
{NULL},
};
-static void print_usage(const char *name, const char *version) __attribute__((noreturn));
-
#define prog_name iptables_globals.program_name
+#define prog_vers iptables_globals.program_version
static void print_usage(const char *name, const char *version)
{
- fprintf(stderr, "Usage: %s [-c] [-v] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
+ fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
+ " [ --version]\n"
" [ --test ]\n"
" [ --help ]\n"
" [ --noflush ]\n"
@@ -59,8 +60,6 @@ static void print_usage(const char *name, const char *version)
" [ --wait-interval=<usecs>\n"
" [ --table=<TABLE> ]\n"
" [ --modprobe=<command> ]\n", name);
-
- exit(1);
}
static struct xtc_handle *create_handle(const char *tablename)
@@ -163,8 +162,11 @@ static void add_param_to_argv(char *parsestart)
param_buffer[param_len] = '\0';
/* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
+ if ((param_buffer[0] == '-' &&
+ param_buffer[1] != '-' &&
+ strchr(param_buffer, 't')) ||
+ (!strncmp(param_buffer, "--t", 3) &&
+ !strncmp(param_buffer, "--table", strlen(param_buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be "
"used in iptables-restore.\n", line);
@@ -212,7 +214,7 @@ iptables_restore_main(int argc, char *argv[])
init_extensions4();
#endif
- while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcvVthnwWM:T:", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -223,13 +225,16 @@ iptables_restore_main(int argc, char *argv[])
case 'v':
verbose = 1;
break;
+ case 'V':
+ printf("%s v%s\n", prog_name, prog_vers);
+ exit(0);
case 't':
testing = 1;
break;
case 'h':
print_usage("iptables-restore",
IPTABLES_VERSION);
- break;
+ exit(0);
case 'n':
noflush = 1;
break;
@@ -245,6 +250,10 @@ iptables_restore_main(int argc, char *argv[])
case 'T':
tablename = optarg;
break;
+ default:
+ fprintf(stderr,
+ "Try `iptables-restore -h' for more information.\n");
+ exit(1);
}
}
@@ -262,6 +271,11 @@ iptables_restore_main(int argc, char *argv[])
}
else in = stdin;
+ if (!wait_interval.tv_sec && !wait) {
+ fprintf(stderr, "Option --wait-interval requires option --wait\n");
+ exit(1);
+ }
+
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret = 0;
diff --git a/iptables/iptables-save.8.in b/iptables/iptables-save.8.in
index 7f99d8a3..51e11f3e 100644
--- a/iptables/iptables-save.8.in
+++ b/iptables/iptables-save.8.in
@@ -19,27 +19,31 @@
.\"
.\"
.SH NAME
-iptables-save \(em dump iptables rules to stdout
+iptables-save \(em dump iptables rules
.P
-ip6tables-save \(em dump iptables rules to stdout
+ip6tables-save \(em dump iptables rules
.SH SYNOPSIS
\fBiptables\-save\fP [\fB\-M\fP \fImodprobe\fP] [\fB\-c\fP]
-[\fB\-t\fP \fItable\fP]
+[\fB\-t\fP \fItable\fP] [\fB\-f\fP \fIfilename\fP]
.P
\fBip6tables\-save\fP [\fB\-M\fP \fImodprobe\fP] [\fB\-c\fP]
-[\fB\-t\fP \fItable\fP]
+[\fB\-t\fP \fItable\fP] [\fB\-f\fP \fIfilename\fP]
.SH DESCRIPTION
.PP
.B iptables-save
and
.B ip6tables-save
are used to dump the contents of IP or IPv6 Table in easily parseable format
-to STDOUT. Use I/O-redirection provided by your shell to write to a file.
+either to STDOUT or to a specified file.
.TP
\fB\-M\fR, \fB\-\-modprobe\fR \fImodprobe_program\fP
Specify the path to the modprobe program. By default, iptables-save will
inspect /proc/sys/kernel/modprobe to determine the executable's path.
.TP
+\fB\-f\fR, \fB\-\-file\fR \fIfilename\fP
+Specify a filename to log the output to. If not specified, iptables-save
+will log to STDOUT.
+.TP
\fB\-c\fR, \fB\-\-counters\fR
include the current values of all packet and byte counters in the output
.TP
diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c
index e8ae9c6c..d59bd34a 100644
--- a/iptables/iptables-save.c
+++ b/iptables/iptables-save.c
@@ -13,17 +13,19 @@
#include <string.h>
#include <time.h>
#include <netdb.h>
+#include <unistd.h>
#include "libiptc/libiptc.h"
#include "iptables.h"
#include "iptables-multi.h"
-static int show_counters = 0;
+static int show_counters;
static const struct option options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "dump", .has_arg = false, .val = 'd'},
{.name = "table", .has_arg = true, .val = 't'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
+ {.name = "file", .has_arg = true, .val = 'f'},
{NULL},
};
@@ -127,7 +129,8 @@ int
iptables_save_main(int argc, char *argv[])
{
const char *tablename = NULL;
- int c;
+ FILE *file = NULL;
+ int ret, c;
iptables_globals.program_name = "iptables-save";
c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
@@ -142,7 +145,7 @@ iptables_save_main(int argc, char *argv[])
init_extensions4();
#endif
- while ((c = getopt_long(argc, argv, "bcdt:M:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcdt:M:f:", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -158,9 +161,28 @@ iptables_save_main(int argc, char *argv[])
case 'M':
xtables_modprobe_program = optarg;
break;
+ case 'f':
+ file = fopen(optarg, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ ret = dup2(fileno(file), STDOUT_FILENO);
+ if (ret == -1) {
+ fprintf(stderr, "Failed to redirect stdout, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ fclose(file);
+ break;
case 'd':
do_output(tablename);
exit(0);
+ default:
+ fprintf(stderr,
+ "Look at manual page `iptables-save.8' for more information.\n");
+ exit(1);
}
}
diff --git a/iptables/iptables-standalone.c b/iptables/iptables-standalone.c
index c60b4b77..3a4d5e37 100644
--- a/iptables/iptables-standalone.c
+++ b/iptables/iptables-standalone.c
@@ -76,9 +76,8 @@ iptables_main(int argc, char *argv[])
fprintf(stderr, "iptables: %s.\n",
iptc_strerror(errno));
}
- if (errno == EAGAIN) {
+ if (errno == EAGAIN)
exit(RESOURCE_PROBLEM);
- }
}
exit(!ret);
diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c
index 740a563c..49674ec1 100644
--- a/iptables/iptables-xml.c
+++ b/iptables/iptables-xml.c
@@ -34,9 +34,9 @@ struct xtables_globals iptables_xml_globals = {
static void print_usage(const char *name, const char *version)
__attribute__ ((noreturn));
-static int verbose = 0;
+static int verbose;
/* Whether to combine actions of sequential rules with identical conditions */
-static int combine = 0;
+static int combine;
/* Keeping track of external matches and targets. */
static struct option options[] = {
{"verbose", 0, NULL, 'v'},
@@ -73,10 +73,10 @@ parse_counters(char *string, struct xt_counters *ctr)
/* global new argv and argc */
static char *newargv[255];
-static unsigned int newargc = 0;
+static unsigned int newargc;
static char *oldargv[255];
-static unsigned int oldargc = 0;
+static unsigned int oldargc;
/* arg meta data, were they quoted, frinstance */
static int newargvattr[255];
@@ -96,7 +96,7 @@ struct chain {
#define maxChains 10240 /* max chains per table */
static struct chain chains[maxChains];
-static int nextChain = 0;
+static int nextChain;
/* funCtion adding one argument to newargv, updating newargc
* returns true if argument added, false otherwise */
@@ -426,12 +426,9 @@ do_rule_part(char *leveltag1, char *leveltag2, int part, int argc,
else
printf("%s%s", spacer, argv[arg]);
spacer = " ";
- } else if (!argvattr[arg] && isTarget(argv[arg])
- && existsChain(argv[arg + 1])
- && (2 + arg >= argc)) {
- if (!((1 + arg) < argc))
- // no args to -j, -m or -g, ignore & finish loop
- break;
+ } else if (!argvattr[arg] && isTarget(argv[arg]) &&
+ (arg + 1 < argc) &&
+ existsChain(argv[arg + 1])) {
CLOSE_LEVEL(2);
if (level1)
printf("%s", leveli1);
@@ -819,9 +816,11 @@ iptables_xml_main(int argc, char *argv[])
*(param_buffer + param_len) = '\0';
/* check if table name specified */
- if (!strncmp(param_buffer, "-t", 3)
- || !strncmp(param_buffer,
- "--table", 8)) {
+ if ((param_buffer[0] == '-' &&
+ param_buffer[1] != '-' &&
+ strchr(param_buffer, 't')) ||
+ (!strncmp(param_buffer, "--t", 3) &&
+ !strncmp(param_buffer, "--table", strlen(param_buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"Line %u seems to have a "
"-t table option.\n",
diff --git a/iptables/iptables.c b/iptables/iptables.c
index d61d5b90..69d19fec 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1114,9 +1114,8 @@ void print_rule4(const struct ipt_entry *e,
e->ip.invflags & IPT_INV_FRAG ? " !" : "");
/* Print matchinfo part */
- if (e->target_offset) {
+ if (e->target_offset)
IPT_MATCH_ITERATE(e, print_match_save, &e->ip);
- }
/* print counters for iptables -R */
if (counters < 0)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index e5947a7c..00dd3e93 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -320,6 +320,8 @@ static void nft_ipv4_print_firewall(struct nftnl_rule *r, unsigned int num,
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
+
+ xtables_rule_matches_free(&cs.matches);
}
static void save_ipv4_addr(char letter, const struct in_addr *addr,
@@ -488,7 +490,7 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
return ret;
/* Always add counters per rule, as in iptables */
- xt_xlate_add(xl, "counter ");
+ xt_xlate_add(xl, "counter");
ret = xlate_action(cs, !!(cs->fw.ip.flags & IPT_F_GOTO), xl);
comment = xt_xlate_get_comment(xl);
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 9cf4058f..9867d1ee 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -251,6 +251,8 @@ static void nft_ipv6_print_firewall(struct nftnl_rule *r, unsigned int num,
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
+
+ xtables_rule_matches_free(&cs.matches);
}
static void save_ipv6_addr(char letter, const struct in6_addr *addr,
@@ -437,7 +439,7 @@ static int nft_ipv6_xlate(const void *data, struct xt_xlate *xl)
return ret;
/* Always add counters per rule, as in iptables */
- xt_xlate_add(xl, "counter ");
+ xt_xlate_add(xl, "counter");
ret = xlate_action(cs, !!(cs->fw6.ipv6.flags & IP6T_F_GOTO), xl);
comment = xt_xlate_get_comment(xl);
diff --git a/iptables/nft.c b/iptables/nft.c
index fee91bc7..91381419 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -147,7 +147,8 @@ static void mnl_nftnl_batch_reset(void)
list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
list_del(&batch_page->head);
- free(batch_page->batch);
+ free(mnl_nlmsg_batch_head(batch_page->batch));
+ mnl_nlmsg_batch_stop(batch_page->batch);
free(batch_page);
batch_num_pages--;
}
@@ -1454,13 +1455,18 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
return ret == 0 ? 1 : 0;
}
+/* From linux/netlink.h */
+#ifndef NLM_F_NONREC
+#define NLM_F_NONREC 0x100 /* Do not delete recursively */
+#endif
+
static int __nft_chain_del(struct nft_handle *h, struct nftnl_chain *c)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
- NLM_F_ACK, h->seq);
+ NLM_F_NONREC | NLM_F_ACK, h->seq);
nftnl_chain_nlmsg_build_payload(nlh, c);
return mnl_talk(h, nlh, NULL, NULL);
@@ -2348,7 +2354,8 @@ static int nft_action(struct nft_handle *h, int action)
break;
case NFT_COMPAT_CHAIN_USER_DEL:
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
- 0, seq++, n->chain);
+ NLM_F_NONREC, seq++,
+ n->chain);
break;
case NFT_COMPAT_CHAIN_UPDATE:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
@@ -2536,8 +2543,8 @@ static void xtables_config_perror(uint32_t flags, const char *fmt, ...)
int nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags)
{
- struct nftnl_table_list *table_list = nftnl_table_list_alloc();
- struct nftnl_chain_list *chain_list = nftnl_chain_list_alloc();
+ struct nftnl_table_list *table_list = NULL;
+ struct nftnl_chain_list *chain_list = NULL;
struct nftnl_table_list_iter *titer = NULL;
struct nftnl_chain_list_iter *citer = NULL;
struct nftnl_table *table;
@@ -2548,6 +2555,9 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
if (h->restore)
return 0;
+ table_list = nftnl_table_list_alloc();
+ chain_list = nftnl_chain_list_alloc();
+
if (xtables_config_parse(filename, table_list, chain_list) < 0) {
if (errno == ENOENT) {
xtables_config_perror(flags,
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 825479c3..06db72d4 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -343,7 +343,7 @@ void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval)
else if (xs_has_arg(argc, argv))
arg = argv[optind++];
else
- return;
+ xtables_error(PARAMETER_PROBLEM, "wait interval value required");
ret = sscanf(arg, "%u", &usec);
if (ret == 1) {
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 6aa000a1..4a968f4b 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -150,7 +150,7 @@ static struct option original_opts[] = {
int RUNTIME_NF_ARP_NUMHOOKS = 3;
static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
+static unsigned int global_option_offset;
extern void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
struct xtables_globals arptables_globals = {
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index a551c8c1..fc39ad9c 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -24,7 +24,7 @@
#define DEBUGP(x, args...)
#endif
-static int counters = 0, verbose = 0, noflush = 0;
+static int counters, verbose, noflush;
/* Keeping track of external matches and targets. */
static const struct option options[] = {
@@ -40,8 +40,6 @@ static const struct option options[] = {
{NULL},
};
-static void print_usage(const char *name, const char *version) __attribute__((noreturn));
-
#define prog_name xtables_globals.program_name
static void print_usage(const char *name, const char *version)
@@ -56,8 +54,6 @@ static void print_usage(const char *name, const char *version)
" [ --modprobe=<command> ]\n"
" [ --ipv4 ]\n"
" [ --ipv6 ]\n", name);
-
- exit(1);
}
static int parse_counters(char *string, struct xt_counters *ctr)
@@ -140,8 +136,11 @@ static void add_param_to_argv(char *parsestart)
param_buffer[param_len] = '\0';
/* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
+ if ((param_buffer[0] == '-' &&
+ param_buffer[1] != '-' &&
+ strchr(param_buffer, 't')) ||
+ (!strncmp(param_buffer, "--t", 3) &&
+ !strncmp(param_buffer, "--table", strlen(param_buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be "
"used in xtables-restore.\n", line);
@@ -181,8 +180,10 @@ static void chain_delete(struct nftnl_chain_list *clist, const char *curtable,
/* This chain has been found, delete from list. Later
* on, unvisited chains will be purged out.
*/
- if (chain_obj != NULL)
+ if (chain_obj != NULL) {
nftnl_chain_list_del(chain_obj);
+ nftnl_chain_free(chain_obj);
+ }
}
struct nft_xt_restore_cb restore_cb = {
@@ -434,6 +435,9 @@ void xtables_restore_parse(struct nft_handle *h,
xt_params->program_name, line + 1);
exit(1);
}
+
+ if (chain_list)
+ nftnl_chain_list_free(chain_list);
}
static int
@@ -486,7 +490,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
case 'h':
print_usage("xtables-restore",
IPTABLES_VERSION);
- break;
+ exit(0);
case 'n':
noflush = 1;
break;
@@ -503,6 +507,10 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
h.family = AF_INET6;
xtables_set_nfproto(AF_INET6);
break;
+ default:
+ fprintf(stderr,
+ "Try `xtables-restore -h' for more information.\n");
+ exit(1);
}
}
@@ -522,6 +530,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
xtables_restore_parse(&h, &p, &restore_cb, argc, argv);
+ nft_fini(&h);
fclose(p.in);
return 0;
}
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index f30867cf..5b498b04 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -14,6 +14,7 @@
#include <string.h>
#include <time.h>
#include <netdb.h>
+#include <unistd.h>
#include "libiptc/libiptc.h"
#include "iptables.h"
#include "xtables-multi.h"
@@ -32,6 +33,7 @@ static const struct option options[] = {
{.name = "dump", .has_arg = false, .val = 'd'},
{.name = "table", .has_arg = true, .val = 't'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
+ {.name = "file", .has_arg = true, .val = 'f'},
{.name = "ipv4", .has_arg = false, .val = '4'},
{.name = "ipv6", .has_arg = false, .val = '6'},
{NULL},
@@ -82,7 +84,8 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
struct nft_handle h = {
.family = family,
};
- int c;
+ FILE *file = NULL;
+ int ret, c;
xtables_globals.program_name = progname;
c = xtables_init_all(&xtables_globals, family);
@@ -104,7 +107,7 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
exit(EXIT_FAILURE);
}
- while ((c = getopt_long(argc, argv, "bcdt:M:46", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcdt:M:f:46", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -120,6 +123,21 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
case 'M':
xtables_modprobe_program = optarg;
break;
+ case 'f':
+ file = fopen(optarg, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ ret = dup2(fileno(file), STDOUT_FILENO);
+ if (ret == -1) {
+ fprintf(stderr, "Failed to redirect stdout, error: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ fclose(file);
+ break;
case 'd':
dump = true;
break;
@@ -130,6 +148,10 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
h.family = AF_INET6;
xtables_set_nfproto(AF_INET6);
break;
+ default:
+ fprintf(stderr,
+ "Look at manual page `xtables-save.8' for more information.\n");
+ exit(1);
}
}
diff --git a/iptables/xtables-standalone.c b/iptables/xtables-standalone.c
index 355a4460..139c477f 100644
--- a/iptables/xtables-standalone.c
+++ b/iptables/xtables-standalone.c
@@ -85,9 +85,8 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
fprintf(stderr, "iptables: %s.\n",
nft_strerror(errno));
}
- if (errno == EAGAIN) {
+ if (errno == EAGAIN)
exit(RESOURCE_PROBLEM);
- }
}
exit(!ret);
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index 153bd650..4f6a9caf 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -60,12 +60,13 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set,
if (cs->target != NULL) {
/* Standard target? */
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
- xt_xlate_add(xl, "accept");
+ xt_xlate_add(xl, " accept");
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
- xt_xlate_add(xl, "drop");
+ xt_xlate_add(xl, " drop");
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
- xt_xlate_add(xl, "return");
+ xt_xlate_add(xl, " return");
else if (cs->target->xlate) {
+ xt_xlate_add(xl, " ");
struct xt_xlate_tg_params params = {
.ip = (const void *)&cs->fw,
.target = cs->target->t,
@@ -79,9 +80,9 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set,
} else if (strlen(cs->jumpto) > 0) {
/* Not standard, then it's a go / jump to chain */
if (goto_set)
- xt_xlate_add(xl, "goto %s", cs->jumpto);
+ xt_xlate_add(xl, " goto %s", cs->jumpto);
else
- xt_xlate_add(xl, "jump %s", cs->jumpto);
+ xt_xlate_add(xl, " jump %s", cs->jumpto);
}
return ret;
@@ -195,6 +196,8 @@ static int xlate(struct nft_handle *h, struct nft_xt_cmd_parse *p,
}
break;
}
+ if (!cs->restore && i < args->s.naddrs - 1)
+ printf("nft ");
}
return ret;
@@ -234,9 +237,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
switch (p.command) {
case CMD_APPEND:
ret = 1;
- if (!xlate(h, &p, &cs, &args, true, nft_rule_xlate_add)) {
+ if (!xlate(h, &p, &cs, &args, true, nft_rule_xlate_add))
print_ipt_cmd(argc, argv);
- }
break;
case CMD_DELETE:
break;
@@ -248,9 +250,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
break;
case CMD_INSERT:
ret = 1;
- if (!xlate(h, &p, &cs, &args, false, nft_rule_xlate_add)) {
+ if (!xlate(h, &p, &cs, &args, false, nft_rule_xlate_add))
print_ipt_cmd(argc, argv);
- }
break;
case CMD_FLUSH:
if (p.chain) {
@@ -356,6 +357,8 @@ static int xlate_chain_set(struct nft_handle *h, const char *table,
if (strcmp(table, "nat") == 0)
type = "nat";
+ else if (strcmp(table, "mangle") == 0 && strcmp(chain, "OUTPUT") == 0)
+ type = "route";
printf("add chain %s %s %s { type %s ",
family2str[h->family], table, chain, type);
@@ -379,6 +382,14 @@ static int xlate_chain_set(struct nft_handle *h, const char *table,
return 1;
}
+static int dummy_compat_rev(const char *name, uint8_t rev, int opt)
+{
+ /* Avoid querying the kernel - it's not needed when just translating
+ * rules and not even possible when running as unprivileged user.
+ */
+ return 1;
+}
+
static struct nft_xt_restore_cb cb_xlate = {
.table_new = xlate_table_new,
.chain_set = xlate_chain_set,
@@ -398,6 +409,7 @@ static int xtables_xlate_main(int family, const char *progname, int argc,
};
xtables_globals.program_name = progname;
+ xtables_globals.compat_rev = dummy_compat_rev;
ret = xtables_init_all(&xtables_globals, family);
if (ret < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
@@ -440,6 +452,7 @@ static int xtables_restore_xlate_main(int family, const char *progname,
int c;
xtables_globals.program_name = progname;
+ xtables_globals.compat_rev = dummy_compat_rev;
ret = xtables_init_all(&xtables_globals, family);
if (ret < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 286866f7..ac113254 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -1281,6 +1281,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
*table = p.table;
xtables_rule_matches_free(&cs.matches);
+ if (cs.target)
+ free(cs.target->t);
if (h->family == AF_INET) {
free(args.s.addr.v4);
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index d21c391e..b28ca0ae 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -1693,7 +1693,8 @@ iptcc_standard_map(struct rule_head *r, int verdict)
static int
iptcc_map_target(struct xtc_handle *const handle,
- struct rule_head *r)
+ struct rule_head *r,
+ bool dry_run)
{
STRUCT_ENTRY *e = r->entry;
STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
@@ -1738,7 +1739,8 @@ iptcc_map_target(struct xtc_handle *const handle,
0,
FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
r->type = IPTCC_R_MODULE;
- set_changed(handle);
+ if (!dry_run)
+ set_changed(handle);
return 1;
}
@@ -1788,7 +1790,7 @@ TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
- if (!iptcc_map_target(handle, r)) {
+ if (!iptcc_map_target(handle, r, false)) {
free(r);
return 0;
}
@@ -1838,7 +1840,7 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
- if (!iptcc_map_target(handle, r)) {
+ if (!iptcc_map_target(handle, r, false)) {
free(r);
return 0;
}
@@ -1877,7 +1879,7 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
- if (!iptcc_map_target(handle, r)) {
+ if (!iptcc_map_target(handle, r, false)) {
DEBUGP("unable to map target of rule for chain `%s'\n", chain);
free(r);
return 0;
@@ -1983,7 +1985,7 @@ static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw,
memcpy(r->entry, origfw, origfw->next_offset);
r->counter_map.maptype = COUNTER_MAP_NOMAP;
- if (!iptcc_map_target(handle, r)) {
+ if (!iptcc_map_target(handle, r, dry_run)) {
DEBUGP("unable to map target of rule for chain `%s'\n", chain);
free(r);
return 0;
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index d43f9706..57a11022 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -538,15 +538,15 @@ void xtables_parse_interface(const char *arg, char *vianame,
} else {
/* Include nul-terminator in match */
memset(mask, 0xFF, vialen + 1);
- for (i = 0; vianame[i]; i++) {
- if (vianame[i] == '/' ||
- vianame[i] == ' ') {
- fprintf(stderr,
- "Warning: weird character in interface"
- " `%s' ('/' and ' ' are not allowed by the kernel).\n",
- vianame);
- break;
- }
+ }
+
+ /* Display warning on invalid characters */
+ for (i = 0; vianame[i]; i++) {
+ if (vianame[i] == '/' || vianame[i] == ' ') {
+ fprintf(stderr, "Warning: weird character in interface"
+ " `%s' ('/' and ' ' are not allowed by the kernel).\n",
+ vianame);
+ break;
}
}
}
@@ -1367,26 +1367,22 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
unsigned int i;
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_RAW;
*naddr = 0;
- if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
+ err = getaddrinfo(name, NULL, &hints, &res);
+ if (err != 0)
return NULL;
- } else {
- for (p = res; p != NULL; p = p->ai_next)
- ++*naddr;
- addr = xtables_calloc(*naddr, sizeof(struct in_addr));
- for (i = 0, p = res; p != NULL; p = p->ai_next)
- memcpy(&addr[i++],
- &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
- sizeof(struct in_addr));
- freeaddrinfo(res);
- return addr;
- }
-
- return NULL;
+ for (p = res; p != NULL; p = p->ai_next)
+ ++*naddr;
+ addr = xtables_calloc(*naddr, sizeof(struct in_addr));
+ for (i = 0, p = res; p != NULL; p = p->ai_next)
+ memcpy(&addr[i++],
+ &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
+ sizeof(struct in_addr));
+ freeaddrinfo(res);
+ return addr;
}
static struct in_addr *
@@ -1657,28 +1653,24 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
unsigned int i;
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
*naddr = 0;
- if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
+ err = getaddrinfo(name, NULL, &hints, &res);
+ if (err != 0)
return NULL;
- } else {
- /* Find length of address chain */
- for (p = res; p != NULL; p = p->ai_next)
- ++*naddr;
- /* Copy each element of the address chain */
- addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
- for (i = 0, p = res; p != NULL; p = p->ai_next)
- memcpy(&addr[i++],
- &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
- sizeof(struct in6_addr));
- freeaddrinfo(res);
- return addr;
- }
-
- return NULL;
+ /* Find length of address chain */
+ for (p = res; p != NULL; p = p->ai_next)
+ ++*naddr;
+ /* Copy each element of the address chain */
+ addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
+ for (i = 0, p = res; p != NULL; p = p->ai_next)
+ memcpy(&addr[i++],
+ &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
+ sizeof(struct in6_addr));
+ freeaddrinfo(res);
+ return addr;
}
static struct in6_addr *network_to_ip6addr(const char *name)
diff --git a/utils/.gitignore b/utils/.gitignore
index 216d1e4a..7c6afbf4 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -1,2 +1,3 @@
/nfnl_osf
+/nfnl_osf.8
/nfbpf_compile
diff --git a/utils/Makefile.am b/utils/Makefile.am
index c4192a9e..80029e30 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -6,8 +6,10 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \
sbin_PROGRAMS =
pkgdata_DATA =
+man_MANS =
if HAVE_LIBNFNETLINK
+man_MANS += nfnl_osf.8
sbin_PROGRAMS += nfnl_osf
pkgdata_DATA += pf.os
@@ -23,3 +25,5 @@ if ENABLE_SYNCONF
sbin_PROGRAMS += nfsynproxy
nfsynproxy_LDADD = -lpcap
endif
+
+CLEANFILES = nfnl_osf.8
diff --git a/utils/nfnl_osf.8.in b/utils/nfnl_osf.8.in
new file mode 100644
index 00000000..140b5c3f
--- /dev/null
+++ b/utils/nfnl_osf.8.in
@@ -0,0 +1,67 @@
+.TH NFNL_OSF 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@"
+
+.SH NAME
+nfnl_osf \- OS fingerprint loader utility
+.SH SYNOPSIS
+
+.ad l
+.in +8
+.ti -8
+.B nfnl_osf
+.BI -f " fingerprints"
+[
+.B -d
+]
+
+.SH DESCRIPTION
+The
+.B nfnl_osf
+utility allows to load a set of operating system signatures into the kernel for
+later matching against using iptables'
+.B osf
+match.
+
+.SH OPTIONS
+
+.TP
+.BI -f " fingerprints"
+Read signatures from file
+.IR fingerprints .
+
+.TP
+.B -d
+Instead of adding the signatures from
+.I fingerprints
+into the kernel, remove them.
+
+.SH EXIT STATUS
+Exit status is 0 if command succeeded, otherwise a negative return code
+indicates the type of error which happened:
+
+.TP
+.B -1
+Illegal arguments passed, fingerprints file not readable or failure in netlink
+communication.
+
+.TP
+.B -ENOENT
+Fingerprints file not specified.
+
+.TP
+.B -EINVAL
+Netlink handle initialization failed or fingerprints file format invalid.
+
+.SH FILES
+
+An up to date set of operating system signatures can be downloaded from
+http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os .
+
+.SH SEE ALSO
+
+The description of
+.B osf
+match in
+.BR iptables-extensions (8)
+contains further information about the topic as well as example
+.B nfnl_osf
+invocations.
diff --git a/utils/nfnl_osf.c b/utils/nfnl_osf.c
index 645ec648..720e3a38 100644
--- a/utils/nfnl_osf.c
+++ b/utils/nfnl_osf.c
@@ -438,7 +438,7 @@ int main(int argc, char *argv[])
break;
default:
fprintf(stderr,
- "Usage: %s -f fingerprints -d <del rules> -h\n",
+ "Usage: %s -f fingerprints [-d]\n",
argv[0]);
return -1;
}
diff --git a/utils/nfsynproxy.c b/utils/nfsynproxy.c
index baedc92c..bf5c4163 100644
--- a/utils/nfsynproxy.c
+++ b/utils/nfsynproxy.c
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
diff --git a/utils/pf.os b/utils/pf.os
index 01fb85be..e285851e 100644
--- a/utils/pf.os
+++ b/utils/pf.os
@@ -1,5 +1,5 @@
# $FreeBSD: head/etc/pf.os 258865 2013-12-03 04:32:02Z eadler $
-# $OpenBSD: pf.os,v 1.26 2012/08/03 12:25:16 jsg Exp $
+# $OpenBSD: pf.os,v 1.27 2016/09/03 17:08:57 sthen Exp $
# passive OS fingerprinting
# -------------------------
#
@@ -315,6 +315,9 @@ S22:64:1:52:M*,N,N,S,N,W0: Linux:2.2:ts:Linux 2.2 w/o timestamps
16384:64:1:64:M*,N,N,S,N,W3,N,N,T: OpenBSD:4.9::OpenBSD 4.9
16384:64:0:64:M*,N,N,S,N,W3,N,N,T: OpenBSD:4.9:no-df:OpenBSD 4.9 (scrub no-df)
+16384:64:1:64:M*,N,N,S,N,W6,N,N,T: OpenBSD:6.1::OpenBSD 6.1
+16384:64:0:64:M*,N,N,S,N,W6,N,N,T: OpenBSD:6.1:no-df:OpenBSD 6.1 (scrub no-df)
+
# ----------------- DragonFly BSD -----------------
57344:64:1:60:M*,N,W0,N,N,T: DragonFly:1.0:A:DragonFly 1.0A
diff --git a/xlate-test.py b/xlate-test.py
new file mode 100755
index 00000000..dbba1d67
--- /dev/null
+++ b/xlate-test.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+
+import os
+import sys
+import shlex
+import argparse
+from subprocess import Popen, PIPE
+
+keywords = ("iptables-translate", "ip6tables-translate")
+
+if sys.stdout.isatty():
+ colors = {"magenta": "\033[95m", "green": "\033[92m", "yellow": "\033[93m",
+ "red": "\033[91m", "end": "\033[0m"}
+else:
+ colors = {"magenta": "", "green": "", "yellow": "", "red": "", "end": ""}
+
+
+def magenta(string):
+ return colors["magenta"] + string + colors["end"]
+
+
+def red(string):
+ return colors["red"] + string + colors["end"]
+
+
+def yellow(string):
+ return colors["yellow"] + string + colors["end"]
+
+
+def green(string):
+ return colors["green"] + string + colors["end"]
+
+
+def run_test(name, payload):
+ test_passed = True
+ tests = passed = failed = errors = 0
+ result = []
+
+ for line in payload:
+ if line.startswith(keywords):
+ tests += 1
+ process = Popen(shlex.split(line), stdout=PIPE, stderr=PIPE)
+ (output, error) = process.communicate()
+ if process.returncode == 0:
+ translation = output.decode("utf-8").rstrip(" \n")
+ expected = next(payload).rstrip(" \n")
+ if translation != expected:
+ test_passed = False
+ failed += 1
+ result.append(name + ": " + red("Fail"))
+ result.append(magenta("src: ") + line.rstrip(" \n"))
+ result.append(magenta("exp: ") + expected)
+ result.append(magenta("res: ") + translation + "\n")
+ test_passed = False
+ else:
+ passed += 1
+ else:
+ test_passed = False
+ errors += 1
+ result.append(name + ": " + red("Error: ") + "iptables-translate failure")
+ result.append(error.decode("utf-8"))
+ if (passed == tests) and not args.test:
+ print(name + ": " + green("OK"))
+ if not test_passed:
+ print("\n".join(result))
+ if args.test:
+ print("1 test file, %d tests, %d tests passed, %d tests failed, %d errors" % (tests, passed, failed, errors))
+ else:
+ return tests, passed, failed, errors
+
+
+def load_test_files():
+ test_files = total_tests = total_passed = total_error = total_failed = 0
+ for test in sorted(os.listdir("extensions")):
+ if test.endswith(".txlate"):
+ with open("extensions/" + test, "r") as payload:
+ tests, passed, failed, errors = run_test(test, payload)
+ test_files += 1
+ total_tests += tests
+ total_passed += passed
+ total_failed += failed
+ total_error += errors
+
+
+ print("%d test files, %d tests, %d tests passed, %d tests failed, %d errors" % (test_files, total_tests, total_passed, total_failed, total_error))
+
+def main():
+ if args.test:
+ if not args.test.endswith(".txlate"):
+ args.test += ".txlate"
+ try:
+ with open(args.test, "r") as payload:
+ run_test(args.test, payload)
+ except IOError:
+ print(red("Error: ") + "test file does not exist")
+ else:
+ load_test_files()
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument("test", nargs="?", help="run only the specified test file")
+args = parser.parse_args()
+main()