Merge these two functions from xtables, iptables, ip6tables and arptables. Both functions were basically identical in the first three, only the last one required a bit more attention. To eliminate access to 'invflags' in variant-specific location, move the call to set_option() into callers. This is actually consistent with parsing of other options in them. As with command_match(), use xt_params instead of the different *_globals objects to refer to 'opts' and 'orig_opts'. It was necessary to rename parse_target() as it otherwise clashes with a static function of same name in libxt_SET. In arptables, the maximum allowed target name is a bit larger, so introduce xtables_globals.target_maxnamelen defining the value. It is used in the shared xt_parse_target() implementation. Implementation of command_jump() in arptables diverted from the others for no obvious reason. The call to parse_target() was done outside of it and a pointer to cs->arp was passed but not used inside. Signed-off-by: Phil Sutter <phil@xxxxxx> --- include/xtables.h | 1 + iptables/ip6tables.c | 66 +++------------------------------------- iptables/iptables.c | 69 +++--------------------------------------- iptables/xshared.c | 63 ++++++++++++++++++++++++++++++++++++++ iptables/xshared.h | 2 ++ iptables/xtables-arp.c | 60 ++---------------------------------- iptables/xtables.c | 68 +++-------------------------------------- 7 files changed, 80 insertions(+), 249 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index bf169b08186f5..fd9e6c33516bc 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -424,6 +424,7 @@ struct xtables_globals struct option *opts; void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); int (*compat_rev)(const char *name, uint8_t rev, int opt); + size_t target_maxnamelen; }; #define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false} diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 1137256a259ca..7a9cd643f8e76 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -125,6 +125,7 @@ struct xtables_globals ip6tables_globals = { .orig_opts = original_opts, .exit_err = ip6tables_exit_error, .compat_rev = xtables_compatible_revision, + .target_maxnamelen = XT_EXTENSION_MAXNAMELEN, }; /* Table of legal combinations of commands and options. If any of the @@ -420,27 +421,6 @@ parse_chain(const char *chainname) "Invalid chain name `%s'", chainname); } -static const char * -parse_target(const char *targetname) -{ - const char *ptr; - - if (strlen(targetname) < 1) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name (too short)"); - - if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s' (%u chars max)", - targetname, XT_EXTENSION_MAXNAMELEN - 1); - - for (ptr = targetname; *ptr; ptr++) - if (isspace(*ptr)) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s'", targetname); - return targetname; -} - static void set_option(unsigned int *options, unsigned int option, uint8_t *invflg, int invert) @@ -1221,46 +1201,6 @@ generate_entry(const struct ip6t_entry *fw, return e; } -static void command_jump(struct iptables_command_state *cs) -{ - size_t size; - - set_option(&cs->options, OPT_JUMP, &cs->fw6.ipv6.invflags, cs->invert); - cs->jumpto = parse_target(optarg); - /* TRY_LOAD (may be chain name) */ - cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); - - if (cs->target == NULL) - return; - - size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size; - - cs->target->t = xtables_calloc(1, size); - cs->target->t->u.target_size = size; - if (cs->target->real_name == NULL) { - strcpy(cs->target->t->u.user.name, cs->jumpto); - } else { - strcpy(cs->target->t->u.user.name, cs->target->real_name); - if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) - fprintf(stderr, "Notice: The %s target is converted into %s target " - "in rule listing and saving.\n", - cs->jumpto, cs->target->real_name); - } - cs->target->t->u.user.revision = cs->target->revision; - - xs_init_target(cs->target); - if (cs->target->x6_options != NULL) - opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts, - cs->target->x6_options, - &cs->target->option_offset); - else - opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, - cs->target->extra_opts, - &cs->target->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); -} - int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle, bool restore) { @@ -1495,11 +1435,13 @@ int do_command6(int argc, char *argv[], char **table, set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, cs.invert); cs.fw6.ipv6.flags |= IP6T_F_GOTO; - cs.jumpto = parse_target(optarg); + cs.jumpto = xt_parse_target(optarg); break; #endif case 'j': + set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, + cs.invert); command_jump(&cs); break; diff --git a/iptables/iptables.c b/iptables/iptables.c index 70ba67c9a9701..b9ce64e6b32a6 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -124,6 +124,7 @@ struct xtables_globals iptables_globals = { .orig_opts = original_opts, .exit_err = iptables_exit_error, .compat_rev = xtables_compatible_revision, + .target_maxnamelen = XT_EXTENSION_MAXNAMELEN, }; /* Table of legal combinations of commands and options. If any of the @@ -405,27 +406,6 @@ parse_chain(const char *chainname) "Invalid chain name `%s'", chainname); } -static const char * -parse_target(const char *targetname) -{ - const char *ptr; - - if (strlen(targetname) < 1) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name (too short)"); - - if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s' (%u chars max)", - targetname, XT_EXTENSION_MAXNAMELEN - 1); - - for (ptr = targetname; *ptr; ptr++) - if (isspace(*ptr)) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s'", targetname); - return targetname; -} - static void set_option(unsigned int *options, unsigned int option, uint8_t *invflg, int invert) @@ -1211,49 +1191,6 @@ generate_entry(const struct ipt_entry *fw, return e; } -static void command_jump(struct iptables_command_state *cs) -{ - size_t size; - - set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, cs->invert); - cs->jumpto = parse_target(optarg); - /* TRY_LOAD (may be chain name) */ - cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); - - if (cs->target == NULL) - return; - - size = XT_ALIGN(sizeof(struct xt_entry_target)) - + cs->target->size; - - cs->target->t = xtables_calloc(1, size); - cs->target->t->u.target_size = size; - if (cs->target->real_name == NULL) { - strcpy(cs->target->t->u.user.name, cs->jumpto); - } else { - /* Alias support for userspace side */ - strcpy(cs->target->t->u.user.name, cs->target->real_name); - if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) - fprintf(stderr, "Notice: The %s target is converted into %s target " - "in rule listing and saving.\n", - cs->jumpto, cs->target->real_name); - } - cs->target->t->u.user.revision = cs->target->revision; - - xs_init_target(cs->target); - - if (cs->target->x6_options != NULL) - opts = xtables_options_xfrm(iptables_globals.orig_opts, opts, - cs->target->x6_options, - &cs->target->option_offset); - else - opts = xtables_merge_options(iptables_globals.orig_opts, opts, - cs->target->extra_opts, - &cs->target->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); -} - int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle, bool restore) { @@ -1478,11 +1415,13 @@ int do_command4(int argc, char *argv[], char **table, set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, cs.invert); cs.fw.ip.flags |= IPT_F_GOTO; - cs.jumpto = parse_target(optarg); + cs.jumpto = xt_parse_target(optarg); break; #endif case 'j': + set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, + cs.invert); command_jump(&cs); break; diff --git a/iptables/xshared.c b/iptables/xshared.c index 860373cb2db84..d5365d9398e90 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -1,4 +1,5 @@ #include <config.h> +#include <ctype.h> #include <getopt.h> #include <errno.h> #include <libgen.h> @@ -631,3 +632,65 @@ void command_match(struct iptables_command_state *cs) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); xt_params->opts = opts; } + +const char *xt_parse_target(const char *targetname) +{ + const char *ptr; + + if (strlen(targetname) < 1) + xtables_error(PARAMETER_PROBLEM, + "Invalid target name (too short)"); + + if (strlen(targetname) >= xt_params->target_maxnamelen) + xtables_error(PARAMETER_PROBLEM, + "Invalid target name `%s' (%zu chars max)", + targetname, xt_params->target_maxnamelen - 1); + + for (ptr = targetname; *ptr; ptr++) + if (isspace(*ptr)) + xtables_error(PARAMETER_PROBLEM, + "Invalid target name `%s'", targetname); + return targetname; +} + +void command_jump(struct iptables_command_state *cs) +{ + struct option *opts = xt_params->opts; + size_t size; + + cs->jumpto = xt_parse_target(optarg); + /* TRY_LOAD (may be chain name) */ + cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); + + if (cs->target == NULL) + return; + + size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size; + + cs->target->t = xtables_calloc(1, size); + cs->target->t->u.target_size = size; + if (cs->target->real_name == NULL) { + strcpy(cs->target->t->u.user.name, cs->jumpto); + } else { + /* Alias support for userspace side */ + strcpy(cs->target->t->u.user.name, cs->target->real_name); + if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) + fprintf(stderr, "Notice: The %s target is converted into %s target " + "in rule listing and saving.\n", + cs->jumpto, cs->target->real_name); + } + 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, + cs->target->x6_options, + &cs->target->option_offset); + else + 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!"); + xt_params->opts = opts; +} diff --git a/iptables/xshared.h b/iptables/xshared.h index 9039a24ba75e6..db499f29236ed 100644 --- a/iptables/xshared.h +++ b/iptables/xshared.h @@ -175,5 +175,7 @@ void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags, unsigned int format); void command_match(struct iptables_command_state *cs); +const char *xt_parse_target(const char *targetname); +void command_jump(struct iptables_command_state *cs); #endif /* IPTABLES_XSHARED_H */ diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c index a457ea30ad685..4a782148d0f6a 100644 --- a/iptables/xtables-arp.c +++ b/iptables/xtables-arp.c @@ -158,6 +158,7 @@ struct xtables_globals arptables_globals = { .orig_opts = original_opts, .exit_err = xtables_exit_error, .compat_rev = nft_compatible_revision, + .target_maxnamelen = sizeof(arpt_chainlabel), }; /* Table of legal combinations of commands and options. If any of the @@ -755,27 +756,6 @@ parse_rulenumber(const char *rule) return rulenum; } -static const char * -parse_target(const char *targetname) -{ - const char *ptr; - - if (strlen(targetname) < 1) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name (too short)"); - - if (strlen(targetname)+1 > sizeof(arpt_chainlabel)) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s' (%zu chars max)", - targetname, sizeof(arpt_chainlabel)-1); - - for (ptr = targetname; *ptr; ptr++) - if (isspace(*ptr)) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s'", targetname); - return targetname; -} - static void set_option(unsigned int *options, unsigned int option, u_int16_t *invflg, int invert) @@ -822,41 +802,6 @@ list_entries(struct nft_handle *h, const char *chain, const char *table, return nft_rule_list(h, chain, table, rulenum, format); } -static struct xtables_target *command_jump(struct arpt_entry *fw, - const char *jumpto) -{ - struct xtables_target *target; - size_t size; - - /* XTF_TRY_LOAD (may be chain name) */ - target = xtables_find_target(jumpto, XTF_TRY_LOAD); - - if (!target) - return NULL; - - size = XT_ALIGN(sizeof(struct xt_entry_target)) - + target->size; - - target->t = xtables_calloc(1, size); - target->t->u.target_size = size; - strncpy(target->t->u.user.name, jumpto, sizeof(target->t->u.user.name) - 1); - target->t->u.user.name[sizeof(target->t->u.user.name)-1] = '\0'; - target->t->u.user.revision = target->revision; - - xs_init_target(target); - - if (target->x6_options != NULL) - opts = xtables_options_xfrm(arptables_globals.orig_opts, - opts, target->x6_options, - &target->option_offset); - else - opts = xtables_merge_options(arptables_globals.orig_opts, - opts, target->extra_opts, - &target->option_offset); - - return target; -} - static int append_entry(struct nft_handle *h, const char *chain, @@ -1216,8 +1161,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, case 'j': set_option(&options, OPT_JUMP, &cs.arp.arp.invflags, invert); - cs.jumpto = parse_target(optarg); - cs.target = command_jump(&cs.arp, cs.jumpto); + command_jump(&cs); break; case 'i': diff --git a/iptables/xtables.c b/iptables/xtables.c index 423be37f51fbc..c17e66f1a805f 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -108,6 +108,7 @@ struct xtables_globals xtables_globals = { .orig_opts = original_opts, .exit_err = xtables_exit_error, .compat_rev = nft_compatible_revision, + .target_maxnamelen = XT_EXTENSION_MAXNAMELEN, }; /* Table of legal combinations of commands and options. If any of the @@ -363,27 +364,6 @@ parse_rulenumber(const char *rule) return rulenum; } -static const char * -parse_target(const char *targetname) -{ - const char *ptr; - - if (strlen(targetname) < 1) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name (too short)"); - - if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s' (%u chars max)", - targetname, XT_EXTENSION_MAXNAMELEN - 1); - - for (ptr = targetname; *ptr; ptr++) - if (isspace(*ptr)) - xtables_error(PARAMETER_PROBLEM, - "Invalid target name `%s'", targetname); - return targetname; -} - static void set_option(unsigned int *options, unsigned int option, uint8_t *invflg, int invert) @@ -602,48 +582,6 @@ list_rules(struct nft_handle *h, const char *chain, const char *table, return nft_rule_list_save(h, chain, table, rulenum, counters); } -static void command_jump(struct iptables_command_state *cs) -{ - size_t size; - - set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, cs->invert); - cs->jumpto = parse_target(optarg); - /* TRY_LOAD (may be chain name) */ - cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); - - if (cs->target == NULL) - return; - - size = XT_ALIGN(sizeof(struct xt_entry_target)) - + cs->target->size; - - cs->target->t = xtables_calloc(1, size); - cs->target->t->u.target_size = size; - if (cs->target->real_name == NULL) { - strcpy(cs->target->t->u.user.name, cs->jumpto); - } else { - /* Alias support for userspace side */ - strcpy(cs->target->t->u.user.name, cs->target->real_name); - if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) - fprintf(stderr, "Notice: The %s target is converted into %s target " - "in rule listing and saving.\n", - cs->jumpto, cs->target->real_name); - } - cs->target->t->u.user.revision = cs->target->revision; - xs_init_target(cs->target); - - if (cs->target->x6_options != NULL) - opts = xtables_options_xfrm(xtables_globals.orig_opts, opts, - cs->target->x6_options, - &cs->target->option_offset); - else - opts = xtables_merge_options(xtables_globals.orig_opts, opts, - cs->target->extra_opts, - &cs->target->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, "can't alloc memory!"); -} - void do_parse(struct nft_handle *h, int argc, char *argv[], struct nft_xt_cmd_parse *p, struct iptables_command_state *cs, struct xtables_args *args) @@ -876,11 +814,13 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], set_option(&cs->options, OPT_JUMP, &args->invflags, cs->invert); args->goto_set = true; - cs->jumpto = parse_target(optarg); + cs->jumpto = xt_parse_target(optarg); break; #endif case 'j': + set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, + cs->invert); command_jump(cs); break; -- 2.19.0