iptables: add exception handling
authorJo-Philipp Wich <jo@mein.io>
Tue, 2 May 2017 13:01:02 +0000 (15:01 +0200)
committerJo-Philipp Wich <jo@mein.io>
Fri, 12 May 2017 14:10:06 +0000 (16:10 +0200)
Override libxtables standard error handler to not exit the program but to
longjmp() back to error handling code which is simply skipping the rule.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
iptables.c

index 10bfea5e084333cf7b2db28ebda23acaa1c0dc2e..319c5f6c98a553c39b26dee2a33384ee55211d76 100644 (file)
@@ -40,6 +40,8 @@
 #include <libiptc/libip6tc.h>
 #include <xtables.h>
 
+#include <setjmp.h>
+
 #include "options.h"
 
 /* xtables interface */
@@ -78,10 +80,29 @@ static struct option base_opts[] = {
        { NULL }
 };
 
+
+static jmp_buf fw3_ipt_error_jmp;
+
+static __attribute__((noreturn))
+void fw3_ipt_error_handler(enum xtables_exittype status,
+                           const char *fmt, ...)
+{
+       va_list args;
+
+       fprintf(stderr, "     ! Exception: ");
+
+       va_start(args, fmt);
+       vfprintf(stderr, fmt, args);
+       va_end(args);
+
+       longjmp(fw3_ipt_error_jmp, status);
+}
+
 static struct xtables_globals xtg = {
        .option_offset = 0,
        .program_version = "4",
        .orig_opts = base_opts,
+       .exit_err = fw3_ipt_error_handler,
 #if XTABLES_VERSION_CODE > 10
        .compat_rev = xtables_compatible_revision,
 #endif
@@ -91,6 +112,7 @@ static struct xtables_globals xtg6 = {
        .option_offset = 0,
        .program_version = "6",
        .orig_opts = base_opts,
+       .exit_err = fw3_ipt_error_handler,
 #if XTABLES_VERSION_CODE > 10
        .compat_rev = xtables_compatible_revision,
 #endif
@@ -1524,6 +1546,8 @@ __fw3_ipt_rule_append(struct fw3_ipt_rule *r, bool repl, const char *fmt, ...)
        struct xtables_target *et;
        struct xtables_globals *g;
 
+       enum xtables_exittype status;
+
        int i, optc;
        bool inv = false;
        char buf[32];
@@ -1539,6 +1563,14 @@ __fw3_ipt_rule_append(struct fw3_ipt_rule *r, bool repl, const char *fmt, ...)
        optind = 0;
        opterr = 0;
 
+       status = setjmp(fw3_ipt_error_jmp);
+
+       if (status > 0)
+       {
+               info("     ! Skipping due to previous exception (code %u)", status);
+               goto free;
+       }
+
        set_rule_tag(r);
 
        while ((optc = getopt_long(r->argc, r->argv, "-:m:j:", g->opts,