From aaafda4b9acc1040308b504c4cccd593dc212e93 Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 14:59:43 +1100 Subject: [PATCH 01/11] catch ABI errors --- ipthelper/xshared.c | 135 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 18 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index aaf42be6..ce75f4b7 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -14,10 +14,83 @@ #include #include #include +#if defined(__unix__) || defined(__APPLE__) +#include +#endif #include "xtables.h" #include #include "xshared.h" +#define XS_LONGOPTS_SCAN_LIMIT 4096U + +#if defined(__unix__) || defined(__APPLE__) +#define XS_HAVE_DLADDR 1 +#else +#define XS_HAVE_DLADDR 0 +#endif + +static size_t xs_longopts_count(const struct option *opts, const char *ext_name) +{ + size_t i; + + if (opts == NULL) + return 0; + + for (i = 0; i < XS_LONGOPTS_SCAN_LIMIT; ++i) { + if (opts[i].name == NULL) + return i; + } + + if (ext_name != NULL) + xtables_error(OTHER_PROBLEM, + "Extension \"%s\" returned an unterminated option table.", + ext_name); + + xtables_error(OTHER_PROBLEM, + "xtables option table is missing its terminator."); + return 0; +} + +#if XS_HAVE_DLADDR +static bool xs_option_name_pointer_is_valid(const char *name) +{ + Dl_info info; + + if (name == NULL) + return true; + + return dladdr((const void *)name, &info) != 0; +} +#else +static bool xs_option_name_pointer_is_valid(const char *name) +{ + (void)name; + return true; +} +#endif + +static void xs_validate_new_longopts(struct option *opts, size_t start, + const char *ext_name) +{ + size_t total; + size_t i; + + if (opts == NULL || ext_name == NULL) + return; + + total = xs_longopts_count(opts, ext_name); + if (start >= total) + return; + + for (i = start; i < total; ++i) { + if (!xs_option_name_pointer_is_valid(opts[i].name)) { + xtables_error(OTHER_PROBLEM, + "Extension \"%s\" was built against an incompatible libxtables release (detected corrupt option metadata). Please rebuild the module.", + ext_name); + } + } +} + /* * Print out any special helps. A user might like to be able to add a --help * to the commandline, and see expected results. So we call help for all @@ -146,6 +219,7 @@ int command_default(struct iptables_command_state *cs, m = load_proto(cs); if (m != NULL) { size_t size; + size_t merge_start; cs->proto_used = 1; @@ -157,6 +231,7 @@ int command_default(struct iptables_command_state *cs, m->m->u.user.revision = m->revision; xs_init_match(m); + merge_start = xs_longopts_count(gl->opts, NULL); if (m->x6_options != NULL) gl->opts = xtables_options_xfrm(gl->orig_opts, gl->opts, @@ -164,11 +239,14 @@ int command_default(struct iptables_command_state *cs, &m->option_offset); else gl->opts = xtables_merge_options(gl->orig_opts, - gl->opts, - m->extra_opts, - &m->option_offset); + gl->opts, + m->extra_opts, + &m->option_offset); if (gl->opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + xs_validate_new_longopts(gl->opts, merge_start, + m->real_name != NULL ? + m->real_name : m->name); optind--; /* Indicate to rerun getopt *immediately* */ return 1; @@ -564,18 +642,27 @@ void command_match(struct iptables_command_state *cs) if (m == m->next) return; /* Merge options for non-cloned matches */ - if (m->x6_options != NULL){ - opts = xtables_options_xfrm(xt_params->orig_opts, opts, + { + bool merged = false; + size_t merge_start = xs_longopts_count(opts, NULL); + + if (m->x6_options != NULL) { + opts = xtables_options_xfrm(xt_params->orig_opts, opts, m->x6_options, &m->option_offset); -int num_orig; -for (num_orig = 0; opts[num_orig].name != NULL; ++num_orig) {} + merged = true; + } else if (m->extra_opts != NULL) { + opts = xtables_merge_options(xt_params->orig_opts, opts, + m->extra_opts, &m->option_offset); + merged = true; + } + if (opts == NULL) + xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + if (merged) + xs_validate_new_longopts(opts, merge_start, + m->real_name != NULL ? + m->real_name : m->name); } - else if (m->extra_opts != NULL) - opts = xtables_merge_options(xt_params->orig_opts, opts, - m->extra_opts, &m->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); xt_params->opts = opts; } @@ -628,15 +715,27 @@ void command_jump(struct iptables_command_state *cs) cs->target->t->u.user.revision = cs->target->revision; xs_init_target(cs->target); - if (cs->target->x6_options != NULL) - opts = xtables_options_xfrm(xt_params->orig_opts, opts, + { + bool merged = false; + size_t merge_start = xs_longopts_count(opts, NULL); + + if (cs->target->x6_options != NULL) { + opts = xtables_options_xfrm(xt_params->orig_opts, opts, cs->target->x6_options, &cs->target->option_offset); - else - opts = xtables_merge_options(xt_params->orig_opts, opts, + merged = true; + } else if (cs->target->extra_opts != NULL) { + opts = xtables_merge_options(xt_params->orig_opts, opts, cs->target->extra_opts, &cs->target->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + merged = true; + } + if (opts == NULL) + xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + if (merged) + xs_validate_new_longopts(opts, merge_start, + cs->target->real_name != NULL ? + cs->target->real_name : cs->jumpto); + } xt_params->opts = opts; } From 880db7f0938f8c653cd8aad002ddedf0be4cc274 Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 10:42:32 +1100 Subject: [PATCH 02/11] fixing with new libxtables --- ipthelper/ip6tables.c | 28 +++++++++++++++++++++++++--- ipthelper/iptables.c | 28 ++++++++++++++++++++++++++-- ipthelper/xshared.c | 32 ++++++++++++++------------------ 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/ipthelper/ip6tables.c b/ipthelper/ip6tables.c index 10fd748d..0021e7fa 100644 --- a/ipthelper/ip6tables.c +++ b/ipthelper/ip6tables.c @@ -216,7 +216,6 @@ static const unsigned int inverse_for_options[NUMBER_OF_OPT] = 0, }; -#define opts iptables_globals.opts #define prog_name iptables_globals.program_name #define prog_vers iptables_globals.program_version /* A few hardcoded protocols for 'all' and in case the user has no @@ -1439,10 +1438,27 @@ int do_command6(int argc, char *argv[], char **table, void **handle) demand-load a protocol. */ opterr = 0; - opts = xt_params->orig_opts; + /* Create a malloc'd copy of orig_opts */ + if (iptables_globals.opts == NULL) { + size_t num_opts = 0; + struct option *orig_opts = iptables_globals.orig_opts; + + /* Count the number of options (including the NULL terminator) */ + while (orig_opts[num_opts].name != NULL) { + num_opts++; + } + num_opts++; /* Include the NULL terminator */ + + /* Allocate memory and copy the options */ + iptables_globals.opts = malloc(num_opts * sizeof(struct option)); + if (iptables_globals.opts == NULL) { + xtables_error(OTHER_PROBLEM, "malloc failed for options array"); + } + memcpy(iptables_globals.opts, iptables_globals.orig_opts, num_opts * sizeof(struct option)); + } while ((cs.c = getopt_long(argc, argv, "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:46", - opts, NULL)) != -1) { + iptables_globals.opts?: iptables_globals.orig_opts, NULL)) != -1) { switch (cs.c) { /* * Command selection @@ -2017,5 +2033,11 @@ int do_command6(int argc, char *argv[], char **table, void **handle) free(dmasks); xtables_free_opts(1); + /* Free the malloc'd copy of opts if it was allocated */ + if (iptables_globals.opts != iptables_globals.orig_opts) { + free(iptables_globals.opts); + iptables_globals.opts = NULL; + } + return ret; } diff --git a/ipthelper/iptables.c b/ipthelper/iptables.c index 4c0e0266..a852412a 100644 --- a/ipthelper/iptables.c +++ b/ipthelper/iptables.c @@ -1017,10 +1017,28 @@ int do_command4(int argc, char *argv[], char **table, void **handle) demand-load a protocol. */ opterr = 0; - iptables_globals.opts = iptables_globals.orig_opts; + /* Create a malloc'd copy of orig_opts */ + if (iptables_globals.opts == NULL) { + size_t num_opts = 0; + struct option *orig_opts = iptables_globals.orig_opts; + + /* Count the number of options (including the NULL terminator) */ + while (orig_opts[num_opts].name != NULL) { + num_opts++; + } + num_opts++; /* Include the NULL terminator */ + + /* Allocate memory and copy the options */ + iptables_globals.opts = malloc(num_opts * sizeof(struct option)); + if (iptables_globals.opts == NULL) { + xtables_error(OTHER_PROBLEM, "malloc failed for options array"); + } + memcpy(iptables_globals.opts, iptables_globals.orig_opts, num_opts * sizeof(struct option)); + } while ((cs.c = getopt_long(argc, argv, "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:46", - iptables_globals.opts, NULL)) != -1) { + iptables_globals.opts?: iptables_globals.orig_opts, + NULL)) != -1) { switch (cs.c) { /* * Command selection @@ -1523,5 +1541,11 @@ int do_command4(int argc, char *argv[], char **table, void **handle) free(dmasks); //xtables_free_opts(1); + /* Free the malloc'd copy of opts if it was allocated */ + if (iptables_globals.opts != iptables_globals.orig_opts) { + free(iptables_globals.opts); + iptables_globals.opts = NULL; + } + return ret; } \ No newline at end of file diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index ce75f4b7..f566b5b1 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -643,23 +643,22 @@ void command_match(struct iptables_command_state *cs) return; /* Merge options for non-cloned matches */ { - bool merged = false; size_t merge_start = xs_longopts_count(opts, NULL); if (m->x6_options != NULL) { opts = xtables_options_xfrm(xt_params->orig_opts, opts, m->x6_options, &m->option_offset); - merged = true; } else if (m->extra_opts != NULL) { opts = xtables_merge_options(xt_params->orig_opts, opts, m->extra_opts, &m->option_offset); - merged = true; - } + + } else + return; if (opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); - if (merged) - xs_validate_new_longopts(opts, merge_start, + + xs_validate_new_longopts(opts, merge_start, m->real_name != NULL ? m->real_name : m->name); } @@ -723,19 +722,16 @@ void command_jump(struct iptables_command_state *cs) opts = xtables_options_xfrm(xt_params->orig_opts, opts, cs->target->x6_options, &cs->target->option_offset); - merged = true; - } else if (cs->target->extra_opts != NULL) { - opts = xtables_merge_options(xt_params->orig_opts, opts, + else if (cs->target->extra_opts != NULL) + opts = xtables_merge_options(xt_params->orig_opts, opts, cs->target->extra_opts, &cs->target->option_offset); - merged = true; - } - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); - if (merged) - xs_validate_new_longopts(opts, merge_start, - cs->target->real_name != NULL ? - cs->target->real_name : cs->jumpto); - } + else + return; + if (opts == NULL) + xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + xs_validate_new_longopts(opts, merge_start, + cs->target->real_name != NULL ? + cs->target->real_name : cs->jumpto); xt_params->opts = opts; } From 0c7d2979de3dae7c620bd6ec32fc85d3fe51904a Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 11:10:23 +1100 Subject: [PATCH 03/11] Update xshared.c From 661db311e82bea1355a4ef8976b85171f7889a83 Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 15:03:43 +1100 Subject: [PATCH 04/11] Update xshared.c --- ipthelper/xshared.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index f566b5b1..474a782e 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -1,3 +1,7 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + #include #include #include @@ -64,7 +68,13 @@ static bool xs_option_name_pointer_is_valid(const char *name) #else static bool xs_option_name_pointer_is_valid(const char *name) { - (void)name; + if (name == NULL) + return true; + +#if INTPTR_MAX > 0xffffffff + if ((uintptr_t)name < 0x100000000ULL) + return false; +#endif return true; } #endif From 490906ba09416b6a68408fbb6c09bec6070b1f78 Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 15:37:51 +1100 Subject: [PATCH 05/11] Update xshared.c --- ipthelper/xshared.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index 474a782e..506fd48c 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -724,14 +724,12 @@ void command_jump(struct iptables_command_state *cs) cs->target->t->u.user.revision = cs->target->revision; xs_init_target(cs->target); - { - bool merged = false; - size_t merge_start = xs_longopts_count(opts, NULL); + size_t merge_start = xs_longopts_count(opts, NULL); - if (cs->target->x6_options != NULL) { - opts = xtables_options_xfrm(xt_params->orig_opts, opts, - cs->target->x6_options, - &cs->target->option_offset); + if (cs->target->x6_options != NULL) { + opts = xtables_options_xfrm(xt_params->orig_opts, opts, + cs->target->x6_options, + &cs->target->option_offset); else if (cs->target->extra_opts != NULL) opts = xtables_merge_options(xt_params->orig_opts, opts, cs->target->extra_opts, From c6fe1447324c361f1d57a558a3914d498a315c2b Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 15:39:17 +1100 Subject: [PATCH 06/11] Update xshared.c --- ipthelper/xshared.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index 506fd48c..5b378eb6 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -730,7 +730,7 @@ void command_jump(struct iptables_command_state *cs) opts = xtables_options_xfrm(xt_params->orig_opts, opts, cs->target->x6_options, &cs->target->option_offset); - else if (cs->target->extra_opts != NULL) + } else if (cs->target->extra_opts != NULL) opts = xtables_merge_options(xt_params->orig_opts, opts, cs->target->extra_opts, &cs->target->option_offset); From 38b779bab5736b10673a29fb596f7ac7825a19cc Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 15:42:10 +1100 Subject: [PATCH 07/11] Update xshared.c --- ipthelper/xshared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index 5b378eb6..e4a03c01 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -738,8 +738,8 @@ void command_jump(struct iptables_command_state *cs) return; if (opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); - xs_validate_new_longopts(opts, merge_start, + /*xs_validate_new_longopts(opts, merge_start, cs->target->real_name != NULL ? - cs->target->real_name : cs->jumpto); + cs->target->real_name : cs->jumpto);*/ xt_params->opts = opts; } From aa2603e5156421ae14e77fe58e441002e871435a Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 15:59:59 +1100 Subject: [PATCH 08/11] Revert "Update xshared.c" This reverts commit 38b779bab5736b10673a29fb596f7ac7825a19cc. --- ipthelper/xshared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index e4a03c01..5b378eb6 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -738,8 +738,8 @@ void command_jump(struct iptables_command_state *cs) return; if (opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); - /*xs_validate_new_longopts(opts, merge_start, + xs_validate_new_longopts(opts, merge_start, cs->target->real_name != NULL ? - cs->target->real_name : cs->jumpto);*/ + cs->target->real_name : cs->jumpto); xt_params->opts = opts; } From 50c2f1459487d9cd2f0b5074e9f99040e07f993e Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 16:07:44 +1100 Subject: [PATCH 09/11] ... --- ipthelper/xshared.c | 6 ++-- ipthelper/xshared.h | 4 +++ ipthelper/xtoptions.c | 65 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index 5b378eb6..29d2e393 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -248,7 +248,7 @@ int command_default(struct iptables_command_state *cs, m->x6_options, &m->option_offset); else - gl->opts = xtables_merge_options(gl->orig_opts, + gl->opts = xs_merge_options(gl->orig_opts, gl->opts, m->extra_opts, &m->option_offset); @@ -659,7 +659,7 @@ void command_match(struct iptables_command_state *cs) opts = xtables_options_xfrm(xt_params->orig_opts, opts, m->x6_options, &m->option_offset); } else if (m->extra_opts != NULL) { - opts = xtables_merge_options(xt_params->orig_opts, opts, + opts = xs_merge_options(xt_params->orig_opts, opts, m->extra_opts, &m->option_offset); } else @@ -731,7 +731,7 @@ void command_jump(struct iptables_command_state *cs) cs->target->x6_options, &cs->target->option_offset); } else if (cs->target->extra_opts != NULL) - opts = xtables_merge_options(xt_params->orig_opts, opts, + opts = xs_merge_options(xt_params->orig_opts, opts, cs->target->extra_opts, &cs->target->option_offset); else diff --git a/ipthelper/xshared.h b/ipthelper/xshared.h index 52a91b21..16073a29 100644 --- a/ipthelper/xshared.h +++ b/ipthelper/xshared.h @@ -179,5 +179,9 @@ void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags, void command_match(struct iptables_command_state *cs); const char *xt_parse_target(const char *targetname); void command_jump(struct iptables_command_state *cs); +struct option *xs_merge_options(struct option *orig_opts, + struct option *oldopts, + const struct option *newopts, + unsigned int *option_offset); #endif /* IPTABLES_XSHARED_H */ diff --git a/ipthelper/xtoptions.c b/ipthelper/xtoptions.c index d329f2ff..69fc86aa 100644 --- a/ipthelper/xtoptions.c +++ b/ipthelper/xtoptions.c @@ -120,13 +120,76 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, memcpy(mp, oldopts, sizeof(*mp) * num_old); mp += num_old; } - xtables_free_opts(0); + if (xt_params->opts != NULL && xt_params->opts != xt_params->orig_opts) + xtables_free_opts(0); /* Clear trailing entry */ memset(mp, 0, sizeof(*mp)); return merge; } +struct option * +xs_merge_options(struct option *orig_opts, struct option *oldopts, + const struct option *newopts, unsigned int *option_offset) +{ + unsigned int num_orig = 0, num_old = 0, num_new = 0, i; + struct option *merge; + struct option *mp; + struct option *old_base = oldopts; + + if (newopts == NULL || newopts->name == NULL) + return oldopts; + + if (orig_opts != NULL) + for (; orig_opts[num_orig].name != NULL; ++num_orig) + ; + + if (oldopts != NULL) + for (; oldopts[num_old].name != NULL; ++num_old) + ; + + for (; newopts[num_new].name != NULL; ++num_new) + ; + + if (oldopts != NULL && num_old >= num_orig) { + oldopts += num_orig; + num_old -= num_orig; + } else { + oldopts = NULL; + num_old = 0; + } + + merge = malloc(sizeof(*merge) * (num_orig + num_new + num_old + 1)); + if (merge == NULL) + return NULL; + + if (num_orig != 0) + memcpy(merge, orig_opts, sizeof(*merge) * num_orig); + mp = merge + num_orig; + + xt_params->option_offset += XT_OPTION_OFFSET_SCALE; + *option_offset = xt_params->option_offset; + + for (i = 0; i < num_new; ++i, ++mp) { + mp->name = newopts[i].name; + mp->has_arg = newopts[i].has_arg; + mp->flag = newopts[i].flag; + mp->val = newopts[i].val + *option_offset; + } + + if (oldopts != NULL && num_old != 0) { + memcpy(mp, oldopts, sizeof(*mp) * num_old); + mp += num_old; + } + + memset(mp, 0, sizeof(*mp)); + + if (old_base != NULL && old_base != orig_opts && old_base != xt_params->orig_opts) + free(old_base); + + return merge; +} + /** * Give the upper limit for a certain type. */ From 0ad5a1ef0379058073ced0f5eb38b660c85b626e Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 16:16:03 +1100 Subject: [PATCH 10/11] ... --- ipthelper/xshared.c | 63 +++++++++++++++++++++++++++++++++++++++++++ ipthelper/xtoptions.c | 62 ------------------------------------------ 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/ipthelper/xshared.c b/ipthelper/xshared.c index 29d2e393..fa893b61 100644 --- a/ipthelper/xshared.c +++ b/ipthelper/xshared.c @@ -743,3 +743,66 @@ void command_jump(struct iptables_command_state *cs) cs->target->real_name : cs->jumpto); xt_params->opts = opts; } + + +struct option * +xs_merge_options(struct option *orig_opts, struct option *oldopts, + const struct option *newopts, unsigned int *option_offset) +{ + unsigned int num_orig = 0, num_old = 0, num_new = 0, i; + struct option *merge; + struct option *mp; + struct option *old_base = oldopts; + + if (newopts == NULL || newopts->name == NULL) + return oldopts; + + if (orig_opts != NULL) + for (; orig_opts[num_orig].name != NULL; ++num_orig) + ; + + if (oldopts != NULL) + for (; oldopts[num_old].name != NULL; ++num_old) + ; + + for (; newopts[num_new].name != NULL; ++num_new) + ; + + if (oldopts != NULL && num_old >= num_orig) { + oldopts += num_orig; + num_old -= num_orig; + } else { + oldopts = NULL; + num_old = 0; + } + + merge = malloc(sizeof(*merge) * (num_orig + num_new + num_old + 1)); + if (merge == NULL) + return NULL; + + if (num_orig != 0) + memcpy(merge, orig_opts, sizeof(*merge) * num_orig); + mp = merge + num_orig; + + xt_params->option_offset += XT_OPTION_OFFSET_SCALE; + *option_offset = xt_params->option_offset; + + for (i = 0; i < num_new; ++i, ++mp) { + mp->name = newopts[i].name; + mp->has_arg = newopts[i].has_arg; + mp->flag = newopts[i].flag; + mp->val = newopts[i].val + *option_offset; + } + + if (oldopts != NULL && num_old != 0) { + memcpy(mp, oldopts, sizeof(*mp) * num_old); + mp += num_old; + } + + memset(mp, 0, sizeof(*mp)); + + if (old_base != NULL && old_base != orig_opts && old_base != xt_params->orig_opts) + free(old_base); + + return merge; +} \ No newline at end of file diff --git a/ipthelper/xtoptions.c b/ipthelper/xtoptions.c index 69fc86aa..d0af9626 100644 --- a/ipthelper/xtoptions.c +++ b/ipthelper/xtoptions.c @@ -128,68 +128,6 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, return merge; } -struct option * -xs_merge_options(struct option *orig_opts, struct option *oldopts, - const struct option *newopts, unsigned int *option_offset) -{ - unsigned int num_orig = 0, num_old = 0, num_new = 0, i; - struct option *merge; - struct option *mp; - struct option *old_base = oldopts; - - if (newopts == NULL || newopts->name == NULL) - return oldopts; - - if (orig_opts != NULL) - for (; orig_opts[num_orig].name != NULL; ++num_orig) - ; - - if (oldopts != NULL) - for (; oldopts[num_old].name != NULL; ++num_old) - ; - - for (; newopts[num_new].name != NULL; ++num_new) - ; - - if (oldopts != NULL && num_old >= num_orig) { - oldopts += num_orig; - num_old -= num_orig; - } else { - oldopts = NULL; - num_old = 0; - } - - merge = malloc(sizeof(*merge) * (num_orig + num_new + num_old + 1)); - if (merge == NULL) - return NULL; - - if (num_orig != 0) - memcpy(merge, orig_opts, sizeof(*merge) * num_orig); - mp = merge + num_orig; - - xt_params->option_offset += XT_OPTION_OFFSET_SCALE; - *option_offset = xt_params->option_offset; - - for (i = 0; i < num_new; ++i, ++mp) { - mp->name = newopts[i].name; - mp->has_arg = newopts[i].has_arg; - mp->flag = newopts[i].flag; - mp->val = newopts[i].val + *option_offset; - } - - if (oldopts != NULL && num_old != 0) { - memcpy(mp, oldopts, sizeof(*mp) * num_old); - mp += num_old; - } - - memset(mp, 0, sizeof(*mp)); - - if (old_base != NULL && old_base != orig_opts && old_base != xt_params->orig_opts) - free(old_base); - - return merge; -} - /** * Give the upper limit for a certain type. */ From b2889d1c0578cdc4ea40b3c3e1f539fbe16f6dba Mon Sep 17 00:00:00 2001 From: Mathew Date: Thu, 6 Nov 2025 16:19:32 +1100 Subject: [PATCH 11/11] Update ip6tables.c --- ipthelper/ip6tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipthelper/ip6tables.c b/ipthelper/ip6tables.c index 0021e7fa..5952f7e2 100644 --- a/ipthelper/ip6tables.c +++ b/ipthelper/ip6tables.c @@ -1790,7 +1790,7 @@ int do_command6(int argc, char *argv[], char **table, void **handle) continue; break; } - cs.invert = 2; + cs.invert = FALSE; } for (matchp = cs.matches; matchp; matchp = matchp->next)