]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Embed compat extensions in rule userdata
authorPhil Sutter <phil@nwl.cc>
Wed, 31 Jul 2024 19:28:11 +0000 (21:28 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 10 Apr 2025 16:45:46 +0000 (18:45 +0200)
If enabled (via --compat flag or XTABLES_COMPAT env variable), attach
any extensions for which native nftables expressions are generated to
userdata. An earlier version of the tool trying to parse the
kernel-dumped ruleset may then fall back to these extensions if native
expression parsing fails.

Signed-off-by: Phil Sutter <phil@nwl.cc>
16 files changed:
iptables/arptables-nft.8
iptables/ebtables-nft.8
iptables/iptables-restore.8.in
iptables/iptables.8.in
iptables/nft-compat.c
iptables/nft-compat.h
iptables/nft-ruleparse.c
iptables/nft.c
iptables/nft.h
iptables/xshared.c
iptables/xshared.h
iptables/xtables-arp.c
iptables/xtables-eb.c
iptables/xtables-nft.8
iptables/xtables-restore.c
iptables/xtables.c

index c48a2cc2286baf2fb712fc124362eb31da9b2651..8d1eb9fb651ed6c1c480d674c3bf3ba10d7c030f 100644 (file)
@@ -234,6 +234,18 @@ counters of a rule (during
 .B APPEND,
 .B REPLACE
 operations).
+.TP
+.B --compat
+When creating a rule, attach compatibility data to the rule's userdata section
+for use as aid in parsing the rule by an older version of the program. The old
+version obviously needs to support this, though.
+Specifying this option a second time instructs the program to default to the
+rule's compatibility data when parsing, which is mostly useful for debugging or
+testing purposes.
+
+The \fBXTABLES_COMPAT\fP environment variable can be used to override the
+default setting. The expected value is a natural number representing the number
+of times \fB--compat\fP was specified.
 
 .SS RULE-SPECIFICATIONS
 The following command line arguments make up a rule specification (as used 
index 8698165024de192cd9672706ccf7f1fa421924d1..3088bb0cce36645dbfb441930f2e5d601645a1fb 100644 (file)
@@ -360,6 +360,18 @@ to try to automatically load missing kernel modules.
 .B --concurrent
 This would use a file lock to support concurrent scripts updating the ebtables
 kernel tables. It is not needed with \fBebtables-nft\fP though and thus ignored.
+.TP
+.B --compat
+When creating a rule, attach compatibility data to the rule's userdata section
+for use as aid in parsing the rule by an older version of the program. The old
+version obviously needs to support this, though.
+Specifying this option a second time instructs the program to default to the
+rule's compatibility data when parsing, which is mostly useful for debugging or
+testing purposes.
+
+The \fBXTABLES_COMPAT\fP environment variable can be used to override the
+default setting. The expected value is a natural number representing the number
+of times \fB--compat\fP was specified.
 
 .SS
 RULE SPECIFICATIONS
index aa816f794d6f38d3269e49fa33359ddb09515952..df61b2a623f6403729c121c1bf1ba92f6e470a22 100644 (file)
@@ -74,6 +74,18 @@ determine the executable's path.
 .TP
 \fB\-T\fP, \fB\-\-table\fP \fIname\fP
 Restore only the named table even if the input stream contains other ones.
+.TP
+\fB\-\-compat\fP (nft-variants only)
+When creating a rule, attach compatibility data to the rule's userdata section
+for use as aid in parsing the rule by an older version of the program. The old
+version obviously needs to support this, though.
+Specifying this option a second time instructs the program to default to the
+rule's compatibility data when parsing, which is mostly useful for debugging or
+testing purposes.
+
+The \fBXTABLES_COMPAT\fP environment variable can be used to override the
+default setting. The expected value is a natural number representing the number
+of times \fB--compat\fP was specified.
 .SH BUGS
 None known as of iptables-1.2.1 release
 .SH AUTHORS
index 21fb891dc6373fc1763f022a71c2d700165fae66..41c45a4a6e9918010b873d840d9b0e2879941854 100644 (file)
@@ -397,6 +397,18 @@ corresponding to that rule's position in the chain.
 \fB\-\-modprobe=\fP\fIcommand\fP
 When adding or inserting rules into a chain, use \fIcommand\fP
 to load any necessary modules (targets, match extensions, etc).
+.TP
+\fB\-\-compat\fP (nft-variants only)
+When creating a rule, attach compatibility data to the rule's userdata section
+for use as aid in parsing the rule by an older version of the program. The old
+version obviously needs to support this, though.
+Specifying this option a second time instructs the program to default to the
+rule's compatibility data when parsing, which is mostly useful for debugging or
+testing purposes.
+
+The \fBXTABLES_COMPAT\fP environment variable can be used to override the
+default setting. The expected value is a natural number representing the number
+of times \fB--compat\fP was specified.
 
 .SH LOCK FILE
 iptables uses the \fI@XT_LOCK_NAME@\fP file to take an exclusive lock at
index 1edf08851c5796be589f4bd2191aea3cff31812a..632733ca0cadee27476c16e20dab2bfee18c8663 100644 (file)
 
 #include <libnftnl/udata.h>
 
+int nftnl_rule_expr_count(const struct nftnl_rule *r)
+{
+       struct nftnl_expr_iter *iter = nftnl_expr_iter_create(r);
+       int cnt = 0;
+
+       if (!iter)
+               return -1;
+
+       while (nftnl_expr_iter_next(iter))
+               cnt++;
+
+       nftnl_expr_iter_destroy(iter);
+       return cnt;
+}
+
 static struct rule_udata_ext *
 rule_get_udata_ext(const struct nftnl_rule *r, uint32_t *outlen)
 {
@@ -44,6 +59,65 @@ rule_get_udata_ext(const struct nftnl_rule *r, uint32_t *outlen)
        return nftnl_udata_get(tb[UDATA_TYPE_COMPAT_EXT]);
 }
 
+static void
+pack_rule_udata_ext_data(struct rule_udata_ext *rue,
+                        const void *data, size_t datalen)
+{
+       size_t datalen_out = datalen;
+#ifdef HAVE_ZLIB
+       compress(rue->data, &datalen_out, data, datalen);
+       rue->flags |= RUE_FLAG_ZIP;
+#else
+       memcpy(rue->data, data, datalen);
+#endif
+       rue->size = datalen_out;
+}
+
+void rule_add_udata_ext(struct nft_handle *h, struct nftnl_rule *r,
+                       uint16_t start_idx, uint16_t end_idx,
+                       uint8_t flags, uint16_t size, const void *data)
+{
+       struct rule_udata_ext *ext = NULL;
+       uint32_t extlen = 0, newextlen;
+       char *newext;
+       void *udata;
+
+       if (!h->compat)
+               return;
+
+       ext = rule_get_udata_ext(r, &extlen);
+       if (!ext)
+               extlen = 0;
+
+       udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+       if (!udata)
+               xtables_error(OTHER_PROBLEM, "can't alloc memory!");
+
+       newextlen = sizeof(*ext) + size;
+       newext = xtables_malloc(extlen + newextlen);
+       if (extlen)
+               memcpy(newext, ext, extlen);
+       memset(newext + extlen, 0, newextlen);
+
+       ext = (struct rule_udata_ext *)(newext + extlen);
+       ext->start_idx  = start_idx;
+       ext->end_idx    = end_idx;
+       ext->flags      = flags;
+       ext->orig_size  = size;
+       pack_rule_udata_ext_data(ext, data, size);
+       newextlen = sizeof(*ext) + ext->size;
+
+       if (!nftnl_udata_put(udata, UDATA_TYPE_COMPAT_EXT,
+                            extlen + newextlen, newext) ||
+           nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
+                               nftnl_udata_buf_data(udata),
+                               nftnl_udata_buf_len(udata)))
+               xtables_error(OTHER_PROBLEM, "can't alloc memory!");
+
+       free(newext);
+       nftnl_udata_buf_free(udata);
+}
+
 static struct nftnl_expr *
 __nftnl_expr_from_udata_ext(struct rule_udata_ext *rue, const void *data)
 {
index 1147f08a0b6d5d32e9db0f28c369e64b4d671b9e..59b3c0267f8d08302b3a8a43173851b1fccf0641 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <linux/netfilter/x_tables.h>
 
+int nftnl_rule_expr_count(const struct nftnl_rule *r);
+
 enum rule_udata_ext_flags {
        RUE_FLAG_MATCH_TYPE     = (1 << 0),
        RUE_FLAG_TARGET_TYPE    = (1 << 1),
@@ -21,6 +23,29 @@ struct rule_udata_ext {
        unsigned char data[];
 };
 
+struct nft_handle;
+
+void rule_add_udata_ext(struct nft_handle *h, struct nftnl_rule *r,
+                       uint16_t start_idx, uint16_t end_idx,
+                       uint8_t flags, uint16_t size, const void *data);
+static inline void
+rule_add_udata_match(struct nft_handle *h, struct nftnl_rule *r,
+                    uint16_t start_idx, uint16_t end_idx,
+                    const struct xt_entry_match *m)
+{
+       rule_add_udata_ext(h, r, start_idx, end_idx,
+                          RUE_FLAG_MATCH_TYPE, m->u.match_size, m);
+}
+
+static inline void
+rule_add_udata_target(struct nft_handle *h, struct nftnl_rule *r,
+                     uint16_t start_idx, uint16_t end_idx,
+                     const struct xt_entry_target *t)
+{
+       rule_add_udata_ext(h, r, start_idx, end_idx,
+                          RUE_FLAG_TARGET_TYPE, t->u.target_size, t);
+}
+
 struct nft_xt_ctx;
 
 bool rule_has_udata_ext(const struct nftnl_rule *r);
index 34270e46ae888a17e724ad9f4950cbdca060dd53..cdf1af4fab2774ddcebfebbb595a6c1d2974a728 100644 (file)
@@ -950,7 +950,7 @@ bool nft_rule_to_iptables_command_state(struct nft_handle *h,
                        ret = false;
                expr = nftnl_expr_iter_next(ctx.iter);
        }
-       if (!ret && rule_has_udata_ext(r)) {
+       if ((!ret || h->compat > 1) && rule_has_udata_ext(r)) {
                fprintf(stderr,
                        "Warning: Rule parser failed, trying compat fallback\n");
 
index a368b7d1960328adf107f09ba0f9f0418bd4eb40..908f544319b746aef74c2d9a30e11688f2036321 100644 (file)
@@ -9,6 +9,7 @@
  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
  */
 
+#include "config.h"
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
@@ -60,6 +61,7 @@
 #include "nft-cache.h"
 #include "nft-shared.h"
 #include "nft-bridge.h" /* EBT_NOPROTO */
+#include "nft-compat.h"
 
 static void *nft_fn;
 
@@ -1046,9 +1048,11 @@ void __add_match(struct nftnl_expr *e, const struct xt_entry_match *m)
        nftnl_expr_set(e, NFTNL_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
 }
 
-static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
+static int add_nft_limit(struct nft_handle *h, struct nftnl_rule *r,
+                        struct xt_entry_match *m)
 {
        struct xt_rateinfo *rinfo = (void *)m->data;
+       int i, ecnt = nftnl_rule_expr_count(r);
        static const uint32_t mult[] = {
                XT_LIMIT_SCALE*24*60*60,        /* day */
                XT_LIMIT_SCALE*60*60,           /* hour */
@@ -1056,7 +1060,8 @@ static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
                XT_LIMIT_SCALE,                 /* sec */
        };
        struct nftnl_expr *expr;
-       int i;
+
+       rule_add_udata_match(h, r, ecnt, ecnt + 1, m);
 
        expr = nftnl_expr_alloc("limit");
        if (!expr)
@@ -1371,6 +1376,7 @@ static bool udp_all_zero(const struct xt_udp *u)
 static int add_nft_udp(struct nft_handle *h, struct nftnl_rule *r,
                       struct xt_entry_match *m)
 {
+       int ret, ecnt = nftnl_rule_expr_count(r);
        struct xt_udp *udp = (void *)m->data;
 
        if (udp->invflags > XT_UDP_INV_MASK ||
@@ -1385,8 +1391,12 @@ static int add_nft_udp(struct nft_handle *h, struct nftnl_rule *r,
        if (nftnl_rule_get_u32(r, NFTNL_RULE_COMPAT_PROTO) != IPPROTO_UDP)
                xtables_error(PARAMETER_PROBLEM, "UDP match requires '-p udp'");
 
-       return add_nft_tcpudp(h, r, udp->spts, udp->invflags & XT_UDP_INV_SRCPT,
-                             udp->dpts, udp->invflags & XT_UDP_INV_DSTPT);
+       ret = add_nft_tcpudp(h, r, udp->spts, udp->invflags & XT_UDP_INV_SRCPT,
+                            udp->dpts, udp->invflags & XT_UDP_INV_DSTPT);
+
+       rule_add_udata_match(h, r, ecnt, nftnl_rule_expr_count(r), m);
+
+       return ret;
 }
 
 static int add_nft_tcpflags(struct nft_handle *h, struct nftnl_rule *r,
@@ -1423,6 +1433,7 @@ static int add_nft_tcp(struct nft_handle *h, struct nftnl_rule *r,
                       struct xt_entry_match *m)
 {
        static const uint8_t supported = XT_TCP_INV_SRCPT | XT_TCP_INV_DSTPT | XT_TCP_INV_FLAGS;
+       int ret, ecnt = nftnl_rule_expr_count(r);
        struct xt_tcp *tcp = (void *)m->data;
 
        if (tcp->invflags & ~supported || tcp->option ||
@@ -1438,23 +1449,27 @@ static int add_nft_tcp(struct nft_handle *h, struct nftnl_rule *r,
                xtables_error(PARAMETER_PROBLEM, "TCP match requires '-p tcp'");
 
        if (tcp->flg_mask) {
-               int ret = add_nft_tcpflags(h, r, tcp->flg_cmp, tcp->flg_mask,
-                                          tcp->invflags & XT_TCP_INV_FLAGS);
+               ret = add_nft_tcpflags(h, r, tcp->flg_cmp, tcp->flg_mask,
+                                      tcp->invflags & XT_TCP_INV_FLAGS);
 
                if (ret < 0)
                        return ret;
        }
 
-       return add_nft_tcpudp(h, r, tcp->spts, tcp->invflags & XT_TCP_INV_SRCPT,
-                             tcp->dpts, tcp->invflags & XT_TCP_INV_DSTPT);
+       ret = add_nft_tcpudp(h, r, tcp->spts, tcp->invflags & XT_TCP_INV_SRCPT,
+                            tcp->dpts, tcp->invflags & XT_TCP_INV_DSTPT);
+
+       rule_add_udata_match(h, r, ecnt, nftnl_rule_expr_count(r), m);
+
+       return ret;
 }
 
 static int add_nft_mark(struct nft_handle *h, struct nftnl_rule *r,
                        struct xt_entry_match *m)
 {
        struct xt_mark_mtinfo1 *mark = (void *)m->data;
+       int op, ecnt = nftnl_rule_expr_count(r);
        uint8_t reg;
-       int op;
 
        add_meta(h, r, NFT_META_MARK, &reg);
        if (mark->mask != 0xffffffff)
@@ -1467,6 +1482,8 @@ static int add_nft_mark(struct nft_handle *h, struct nftnl_rule *r,
 
        add_cmp_u32(r, mark->mark, op, reg);
 
+       rule_add_udata_match(h, r, ecnt, nftnl_rule_expr_count(r), m);
+
        return 0;
 }
 
@@ -1480,7 +1497,7 @@ int add_match(struct nft_handle *h, struct nft_rule_ctx *ctx,
        case NFT_COMPAT_RULE_INSERT:
        case NFT_COMPAT_RULE_REPLACE:
                if (!strcmp(m->u.user.name, "limit"))
-                       return add_nft_limit(r, m);
+                       return add_nft_limit(h, r, m);
                else if (!strcmp(m->u.user.name, "among"))
                        return add_nft_among(h, r, m);
                else if (!strcmp(m->u.user.name, "udp"))
@@ -1517,10 +1534,14 @@ void __add_target(struct nftnl_expr *e, const struct xt_entry_target *t)
        nftnl_expr_set(e, NFTNL_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
 }
 
-static int add_meta_nftrace(struct nftnl_rule *r)
+static int add_meta_nftrace(struct nft_handle *h, struct nftnl_rule *r,
+                           struct xt_entry_target *t)
 {
+       int ecnt = nftnl_rule_expr_count(r);
        struct nftnl_expr *expr;
 
+       rule_add_udata_target(h, r, ecnt, ecnt + 2, t);
+
        expr = nftnl_expr_alloc("immediate");
        if (expr == NULL)
                return -ENOMEM;
@@ -1545,7 +1566,7 @@ int add_target(struct nft_handle *h, struct nftnl_rule *r,
        struct nftnl_expr *expr;
 
        if (strcmp(t->u.user.name, "TRACE") == 0)
-               return add_meta_nftrace(r);
+               return add_meta_nftrace(h, r, t);
 
        expr = nftnl_expr_alloc("target");
        if (expr == NULL)
@@ -1588,7 +1609,8 @@ int add_verdict(struct nftnl_rule *r, int verdict)
        return 0;
 }
 
-static int add_log(struct nftnl_rule *r, struct iptables_command_state *cs);
+static int add_log(struct nft_handle *h, struct nftnl_rule *r,
+                  struct iptables_command_state *cs);
 
 int add_action(struct nft_handle *h, struct nftnl_rule *r,
               struct iptables_command_state *cs, bool goto_set)
@@ -1605,7 +1627,7 @@ int add_action(struct nft_handle *h, struct nftnl_rule *r,
                else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
                        ret = add_verdict(r, NFT_RETURN);
                else if (strcmp(cs->jumpto, "NFLOG") == 0)
-                       ret = add_log(r, cs);
+                       ret = add_log(h, r, cs);
                else
                        ret = add_target(h, r, cs->target->t);
        } else if (strlen(cs->jumpto) > 0) {
@@ -1618,10 +1640,14 @@ int add_action(struct nft_handle *h, struct nftnl_rule *r,
        return ret;
 }
 
-static int add_log(struct nftnl_rule *r, struct iptables_command_state *cs)
+static int add_log(struct nft_handle *h, struct nftnl_rule *r,
+                  struct iptables_command_state *cs)
 {
        struct nftnl_expr *expr;
        struct xt_nflog_info *info = (struct xt_nflog_info *)cs->target->t->data;
+       int ecnt = nftnl_rule_expr_count(r);
+
+       rule_add_udata_target(h, r, ecnt, ecnt + 1, cs->target->t);
 
        expr = nftnl_expr_alloc("log");
        if (!expr)
@@ -4042,3 +4068,10 @@ void nft_assert_table_compatible(struct nft_handle *h,
                      "%s%s%stable `%s' is incompatible, use 'nft' tool.",
                      pfx, chain, sfx, table);
 }
+
+uint8_t compat_env_val(void)
+{
+       const char *val = getenv("XTABLES_COMPAT");
+
+       return val ? atoi(val) : 0;
+}
index e2004ba6e8292abb17d6ea7a678c3aa140b4c38f..94d90bef44fb369504e8072798f9bab865e4bb36 100644 (file)
@@ -108,6 +108,7 @@ struct nft_handle {
        struct nft_cache_req    cache_req;
        bool                    restore;
        bool                    noflush;
+       uint8_t                 compat;
        int8_t                  config_done;
        struct list_head        cmd_list;
        bool                    cache_init;
@@ -289,4 +290,6 @@ enum udata_type {
 
 int parse_udata_cb(const struct nftnl_udata *attr, void *data);
 
+uint8_t compat_env_val(void);
+
 #endif
index 2f663f9762016d0768baa13ea5e47c002ed4783b..cdfd11ab2f279a0ffa22f0f9747406cc3bea5cf2 100644 (file)
@@ -1254,6 +1254,9 @@ void xtables_printhelp(struct iptables_command_state *cs)
                printf(
 "[!] --fragment        -f              match second or further fragments only\n");
 
+       if (strstr(xt_params->program_version, "nf_tables"))
+       printf(
+"  --compat                    append compatibility data to new rules\n");
        printf(
 "  --modprobe=<command>                try to insert modules using this command\n"
 "  --set-counters -c PKTS BYTES        set the counter during insert/append\n"
@@ -1918,6 +1921,10 @@ void do_parse(int argc, char *argv[],
 
                        exit_tryhelp(2, p->line);
 
+               case 20: /* --compat */
+                       p->compat++;
+                       break;
+
                case 1: /* non option */
                        if (optarg[0] == '!' && optarg[1] == '\0') {
                                if (invert)
index af756738e7c440e4bf6ab3a7e98ab116c14d3a5e..9d2d6d9ffa29971ce90c144ab3f11af187a22707 100644 (file)
@@ -299,6 +299,7 @@ struct xt_cmd_parse {
        bool                            restore;
        int                             line;
        int                             verbose;
+       uint8_t                         compat;
        bool                            rule_ranges;
        struct xt_cmd_parse_ops         *ops;
 };
index 71518a9cbdb6a14482f0772228fe93e1ffc3b75a..fe45c370d21dbc2d93c31e621cc88cb587ebc786 100644 (file)
@@ -78,6 +78,7 @@ static struct option original_opts[] = {
        { "line-numbers", 0, 0, '0' },
        { "modprobe", 1, 0, 'M' },
        { "set-counters", 1, 0, 'c' },
+       { "compat", 0, 0, 20 },
        { 0 }
 };
 
index 86c33b4e7dcb6600841fdaaf951f6cd7050c7944..4beebfd68969ad3e3bf5736a8a2fdf31389de5ab 100644 (file)
@@ -131,6 +131,7 @@ struct option ebt_original_options[] =
        { "init-table"     , no_argument      , 0, 11  },
        { "concurrent"     , no_argument      , 0, 13  },
        { "check"          , required_argument, 0, 14  },
+       { "compat"         , no_argument      , 0, 20  },
        { 0 }
 };
 
@@ -234,6 +235,7 @@ void nft_bridge_print_help(struct iptables_command_state *cs)
 "[!] --logical-out name[+]     : logical bridge output interface name\n"
 "--set-counters -c chain\n"
 "          pcnt bcnt           : set the counters of the to be added rule\n"
+"--compat                      : append compatibility data to new rules\n"
 "--modprobe -M program         : try to insert modules using this program\n"
 "--concurrent                  : use a file lock to support concurrent scripts\n"
 "--verbose -v                  : verbose mode\n"
@@ -562,6 +564,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
                .line           = line,
                .rule_ranges    = true,
                .ops            = &h->ops->cmd_parse,
+               .compat         = compat_env_val(),
        };
        int ret = 0;
 
@@ -571,6 +574,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
        do_parse(argc, argv, &p, &cs, &args);
 
        h->verbose      = p.verbose;
+       h->compat       = p.compat;
 
        t = nft_table_builtin_find(h, p.table);
        if (!t)
index ae54476c6cf87fb2c70f1d9da3626b5dcafd6f37..2ed67ba9d471c4c05d33c50756bb5f0e27105c29 100644 (file)
@@ -100,6 +100,17 @@ When using \-j TRACE to debug packet traversal to the ruleset, note that you wil
 .B xtables\-monitor(8)
 in \-\-trace mode to obtain monitoring trace events.
 
+Some extensions are implemented via native nf_tables expressions instead of
+\fBnft_compat\fP module. This is transparent to the user as such parts of a
+rule are detected and parsed into an extension again before listing. Also,
+run-time behaviour is supposed to be identical. Implementing extensions this
+way is beneficial from a kernel maintainer's perspective as xtables extension
+modules may at some point become unused, so increasing extension conversion is
+to be expected. Since this may break older versions parsing the ruleset
+in-kernel (a possible scenario with containers sharing a network namespace),
+there is \fB--compat\fP flag which causes the replaced extensions to be
+appended to the rule in userdata storage for the parser to fall back to.
+
 .SH EXAMPLES
 One basic example is creating the skeleton ruleset in nf_tables from the
 xtables-nft tools, in a fresh machine:
index 23cd349819f4f5258054901c7a5807665beacbb7..e7802b9e140bddb7199c1c6791837dcaf6ae42d5 100644 (file)
@@ -37,6 +37,7 @@ static const struct option options[] = {
        {.name = "ipv6",     .has_arg = false, .val = '6'},
        {.name = "wait",          .has_arg = 2, .val = 'w'},
        {.name = "wait-interval", .has_arg = 2, .val = 'W'},
+       {.name = "compat",   .has_arg = false, .val = 20 },
        {NULL},
 };
 
@@ -54,6 +55,7 @@ static void print_usage(const char *name, const char *version)
                        "          [ --noflush ]\n"
                        "          [ --table=<TABLE> ]\n"
                        "          [ --modprobe=<command> ]\n"
+                       "          [ --compat ]\n"
                        "          [ --ipv4 ]\n"
                        "          [ --ipv6 ]\n", name);
 }
@@ -284,6 +286,7 @@ void xtables_restore_parse(struct nft_handle *h,
 static int
 xtables_restore_main(int family, const char *progname, int argc, char *argv[])
 {
+       uint8_t compat = compat_env_val();
        struct nft_xt_restore_parse p = {
                .commit = true,
                .cb = &restore_cb,
@@ -337,6 +340,9 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
                                if (!optarg && xs_has_arg(argc, argv))
                                        optind++;
                                break;
+                       case 20:
+                               compat++;
+                               break;
                        default:
                                fprintf(stderr,
                                        "Try `%s -h' for more information.\n",
@@ -387,6 +393,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
        }
        h.noflush = noflush;
        h.restore = true;
+       h.compat  = compat;
 
        xtables_restore_parse(&h, &p);
 
@@ -419,11 +426,13 @@ static const struct nft_xt_restore_cb ebt_restore_cb = {
 static const struct option ebt_restore_options[] = {
        {.name = "noflush", .has_arg = 0, .val = 'n'},
        {.name = "verbose", .has_arg = 0, .val = 'v'},
+       {.name = "compat",  .has_arg = 0, .val = 20},
        { 0 }
 };
 
 int xtables_eb_restore_main(int argc, char *argv[])
 {
+       uint8_t compat = compat_env_val();
        struct nft_xt_restore_parse p = {
                .in = stdin,
                .cb = &ebt_restore_cb,
@@ -441,9 +450,12 @@ int xtables_eb_restore_main(int argc, char *argv[])
                case 'v':
                        verbose++;
                        break;
+               case 20: /* --compat */
+                       compat++;
+                       break;
                default:
                        fprintf(stderr,
-                               "Usage: ebtables-restore [ --verbose ] [ --noflush ]\n");
+                               "Usage: ebtables-restore [ --verbose ] [ --noflush ] [ --compat ]\n");
                        exit(1);
                        break;
                }
@@ -451,6 +463,7 @@ int xtables_eb_restore_main(int argc, char *argv[])
 
        nft_init_eb(&h, "ebtables-restore");
        h.noflush = noflush;
+       h.compat = compat;
        xtables_restore_parse(&h, &p);
        nft_fini_eb(&h);
 
index 5d73481c25761b1eaf2f329051d39bbff88c1929..7d540880da4710917faf029304aa4ebd9cee1ee0 100644 (file)
@@ -82,6 +82,7 @@ static struct option original_opts[] = {
        {.name = "goto",          .has_arg = 1, .val = 'g'},
        {.name = "ipv4",          .has_arg = 0, .val = '4'},
        {.name = "ipv6",          .has_arg = 0, .val = '6'},
+       {.name = "compat",        .has_arg = 0, .val = 20},
        {NULL},
 };
 
@@ -147,6 +148,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
                .restore        = restore,
                .line           = line,
                .ops            = &h->ops->cmd_parse,
+               .compat         = compat_env_val(),
        };
        struct iptables_command_state cs = {
                .jumpto = "",
@@ -161,6 +163,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 
        do_parse(argc, argv, &p, &cs, &args);
        h->verbose = p.verbose;
+       h->compat  = p.compat;
 
        if (!nft_table_builtin_find(h, p.table))
                xtables_error(VERSION_PROBLEM,