From 3a9d8b0bcaeeb7f260c881fbaaea62f705d0d47e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Feb 2011 15:52:11 +0100 Subject: src: collect do_command variables in a struct This will make it easier to put the code for the cases into separate functions. Signed-off-by: Jan Engelhardt --- ip6tables.c | 323 +++++++++++++++++++++++++++++++----------------------------- iptables.c | 323 +++++++++++++++++++++++++++++++----------------------------- 2 files changed, 330 insertions(+), 316 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index 8c1b5049..cb9e1f58 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1288,32 +1288,39 @@ static void clear_rule_matches(struct xtables_rule_match **matches) *matches = NULL; } +struct iptables_command_state { + struct ip6t_entry fw; + int invert; + int c; + unsigned int options; + struct xtables_rule_match *matches; + struct xtables_target *target; + char *protocol; + int proto_used; +}; + int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle) { - struct ip6t_entry fw, *e = NULL; - int invert = 0; + struct iptables_command_state cs; + struct ip6t_entry *e = NULL; unsigned int nsaddrs = 0, ndaddrs = 0; struct in6_addr *saddrs = NULL, *daddrs = NULL; struct in6_addr *smasks = NULL, *dmasks = NULL; - int c, verbose = 0; + int verbose = 0; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; - unsigned int rulenum = 0, options = 0, command = 0; + unsigned int rulenum = 0, command = 0; const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct xtables_match *m; - struct xtables_rule_match *matches = NULL; struct xtables_rule_match *matchp; - struct xtables_target *target = NULL; struct xtables_target *t; const char *jumpto = ""; - char *protocol = NULL; - int proto_used = 0; unsigned long long cnt; - memset(&fw, 0, sizeof(fw)); + memset(&cs, 0, sizeof(cs)); /* re-set optind to 0 in case do_command gets called * a second time */ @@ -1334,22 +1341,22 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand opterr = 0; opts = xt_params->orig_opts; - while ((c = getopt_long(argc, argv, + while ((cs.c = getopt_long(argc, argv, "-A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:", opts, NULL)) != -1) { - switch (c) { + switch (cs.c) { /* * Command selection */ case 'A': add_command(&command, CMD_APPEND, CMD_NONE, - invert); + cs.invert); chain = optarg; break; case 'D': add_command(&command, CMD_DELETE, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') { @@ -1360,7 +1367,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'R': add_command(&command, CMD_REPLACE, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1373,7 +1380,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'I': add_command(&command, CMD_INSERT, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1383,7 +1390,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'L': add_command(&command, CMD_LIST, - CMD_ZERO | CMD_ZERO_NUM, invert); + CMD_ZERO | CMD_ZERO_NUM, cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1395,7 +1402,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'S': add_command(&command, CMD_LIST_RULES, - CMD_ZERO | CMD_ZERO_NUM, invert); + CMD_ZERO | CMD_ZERO_NUM, cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1407,7 +1414,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'F': add_command(&command, CMD_FLUSH, CMD_NONE, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1416,7 +1423,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'Z': add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1438,13 +1445,13 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand "chain name may not clash " "with target name\n"); add_command(&command, CMD_NEW_CHAIN, CMD_NONE, - invert); + cs.invert); chain = optarg; break; case 'X': add_command(&command, CMD_DELETE_CHAIN, CMD_NONE, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1453,7 +1460,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'E': add_command(&command, CMD_RENAME_CHAIN, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1467,7 +1474,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'P': add_command(&command, CMD_SET_POLICY, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1483,86 +1490,86 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand optarg = argv[optind]; /* ip6tables -p icmp -h */ - if (!matches && protocol) - xtables_find_match(protocol, XTF_TRY_LOAD, - &matches); + if (!cs.matches && cs.protocol) + xtables_find_match(cs.protocol, XTF_TRY_LOAD, + &cs.matches); - exit_printhelp(matches); + exit_printhelp(cs.matches); /* * Option selection */ case 'p': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_PROTOCOL, &fw.ipv6.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ipv6.invflags, + cs.invert); /* Canonicalize into lower case */ - for (protocol = optarg; *protocol; protocol++) - *protocol = tolower(*protocol); + for (cs.protocol = optarg; *cs.protocol; cs.protocol++) + *cs.protocol = tolower(*cs.protocol); - protocol = optarg; - fw.ipv6.proto = xtables_parse_protocol(protocol); - fw.ipv6.flags |= IP6T_F_PROTO; + cs.protocol = optarg; + cs.fw.ipv6.proto = xtables_parse_protocol(cs.protocol); + cs.fw.ipv6.flags |= IP6T_F_PROTO; - if (fw.ipv6.proto == 0 - && (fw.ipv6.invflags & IP6T_INV_PROTO)) + if (cs.fw.ipv6.proto == 0 + && (cs.fw.ipv6.invflags & IP6T_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "rule would never match protocol"); - if (is_exthdr(fw.ipv6.proto) - && (fw.ipv6.invflags & IP6T_INV_PROTO) == 0) + if (is_exthdr(cs.fw.ipv6.proto) + && (cs.fw.ipv6.invflags & IP6T_INV_PROTO) == 0) fprintf(stderr, "Warning: never matched protocol: %s. " "use extension match instead.\n", - protocol); + cs.protocol); break; case 's': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_SOURCE, &fw.ipv6.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_SOURCE, &cs.fw.ipv6.invflags, + cs.invert); shostnetworkmask = optarg; break; case 'd': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_DESTINATION, &fw.ipv6.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_DESTINATION, &cs.fw.ipv6.invflags, + cs.invert); dhostnetworkmask = optarg; break; #ifdef IP6T_F_GOTO case 'g': - set_option(&options, OPT_JUMP, &fw.ipv6.invflags, - invert); - fw.ipv6.flags |= IP6T_F_GOTO; + set_option(&cs.options, OPT_JUMP, &cs.fw.ipv6.invflags, + cs.invert); + cs.fw.ipv6.flags |= IP6T_F_GOTO; jumpto = parse_target(optarg); break; #endif case 'j': - set_option(&options, OPT_JUMP, &fw.ipv6.invflags, - invert); + set_option(&cs.options, OPT_JUMP, &cs.fw.ipv6.invflags, + cs.invert); jumpto = parse_target(optarg); /* TRY_LOAD (may be chain name) */ - target = xtables_find_target(jumpto, XTF_TRY_LOAD); + cs.target = xtables_find_target(jumpto, XTF_TRY_LOAD); - if (target) { + if (cs.target) { size_t size; size = IP6T_ALIGN(sizeof(struct ip6t_entry_target)) - + target->size; - - target->t = xtables_calloc(1, size); - target->t->u.target_size = size; - strcpy(target->t->u.user.name, jumpto); - target->t->u.user.revision = target->revision; - if (target->init != NULL) - target->init(target->t); + + cs.target->size; + + cs.target->t = xtables_calloc(1, size); + cs.target->t->u.target_size = size; + strcpy(cs.target->t->u.user.name, jumpto); + cs.target->t->u.user.revision = cs.target->revision; + if (cs.target->init != NULL) + cs.target->init(cs.target->t); opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, - target->extra_opts, - &target->option_offset); + cs.target->extra_opts, + &cs.target->option_offset); if (opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); @@ -1575,12 +1582,12 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_VIANAMEIN, &fw.ipv6.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ipv6.invflags, + cs.invert); xtables_parse_interface(optarg, - fw.ipv6.iniface, - fw.ipv6.iniface_mask); + cs.fw.ipv6.iniface, + cs.fw.ipv6.iniface_mask); break; case 'o': @@ -1588,30 +1595,30 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_VIANAMEOUT, &fw.ipv6.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ipv6.invflags, + cs.invert); xtables_parse_interface(optarg, - fw.ipv6.outiface, - fw.ipv6.outiface_mask); + cs.fw.ipv6.outiface, + cs.fw.ipv6.outiface_mask); break; case 'v': if (!verbose) - set_option(&options, OPT_VERBOSE, - &fw.ipv6.invflags, invert); + set_option(&cs.options, OPT_VERBOSE, + &cs.fw.ipv6.invflags, cs.invert); verbose++; break; case 'm': { size_t size; - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --match"); m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, - &matches); + &cs.matches); size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; m->m = xtables_calloc(1, size); @@ -1627,24 +1634,24 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand break; case 'n': - set_option(&options, OPT_NUMERIC, &fw.ipv6.invflags, - invert); + set_option(&cs.options, OPT_NUMERIC, &cs.fw.ipv6.invflags, + cs.invert); break; case 't': - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --table"); *table = optarg; break; case 'x': - set_option(&options, OPT_EXPANDED, &fw.ipv6.invflags, - invert); + set_option(&cs.options, OPT_EXPANDED, &cs.fw.ipv6.invflags, + cs.invert); break; case 'V': - if (invert) + if (cs.invert) printf("Not %s ;-)\n", prog_vers); else printf("%s v%s\n", @@ -1652,8 +1659,8 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand exit(0); case '0': - set_option(&options, OPT_LINENUMBERS, &fw.ipv6.invflags, - invert); + set_option(&cs.options, OPT_LINENUMBERS, &cs.fw.ipv6.invflags, + cs.invert); break; case 'M': @@ -1662,8 +1669,8 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'c': - set_option(&options, OPT_COUNTERS, &fw.ipv6.invflags, - invert); + set_option(&cs.options, OPT_COUNTERS, &cs.fw.ipv6.invflags, + cs.invert); pcnt = optarg; bcnt = strchr(pcnt + 1, ','); if (bcnt) @@ -1680,22 +1687,22 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "-%c packet counter not numeric", opt2char(OPT_COUNTERS)); - fw.counters.pcnt = cnt; + cs.fw.counters.pcnt = cnt; if (sscanf(bcnt, "%llu", &cnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c byte counter not numeric", opt2char(OPT_COUNTERS)); - fw.counters.bcnt = cnt; + cs.fw.counters.bcnt = cnt; break; case 1: /* non option */ if (optarg[0] == '!' && optarg[1] == '\0') { - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "multiple consecutive ! not" " allowed"); - invert = TRUE; + cs.invert = TRUE; optarg[0] = '\0'; continue; } @@ -1703,24 +1710,24 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand exit_tryhelp(2); default: - if (target == NULL || target->parse == NULL || - c < target->option_offset || - c >= target->option_offset + XT_OPTION_OFFSET_SCALE || - !target->parse(c - target->option_offset, - argv, invert, - &target->tflags, - &fw, &target->t)) { - for (matchp = matches; matchp; matchp = matchp->next) { + if (cs.target == NULL || cs.target->parse == NULL || + cs.c < cs.target->option_offset || + cs.c >= cs.target->option_offset + XT_OPTION_OFFSET_SCALE || + !cs.target->parse(cs.c - cs.target->option_offset, + argv, cs.invert, + &cs.target->tflags, + &cs.fw, &cs.target->t)) { + for (matchp = cs.matches; matchp; matchp = matchp->next) { if (matchp->completed || matchp->match->parse == NULL) continue; - if (c < matchp->match->option_offset || - c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) + if (cs.c < matchp->match->option_offset || + cs.c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) continue; - if (matchp->match->parse(c - matchp->match->option_offset, - argv, invert, + if (matchp->match->parse(cs.c - matchp->match->option_offset, + argv, cs.invert, &matchp->match->mflags, - &fw, + &cs.fw, &matchp->match->m)) break; } @@ -1750,19 +1757,19 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand * loaded */ if (m == NULL - && protocol - && (!find_proto(protocol, XTF_DONT_LOAD, - options&OPT_NUMERIC, NULL) - || (find_proto(protocol, XTF_DONT_LOAD, - options&OPT_NUMERIC, NULL) - && (proto_used == 0)) + && cs.protocol + && (!find_proto(cs.protocol, XTF_DONT_LOAD, + cs.options&OPT_NUMERIC, NULL) + || (find_proto(cs.protocol, XTF_DONT_LOAD, + cs.options&OPT_NUMERIC, NULL) + && (cs.proto_used == 0)) ) - && (m = find_proto(protocol, XTF_TRY_LOAD, - options&OPT_NUMERIC, &matches))) { + && (m = find_proto(cs.protocol, XTF_TRY_LOAD, + cs.options&OPT_NUMERIC, &cs.matches))) { /* Try loading protocol */ size_t size; - proto_used = 1; + cs.proto_used = 1; size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; @@ -1782,7 +1789,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand } if (!m) { - if (c == '?') { + if (cs.c == '?') { if (optopt) { xtables_error( PARAMETER_PROBLEM, @@ -1803,15 +1810,15 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand } } } - invert = FALSE; + cs.invert = FALSE; } - for (matchp = matches; matchp; matchp = matchp->next) + for (matchp = cs.matches; matchp; matchp = matchp->next) if (matchp->match->final_check != NULL) matchp->match->final_check(matchp->match->mflags); - if (target != NULL && target->final_check != NULL) - target->final_check(target->tflags); + if (cs.target != NULL && cs.target->final_check != NULL) + cs.target->final_check(cs.target->tflags); /* Fix me: must put inverse options checking here --MN */ @@ -1820,14 +1827,14 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand "unknown arguments found on commandline"); if (!command) xtables_error(PARAMETER_PROBLEM, "no command specified"); - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "nothing appropriate following !"); if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { - if (!(options & OPT_DESTINATION)) + if (!(cs.options & OPT_DESTINATION)) dhostnetworkmask = "::0/0"; - if (!(options & OPT_SOURCE)) + if (!(cs.options & OPT_SOURCE)) shostnetworkmask = "::0/0"; } @@ -1840,7 +1847,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand &dmasks, &ndaddrs); if ((nsaddrs > 1 || ndaddrs > 1) && - (fw.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP))) + (cs.fw.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP))) xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); @@ -1848,7 +1855,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "Replacement rule does not " "specify a unique address"); - generic_opt_check(command, options); + generic_opt_check(command, cs.options); if (chain != NULL && strlen(chain) >= XT_EXTENSION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, @@ -1875,7 +1882,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand if (strcmp(chain, "PREROUTING") == 0 || strcmp(chain, "INPUT") == 0) { /* -o not valid with incoming packets. */ - if (options & OPT_VIANAMEOUT) + if (cs.options & OPT_VIANAMEOUT) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEOUT), @@ -1885,57 +1892,57 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand if (strcmp(chain, "POSTROUTING") == 0 || strcmp(chain, "OUTPUT") == 0) { /* -i not valid with outgoing packets */ - if (options & OPT_VIANAMEIN) + if (cs.options & OPT_VIANAMEIN) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEIN), chain); } - if (target && ip6tc_is_chain(jumpto, *handle)) { + if (cs.target && ip6tc_is_chain(jumpto, *handle)) { fprintf(stderr, "Warning: using chain %s, not extension\n", jumpto); - if (target->t) - free(target->t); + if (cs.target->t) + free(cs.target->t); - target = NULL; + cs.target = NULL; } /* If they didn't specify a target, or it's a chain name, use standard. */ - if (!target + if (!cs.target && (strlen(jumpto) == 0 || ip6tc_is_chain(jumpto, *handle))) { size_t size; - target = xtables_find_target(IP6T_STANDARD_TARGET, + cs.target = xtables_find_target(IP6T_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); size = sizeof(struct ip6t_entry_target) - + target->size; - target->t = xtables_calloc(1, size); - target->t->u.target_size = size; - strcpy(target->t->u.user.name, jumpto); - if (target->init != NULL) - target->init(target->t); + + cs.target->size; + cs.target->t = xtables_calloc(1, size); + cs.target->t->u.target_size = size; + strcpy(cs.target->t->u.user.name, jumpto); + if (cs.target->init != NULL) + cs.target->init(cs.target->t); } - if (!target) { + if (!cs.target) { /* it is no chain, and we can't load a plugin. * We cannot know if the plugin is corrupt, non * existant OR if the user just misspelled a * chain. */ #ifdef IP6T_F_GOTO - if (fw.ipv6.flags & IP6T_F_GOTO) + if (cs.fw.ipv6.flags & IP6T_F_GOTO) xtables_error(PARAMETER_PROBLEM, "goto '%s' is not a chain\n", jumpto); #endif xtables_find_target(jumpto, XTF_LOAD_MUST_SUCCEED); } else { - e = generate_entry(&fw, matches, target->t); - free(target->t); + e = generate_entry(&cs.fw, cs.matches, cs.target->t); + free(cs.target->t); } } @@ -1944,15 +1951,15 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand ret = append_entry(chain, e, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); break; case CMD_DELETE: ret = delete_entry(chain, e, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, - *handle, matches, target); + cs.options&OPT_VERBOSE, + *handle, cs.matches, cs.target); break; case CMD_DELETE_NUM: ret = ip6tc_delete_num_entry(chain, rulenum - 1, *handle); @@ -1960,20 +1967,20 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case CMD_REPLACE: ret = replace_entry(chain, e, rulenum - 1, saddrs, smasks, daddrs, dmasks, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); break; case CMD_INSERT: ret = insert_entry(chain, e, rulenum - 1, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); break; case CMD_FLUSH: - ret = flush_entries(chain, options&OPT_VERBOSE, *handle); + ret = flush_entries(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_ZERO: - ret = zero_entries(chain, options&OPT_VERBOSE, *handle); + ret = zero_entries(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_ZERO_NUM: ret = ip6tc_zero_counter(chain, rulenum, *handle); @@ -1983,14 +1990,14 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case CMD_LIST|CMD_ZERO_NUM: ret = list_entries(chain, rulenum, - options&OPT_VERBOSE, - options&OPT_NUMERIC, - options&OPT_EXPANDED, - options&OPT_LINENUMBERS, + cs.options&OPT_VERBOSE, + cs.options&OPT_NUMERIC, + cs.options&OPT_EXPANDED, + cs.options&OPT_LINENUMBERS, *handle); if (ret && (command & CMD_ZERO)) ret = zero_entries(chain, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO_NUM)) ret = ip6tc_zero_counter(chain, rulenum, *handle); break; @@ -1999,11 +2006,11 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case CMD_LIST_RULES|CMD_ZERO_NUM: ret = list_rules(chain, rulenum, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO)) ret = zero_entries(chain, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO_NUM)) ret = ip6tc_zero_counter(chain, rulenum, *handle); break; @@ -2011,13 +2018,13 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand ret = ip6tc_create_chain(chain, *handle); break; case CMD_DELETE_CHAIN: - ret = delete_chain(chain, options&OPT_VERBOSE, *handle); + ret = delete_chain(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_RENAME_CHAIN: ret = ip6tc_rename_chain(chain, newname, *handle); break; case CMD_SET_POLICY: - ret = ip6tc_set_policy(chain, policy, options&OPT_COUNTERS ? &fw.counters : NULL, *handle); + ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw.counters : NULL, *handle); break; default: /* We should never reach this... */ @@ -2027,7 +2034,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand if (verbose > 1) dump_entries6(*handle); - clear_rule_matches(&matches); + clear_rule_matches(&cs.matches); if (e != NULL) { free(e); diff --git a/iptables.c b/iptables.c index 2459b648..5f62ae5a 100644 --- a/iptables.c +++ b/iptables.c @@ -1311,32 +1311,39 @@ get_kernel_version(void) { kernel_version = LINUX_VERSION(x, y, z); } +struct iptables_command_state { + struct ipt_entry fw; + int invert; + int c; + unsigned int options; + struct xtables_rule_match *matches; + struct xtables_target *target; + char *protocol; + int proto_used; +}; + int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle) { - struct ipt_entry fw, *e = NULL; - int invert = 0; + struct iptables_command_state cs; + struct ipt_entry *e = NULL; unsigned int nsaddrs = 0, ndaddrs = 0; struct in_addr *saddrs = NULL, *smasks = NULL; struct in_addr *daddrs = NULL, *dmasks = NULL; - int c, verbose = 0; + int verbose = 0; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; - unsigned int rulenum = 0, options = 0, command = 0; + unsigned int rulenum = 0, command = 0; const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct xtables_match *m; - struct xtables_rule_match *matches = NULL; struct xtables_rule_match *matchp; - struct xtables_target *target = NULL; struct xtables_target *t; const char *jumpto = ""; - char *protocol = NULL; - int proto_used = 0; unsigned long long cnt; - memset(&fw, 0, sizeof(fw)); + memset(&cs, 0, sizeof(cs)); /* re-set optind to 0 in case do_command gets called * a second time */ @@ -1357,22 +1364,22 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle opterr = 0; opts = xt_params->orig_opts; - while ((c = getopt_long(argc, argv, + while ((cs.c = getopt_long(argc, argv, "-A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:", opts, NULL)) != -1) { - switch (c) { + switch (cs.c) { /* * Command selection */ case 'A': add_command(&command, CMD_APPEND, CMD_NONE, - invert); + cs.invert); chain = optarg; break; case 'D': add_command(&command, CMD_DELETE, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') { @@ -1383,7 +1390,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'R': add_command(&command, CMD_REPLACE, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1396,7 +1403,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'I': add_command(&command, CMD_INSERT, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1406,7 +1413,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'L': add_command(&command, CMD_LIST, - CMD_ZERO | CMD_ZERO_NUM, invert); + CMD_ZERO | CMD_ZERO_NUM, cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1418,7 +1425,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'S': add_command(&command, CMD_LIST_RULES, - CMD_ZERO|CMD_ZERO_NUM, invert); + CMD_ZERO|CMD_ZERO_NUM, cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1430,7 +1437,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'F': add_command(&command, CMD_FLUSH, CMD_NONE, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1439,7 +1446,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'Z': add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1461,13 +1468,13 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle "chain name may not clash " "with target name\n"); add_command(&command, CMD_NEW_CHAIN, CMD_NONE, - invert); + cs.invert); chain = optarg; break; case 'X': add_command(&command, CMD_DELETE_CHAIN, CMD_NONE, - invert); + cs.invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1476,7 +1483,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'E': add_command(&command, CMD_RENAME_CHAIN, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1490,7 +1497,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'P': add_command(&command, CMD_SET_POLICY, CMD_NONE, - invert); + cs.invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') @@ -1506,80 +1513,80 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle optarg = argv[optind]; /* iptables -p icmp -h */ - if (!matches && protocol) - xtables_find_match(protocol, - XTF_TRY_LOAD, &matches); + if (!cs.matches && cs.protocol) + xtables_find_match(cs.protocol, + XTF_TRY_LOAD, &cs.matches); - exit_printhelp(matches); + exit_printhelp(cs.matches); /* * Option selection */ case 'p': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_PROTOCOL, &fw.ip.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ip.invflags, + cs.invert); /* Canonicalize into lower case */ - for (protocol = optarg; *protocol; protocol++) - *protocol = tolower(*protocol); + for (cs.protocol = optarg; *cs.protocol; cs.protocol++) + *cs.protocol = tolower(*cs.protocol); - protocol = optarg; - fw.ip.proto = xtables_parse_protocol(protocol); + cs.protocol = optarg; + cs.fw.ip.proto = xtables_parse_protocol(cs.protocol); - if (fw.ip.proto == 0 - && (fw.ip.invflags & IPT_INV_PROTO)) + if (cs.fw.ip.proto == 0 + && (cs.fw.ip.invflags & IPT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "rule would never match protocol"); break; case 's': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_SOURCE, &fw.ip.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_SOURCE, &cs.fw.ip.invflags, + cs.invert); shostnetworkmask = optarg; break; case 'd': - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_DESTINATION, &fw.ip.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_DESTINATION, &cs.fw.ip.invflags, + cs.invert); dhostnetworkmask = optarg; break; #ifdef IPT_F_GOTO case 'g': - set_option(&options, OPT_JUMP, &fw.ip.invflags, - invert); - fw.ip.flags |= IPT_F_GOTO; + set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, + cs.invert); + cs.fw.ip.flags |= IPT_F_GOTO; jumpto = parse_target(optarg); break; #endif case 'j': - set_option(&options, OPT_JUMP, &fw.ip.invflags, - invert); + set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, + cs.invert); jumpto = parse_target(optarg); /* TRY_LOAD (may be chain name) */ - target = xtables_find_target(jumpto, XTF_TRY_LOAD); + cs.target = xtables_find_target(jumpto, XTF_TRY_LOAD); - if (target) { + if (cs.target) { size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + target->size; - - target->t = xtables_calloc(1, size); - target->t->u.target_size = size; - strcpy(target->t->u.user.name, jumpto); - target->t->u.user.revision = target->revision; - if (target->init != NULL) - target->init(target->t); + + cs.target->size; + + cs.target->t = xtables_calloc(1, size); + cs.target->t->u.target_size = size; + strcpy(cs.target->t->u.user.name, jumpto); + cs.target->t->u.user.revision = cs.target->revision; + if (cs.target->init != NULL) + cs.target->init(cs.target->t); opts = xtables_merge_options( iptables_globals.orig_opts, opts, - target->extra_opts, - &target->option_offset); + cs.target->extra_opts, + &cs.target->option_offset); if (opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); @@ -1592,12 +1599,12 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_VIANAMEIN, &fw.ip.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ip.invflags, + cs.invert); xtables_parse_interface(optarg, - fw.ip.iniface, - fw.ip.iniface_mask); + cs.fw.ip.iniface, + cs.fw.ip.iniface_mask); break; case 'o': @@ -1605,36 +1612,36 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &invert, &optind, argc, argv); - set_option(&options, OPT_VIANAMEOUT, &fw.ip.invflags, - invert); + xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); + set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ip.invflags, + cs.invert); xtables_parse_interface(optarg, - fw.ip.outiface, - fw.ip.outiface_mask); + cs.fw.ip.outiface, + cs.fw.ip.outiface_mask); break; case 'f': - set_option(&options, OPT_FRAGMENT, &fw.ip.invflags, - invert); - fw.ip.flags |= IPT_F_FRAG; + set_option(&cs.options, OPT_FRAGMENT, &cs.fw.ip.invflags, + cs.invert); + cs.fw.ip.flags |= IPT_F_FRAG; break; case 'v': if (!verbose) - set_option(&options, OPT_VERBOSE, - &fw.ip.invflags, invert); + set_option(&cs.options, OPT_VERBOSE, + &cs.fw.ip.invflags, cs.invert); verbose++; break; case 'm': { size_t size; - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --match"); m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, - &matches); + &cs.matches); size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; m->m = xtables_calloc(1, size); @@ -1658,24 +1665,24 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle break; case 'n': - set_option(&options, OPT_NUMERIC, &fw.ip.invflags, - invert); + set_option(&cs.options, OPT_NUMERIC, &cs.fw.ip.invflags, + cs.invert); break; case 't': - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --table"); *table = optarg; break; case 'x': - set_option(&options, OPT_EXPANDED, &fw.ip.invflags, - invert); + set_option(&cs.options, OPT_EXPANDED, &cs.fw.ip.invflags, + cs.invert); break; case 'V': - if (invert) + if (cs.invert) printf("Not %s ;-)\n", prog_vers); else printf("%s v%s\n", @@ -1683,8 +1690,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle exit(0); case '0': - set_option(&options, OPT_LINENUMBERS, &fw.ip.invflags, - invert); + set_option(&cs.options, OPT_LINENUMBERS, &cs.fw.ip.invflags, + cs.invert); break; case 'M': @@ -1693,8 +1700,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case 'c': - set_option(&options, OPT_COUNTERS, &fw.ip.invflags, - invert); + set_option(&cs.options, OPT_COUNTERS, &cs.fw.ip.invflags, + cs.invert); pcnt = optarg; bcnt = strchr(pcnt + 1, ','); if (bcnt) @@ -1711,23 +1718,23 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle xtables_error(PARAMETER_PROBLEM, "-%c packet counter not numeric", opt2char(OPT_COUNTERS)); - fw.counters.pcnt = cnt; + cs.fw.counters.pcnt = cnt; if (sscanf(bcnt, "%llu", &cnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c byte counter not numeric", opt2char(OPT_COUNTERS)); - fw.counters.bcnt = cnt; + cs.fw.counters.bcnt = cnt; break; case 1: /* non option */ if (optarg[0] == '!' && optarg[1] == '\0') { - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "multiple consecutive ! not" " allowed"); - invert = TRUE; + cs.invert = TRUE; optarg[0] = '\0'; continue; } @@ -1735,24 +1742,24 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle exit_tryhelp(2); default: - if (target == NULL || target->parse == NULL || - c < target->option_offset || - c >= target->option_offset + XT_OPTION_OFFSET_SCALE || - !target->parse(c - target->option_offset, - argv, invert, - &target->tflags, - &fw, &target->t)) { - for (matchp = matches; matchp; matchp = matchp->next) { + if (cs.target == NULL || cs.target->parse == NULL || + cs.c < cs.target->option_offset || + cs.c >= cs.target->option_offset + XT_OPTION_OFFSET_SCALE || + !cs.target->parse(cs.c - cs.target->option_offset, + argv, cs.invert, + &cs.target->tflags, + &cs.fw, &cs.target->t)) { + for (matchp = cs.matches; matchp; matchp = matchp->next) { if (matchp->completed || matchp->match->parse == NULL) continue; - if (c < matchp->match->option_offset || - c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) + if (cs.c < matchp->match->option_offset || + cs.c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) continue; - if (matchp->match->parse(c - matchp->match->option_offset, - argv, invert, + if (matchp->match->parse(cs.c - matchp->match->option_offset, + argv, cs.invert, &matchp->match->mflags, - &fw, + &cs.fw, &matchp->match->m)) break; } @@ -1782,19 +1789,19 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle * loaded */ if (m == NULL - && protocol - && (!find_proto(protocol, XTF_DONT_LOAD, - options&OPT_NUMERIC, NULL) - || (find_proto(protocol, XTF_DONT_LOAD, - options&OPT_NUMERIC, NULL) - && (proto_used == 0)) + && cs.protocol + && (!find_proto(cs.protocol, XTF_DONT_LOAD, + cs.options&OPT_NUMERIC, NULL) + || (find_proto(cs.protocol, XTF_DONT_LOAD, + cs.options&OPT_NUMERIC, NULL) + && (cs.proto_used == 0)) ) - && (m = find_proto(protocol, XTF_TRY_LOAD, - options&OPT_NUMERIC, &matches))) { + && (m = find_proto(cs.protocol, XTF_TRY_LOAD, + cs.options&OPT_NUMERIC, &cs.matches))) { /* Try loading protocol */ size_t size; - proto_used = 1; + cs.proto_used = 1; size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; @@ -1819,7 +1826,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle continue; } if (!m) { - if (c == '?') { + if (cs.c == '?') { if (optopt) { xtables_error( PARAMETER_PROBLEM, @@ -1840,7 +1847,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle } } } - invert = FALSE; + cs.invert = FALSE; } if (strcmp(*table, "nat") == 0 && @@ -1850,12 +1857,12 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle "\nThe \"nat\" table is not intended for filtering, " "the use of DROP is therefore inhibited.\n\n"); - for (matchp = matches; matchp; matchp = matchp->next) + for (matchp = cs.matches; matchp; matchp = matchp->next) if (matchp->match->final_check != NULL) matchp->match->final_check(matchp->match->mflags); - if (target != NULL && target->final_check != NULL) - target->final_check(target->tflags); + if (cs.target != NULL && cs.target->final_check != NULL) + cs.target->final_check(cs.target->tflags); /* Fix me: must put inverse options checking here --MN */ @@ -1864,14 +1871,14 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle "unknown arguments found on commandline"); if (!command) xtables_error(PARAMETER_PROBLEM, "no command specified"); - if (invert) + if (cs.invert) xtables_error(PARAMETER_PROBLEM, "nothing appropriate following !"); if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { - if (!(options & OPT_DESTINATION)) + if (!(cs.options & OPT_DESTINATION)) dhostnetworkmask = "0.0.0.0/0"; - if (!(options & OPT_SOURCE)) + if (!(cs.options & OPT_SOURCE)) shostnetworkmask = "0.0.0.0/0"; } @@ -1884,7 +1891,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle &dmasks, &ndaddrs); if ((nsaddrs > 1 || ndaddrs > 1) && - (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) + (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); @@ -1892,7 +1899,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle xtables_error(PARAMETER_PROBLEM, "Replacement rule does not " "specify a unique address"); - generic_opt_check(command, options); + generic_opt_check(command, cs.options); if (chain != NULL && strlen(chain) >= XT_EXTENSION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, @@ -1919,7 +1926,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle if (strcmp(chain, "PREROUTING") == 0 || strcmp(chain, "INPUT") == 0) { /* -o not valid with incoming packets. */ - if (options & OPT_VIANAMEOUT) + if (cs.options & OPT_VIANAMEOUT) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEOUT), @@ -1929,59 +1936,59 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle if (strcmp(chain, "POSTROUTING") == 0 || strcmp(chain, "OUTPUT") == 0) { /* -i not valid with outgoing packets */ - if (options & OPT_VIANAMEIN) + if (cs.options & OPT_VIANAMEIN) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEIN), chain); } - if (target && iptc_is_chain(jumpto, *handle)) { + if (cs.target && iptc_is_chain(jumpto, *handle)) { fprintf(stderr, "Warning: using chain %s, not extension\n", jumpto); - if (target->t) - free(target->t); + if (cs.target->t) + free(cs.target->t); - target = NULL; + cs.target = NULL; } /* If they didn't specify a target, or it's a chain name, use standard. */ - if (!target + if (!cs.target && (strlen(jumpto) == 0 || iptc_is_chain(jumpto, *handle))) { size_t size; - target = xtables_find_target(IPT_STANDARD_TARGET, + cs.target = xtables_find_target(IPT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); size = sizeof(struct ipt_entry_target) - + target->size; - target->t = xtables_calloc(1, size); - target->t->u.target_size = size; - strcpy(target->t->u.user.name, jumpto); + + cs.target->size; + cs.target->t = xtables_calloc(1, size); + cs.target->t->u.target_size = size; + strcpy(cs.target->t->u.user.name, jumpto); if (!iptc_is_chain(jumpto, *handle)) - target->t->u.user.revision = target->revision; - if (target->init != NULL) - target->init(target->t); + cs.target->t->u.user.revision = cs.target->revision; + if (cs.target->init != NULL) + cs.target->init(cs.target->t); } - if (!target) { + if (!cs.target) { /* it is no chain, and we can't load a plugin. * We cannot know if the plugin is corrupt, non * existant OR if the user just misspelled a * chain. */ #ifdef IPT_F_GOTO - if (fw.ip.flags & IPT_F_GOTO) + if (cs.fw.ip.flags & IPT_F_GOTO) xtables_error(PARAMETER_PROBLEM, "goto '%s' is not a chain\n", jumpto); #endif xtables_find_target(jumpto, XTF_LOAD_MUST_SUCCEED); } else { - e = generate_entry(&fw, matches, target->t); - free(target->t); + e = generate_entry(&cs.fw, cs.matches, cs.target->t); + free(cs.target->t); } } @@ -1990,15 +1997,15 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle ret = append_entry(chain, e, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); break; case CMD_DELETE: ret = delete_entry(chain, e, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, - *handle, matches, target); + cs.options&OPT_VERBOSE, + *handle, cs.matches, cs.target); break; case CMD_DELETE_NUM: ret = iptc_delete_num_entry(chain, rulenum - 1, *handle); @@ -2006,20 +2013,20 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case CMD_REPLACE: ret = replace_entry(chain, e, rulenum - 1, saddrs, smasks, daddrs, dmasks, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); break; case CMD_INSERT: ret = insert_entry(chain, e, rulenum - 1, nsaddrs, saddrs, smasks, ndaddrs, daddrs, dmasks, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); break; case CMD_FLUSH: - ret = flush_entries(chain, options&OPT_VERBOSE, *handle); + ret = flush_entries(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_ZERO: - ret = zero_entries(chain, options&OPT_VERBOSE, *handle); + ret = zero_entries(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_ZERO_NUM: ret = iptc_zero_counter(chain, rulenum, *handle); @@ -2029,14 +2036,14 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case CMD_LIST|CMD_ZERO_NUM: ret = list_entries(chain, rulenum, - options&OPT_VERBOSE, - options&OPT_NUMERIC, - options&OPT_EXPANDED, - options&OPT_LINENUMBERS, + cs.options&OPT_VERBOSE, + cs.options&OPT_NUMERIC, + cs.options&OPT_EXPANDED, + cs.options&OPT_LINENUMBERS, *handle); if (ret && (command & CMD_ZERO)) ret = zero_entries(chain, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO_NUM)) ret = iptc_zero_counter(chain, rulenum, *handle); break; @@ -2045,11 +2052,11 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle case CMD_LIST_RULES|CMD_ZERO_NUM: ret = list_rules(chain, rulenum, - options&OPT_VERBOSE, + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO)) ret = zero_entries(chain, - options&OPT_VERBOSE, *handle); + cs.options&OPT_VERBOSE, *handle); if (ret && (command & CMD_ZERO_NUM)) ret = iptc_zero_counter(chain, rulenum, *handle); break; @@ -2057,13 +2064,13 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle ret = iptc_create_chain(chain, *handle); break; case CMD_DELETE_CHAIN: - ret = delete_chain(chain, options&OPT_VERBOSE, *handle); + ret = delete_chain(chain, cs.options&OPT_VERBOSE, *handle); break; case CMD_RENAME_CHAIN: ret = iptc_rename_chain(chain, newname, *handle); break; case CMD_SET_POLICY: - ret = iptc_set_policy(chain, policy, options&OPT_COUNTERS ? &fw.counters : NULL, *handle); + ret = iptc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw.counters : NULL, *handle); break; default: /* We should never reach this... */ @@ -2073,7 +2080,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle if (verbose > 1) dump_entries(*handle); - clear_rule_matches(&matches); + clear_rule_matches(&cs.matches); if (e != NULL) { free(e); -- cgit v1.2.3 From f935ae05040d2d790433abee49ef79f4a8ed393c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Feb 2011 17:14:48 +0100 Subject: src: move large default: block from do_command6 into its own function Signed-off-by: Jan Engelhardt --- ip6tables.c | 209 ++++++++++++++++++++++++++++++--------------------------- iptables.c | 219 +++++++++++++++++++++++++++++++----------------------------- 2 files changed, 225 insertions(+), 203 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index cb9e1f58..947f3c9b 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1297,8 +1297,115 @@ struct iptables_command_state { struct xtables_target *target; char *protocol; int proto_used; + char **argv; }; +static void command_default(struct iptables_command_state *cs) +{ + struct xtables_rule_match *matchp; + struct xtables_match *m; + + if (cs->target == NULL || cs->target->parse == NULL || + cs->c < cs->target->option_offset || + cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE || + !cs->target->parse(cs->c - cs->target->option_offset, + cs->argv, cs->invert, + &cs->target->tflags, + &cs->fw, &cs->target->t)) { + for (matchp = cs->matches; matchp; matchp = matchp->next) { + if (matchp->completed || + matchp->match->parse == NULL) + continue; + if (cs->c < matchp->match->option_offset || + cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) + continue; + if (matchp->match->parse(cs->c - matchp->match->option_offset, + cs->argv, cs->invert, + &matchp->match->mflags, + &cs->fw, + &matchp->match->m)) + break; + } + m = matchp ? matchp->match : NULL; + + /* If you listen carefully, you can + actually hear this code suck. */ + + /* some explanations (after four different bugs + * in 3 different releases): If we encounter a + * parameter, that has not been parsed yet, + * it's not an option of an explicitly loaded + * match or a target. However, we support + * implicit loading of the protocol match + * extension. '-p tcp' means 'l4 proto 6' and + * at the same time 'load tcp protocol match on + * demand if we specify --dport'. + * + * To make this work, we need to make sure: + * - the parameter has not been parsed by + * a match (m above) + * - a protocol has been specified + * - the protocol extension has not been + * loaded yet, or is loaded and unused + * [think of ip6tables-restore!] + * - the protocol extension can be successively + * loaded + */ + if (m == NULL + && cs->protocol + && (!find_proto(cs->protocol, XTF_DONT_LOAD, + cs->options&OPT_NUMERIC, NULL) + || (find_proto(cs->protocol, XTF_DONT_LOAD, + cs->options&OPT_NUMERIC, NULL) + && (cs->proto_used == 0)) + ) + && (m = find_proto(cs->protocol, XTF_TRY_LOAD, + cs->options&OPT_NUMERIC, &cs->matches))) { + /* Try loading protocol */ + size_t size; + + cs->proto_used = 1; + + size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + + m->size; + + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); + + opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, + m->extra_opts, &m->option_offset); + + optind--; + return; + } + + if (!m) { + if (cs->c == '?') { + if (optopt) { + xtables_error( + PARAMETER_PROBLEM, + "option `%s' " + "requires an " + "argument", + cs->argv[optind-1]); + } else { + xtables_error( + PARAMETER_PROBLEM, + "unknown option " + "`%s'", + cs->argv[optind-1]); + } + } + xtables_error(PARAMETER_PROBLEM, + "Unknown arg `%s'", optarg); + } + } +} + int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle) { struct iptables_command_state cs; @@ -1321,6 +1428,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand unsigned long long cnt; memset(&cs, 0, sizeof(cs)); + cs.argv = argv; /* re-set optind to 0 in case do_command gets called * a second time */ @@ -1710,105 +1818,8 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand exit_tryhelp(2); default: - if (cs.target == NULL || cs.target->parse == NULL || - cs.c < cs.target->option_offset || - cs.c >= cs.target->option_offset + XT_OPTION_OFFSET_SCALE || - !cs.target->parse(cs.c - cs.target->option_offset, - argv, cs.invert, - &cs.target->tflags, - &cs.fw, &cs.target->t)) { - for (matchp = cs.matches; matchp; matchp = matchp->next) { - if (matchp->completed || - matchp->match->parse == NULL) - continue; - if (cs.c < matchp->match->option_offset || - cs.c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) - continue; - if (matchp->match->parse(cs.c - matchp->match->option_offset, - argv, cs.invert, - &matchp->match->mflags, - &cs.fw, - &matchp->match->m)) - break; - } - m = matchp ? matchp->match : NULL; - - /* If you listen carefully, you can - actually hear this code suck. */ - - /* some explanations (after four different bugs - * in 3 different releases): If we encounter a - * parameter, that has not been parsed yet, - * it's not an option of an explicitly loaded - * match or a target. However, we support - * implicit loading of the protocol match - * extension. '-p tcp' means 'l4 proto 6' and - * at the same time 'load tcp protocol match on - * demand if we specify --dport'. - * - * To make this work, we need to make sure: - * - the parameter has not been parsed by - * a match (m above) - * - a protocol has been specified - * - the protocol extension has not been - * loaded yet, or is loaded and unused - * [think of ip6tables-restore!] - * - the protocol extension can be successively - * loaded - */ - if (m == NULL - && cs.protocol - && (!find_proto(cs.protocol, XTF_DONT_LOAD, - cs.options&OPT_NUMERIC, NULL) - || (find_proto(cs.protocol, XTF_DONT_LOAD, - cs.options&OPT_NUMERIC, NULL) - && (cs.proto_used == 0)) - ) - && (m = find_proto(cs.protocol, XTF_TRY_LOAD, - cs.options&OPT_NUMERIC, &cs.matches))) { - /* Try loading protocol */ - size_t size; - - cs.proto_used = 1; - - size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) - + m->size; - - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); - - opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, - m->extra_opts, &m->option_offset); - - optind--; - continue; - } - - if (!m) { - if (cs.c == '?') { - if (optopt) { - xtables_error( - PARAMETER_PROBLEM, - "option `%s' " - "requires an " - "argument", - argv[optind-1]); - } else { - xtables_error( - PARAMETER_PROBLEM, - "unknown option " - "`%s'", - argv[optind-1]); - } - } - xtables_error(PARAMETER_PROBLEM, - "Unknown arg `%s'", optarg); - } - } + command_default(&cs); + break; } cs.invert = FALSE; } diff --git a/iptables.c b/iptables.c index 5f62ae5a..4303cdf6 100644 --- a/iptables.c +++ b/iptables.c @@ -1320,8 +1320,120 @@ struct iptables_command_state { struct xtables_target *target; char *protocol; int proto_used; + char **argv; }; +static void command_default(struct iptables_command_state *cs) +{ + struct xtables_rule_match *matchp; + struct xtables_match *m; + + if (cs->target == NULL || cs->target->parse == NULL || + cs->c < cs->target->option_offset || + cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE || + !cs->target->parse(cs->c - cs->target->option_offset, + cs->argv, cs->invert, + &cs->target->tflags, + &cs->fw, &cs->target->t)) { + for (matchp = cs->matches; matchp; matchp = matchp->next) { + if (matchp->completed || + matchp->match->parse == NULL) + continue; + if (cs->c < matchp->match->option_offset || + cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) + continue; + if (matchp->match->parse(cs->c - matchp->match->option_offset, + cs->argv, cs->invert, + &matchp->match->mflags, + &cs->fw, + &matchp->match->m)) + break; + } + m = matchp ? matchp->match : NULL; + + /* If you listen carefully, you can + actually hear this code suck. */ + + /* some explanations (after four different bugs + * in 3 different releases): If we encounter a + * parameter, that has not been parsed yet, + * it's not an option of an explicitly loaded + * match or a target. However, we support + * implicit loading of the protocol match + * extension. '-p tcp' means 'l4 proto 6' and + * at the same time 'load tcp protocol match on + * demand if we specify --dport'. + * + * To make this work, we need to make sure: + * - the parameter has not been parsed by + * a match (m above) + * - a protocol has been specified + * - the protocol extension has not been + * loaded yet, or is loaded and unused + * [think of iptables-restore!] + * - the protocol extension can be successively + * loaded + */ + if (m == NULL + && cs->protocol + && (!find_proto(cs->protocol, XTF_DONT_LOAD, + cs->options&OPT_NUMERIC, NULL) + || (find_proto(cs->protocol, XTF_DONT_LOAD, + cs->options&OPT_NUMERIC, NULL) + && (cs->proto_used == 0)) + ) + && (m = find_proto(cs->protocol, XTF_TRY_LOAD, + cs->options&OPT_NUMERIC, &cs->matches))) { + /* Try loading protocol */ + size_t size; + + cs->proto_used = 1; + + size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + + m->size; + + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); + + opts = xtables_merge_options( + iptables_globals.orig_opts, + opts, + m->extra_opts, + &m->option_offset); + if (opts == NULL) + xtables_error(OTHER_PROBLEM, + "can't alloc memory!"); + + optind--; + return; + } + if (!m) { + if (cs->c == '?') { + if (optopt) { + xtables_error( + PARAMETER_PROBLEM, + "option `%s' " + "requires an " + "argument", + cs->argv[optind-1]); + } else { + xtables_error( + PARAMETER_PROBLEM, + "unknown option " + "`%s'", + cs->argv[optind-1]); + } + } + xtables_error(PARAMETER_PROBLEM, + "Unknown arg `%s'", optarg); + } + } +} + int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle) { struct iptables_command_state cs; @@ -1344,6 +1456,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle unsigned long long cnt; memset(&cs, 0, sizeof(cs)); + cs.argv = argv; /* re-set optind to 0 in case do_command gets called * a second time */ @@ -1742,110 +1855,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle exit_tryhelp(2); default: - if (cs.target == NULL || cs.target->parse == NULL || - cs.c < cs.target->option_offset || - cs.c >= cs.target->option_offset + XT_OPTION_OFFSET_SCALE || - !cs.target->parse(cs.c - cs.target->option_offset, - argv, cs.invert, - &cs.target->tflags, - &cs.fw, &cs.target->t)) { - for (matchp = cs.matches; matchp; matchp = matchp->next) { - if (matchp->completed || - matchp->match->parse == NULL) - continue; - if (cs.c < matchp->match->option_offset || - cs.c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) - continue; - if (matchp->match->parse(cs.c - matchp->match->option_offset, - argv, cs.invert, - &matchp->match->mflags, - &cs.fw, - &matchp->match->m)) - break; - } - m = matchp ? matchp->match : NULL; - - /* If you listen carefully, you can - actually hear this code suck. */ - - /* some explanations (after four different bugs - * in 3 different releases): If we encounter a - * parameter, that has not been parsed yet, - * it's not an option of an explicitly loaded - * match or a target. However, we support - * implicit loading of the protocol match - * extension. '-p tcp' means 'l4 proto 6' and - * at the same time 'load tcp protocol match on - * demand if we specify --dport'. - * - * To make this work, we need to make sure: - * - the parameter has not been parsed by - * a match (m above) - * - a protocol has been specified - * - the protocol extension has not been - * loaded yet, or is loaded and unused - * [think of iptables-restore!] - * - the protocol extension can be successively - * loaded - */ - if (m == NULL - && cs.protocol - && (!find_proto(cs.protocol, XTF_DONT_LOAD, - cs.options&OPT_NUMERIC, NULL) - || (find_proto(cs.protocol, XTF_DONT_LOAD, - cs.options&OPT_NUMERIC, NULL) - && (cs.proto_used == 0)) - ) - && (m = find_proto(cs.protocol, XTF_TRY_LOAD, - cs.options&OPT_NUMERIC, &cs.matches))) { - /* Try loading protocol */ - size_t size; - - cs.proto_used = 1; - - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + m->size; - - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); - - opts = xtables_merge_options( - iptables_globals.orig_opts, - opts, - m->extra_opts, - &m->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, - "can't alloc memory!"); - - optind--; - continue; - } - if (!m) { - if (cs.c == '?') { - if (optopt) { - xtables_error( - PARAMETER_PROBLEM, - "option `%s' " - "requires an " - "argument", - argv[optind-1]); - } else { - xtables_error( - PARAMETER_PROBLEM, - "unknown option " - "`%s'", - argv[optind-1]); - } - } - xtables_error(PARAMETER_PROBLEM, - "Unknown arg `%s'", optarg); - } - } + command_default(&cs); + break; } cs.invert = FALSE; } -- cgit v1.2.3 From 7a548b32d9ad8d6e4a8398573d4fa8c4e4a1f9e0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 00:00:42 +0100 Subject: src: share iptables_command_state across the two programs struct iptables_command_state and quite a bit of the code looks worthy of deduplication. Signed-off-by: Jan Engelhardt --- ip6tables.c | 74 ++++++++++++++++++++++++++----------------------------------- iptables.c | 12 ---------- xshared.h | 18 +++++++++++++++ 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index 947f3c9b..dac0c524 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1288,18 +1288,6 @@ static void clear_rule_matches(struct xtables_rule_match **matches) *matches = NULL; } -struct iptables_command_state { - struct ip6t_entry fw; - int invert; - int c; - unsigned int options; - struct xtables_rule_match *matches; - struct xtables_target *target; - char *protocol; - int proto_used; - char **argv; -}; - static void command_default(struct iptables_command_state *cs) { struct xtables_rule_match *matchp; @@ -1311,7 +1299,7 @@ static void command_default(struct iptables_command_state *cs) !cs->target->parse(cs->c - cs->target->option_offset, cs->argv, cs->invert, &cs->target->tflags, - &cs->fw, &cs->target->t)) { + &cs->fw6, &cs->target->t)) { for (matchp = cs->matches; matchp; matchp = matchp->next) { if (matchp->completed || matchp->match->parse == NULL) @@ -1322,7 +1310,7 @@ static void command_default(struct iptables_command_state *cs) if (matchp->match->parse(cs->c - matchp->match->option_offset, cs->argv, cs->invert, &matchp->match->mflags, - &cs->fw, + &cs->fw6, &matchp->match->m)) break; } @@ -1609,7 +1597,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand */ case 'p': xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); - set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_PROTOCOL, &cs.fw6.ipv6.invflags, cs.invert); /* Canonicalize into lower case */ @@ -1617,16 +1605,16 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand *cs.protocol = tolower(*cs.protocol); cs.protocol = optarg; - cs.fw.ipv6.proto = xtables_parse_protocol(cs.protocol); - cs.fw.ipv6.flags |= IP6T_F_PROTO; + cs.fw6.ipv6.proto = xtables_parse_protocol(cs.protocol); + cs.fw6.ipv6.flags |= IP6T_F_PROTO; - if (cs.fw.ipv6.proto == 0 - && (cs.fw.ipv6.invflags & IP6T_INV_PROTO)) + if (cs.fw6.ipv6.proto == 0 + && (cs.fw6.ipv6.invflags & IP6T_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "rule would never match protocol"); - if (is_exthdr(cs.fw.ipv6.proto) - && (cs.fw.ipv6.invflags & IP6T_INV_PROTO) == 0) + if (is_exthdr(cs.fw6.ipv6.proto) + && (cs.fw6.ipv6.invflags & IP6T_INV_PROTO) == 0) fprintf(stderr, "Warning: never matched protocol: %s. " "use extension match instead.\n", @@ -1635,29 +1623,29 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 's': xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); - set_option(&cs.options, OPT_SOURCE, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_SOURCE, &cs.fw6.ipv6.invflags, cs.invert); shostnetworkmask = optarg; break; case 'd': xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); - set_option(&cs.options, OPT_DESTINATION, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_DESTINATION, &cs.fw6.ipv6.invflags, cs.invert); dhostnetworkmask = optarg; break; #ifdef IP6T_F_GOTO case 'g': - set_option(&cs.options, OPT_JUMP, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, cs.invert); - cs.fw.ipv6.flags |= IP6T_F_GOTO; + cs.fw6.ipv6.flags |= IP6T_F_GOTO; jumpto = parse_target(optarg); break; #endif case 'j': - set_option(&cs.options, OPT_JUMP, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, cs.invert); jumpto = parse_target(optarg); /* TRY_LOAD (may be chain name) */ @@ -1691,11 +1679,11 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand "Empty interface is likely to be " "undesired"); xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); - set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_VIANAMEIN, &cs.fw6.ipv6.invflags, cs.invert); xtables_parse_interface(optarg, - cs.fw.ipv6.iniface, - cs.fw.ipv6.iniface_mask); + cs.fw6.ipv6.iniface, + cs.fw6.ipv6.iniface_mask); break; case 'o': @@ -1704,17 +1692,17 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand "Empty interface is likely to be " "undesired"); xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); - set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw6.ipv6.invflags, cs.invert); xtables_parse_interface(optarg, - cs.fw.ipv6.outiface, - cs.fw.ipv6.outiface_mask); + cs.fw6.ipv6.outiface, + cs.fw6.ipv6.outiface_mask); break; case 'v': if (!verbose) set_option(&cs.options, OPT_VERBOSE, - &cs.fw.ipv6.invflags, cs.invert); + &cs.fw6.ipv6.invflags, cs.invert); verbose++; break; @@ -1742,7 +1730,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand break; case 'n': - set_option(&cs.options, OPT_NUMERIC, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_NUMERIC, &cs.fw6.ipv6.invflags, cs.invert); break; @@ -1754,7 +1742,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand break; case 'x': - set_option(&cs.options, OPT_EXPANDED, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_EXPANDED, &cs.fw6.ipv6.invflags, cs.invert); break; @@ -1767,7 +1755,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand exit(0); case '0': - set_option(&cs.options, OPT_LINENUMBERS, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_LINENUMBERS, &cs.fw6.ipv6.invflags, cs.invert); break; @@ -1777,7 +1765,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand case 'c': - set_option(&cs.options, OPT_COUNTERS, &cs.fw.ipv6.invflags, + set_option(&cs.options, OPT_COUNTERS, &cs.fw6.ipv6.invflags, cs.invert); pcnt = optarg; bcnt = strchr(pcnt + 1, ','); @@ -1795,13 +1783,13 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "-%c packet counter not numeric", opt2char(OPT_COUNTERS)); - cs.fw.counters.pcnt = cnt; + cs.fw6.counters.pcnt = cnt; if (sscanf(bcnt, "%llu", &cnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c byte counter not numeric", opt2char(OPT_COUNTERS)); - cs.fw.counters.bcnt = cnt; + cs.fw6.counters.bcnt = cnt; break; case 1: /* non option */ @@ -1858,7 +1846,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand &dmasks, &ndaddrs); if ((nsaddrs > 1 || ndaddrs > 1) && - (cs.fw.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP))) + (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP))) xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); @@ -1946,13 +1934,13 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand * existant OR if the user just misspelled a * chain. */ #ifdef IP6T_F_GOTO - if (cs.fw.ipv6.flags & IP6T_F_GOTO) + if (cs.fw6.ipv6.flags & IP6T_F_GOTO) xtables_error(PARAMETER_PROBLEM, "goto '%s' is not a chain\n", jumpto); #endif xtables_find_target(jumpto, XTF_LOAD_MUST_SUCCEED); } else { - e = generate_entry(&cs.fw, cs.matches, cs.target->t); + e = generate_entry(&cs.fw6, cs.matches, cs.target->t); free(cs.target->t); } } @@ -2035,7 +2023,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand ret = ip6tc_rename_chain(chain, newname, *handle); break; case CMD_SET_POLICY: - ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw.counters : NULL, *handle); + ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw6.counters : NULL, *handle); break; default: /* We should never reach this... */ diff --git a/iptables.c b/iptables.c index 4303cdf6..68819819 100644 --- a/iptables.c +++ b/iptables.c @@ -1311,18 +1311,6 @@ get_kernel_version(void) { kernel_version = LINUX_VERSION(x, y, z); } -struct iptables_command_state { - struct ipt_entry fw; - int invert; - int c; - unsigned int options; - struct xtables_rule_match *matches; - struct xtables_target *target; - char *protocol; - int proto_used; - char **argv; -}; - static void command_default(struct iptables_command_state *cs) { struct xtables_rule_match *matchp; diff --git a/xshared.h b/xshared.h index e5b2a02b..4a7f96fc 100644 --- a/xshared.h +++ b/xshared.h @@ -1,9 +1,27 @@ #ifndef IPTABLES_XSHARED_H #define IPTABLES_XSHARED_H 1 +#include +#include + struct xtables_rule_match; struct xtables_target; +struct iptables_command_state { + union { + struct ipt_entry fw; + struct ip6t_entry fw6; + }; + int invert; + int c; + unsigned int options; + struct xtables_rule_match *matches; + struct xtables_target *target; + char *protocol; + int proto_used; + char **argv; +}; + enum { XT_OPTION_OFFSET_SCALE = 256, }; -- cgit v1.2.3 From f6992cbb211a42f776333fe65dfad49f17455a3f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:05:49 +0100 Subject: src: deduplicate find_proto function Signed-off-by: Jan Engelhardt --- ip6tables.c | 36 ------------------------------------ iptables.c | 35 ----------------------------------- xshared.c | 37 +++++++++++++++++++++++++++++++++++++ xshared.h | 4 ++++ 4 files changed, 41 insertions(+), 71 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index dac0c524..ac376e23 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -205,24 +205,6 @@ struct pprot { uint8_t num; }; -static const char * -proto_to_name(uint8_t proto, int nolookup) -{ - unsigned int i; - - if (proto && !nolookup) { - const struct protoent *pent = getprotobynumber(proto); - if (pent) - return pent->p_name; - } - - for (i = 0; xtables_chain_protos[i].name != NULL; ++i) - if (xtables_chain_protos[i].num == proto) - return xtables_chain_protos[i].name; - - return NULL; -} - static void __attribute__((noreturn)) exit_tryhelp(int status) { @@ -406,24 +388,6 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds, * return global static data. */ -/* Christophe Burki wants `-p 6' to imply `-m tcp'. */ -static struct xtables_match * -find_proto(const char *pname, enum xtables_tryload tryload, - int nolookup, struct xtables_rule_match **matches) -{ - unsigned int proto; - - if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { - const char *protoname = proto_to_name(proto, nolookup); - - if (protoname) - return xtables_find_match(protoname, tryload, matches); - } else - return xtables_find_match(pname, tryload, matches); - - return NULL; -} - /* These are invalid numbers as upper layer protocol */ static int is_exthdr(uint16_t proto) { diff --git a/iptables.c b/iptables.c index 68819819..9d4f10c4 100644 --- a/iptables.c +++ b/iptables.c @@ -213,24 +213,6 @@ int kernel_version; #endif #endif -static const char * -proto_to_name(uint8_t proto, int nolookup) -{ - unsigned int i; - - if (proto && !nolookup) { - struct protoent *pent = getprotobynumber(proto); - if (pent) - return pent->p_name; - } - - for (i = 0; xtables_chain_protos[i].name != NULL; ++i) - if (xtables_chain_protos[i].num == proto) - return xtables_chain_protos[i].name; - - return NULL; -} - enum { IPT_DOTTED_ADDR = 0, IPT_DOTTED_MASK @@ -420,23 +402,6 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds, */ /* Christophe Burki wants `-p 6' to imply `-m tcp'. */ -static struct xtables_match * -find_proto(const char *pname, enum xtables_tryload tryload, - int nolookup, struct xtables_rule_match **matches) -{ - unsigned int proto; - - if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { - const char *protoname = proto_to_name(proto, nolookup); - - if (protoname) - return xtables_find_match(protoname, tryload, matches); - } else - return xtables_find_match(pname, tryload, matches); - - return NULL; -} - /* Can't be zero. */ static int parse_rulenumber(const char *rule) diff --git a/xshared.c b/xshared.c index 21b5b2cb..40b6b560 100644 --- a/xshared.c +++ b/xshared.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include "xshared.h" @@ -29,3 +31,38 @@ void print_extension_helps(const struct xtables_target *t, m->match->help(); } } + +const char * +proto_to_name(uint8_t proto, int nolookup) +{ + unsigned int i; + + if (proto && !nolookup) { + struct protoent *pent = getprotobynumber(proto); + if (pent) + return pent->p_name; + } + + for (i = 0; xtables_chain_protos[i].name != NULL; ++i) + if (xtables_chain_protos[i].num == proto) + return xtables_chain_protos[i].name; + + return NULL; +} + +struct xtables_match * +find_proto(const char *pname, enum xtables_tryload tryload, + int nolookup, struct xtables_rule_match **matches) +{ + unsigned int proto; + + if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { + const char *protoname = proto_to_name(proto, nolookup); + + if (protoname) + return xtables_find_match(protoname, tryload, matches); + } else + return xtables_find_match(pname, tryload, matches); + + return NULL; +} diff --git a/xshared.h b/xshared.h index 4a7f96fc..11d95fe5 100644 --- a/xshared.h +++ b/xshared.h @@ -1,6 +1,7 @@ #ifndef IPTABLES_XSHARED_H #define IPTABLES_XSHARED_H 1 +#include #include #include @@ -28,5 +29,8 @@ enum { extern void print_extension_helps(const struct xtables_target *, const struct xtables_rule_match *); +extern const char *proto_to_name(uint8_t, int); +extern struct xtables_match *find_proto(const char *, enum xtables_tryload, + int, struct xtables_rule_match **); #endif /* IPTABLES_XSHARED_H */ -- cgit v1.2.3 From f1e71016dddb65709afe0746a96a3fefbec3ba27 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:13:43 +0100 Subject: src: move OPT_FRAGMENT to the end so the list can be shared --- iptables.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/iptables.c b/iptables.c index 9d4f10c4..4a3860aa 100644 --- a/iptables.c +++ b/iptables.c @@ -93,12 +93,12 @@ static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', #define OPT_EXPANDED 0x00040U #define OPT_VIANAMEIN 0x00080U #define OPT_VIANAMEOUT 0x00100U -#define OPT_FRAGMENT 0x00200U -#define OPT_LINENUMBERS 0x00400U -#define OPT_COUNTERS 0x00800U +#define OPT_LINENUMBERS 0x00200U +#define OPT_COUNTERS 0x00400U +#define OPT_FRAGMENT 0x00800U #define NUMBER_OF_OPT 12 static const char optflags[NUMBER_OF_OPT] -= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '0', 'c'}; += { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '0', 'c', 'f'}; static struct option original_opts[] = { {.name = "append", .has_arg = 1, .val = 'A'}, @@ -163,19 +163,19 @@ struct xtables_globals iptables_globals = { static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /* Well, it's better than "Re: Linux vs FreeBSD" */ { - /* -n -s -d -p -j -v -x -i -o -f --line -c */ -/*INSERT*/ {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '}, -/*DELETE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x','x'}, + /* -n -s -d -p -j -v -x -i -o --line -c -f */ +/*INSERT*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' ',' '}, +/*DELETE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x','x',' '}, /*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x','x'}, -/*REPLACE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '}, -/*APPEND*/ {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '}, -/*LIST*/ {' ','x','x','x','x',' ',' ','x','x','x',' ','x'}, +/*REPLACE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' ',' '}, +/*APPEND*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' ',' '}, +/*LIST*/ {' ','x','x','x','x',' ',' ','x','x',' ','x','x'}, /*FLUSH*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, /*ZERO*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, /*ZERO_NUM*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, /*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, /*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, -/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x',' '}, +/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x',' ','x'}, /*RENAME*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'}, /*LIST_RULES*/{'x','x','x','x','x',' ','x','x','x','x','x','x'} }; -- cgit v1.2.3 From f4b6e5290e869fccb87c03da5603a38b7e55abc5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:16:14 +0100 Subject: src: put shared option flags into xshared This will be needed for the find_proto function. Signed-off-by: Jan Engelhardt --- ip6tables.c | 16 ++-------------- iptables.c | 16 ++-------------- xshared.h | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index ac376e23..7f8a8df6 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -86,20 +86,8 @@ static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', 'Z', 'N', 'X', 'P', 'E', 'S' }; -#define OPT_NONE 0x00000U -#define OPT_NUMERIC 0x00001U -#define OPT_SOURCE 0x00002U -#define OPT_DESTINATION 0x00004U -#define OPT_PROTOCOL 0x00008U -#define OPT_JUMP 0x00010U -#define OPT_VERBOSE 0x00020U -#define OPT_EXPANDED 0x00040U -#define OPT_VIANAMEIN 0x00080U -#define OPT_VIANAMEOUT 0x00100U -#define OPT_LINENUMBERS 0x00200U -#define OPT_COUNTERS 0x00400U -#define NUMBER_OF_OPT 11 -static const char optflags[NUMBER_OF_OPT] +#define NUMBER_OF_OPT ARRAY_SIZE(optflags) +static const char optflags[] = { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '0', 'c'}; static struct option original_opts[] = { diff --git a/iptables.c b/iptables.c index 4a3860aa..0de656e9 100644 --- a/iptables.c +++ b/iptables.c @@ -83,21 +83,9 @@ static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', 'Z', 'N', 'X', 'P', 'E', 'S' }; -#define OPT_NONE 0x00000U -#define OPT_NUMERIC 0x00001U -#define OPT_SOURCE 0x00002U -#define OPT_DESTINATION 0x00004U -#define OPT_PROTOCOL 0x00008U -#define OPT_JUMP 0x00010U -#define OPT_VERBOSE 0x00020U -#define OPT_EXPANDED 0x00040U -#define OPT_VIANAMEIN 0x00080U -#define OPT_VIANAMEOUT 0x00100U -#define OPT_LINENUMBERS 0x00200U -#define OPT_COUNTERS 0x00400U #define OPT_FRAGMENT 0x00800U -#define NUMBER_OF_OPT 12 -static const char optflags[NUMBER_OF_OPT] +#define NUMBER_OF_OPT ARRAY_SIZE(optflags) +static const char optflags[] = { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '0', 'c', 'f'}; static struct option original_opts[] = { diff --git a/xshared.h b/xshared.h index 11d95fe5..06d73ab9 100644 --- a/xshared.h +++ b/xshared.h @@ -5,6 +5,21 @@ #include #include +enum { + OPT_NONE = 0, + OPT_NUMERIC = 1 << 0, + OPT_SOURCE = 1 << 1, + OPT_DESTINATION = 1 << 2, + OPT_PROTOCOL = 1 << 3, + OPT_JUMP = 1 << 4, + OPT_VERBOSE = 1 << 5, + OPT_EXPANDED = 1 << 6, + OPT_VIANAMEIN = 1 << 7, + OPT_VIANAMEOUT = 1 << 8, + OPT_LINENUMBERS = 1 << 9, + OPT_COUNTERS = 1 << 10, +}; + struct xtables_rule_match; struct xtables_target; -- cgit v1.2.3 From acef6043f647806096c41294b00472f6ce7462d7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:18:53 +0100 Subject: src: deduplicate and simplify implicit protocol extension loading Signed-off-by: Jan Engelhardt --- ip6tables.c | 34 +--------------------------------- iptables.c | 34 +--------------------------------- xshared.c | 35 ++++++++++++++++++++++++++++++++++- xshared.h | 3 +-- 4 files changed, 37 insertions(+), 69 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index 7f8a8df6..3330420f 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1268,39 +1268,7 @@ static void command_default(struct iptables_command_state *cs) } m = matchp ? matchp->match : NULL; - /* If you listen carefully, you can - actually hear this code suck. */ - - /* some explanations (after four different bugs - * in 3 different releases): If we encounter a - * parameter, that has not been parsed yet, - * it's not an option of an explicitly loaded - * match or a target. However, we support - * implicit loading of the protocol match - * extension. '-p tcp' means 'l4 proto 6' and - * at the same time 'load tcp protocol match on - * demand if we specify --dport'. - * - * To make this work, we need to make sure: - * - the parameter has not been parsed by - * a match (m above) - * - a protocol has been specified - * - the protocol extension has not been - * loaded yet, or is loaded and unused - * [think of ip6tables-restore!] - * - the protocol extension can be successively - * loaded - */ - if (m == NULL - && cs->protocol - && (!find_proto(cs->protocol, XTF_DONT_LOAD, - cs->options&OPT_NUMERIC, NULL) - || (find_proto(cs->protocol, XTF_DONT_LOAD, - cs->options&OPT_NUMERIC, NULL) - && (cs->proto_used == 0)) - ) - && (m = find_proto(cs->protocol, XTF_TRY_LOAD, - cs->options&OPT_NUMERIC, &cs->matches))) { + if (m == NULL && (m = load_proto(cs)) != NULL) { /* Try loading protocol */ size_t size; diff --git a/iptables.c b/iptables.c index 0de656e9..bae14afc 100644 --- a/iptables.c +++ b/iptables.c @@ -1292,39 +1292,7 @@ static void command_default(struct iptables_command_state *cs) } m = matchp ? matchp->match : NULL; - /* If you listen carefully, you can - actually hear this code suck. */ - - /* some explanations (after four different bugs - * in 3 different releases): If we encounter a - * parameter, that has not been parsed yet, - * it's not an option of an explicitly loaded - * match or a target. However, we support - * implicit loading of the protocol match - * extension. '-p tcp' means 'l4 proto 6' and - * at the same time 'load tcp protocol match on - * demand if we specify --dport'. - * - * To make this work, we need to make sure: - * - the parameter has not been parsed by - * a match (m above) - * - a protocol has been specified - * - the protocol extension has not been - * loaded yet, or is loaded and unused - * [think of iptables-restore!] - * - the protocol extension can be successively - * loaded - */ - if (m == NULL - && cs->protocol - && (!find_proto(cs->protocol, XTF_DONT_LOAD, - cs->options&OPT_NUMERIC, NULL) - || (find_proto(cs->protocol, XTF_DONT_LOAD, - cs->options&OPT_NUMERIC, NULL) - && (cs->proto_used == 0)) - ) - && (m = find_proto(cs->protocol, XTF_TRY_LOAD, - cs->options&OPT_NUMERIC, &cs->matches))) { + if (m == NULL && (m = load_proto(cs)) != NULL) { /* Try loading protocol */ size_t size; diff --git a/xshared.c b/xshared.c index 40b6b560..b47beb1e 100644 --- a/xshared.c +++ b/xshared.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -50,7 +51,7 @@ proto_to_name(uint8_t proto, int nolookup) return NULL; } -struct xtables_match * +static struct xtables_match * find_proto(const char *pname, enum xtables_tryload tryload, int nolookup, struct xtables_rule_match **matches) { @@ -66,3 +67,35 @@ find_proto(const char *pname, enum xtables_tryload tryload, return NULL; } + +/* + * Some explanations (after four different bugs in 3 different releases): If + * we encounter a parameter, that has not been parsed yet, it's not an option + * of an explicitly loaded match or a target. However, we support implicit + * loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at + * the same time 'load tcp protocol match on demand if we specify --dport'. + * + * To make this work, we need to make sure: + * - the parameter has not been parsed by a match (m above) + * - a protocol has been specified + * - the protocol extension has not been loaded yet, or is loaded and unused + * [think of ip6tables-restore!] + * - the protocol extension can be successively loaded + */ +static bool should_load_proto(struct iptables_command_state *cs) +{ + if (cs->protocol == NULL) + return false; + if (find_proto(cs->protocol, XTF_DONT_LOAD, + cs->options & OPT_NUMERIC, NULL) != NULL) + return true; + return cs->proto_used; +} + +struct xtables_match *load_proto(struct iptables_command_state *cs) +{ + if (!should_load_proto(cs)) + return NULL; + return find_proto(cs->protocol, XTF_TRY_LOAD, + cs->options & OPT_NUMERIC, &cs->matches); +} diff --git a/xshared.h b/xshared.h index 06d73ab9..d0cb5162 100644 --- a/xshared.h +++ b/xshared.h @@ -45,7 +45,6 @@ enum { extern void print_extension_helps(const struct xtables_target *, const struct xtables_rule_match *); extern const char *proto_to_name(uint8_t, int); -extern struct xtables_match *find_proto(const char *, enum xtables_tryload, - int, struct xtables_rule_match **); +extern struct xtables_match *load_proto(struct iptables_command_state *); #endif /* IPTABLES_XSHARED_H */ -- cgit v1.2.3 From 94e247b80a0c28140056ee07ea24e54ca5dbebaf Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:20:02 +0100 Subject: src: unclutter command_default function (Essentially, 5 levels of indentation have been stripped compared to the original layout, and this is surely a result that looks a lot better than it did before.) Things to note: 1. If the m->parse call succeeded, we can return from the function and do not need to go through the other code. As such, "m" is guaranteed to be useless at the end of the match loop, and so, conditions can be removed. 2. Since the per-extension parse function only ever get their own option codes (since v1.4.10-26-gd09b6d5), their return value no longer has a meaning and can be ignored. Signed-off-by: Jan Engelhardt --- ip6tables.c | 100 ++++++++++++++++++++++++------------------------------- iptables.c | 109 ++++++++++++++++++++++++++---------------------------------- 2 files changed, 91 insertions(+), 118 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index 3330420f..c475bf26 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1247,71 +1247,59 @@ static void command_default(struct iptables_command_state *cs) if (cs->target == NULL || cs->target->parse == NULL || cs->c < cs->target->option_offset || - cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE || - !cs->target->parse(cs->c - cs->target->option_offset, - cs->argv, cs->invert, - &cs->target->tflags, - &cs->fw6, &cs->target->t)) { - for (matchp = cs->matches; matchp; matchp = matchp->next) { - if (matchp->completed || - matchp->match->parse == NULL) - continue; - if (cs->c < matchp->match->option_offset || - cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) - continue; - if (matchp->match->parse(cs->c - matchp->match->option_offset, - cs->argv, cs->invert, - &matchp->match->mflags, - &cs->fw6, - &matchp->match->m)) - break; - } - m = matchp ? matchp->match : NULL; + cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE) { + cs->target->parse(cs->c - cs->target->option_offset, cs->argv, + cs->invert, &cs->target->tflags, &cs->fw6, + &cs->target->t); + return; + } - if (m == NULL && (m = load_proto(cs)) != NULL) { - /* Try loading protocol */ - size_t size; + for (matchp = cs->matches; matchp; matchp = matchp->next) { + m = matchp->match; - cs->proto_used = 1; + if (matchp->completed || m->parse == NULL) + continue; + if (cs->c < matchp->match->option_offset || + cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) + continue; + m->parse(cs->c - m->option_offset, cs->argv, cs->invert, + &m->mflags, &cs->fw6, &m->m); + return; + } - size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) - + m->size; + /* Try loading protocol */ + m = load_proto(cs); + if (m != NULL) { + size_t size; - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); + cs->proto_used = 1; - opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, - m->extra_opts, &m->option_offset); + size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; - optind--; - return; - } + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); - if (!m) { - if (cs->c == '?') { - if (optopt) { - xtables_error( - PARAMETER_PROBLEM, - "option `%s' " - "requires an " - "argument", - cs->argv[optind-1]); - } else { - xtables_error( - PARAMETER_PROBLEM, - "unknown option " - "`%s'", - cs->argv[optind-1]); - } - } + opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, + m->extra_opts, &m->option_offset); + + optind--; + return; + } + + if (cs->c == '?') { + if (optopt) xtables_error(PARAMETER_PROBLEM, - "Unknown arg `%s'", optarg); - } + "option \"%s\" requires an argument", + cs->argv[optind-1]); + else + xtables_error(PARAMETER_PROBLEM, + "unknown option \"%s\"", cs->argv[optind-1]); } + xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle) diff --git a/iptables.c b/iptables.c index bae14afc..96732b40 100644 --- a/iptables.c +++ b/iptables.c @@ -1271,76 +1271,61 @@ static void command_default(struct iptables_command_state *cs) if (cs->target == NULL || cs->target->parse == NULL || cs->c < cs->target->option_offset || - cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE || - !cs->target->parse(cs->c - cs->target->option_offset, - cs->argv, cs->invert, - &cs->target->tflags, - &cs->fw, &cs->target->t)) { - for (matchp = cs->matches; matchp; matchp = matchp->next) { - if (matchp->completed || - matchp->match->parse == NULL) - continue; - if (cs->c < matchp->match->option_offset || - cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) - continue; - if (matchp->match->parse(cs->c - matchp->match->option_offset, - cs->argv, cs->invert, - &matchp->match->mflags, - &cs->fw, - &matchp->match->m)) - break; - } - m = matchp ? matchp->match : NULL; + cs->c >= cs->target->option_offset + XT_OPTION_OFFSET_SCALE) { + cs->target->parse(cs->c - cs->target->option_offset, cs->argv, + cs->invert, &cs->target->tflags, &cs->fw, + &cs->target->t); + return; + } - if (m == NULL && (m = load_proto(cs)) != NULL) { - /* Try loading protocol */ - size_t size; + for (matchp = cs->matches; matchp; matchp = matchp->next) { + m = matchp->match; - cs->proto_used = 1; + if (matchp->completed || m->parse == NULL) + continue; + if (cs->c < m->option_offset || + cs->c >= m->option_offset + XT_OPTION_OFFSET_SCALE) + continue; + m->parse(cs->c - m->option_offset, cs->argv, cs->invert, + &m->mflags, &cs->fw, &m->m); + return; + } - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + m->size; + /* Try loading protocol */ + m = load_proto(cs); + if (m != NULL) { + size_t size; - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); + cs->proto_used = 1; - opts = xtables_merge_options( - iptables_globals.orig_opts, - opts, - m->extra_opts, - &m->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, - "can't alloc memory!"); + size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; - optind--; - return; - } - if (!m) { - if (cs->c == '?') { - if (optopt) { - xtables_error( - PARAMETER_PROBLEM, - "option `%s' " - "requires an " - "argument", - cs->argv[optind-1]); - } else { - xtables_error( - PARAMETER_PROBLEM, - "unknown option " - "`%s'", - cs->argv[optind-1]); - } - } + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); + + opts = xtables_merge_options(iptables_globals.orig_opts, opts, + m->extra_opts, &m->option_offset); + if (opts == NULL) + xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + + optind--; + return; + } + + if (cs->c == '?') { + if (optopt) xtables_error(PARAMETER_PROBLEM, - "Unknown arg `%s'", optarg); - } + "option \"%s\" requires an argument", + cs->argv[optind-1]); + else + xtables_error(PARAMETER_PROBLEM, + "unknown option \"%s\"", cs->argv[optind-1]); } + xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle) -- cgit v1.2.3 From 9bb76094b26d22c7a85d98a075640f054b7910f4 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:39:36 +0100 Subject: src: move jump option handling from do_command6 into its own function Signed-off-by: Jan Engelhardt --- ip6tables.c | 72 +++++++++++++++++++++++++++++-------------------------- iptables.c | 79 ++++++++++++++++++++++++++++++++----------------------------- xshared.h | 1 + 3 files changed, 80 insertions(+), 72 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index c475bf26..eb28dc0a 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1302,6 +1302,33 @@ static void command_default(struct iptables_command_state *cs) xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } +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 = IP6T_ALIGN(sizeof(struct ip6t_entry_target)) + cs->target->size; + + cs->target->t = xtables_calloc(1, size); + cs->target->t->u.target_size = size; + strcpy(cs->target->t->u.user.name, cs->jumpto); + cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->init != NULL) + cs->target->init(cs->target->t); + 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 ip6tc_handle **handle) { struct iptables_command_state cs; @@ -1320,10 +1347,10 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand struct xtables_match *m; struct xtables_rule_match *matchp; struct xtables_target *t; - const char *jumpto = ""; unsigned long long cnt; memset(&cs, 0, sizeof(cs)); + cs.jumpto = ""; cs.argv = argv; /* re-set optind to 0 in case do_command gets called @@ -1548,36 +1575,12 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, cs.invert); cs.fw6.ipv6.flags |= IP6T_F_GOTO; - jumpto = parse_target(optarg); + cs.jumpto = parse_target(optarg); break; #endif case 'j': - set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, - cs.invert); - jumpto = parse_target(optarg); - /* TRY_LOAD (may be chain name) */ - cs.target = xtables_find_target(jumpto, XTF_TRY_LOAD); - - if (cs.target) { - size_t size; - - size = IP6T_ALIGN(sizeof(struct ip6t_entry_target)) - + cs.target->size; - - cs.target->t = xtables_calloc(1, size); - cs.target->t->u.target_size = size; - strcpy(cs.target->t->u.user.name, jumpto); - cs.target->t->u.user.revision = cs.target->revision; - if (cs.target->init != NULL) - cs.target->init(cs.target->t); - 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!"); - } + command_jump(&cs); break; @@ -1806,10 +1809,10 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand chain); } - if (cs.target && ip6tc_is_chain(jumpto, *handle)) { + if (cs.target && ip6tc_is_chain(cs.jumpto, *handle)) { fprintf(stderr, "Warning: using chain %s, not extension\n", - jumpto); + cs.jumpto); if (cs.target->t) free(cs.target->t); @@ -1820,8 +1823,8 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand /* If they didn't specify a target, or it's a chain name, use standard. */ if (!cs.target - && (strlen(jumpto) == 0 - || ip6tc_is_chain(jumpto, *handle))) { + && (strlen(cs.jumpto) == 0 + || ip6tc_is_chain(cs.jumpto, *handle))) { size_t size; cs.target = xtables_find_target(IP6T_STANDARD_TARGET, @@ -1831,7 +1834,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; - strcpy(cs.target->t->u.user.name, jumpto); + strcpy(cs.target->t->u.user.name, cs.jumpto); if (cs.target->init != NULL) cs.target->init(cs.target->t); } @@ -1844,9 +1847,10 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand #ifdef IP6T_F_GOTO if (cs.fw6.ipv6.flags & IP6T_F_GOTO) xtables_error(PARAMETER_PROBLEM, - "goto '%s' is not a chain\n", jumpto); + "goto '%s' is not a chain\n", + cs.jumpto); #endif - xtables_find_target(jumpto, XTF_LOAD_MUST_SUCCEED); + xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED); } else { e = generate_entry(&cs.fw6, cs.matches, cs.target->t); free(cs.target->t); diff --git a/iptables.c b/iptables.c index 96732b40..354bc9cb 100644 --- a/iptables.c +++ b/iptables.c @@ -1328,6 +1328,34 @@ static void command_default(struct iptables_command_state *cs) xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } +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 = IPT_ALIGN(sizeof(struct ipt_entry_target)) + + cs->target->size; + + cs->target->t = xtables_calloc(1, size); + cs->target->t->u.target_size = size; + strcpy(cs->target->t->u.user.name, cs->jumpto); + cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->init != NULL) + cs->target->init(cs->target->t); + 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_command(int argc, char *argv[], char **table, struct iptc_handle **handle) { struct iptables_command_state cs; @@ -1346,10 +1374,10 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle struct xtables_match *m; struct xtables_rule_match *matchp; struct xtables_target *t; - const char *jumpto = ""; unsigned long long cnt; memset(&cs, 0, sizeof(cs)); + cs.jumpto = ""; cs.argv = argv; /* re-set optind to 0 in case do_command gets called @@ -1566,38 +1594,12 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, cs.invert); cs.fw.ip.flags |= IPT_F_GOTO; - jumpto = parse_target(optarg); + cs.jumpto = parse_target(optarg); break; #endif case 'j': - set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, - cs.invert); - jumpto = parse_target(optarg); - /* TRY_LOAD (may be chain name) */ - cs.target = xtables_find_target(jumpto, XTF_TRY_LOAD); - - if (cs.target) { - size_t size; - - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + cs.target->size; - - cs.target->t = xtables_calloc(1, size); - cs.target->t->u.target_size = size; - strcpy(cs.target->t->u.user.name, jumpto); - cs.target->t->u.user.revision = cs.target->revision; - if (cs.target->init != NULL) - cs.target->init(cs.target->t); - 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!"); - } + command_jump(&cs); break; @@ -1757,7 +1759,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle if (strcmp(*table, "nat") == 0 && ((policy != NULL && strcmp(policy, "DROP") == 0) || - (jumpto != NULL && strcmp(jumpto, "DROP") == 0))) + (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0))) xtables_error(PARAMETER_PROBLEM, "\nThe \"nat\" table is not intended for filtering, " "the use of DROP is therefore inhibited.\n\n"); @@ -1848,10 +1850,10 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle chain); } - if (cs.target && iptc_is_chain(jumpto, *handle)) { + if (cs.target && iptc_is_chain(cs.jumpto, *handle)) { fprintf(stderr, "Warning: using chain %s, not extension\n", - jumpto); + cs.jumpto); if (cs.target->t) free(cs.target->t); @@ -1862,8 +1864,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle /* If they didn't specify a target, or it's a chain name, use standard. */ if (!cs.target - && (strlen(jumpto) == 0 - || iptc_is_chain(jumpto, *handle))) { + && (strlen(cs.jumpto) == 0 + || iptc_is_chain(cs.jumpto, *handle))) { size_t size; cs.target = xtables_find_target(IPT_STANDARD_TARGET, @@ -1873,8 +1875,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; - strcpy(cs.target->t->u.user.name, jumpto); - if (!iptc_is_chain(jumpto, *handle)) + strcpy(cs.target->t->u.user.name, cs.jumpto); + if (!iptc_is_chain(cs.jumpto, *handle)) cs.target->t->u.user.revision = cs.target->revision; if (cs.target->init != NULL) cs.target->init(cs.target->t); @@ -1888,9 +1890,10 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle #ifdef IPT_F_GOTO if (cs.fw.ip.flags & IPT_F_GOTO) xtables_error(PARAMETER_PROBLEM, - "goto '%s' is not a chain\n", jumpto); + "goto '%s' is not a chain\n", + cs.jumpto); #endif - xtables_find_target(jumpto, XTF_LOAD_MUST_SUCCEED); + xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED); } else { e = generate_entry(&cs.fw, cs.matches, cs.target->t); free(cs.target->t); diff --git a/xshared.h b/xshared.h index d0cb5162..a08e6d98 100644 --- a/xshared.h +++ b/xshared.h @@ -35,6 +35,7 @@ struct iptables_command_state { struct xtables_target *target; char *protocol; int proto_used; + const char *jumpto; char **argv; }; -- cgit v1.2.3 From 17e310b2610448605567644f667c79f41d76f51e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:42:47 +0100 Subject: src: move match option handling from do_command6 into its own functions Signed-off-by: Jan Engelhardt --- ip6tables.c | 48 ++++++++++++++++++++++++++---------------------- iptables.c | 59 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index eb28dc0a..5a550bfb 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1329,6 +1329,29 @@ static void command_jump(struct iptables_command_state *cs) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); } +static void command_match(struct iptables_command_state *cs) +{ + struct xtables_match *m; + size_t size; + + if (cs->invert) + xtables_error(PARAMETER_PROBLEM, + "unexpected ! flag before --match"); + + m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches); + size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); + if (m != m->next) + /* Merge options for non-cloned matches */ + opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, + m->extra_opts, &m->option_offset); +} + int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle) { struct iptables_command_state cs; @@ -1617,28 +1640,9 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand verbose++; break; - case 'm': { - size_t size; - - if (cs.invert) - xtables_error(PARAMETER_PROBLEM, - "unexpected ! flag before --match"); - - m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, - &cs.matches); - size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) - + m->size; - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); - if (m != m->next) - /* Merge options for non-cloned matches */ - opts = xtables_merge_options(ip6tables_globals.orig_opts, opts, m->extra_opts, &m->option_offset); - } - break; + case 'm': + command_match(&cs); + break; case 'n': set_option(&cs.options, OPT_NUMERIC, &cs.fw6.ipv6.invflags, diff --git a/iptables.c b/iptables.c index 354bc9cb..6f5616ba 100644 --- a/iptables.c +++ b/iptables.c @@ -1356,6 +1356,32 @@ static void command_jump(struct iptables_command_state *cs) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); } +static void command_match(struct iptables_command_state *cs) +{ + struct xtables_match *m; + size_t size; + + if (cs->invert) + xtables_error(PARAMETER_PROBLEM, + "unexpected ! flag before --match"); + + m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches); + size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; + m->m = xtables_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->m->u.user.revision = m->revision; + if (m->init != NULL) + m->init(m->m); + if (m != m->next) { + /* Merge options for non-cloned matches */ + opts = xtables_merge_options(iptables_globals.orig_opts, opts, + m->extra_opts, &m->option_offset); + if (opts == NULL) + xtables_error(OTHER_PROBLEM, "can't alloc memory!"); + } +} + int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle) { struct iptables_command_state cs; @@ -1642,36 +1668,9 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle verbose++; break; - case 'm': { - size_t size; - - if (cs.invert) - xtables_error(PARAMETER_PROBLEM, - "unexpected ! flag before --match"); - - m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, - &cs.matches); - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + m->size; - m->m = xtables_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); - if (m != m->next) { - /* Merge options for non-cloned matches */ - opts = xtables_merge_options( - iptables_globals.orig_opts, - opts, - m->extra_opts, - &m->option_offset); - if (opts == NULL) - xtables_error(OTHER_PROBLEM, - "can't alloc memory!"); - } - } - break; + case 'm': + command_match(&cs); + break; case 'n': set_option(&cs.options, OPT_NUMERIC, &cs.fw.ip.invflags, -- cgit v1.2.3 From 58b491f8cb5b4a0315037d0e1f61f8162a556e8a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Feb 2011 03:45:26 +0100 Subject: iptables: fix error message for unknown options -From: iptables v1.4.10: option "-q" requires an argument +To: iptables v1.4.10: unknown option "-q" Signed-off-by: Jan Engelhardt --- ip6tables.c | 17 +++++++---------- iptables.c | 17 +++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/ip6tables.c b/ip6tables.c index 5a550bfb..5561a7d5 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1290,15 +1290,12 @@ static void command_default(struct iptables_command_state *cs) return; } - if (cs->c == '?') { - if (optopt) - xtables_error(PARAMETER_PROBLEM, - "option \"%s\" requires an argument", - cs->argv[optind-1]); - else - xtables_error(PARAMETER_PROBLEM, - "unknown option \"%s\"", cs->argv[optind-1]); - } + if (cs->c == ':') + xtables_error(PARAMETER_PROBLEM, "option \"%s\" " + "requires an argument", cs->argv[optind-1]); + if (cs->c == '?') + xtables_error(PARAMETER_PROBLEM, "unknown option " + "\"%s\"", cs->argv[optind-1]); xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } @@ -1396,7 +1393,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand opts = xt_params->orig_opts; while ((cs.c = getopt_long(argc, argv, - "-A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:", + "-:A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:", opts, NULL)) != -1) { switch (cs.c) { /* diff --git a/iptables.c b/iptables.c index 6f5616ba..33fd8822 100644 --- a/iptables.c +++ b/iptables.c @@ -1316,15 +1316,12 @@ static void command_default(struct iptables_command_state *cs) return; } - if (cs->c == '?') { - if (optopt) - xtables_error(PARAMETER_PROBLEM, - "option \"%s\" requires an argument", - cs->argv[optind-1]); - else - xtables_error(PARAMETER_PROBLEM, - "unknown option \"%s\"", cs->argv[optind-1]); - } + if (cs->c == ':') + xtables_error(PARAMETER_PROBLEM, "option \"%s\" " + "requires an argument", cs->argv[optind-1]); + if (cs->c == '?') + xtables_error(PARAMETER_PROBLEM, "unknown option " + "\"%s\"", cs->argv[optind-1]); xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); } @@ -1426,7 +1423,7 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle opts = xt_params->orig_opts; while ((cs.c = getopt_long(argc, argv, - "-A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:", + "-:A:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:", opts, NULL)) != -1) { switch (cs.c) { /* -- cgit v1.2.3