Discussion:
[libnftnl PATCH 1/2] src: add support for nft_redir expression
Arturo Borrero Gonzalez
2014-10-14 17:36:17 UTC
Permalink
This patch adds support for the new nft_redir expression.

Signed-off-by: Arturo Borrero Gonzalez <***@gmail.com>
---
include/libnftnl/expr.h | 6 +
include/linux/netfilter/nf_tables.h | 37 ++++
src/Makefile.am | 1
src/expr/redir.c | 303 +++++++++++++++++++++++++++++++++++
4 files changed, 347 insertions(+)
create mode 100644 src/expr/redir.c

diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
index 0505dec..9f25993 100644
--- a/include/libnftnl/expr.h
+++ b/include/libnftnl/expr.h
@@ -161,6 +161,12 @@ enum {
NFT_EXPR_MASQ_FLAGS = NFT_RULE_EXPR_ATTR_BASE,
};

+enum {
+ NFT_EXPR_REDIR_REG_PROTO_MIN = NFT_RULE_EXPR_ATTR_BASE,
+ NFT_EXPR_REDIR_REG_PROTO_MAX,
+ NFT_EXPR_REDIR_FLAGS,
+};
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index b72ccfe..8a96a36 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -749,13 +749,34 @@ enum nft_queue_attributes {
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
* @NFT_REJECT_TCP_RST: reject using TCP RST
+ * @NFT_REJECT_ICMPX_UNREACH: abstracted ICMP unreachable for bridge and inet
*/
enum nft_reject_types {
NFT_REJECT_ICMP_UNREACH,
NFT_REJECT_TCP_RST,
+ NFT_REJECT_ICMPX_UNREACH,
};

/**
+ * enum nft_reject_code - Generic reject codes for IPv4/IPv6
+ *
+ * @NFT_REJECT_ICMPX_NO_ROUTE: no route to host / network unreachable
+ * @NFT_REJECT_ICMPX_PORT_UNREACH: port unreachable
+ * @NFT_REJECT_ICMPX_HOST_UNREACH: host unreachable
+ * @NFT_REJECT_ICMPX_ADMIN_PROHIBITED: administratively prohibited
+ *
+ * These codes are mapped to real ICMP and ICMPv6 codes.
+ */
+enum nft_reject_inet_code {
+ NFT_REJECT_ICMPX_NO_ROUTE = 0,
+ NFT_REJECT_ICMPX_PORT_UNREACH,
+ NFT_REJECT_ICMPX_HOST_UNREACH,
+ NFT_REJECT_ICMPX_ADMIN_PROHIBITED,
+ __NFT_REJECT_ICMPX_MAX
+};
+#define NFT_REJECT_ICMPX_MAX (__NFT_REJECT_ICMPX_MAX + 1)
+
+/**
* enum nft_reject_attributes - nf_tables reject expression netlink attributes
*
* @NFTA_REJECT_TYPE: packet type to use (NLA_U32: nft_reject_types)
@@ -828,4 +849,20 @@ enum nft_gen_attributes {
};
#define NFTA_GEN_MAX (__NFTA_GEN_MAX - 1)

+/**
+ * enum nft_redir_attributes - nf_tables redirect expression netlink attributes
+ *
+ * @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
+ * @NFTA_REDIR_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_REDIR_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
+ */
+enum nft_redir_attributes {
+ NFTA_REDIR_UNSPEC,
+ NFTA_REDIR_REG_PROTO_MIN,
+ NFTA_REDIR_REG_PROTO_MAX,
+ NFTA_REDIR_FLAGS,
+ __NFTA_REDIR_MAX
+};
+#define NFTA_REDIR_MAX (__NFTA_REDIR_MAX - 1)
+
#endif /* _LINUX_NF_TABLES_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index 65bc82a..941e69e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,6 +37,7 @@ libnftnl_la_SOURCES = utils.c \
expr/reject.c \
expr/target.c \
expr/masq.c \
+ expr/redir.c \
expr/data_reg.h \
libnftnl.map \
expr_ops.h \
diff --git a/src/expr/redir.c b/src/expr/redir.c
new file mode 100644
index 0000000..960bf34
--- /dev/null
+++ b/src/expr/redir.c
@@ -0,0 +1,303 @@
+/*
+ * (C) 2014 by Arturo Borrero Gonzalez <***@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <linux/netfilter/nf_tables.h>
+
+#include "internal.h"
+#include <libmnl/libmnl.h>
+#include <libnftnl/expr.h>
+#include <libnftnl/rule.h>
+#include "expr_ops.h"
+
+struct nft_expr_redir {
+ enum nft_registers sreg_proto_min;
+ enum nft_registers sreg_proto_max;
+ uint32_t flags;
+};
+
+static int
+nft_rule_expr_redir_set(struct nft_rule_expr *e, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ switch (type) {
+ case NFT_EXPR_REDIR_REG_PROTO_MIN:
+ redir->sreg_proto_min = *((uint32_t *)data);
+ break;
+ case NFT_EXPR_REDIR_REG_PROTO_MAX:
+ redir->sreg_proto_max = *((uint32_t *)data);
+ break;
+ case NFT_EXPR_REDIR_FLAGS:
+ redir->flags = *((uint32_t *)data);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static const void *
+nft_rule_expr_redir_get(const struct nft_rule_expr *e, uint16_t type,
+ uint32_t *data_len)
+{
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ switch (type) {
+ case NFT_EXPR_REDIR_REG_PROTO_MIN:
+ *data_len = sizeof(redir->sreg_proto_min);
+ return &redir->sreg_proto_min;
+ case NFT_EXPR_REDIR_REG_PROTO_MAX:
+ *data_len = sizeof(redir->sreg_proto_max);
+ return &redir->sreg_proto_max;
+ case NFT_EXPR_REDIR_FLAGS:
+ *data_len = sizeof(redir->flags);
+ return &redir->flags;
+ }
+ return NULL;
+}
+
+static int nft_rule_expr_redir_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, NFTA_REDIR_MAX) < 0)
+ return MNL_CB_OK;
+
+ switch (type) {
+ case NFTA_REDIR_REG_PROTO_MIN:
+ case NFTA_REDIR_REG_PROTO_MAX:
+ case NFTA_REDIR_FLAGS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ abi_breakage();
+ break;
+ }
+
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static void
+nft_rule_expr_redir_build(struct nlmsghdr *nlh, struct nft_rule_expr *e)
+{
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ if (e->flags & (1 << NFT_EXPR_REDIR_REG_PROTO_MIN))
+ mnl_attr_put_u32(nlh, NFTA_REDIR_REG_PROTO_MIN,
+ htobe32(redir->sreg_proto_min));
+ if (e->flags & (1 << NFT_EXPR_REDIR_REG_PROTO_MAX))
+ mnl_attr_put_u32(nlh, NFTA_REDIR_REG_PROTO_MAX,
+ htobe32(redir->sreg_proto_max));
+ if (e->flags & (1 << NFT_EXPR_REDIR_FLAGS))
+ mnl_attr_put_u32(nlh, NFTA_REDIR_FLAGS, htobe32(redir->flags));
+}
+
+static int
+nft_rule_expr_redir_parse(struct nft_rule_expr *e, struct nlattr *attr)
+{
+ struct nft_expr_redir *redir = nft_expr_data(e);
+ struct nlattr *tb[NFTA_REDIR_MAX+1] = {};
+
+ if (mnl_attr_parse_nested(attr, nft_rule_expr_redir_cb, tb) < 0)
+ return -1;
+
+ if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
+ redir->sreg_proto_min =
+ ntohl(mnl_attr_get_u32(tb[NFTA_REDIR_REG_PROTO_MIN]));
+ e->flags |= (1 << NFT_EXPR_REDIR_REG_PROTO_MIN);
+ }
+ if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
+ redir->sreg_proto_max =
+ ntohl(mnl_attr_get_u32(tb[NFTA_REDIR_REG_PROTO_MAX]));
+ e->flags |= (1 << NFT_EXPR_REDIR_REG_PROTO_MAX);
+ }
+ if (tb[NFTA_REDIR_FLAGS]) {
+ redir->flags = be32toh(mnl_attr_get_u32(tb[NFTA_REDIR_FLAGS]));
+ e->flags |= (1 << NFT_EXPR_REDIR_FLAGS);
+ }
+
+ return 0;
+}
+
+static int
+nft_rule_expr_redir_json_parse(struct nft_rule_expr *e, json_t *root,
+ struct nft_parse_err *err)
+{
+#ifdef JSON_PARSING
+ uint32_t flags, reg;
+
+ if (nft_jansson_parse_reg(root, "sreg_proto_min", NFT_TYPE_U32,
+ &reg, err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_REG_PROTO_MIN, reg);
+
+ if (nft_jansson_parse_reg(root, "sreg_proto_max", NFT_TYPE_U32,
+ &reg, err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_REG_PROTO_MAX, reg);
+
+ if (nft_jansson_parse_val(root, "flags", NFT_TYPE_U32, &flags,
+ err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_FLAGS, flags);
+
+ return 0;
+#else
+ errno = EOPNOTSUPP;
+ return -1;
+#endif
+}
+
+static int
+nft_rule_expr_redir_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree,
+ struct nft_parse_err *err)
+{
+#ifdef XML_PARSING
+ uint32_t flags, reg;
+
+ if (nft_mxml_reg_parse(tree, "sreg_proto_min", &reg,
+ MXML_DESCEND, NFT_XML_OPT, err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_REG_PROTO_MIN, reg);
+
+ if (nft_mxml_reg_parse(tree, "sreg_proto_max", &reg,
+ MXML_DESCEND, NFT_XML_OPT, err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_REG_PROTO_MAX, reg);
+
+ if (nft_mxml_num_parse(tree, "flags", MXML_DESCEND_FIRST, BASE_DEC,
+ &flags, NFT_TYPE_U32, NFT_XML_OPT, err) == 0)
+ nft_rule_expr_set_u32(e, NFT_EXPR_REDIR_FLAGS, flags);
+
+ return 0;
+#else
+ errno = EOPNOTSUPP;
+ return -1;
+#endif
+}
+
+static int nft_rule_expr_redir_snprintf_json(char *buf, size_t len,
+ struct nft_rule_expr *e)
+{
+ int ret, size = len, offset = 0;
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MIN)) {
+ ret = snprintf(buf + offset, len, "\"sreg_proto_min\":%u,",
+ redir->sreg_proto_min);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MAX)) {
+ ret = snprintf(buf + offset, len, "\"sreg_proto_max\":%u,",
+ redir->sreg_proto_max);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_FLAGS)) {
+ ret = snprintf(buf + offset, len, "\"flags\":%u",
+ redir->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ return offset;
+}
+
+static int nft_rule_expr_redir_snprintf_xml(char *buf, size_t len,
+ struct nft_rule_expr *e)
+{
+ int ret, size = len, offset = 0;
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MIN)) {
+ ret = snprintf(buf + offset, len,
+ "<sreg_proto_min>%u<sreg_proto_min>",
+ redir->sreg_proto_min);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MAX)) {
+ ret = snprintf(buf + offset, len,
+ "<sreg_proto_max>%u</sreg_proto_max>",
+ redir->sreg_proto_max);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_FLAGS)) {
+ ret = snprintf(buf + offset, len, "<flags>%u</flags>",
+ redir->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ return offset;
+}
+
+static int nft_rule_expr_redir_snprintf_default(char *buf, size_t len,
+ struct nft_rule_expr *e)
+{
+ int ret, size = len, offset = 0;
+ struct nft_expr_redir *redir = nft_expr_data(e);
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MIN)) {
+ ret = snprintf(buf + offset, len, "proto_min reg %u ",
+ redir->sreg_proto_min);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_REG_PROTO_MAX)) {
+ ret = snprintf(buf + offset, len, "proto_max reg %u ",
+ redir->sreg_proto_max);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ if (nft_rule_expr_is_set(e, NFT_EXPR_REDIR_FLAGS)) {
+ ret = snprintf(buf + offset , len, "flags 0x%x ",
+ redir->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ return 0;
+}
+
+static int
+nft_rule_expr_redir_snprintf(char *buf, size_t len, uint32_t type,
+ uint32_t flags, struct nft_rule_expr *e)
+{
+ switch (type) {
+ case NFT_OUTPUT_DEFAULT:
+ return nft_rule_expr_redir_snprintf_default(buf, len, e);
+ case NFT_OUTPUT_XML:
+ return nft_rule_expr_redir_snprintf_xml(buf, len, e);
+ case NFT_OUTPUT_JSON:
+ return nft_rule_expr_redir_snprintf_json(buf, len, e);
+ default:
+ break;
+ }
+ return -1;
+}
+
+struct expr_ops expr_ops_redir = {
+ .name = "redir",
+ .alloc_len = sizeof(struct nft_expr_redir),
+ .max_attr = NFTA_REDIR_MAX,
+ .set = nft_rule_expr_redir_set,
+ .get = nft_rule_expr_redir_get,
+ .parse = nft_rule_expr_redir_parse,
+ .build = nft_rule_expr_redir_build,
+ .snprintf = nft_rule_expr_redir_snprintf,
+ .xml_parse = nft_rule_expr_redir_xml_parse,
+ .json_parse = nft_rule_expr_redir_json_parse,
+};
+
+static void __init expr_redir_init(void)
+{
+ nft_expr_ops_register(&expr_ops_redir);
+}

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Arturo Borrero Gonzalez
2014-10-14 17:36:22 UTC
Permalink
This patch add some tests for the nft_redir expression.

Signed-off-by: Arturo Borrero Gonzalez <***@gmail.com>
---
tests/Makefile.am | 4 +
tests/jsonfiles/69-rule-redir.json | 1
tests/nft-expr_redir-test.c | 97 ++++++++++++++++++++++++++++++++++++
tests/test-script.sh | 1
tests/xmlfiles/80-rule-redir.xml | 1
5 files changed, 104 insertions(+)
create mode 100644 tests/jsonfiles/69-rule-redir.json
create mode 100644 tests/nft-expr_redir-test.c
create mode 100644 tests/xmlfiles/80-rule-redir.xml

diff --git a/tests/Makefile.am b/tests/Makefile.am
index d4f44af..bac2106 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -21,6 +21,7 @@ check_PROGRAMS = nft-parsing-test \
nft-expr_log-test \
nft-expr_match-test \
nft-expr_masq-test \
+ nft-expr_redir-test \
nft-expr_meta-test \
nft-expr_nat-test \
nft-expr_payload-test \
@@ -79,6 +80,9 @@ nft_expr_match_test_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
nft_expr_masq_test_SOURCES = nft-expr_masq-test.c
nft_expr_masq_test_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}

+nft_expr_redir_test_SOURCES = nft-expr_redir-test.c
+nft_expr_redir_test_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
+
nft_expr_meta_test_SOURCES = nft-expr_meta-test.c
nft_expr_meta_test_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}

diff --git a/tests/jsonfiles/69-rule-redir.json b/tests/jsonfiles/69-rule-redir.json
new file mode 100644
index 0000000..043fff2
--- /dev/null
+++ b/tests/jsonfiles/69-rule-redir.json
@@ -0,0 +1 @@
+{"nftables":[{"rule":{"family":"ip6","table":"nat","chain":"prerouting","handle":4,"expr":[{"type":"redir"}]}}]}
diff --git a/tests/nft-expr_redir-test.c b/tests/nft-expr_redir-test.c
new file mode 100644
index 0000000..4d41c61
--- /dev/null
+++ b/tests/nft-expr_redir-test.c
@@ -0,0 +1,97 @@
+/*
+ * (C) 2013 by Ana Rey Botello <***@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/netfilter/nf_tables.h>
+#include <libmnl/libmnl.h>
+#include <libnftnl/rule.h>
+#include <libnftnl/expr.h>
+
+static int test_ok = 1;
+
+static void print_err(const char *msg)
+{
+ test_ok = 0;
+ printf("\033[31mERROR:\e[0m %s\n", msg);
+}
+
+static void cmp_nft_rule_expr(struct nft_rule_expr *rule_a,
+ struct nft_rule_expr *rule_b)
+{
+ if (nft_rule_expr_get_u32(rule_a, NFT_EXPR_REDIR_REG_PROTO_MIN) !=
+ nft_rule_expr_get_u32(rule_b, NFT_EXPR_REDIR_REG_PROTO_MIN))
+ print_err("Expr NFT_EXPR_REDIR_REG_PROTO_MIN mismatches");
+ if (nft_rule_expr_get_u32(rule_a, NFT_EXPR_REDIR_REG_PROTO_MAX) !=
+ nft_rule_expr_get_u32(rule_b, NFT_EXPR_REDIR_REG_PROTO_MAX))
+ print_err("Expr NFT_EXPR_REDIR_REG_PROTO_MAX mismatches");
+ if (nft_rule_expr_get_u32(rule_a, NFT_EXPR_REDIR_FLAGS) !=
+ nft_rule_expr_get_u32(rule_b, NFT_EXPR_REDIR_FLAGS))
+ print_err("Expr NFT_EXPR_REDIR_FLAGS mismatches");
+}
+
+int main(int argc, char *argv[])
+{
+ struct nft_rule *a, *b;
+ struct nft_rule_expr *ex;
+ struct nlmsghdr *nlh;
+ char buf[4096];
+ struct nft_rule_expr_iter *iter_a, *iter_b;
+ struct nft_rule_expr *rule_a, *rule_b;
+
+ a = nft_rule_alloc();
+ b = nft_rule_alloc();
+ if (a == NULL || b == NULL)
+ print_err("OOM");
+ ex = nft_rule_expr_alloc("redir");
+ if (ex == NULL)
+ print_err("OOM");
+
+ nft_rule_expr_set_u32(ex, NFT_EXPR_REDIR_REG_PROTO_MIN, 0x1234568);
+ nft_rule_expr_set_u32(ex, NFT_EXPR_REDIR_REG_PROTO_MAX, 0x23456);
+ nft_rule_expr_set_u32(ex, NFT_EXPR_REDIR_FLAGS, 0x1234568);
+
+ nft_rule_add_expr(a, ex);
+
+ nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234);
+ nft_rule_nlmsg_build_payload(nlh, a);
+
+ if (nft_rule_nlmsg_parse(nlh, b) < 0)
+ print_err("Parsing problems");
+
+ iter_a = nft_rule_expr_iter_create(a);
+ iter_b = nft_rule_expr_iter_create(b);
+ if (iter_a == NULL || iter_b == NULL)
+ print_err("OOM");
+
+ rule_a = nft_rule_expr_iter_next(iter_a);
+ rule_b = nft_rule_expr_iter_next(iter_b);
+ if (rule_a == NULL || rule_b == NULL)
+ print_err("OOM");
+
+ cmp_nft_rule_expr(rule_a, rule_b);
+
+ if (nft_rule_expr_iter_next(iter_a) != NULL ||
+ nft_rule_expr_iter_next(iter_b) != NULL)
+ print_err("More than 1 expr.");
+
+ nft_rule_expr_iter_destroy(iter_a);
+ nft_rule_expr_iter_destroy(iter_b);
+ nft_rule_free(a);
+ nft_rule_free(b);
+
+ if (!test_ok)
+ exit(EXIT_FAILURE);
+
+ printf("%s: \033[32mOK\e[0m\n", argv[0]);
+ return EXIT_SUCCESS;
+}
diff --git a/tests/test-script.sh b/tests/test-script.sh
index 93caeb8..b040158 100755
--- a/tests/test-script.sh
+++ b/tests/test-script.sh
@@ -12,6 +12,7 @@
./nft-expr_match-test
./nft-expr_masq-test
./nft-expr_meta-test
+./nft-expr_redir-test
./nft-expr_nat-test
./nft-expr_payload-test
./nft-expr_reject-test
diff --git a/tests/xmlfiles/80-rule-redir.xml b/tests/xmlfiles/80-rule-redir.xml
new file mode 100644
index 0000000..f7dd453
--- /dev/null
+++ b/tests/xmlfiles/80-rule-redir.xml
@@ -0,0 +1 @@
+<nftables><rule><family>ip6</family><table>nat</table><chain>prerouting</chain><handle>4</handle><expr type="redir"></expr></rule></nftables>

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...