]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables-compat: append all errors into single line
authorFlorian Westphal <fw@strlen.de>
Mon, 28 May 2018 20:17:39 +0000 (22:17 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 28 May 2018 21:18:27 +0000 (23:18 +0200)
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 <fw@strlen.de>
iptables/nft.c

index e33d00f4259c311bdf8137063acc2f9db5af3a66..6c68600fd979900d18123bcaff38a9ea072e59a2 100644 (file)
@@ -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;
 }