This fixes a bunch of issues found when actually testing my code:

* Although add_param_to_argv() takes care of the trailing newline
  character, it has to be removed for lines defining tables and chains.
* Table flushing must be done in a separate transaction, otherwise the
  cache still contains old entries and automatic insertion of built-in
  chains does not happen.
* Call nft_table_new() for each table definition to trigger creation of
  built-in chains. Otherwise the relevant batch jobs are later inserted
  after those created by chain definitions, effectively undoing any
  policy changes.
* Fix off-by-one when assigning to variable pointing at chain name in
  chain definition.
* Skip chain policy setting for non-built-in chains.
* Make sure free_argv() is called after each call to do_commandeb().
* Call nft_fini() before returning to caller.

Signed-off-by: Phil Sutter <[email protected]>
---
 iptables/xtables-restore.c | 39 ++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 5c0ae98e8821a..ead61842bc360 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -645,30 +645,38 @@ int xtables_eb_restore_main(int argc, char *argv[])
                if (buffer[0] == '#' || buffer[0] == '\n')
                        continue;
                if (buffer[0] == '*') {
+                       *strchr(buffer, '\n') = '\0';
                        table = ebt_parse_table_name(buffer + 1);
-                       if (flush)
+                       if (flush) {
                                nft_table_flush(&h, table);
+                               nft_commit(&h);
+                       }
+                       nft_table_new(&h, table);
                        continue;
                } else if (!table) {
                        xtables_error(PARAMETER_PROBLEM, "no table specified");
                }
                if (buffer[0] == ':') {
-                       char *ch, *chain = buffer;
+                       char *ch, *chain = buffer + 1;
                        const char *policy;
 
                        if (!(ch = strchr(buffer, ' ')))
                                xtables_error(PARAMETER_PROBLEM, "no policy 
specified");
                        *ch = '\0';
+                       *strchr(ch + 1, '\n') = '\0';
                        policy = ebt_parse_policy_name(ch + 1);
 
                        /* No need to check chain name for consistency, since
                         * we're supposed to be reading an automatically 
generated
                         * file. */
-                       if (ebt_get_current_chain(chain) < 0)
+                       if (ebt_get_current_chain(chain) < 0) {
                                nft_chain_user_add(&h, chain, table);
-                       ret = nft_chain_set(&h, table, chain, policy, NULL);
-                       if (ret < 0)
-                               xtables_error(PARAMETER_PROBLEM, "Wrong 
policy");
+                       } else {
+                               ret = nft_chain_set(&h, table, chain, policy, 
NULL);
+                               if (!ret)
+                                       xtables_error(PARAMETER_PROBLEM,
+                                                     "Wrong policy '%s' of 
chain %s in table %s", policy, chain, table);
+                       }
                        continue;
                }
 
@@ -685,13 +693,20 @@ int xtables_eb_restore_main(int argc, char *argv[])
                        DEBUGP("argv[%u]: %s\n", i, newargv[i]);
 
                optind = 0; /* Setting optind = 1 causes serious annoyances */
-               if (!do_commandeb(&h, newargc, newargv, &newargv[2]))
-                       return 1;
+               ret = do_commandeb(&h, newargc, newargv, &newargv[2]);
+
+               free_argv();
+
+               if (!ret)
+                       break;
        }
 
-       if (!nft_commit(&h)) {
+       if (ret)
+               ret = nft_commit(&h);
+
+       nft_fini(&h);
+
+       if (!ret)
                fprintf(stderr, "%s\n", nft_strerror(errno));
-               return 1;
-       }
-       return 0;
+       return !ret;
 }
-- 
2.18.0

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

Reply via email to