--- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -14,6 +14,8 @@ #include <string.h> #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> +#include <setjmp.h> #include "ip6tables.h" #include "xtables.h" #include "libiptc/libip6tc.h" @@ -25,6 +27,7 @@ #define DEBUGP(x, args...) #endif +static jmp_buf jmp; static int binary = 0, counters = 0, verbose = 0, noflush = 0; /* Keeping track of external matches and targets. */ @@ -35,6 +38,7 @@ static const struct option options[] = { {.name = "test", .has_arg = false, .val = 't'}, {.name = "help", .has_arg = false, .val = 'h'}, {.name = "noflush", .has_arg = false, .val = 'n'}, + {.name = "lenient", .has_arg = false, .val = 'l'}, {.name = "modprobe", .has_arg = true, .val = 'M'}, {.name = "table", .has_arg = true, .val = 'T'}, {NULL}, @@ -51,6 +55,7 @@ static void print_usage(const char *name " [ --test ]\n" " [ --help ]\n" " [ --noflush ]\n" + " [ --lenient ]\n" " [ --modprobe=<command>]\n", name); exit(1); @@ -114,6 +119,17 @@ static void free_argv(void) { free(newargv[i]); } +static void catch_exit_error(enum xtables_exittype status, const char *msg, ...) +{ + va_list args; + fprintf(stderr, "line %d: ", line); + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + longjmp(jmp, status); +} + static void add_param_to_argv(char *parsestart) { int quote_open = 0, escaped = 0, param_len = 0; @@ -204,7 +220,7 @@ int ip6tables_restore_main(int argc, cha init_extensions6(); #endif - while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "bcvthnlM:T:", options, NULL)) != -1) { switch (c) { case 'b': binary = 1; @@ -225,6 +241,9 @@ int ip6tables_restore_main(int argc, cha case 'n': noflush = 1; break; + case 'l': + ip6tables_globals.exit_err = catch_exit_error; + break; case 'M': xtables_modprobe_program = optarg; break; @@ -437,8 +456,11 @@ int ip6tables_restore_main(int argc, cha for (a = 0; a < newargc; a++) DEBUGP("argv[%u]: %s\n", a, newargv[a]); - ret = do_command6(newargc, newargv, - &newargv[2], &handle, true); + if (!setjmp(jmp)) + ret = do_command6(newargc, newargv, + &newargv[2], &handle, true); + else + ret = 1; free_argv(); fflush(stdout); --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -11,6 +11,8 @@ #include <string.h> #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> +#include <setjmp.h> #include "iptables.h" #include "xtables.h" #include "libiptc/libiptc.h" @@ -22,6 +24,7 @@ #define DEBUGP(x, args...) #endif +static jmp_buf jmp; static int binary = 0, counters = 0, verbose = 0, noflush = 0; /* Keeping track of external matches and targets. */ @@ -32,6 +35,7 @@ static const struct option options[] = { {.name = "test", .has_arg = false, .val = 't'}, {.name = "help", .has_arg = false, .val = 'h'}, {.name = "noflush", .has_arg = false, .val = 'n'}, + {.name = "lenient", .has_arg = false, .val = 'l'}, {.name = "modprobe", .has_arg = true, .val = 'M'}, {.name = "table", .has_arg = true, .val = 'T'}, {NULL}, @@ -50,6 +54,7 @@ static void print_usage(const char *name " [ --test ]\n" " [ --help ]\n" " [ --noflush ]\n" + " [ --lenient ]\n" " [ --table=<TABLE> ]\n" " [ --modprobe=<command>]\n", name); @@ -113,6 +118,17 @@ static void free_argv(void) { free(newargv[i]); } +static void catch_exit_error(enum xtables_exittype status, const char *msg, ...) +{ + va_list args; + fprintf(stderr, "line %d: ", line); + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + longjmp(jmp, status); +} + static void add_param_to_argv(char *parsestart) { int quote_open = 0, escaped = 0, param_len = 0; @@ -204,7 +220,7 @@ iptables_restore_main(int argc, char *ar init_extensions4(); #endif - while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "bcvthnlM:T:", options, NULL)) != -1) { switch (c) { case 'b': binary = 1; @@ -225,6 +241,9 @@ iptables_restore_main(int argc, char *ar case 'n': noflush = 1; break; + case 'l': + iptables_globals.exit_err = catch_exit_error; + break; case 'M': xtables_modprobe_program = optarg; break; @@ -437,8 +456,11 @@ iptables_restore_main(int argc, char *ar for (a = 0; a < newargc; a++) DEBUGP("argv[%u]: %s\n", a, newargv[a]); - ret = do_command4(newargc, newargv, - &newargv[2], &handle, true); + if (!setjmp(jmp)) + ret = do_command4(newargc, newargv, + &newargv[2], &handle, true); + else + ret = 1; free_argv(); fflush(stdout);