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 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 165 insertions(+), 158 deletions(-) (limited to 'ip6tables.c') 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); -- 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 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 110 insertions(+), 99 deletions(-) (limited to 'ip6tables.c') 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; } -- 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 ++++++++++++++++++++++++++----------------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) (limited to 'ip6tables.c') 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... */ -- 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 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'ip6tables.c') 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) { -- 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 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'ip6tables.c') 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[] = { -- 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 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'ip6tables.c') 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; -- 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 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 56 deletions(-) (limited to 'ip6tables.c') 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) -- 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 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 34 deletions(-) (limited to 'ip6tables.c') 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); -- 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 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'ip6tables.c') 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, -- 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 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'ip6tables.c') 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) { /* -- cgit v1.2.3