iptables-restore < /tmp/bogus
iptables-restore v1.6.2: iptables-restore:
line 49: RULE_APPEND failed (No such file or directory): rule in chain FOOBAR
line 2023: RULE_APPEND failed (Invalid argument): rule in chain TESTSNAT

This is a followup commit to 437746c7b528f ("xtables: extended error 
reporting").

Signed-off-by: Florian Westphal <f...@strlen.de>
---
 iptables/nft.c | 56 +++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 19 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index e33d00f4259c..6c68600fd979 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -273,11 +273,11 @@ struct obj_update {
        } error;
 };
 
-static void mnl_show_error(const struct nft_handle *h,
-                          const struct obj_update *o,
-                          const struct mnl_err *err)
+static int mnl_append_error(const struct nft_handle *h,
+                           const struct obj_update *o,
+                           const struct mnl_err *err,
+                           char *buf, unsigned int len)
 {
-       const char *prog = xt_params->program_name;
        static const char *type_name[] = {
                [NFT_COMPAT_TABLE_ADD] = "TABLE_ADD",
                [NFT_COMPAT_TABLE_FLUSH] = "TABLE_FLUSH",
@@ -296,8 +296,12 @@ static void mnl_show_error(const struct nft_handle *h,
        char errmsg[256];
        char tcr[128];
 
-       snprintf(errmsg, sizeof(errmsg), "%s: line %u: %s failed (%s): ",
-                prog, o->error.lineno, type_name[o->type], strerror(err->err));
+       if (o->error.lineno)
+               snprintf(errmsg, sizeof(errmsg), "\nline %u: %s failed (%s)",
+                        o->error.lineno, type_name[o->type], 
strerror(err->err));
+       else
+               snprintf(errmsg, sizeof(errmsg), "%s failed (%s)",
+                        type_name[o->type], strerror(err->err));
 
        switch (o->type) {
        case NFT_COMPAT_TABLE_ADD:
@@ -331,7 +335,7 @@ static void mnl_show_error(const struct nft_handle *h,
                break;
        }
 
-       fprintf(stderr, "%s: %s", errmsg, tcr);
+       return snprintf(buf, len, "%s: %s", errmsg, tcr);
 }
 
 static int batch_add(struct nft_handle *h, enum obj_update_type type, void 
*ptr)
@@ -2396,6 +2400,8 @@ static int nft_action(struct nft_handle *h, int action)
 {
        struct obj_update *n, *tmp;
        struct mnl_err *err, *ne;
+       unsigned int buflen, i, len;
+       char errmsg[1024];
        uint32_t seq = 1;
        int ret = 0;
 
@@ -2481,26 +2487,38 @@ static int nft_action(struct nft_handle *h, int action)
 
        ret = mnl_batch_talk(h->nl, h->batch, &h->err_list);
 
-       list_for_each_entry_safe(err, ne, &h->err_list, head) {
-               list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
-                       bool next_err = false;
+       i = 0;
+       buflen = sizeof(errmsg);
+       if (!list_empty(&h->err_list)) {
+               len = snprintf(errmsg, buflen + i, "%s: ", 
xt_params->program_name);
+               if (len > 0) {
+                       i += len;
+                       buflen -= len;
+               }
+       }
+
+       list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
+               list_for_each_entry_safe(err, ne, &h->err_list, head) {
+                       if (err->seqnum > n->seq)
+                               break;
 
                        if (err->seqnum == n->seq) {
-                               mnl_show_error(h, n, err);
-                               next_err = true;
+                               len = mnl_append_error(h, n, err, errmsg + i, 
buflen);
+                               if (len > 0 && len <= buflen) {
+                                       buflen -= len;
+                                       i += len;
+                               }
                        }
-                       batch_obj_del(h, n);
-                       if (next_err)
-                               break;
+                       mnl_err_list_free(err);
                }
-               mnl_err_list_free(err);
-       }
-
-       list_for_each_entry_safe(n, tmp, &h->obj_list, head)
                batch_obj_del(h, n);
+       }
 
        mnl_batch_reset(h->batch);
 
+       if (i)
+               xtables_error(RESOURCE_PROBLEM, "%s", errmsg);
+
        return ret == 0 ? 1 : 0;
 }
 
-- 
2.16.1

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

Reply via email to