]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
ip6tables: Use the shared do_parse, too
authorPhil Sutter <phil@nwl.cc>
Fri, 26 Nov 2021 22:56:57 +0000 (23:56 +0100)
committerPhil Sutter <phil@nwl.cc>
Wed, 12 Jan 2022 13:10:25 +0000 (14:10 +0100)
Same change as with iptables, merely have to set IP6T_F_PROTO flag in
ipv6_proto_parse().

Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/ip6tables.c
iptables/xshared.c

index b4604f83cf8a4001b0e3e91379c6833ae20ba3bc..560b6ed0d74b67a28b1d11674cfb60748d4acf20 100644 (file)
@@ -90,21 +90,12 @@ static struct option original_opts[] = {
 struct xtables_globals ip6tables_globals = {
        .option_offset = 0,
        .program_version = PACKAGE_VERSION " (legacy)",
+       .optstring = OPTSTRING_COMMON "R:S::W::" "46bg:h::m:nvw::x",
        .orig_opts = original_opts,
        .compat_rev = xtables_compatible_revision,
+       .print_help = xtables_printhelp,
 };
 
-#define opts ip6tables_globals.opts
-#define prog_name ip6tables_globals.program_name
-#define prog_vers ip6tables_globals.program_version
-
-static void
-exit_printhelp(const struct xtables_rule_match *matches)
-{
-       xtables_printhelp(matches);
-       exit(0);
-}
-
 /*
  *     All functions starting with "parse" should succeed, otherwise
  *     the program fails.
@@ -114,15 +105,6 @@ exit_printhelp(const struct xtables_rule_match *matches)
  *     return global static data.
 */
 
-/* These are invalid numbers as upper layer protocol */
-static int is_exthdr(uint16_t proto)
-{
-       return (proto == IPPROTO_ROUTING ||
-               proto == IPPROTO_FRAGMENT ||
-               proto == IPPROTO_AH ||
-               proto == IPPROTO_DSTOPTS);
-}
-
 static int
 print_match(const struct xt_entry_match *m,
            const struct ip6t_ip6 *ip,
@@ -714,10 +696,24 @@ generate_entry(const struct ip6t_entry *fw,
 int do_command6(int argc, char *argv[], char **table,
                struct xtc_handle **handle, bool restore)
 {
+       struct xt_cmd_parse_ops cmd_parse_ops = {
+               .proto_parse    = ipv6_proto_parse,
+               .post_parse     = ipv6_post_parse,
+       };
+       struct xt_cmd_parse p = {
+               .table          = *table,
+               .restore        = restore,
+               .line           = line,
+               .ops            = &cmd_parse_ops,
+       };
        struct iptables_command_state cs = {
                .jumpto = "",
                .argv   = argv,
        };
+       struct xtables_args args = {
+               .family = AF_INET6,
+               .wait_interval.tv_sec = 1,
+       };
        struct ip6t_entry *e = NULL;
        unsigned int nsaddrs = 0, ndaddrs = 0;
        struct in6_addr *saddrs = NULL, *daddrs = NULL;
@@ -728,437 +724,28 @@ int do_command6(int argc, char *argv[], char **table,
        struct timeval wait_interval = {
                .tv_sec = 1,
        };
-       bool wait_interval_set = false;
        const char *chain = NULL;
-       const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
        const char *policy = NULL, *newname = NULL;
        unsigned int rulenum = 0, command = 0;
-       const char *pcnt = NULL, *bcnt = NULL;
        int ret = 1;
-       struct xtables_match *m;
-       struct xtables_rule_match *matchp;
-       struct xtables_target *t;
-       unsigned long long cnt;
-       bool table_set = false;
-       uint16_t invflags = 0;
-       bool invert = false;
-
-       /* re-set optind to 0 in case do_command6 gets called
-        * a second time */
-       optind = 0;
-
-       /* clear mflags in case do_command6 gets called a second time
-        * (we clear the global list of all matches for security)*/
-       for (m = xtables_matches; m; m = m->next)
-               m->mflags = 0;
-
-       for (t = xtables_targets; t; t = t->next) {
-               t->tflags = 0;
-               t->used = 0;
-       }
-
-       /* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-       opterr = 0;
-
-       opts = xt_params->orig_opts;
-       while ((cs.c = getopt_long(argc, argv,
-          "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::W::nt:m:xc:g:46",
-                                          opts, NULL)) != -1) {
-               switch (cs.c) {
-                       /*
-                        * Command selection
-                        */
-               case 'A':
-                       add_command(&command, CMD_APPEND, CMD_NONE, invert);
-                       chain = optarg;
-                       break;
-
-               case 'C':
-                       add_command(&command, CMD_CHECK, CMD_NONE, invert);
-                       chain = optarg;
-                       break;
-
-               case 'D':
-                       add_command(&command, CMD_DELETE, CMD_NONE, invert);
-                       chain = optarg;
-                       if (xs_has_arg(argc, argv)) {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_DELETE_NUM;
-                       }
-                       break;
-
-               case 'R':
-                       add_command(&command, CMD_REPLACE, CMD_NONE, invert);
-                       chain = optarg;
-                       if (xs_has_arg(argc, argv))
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "-%c requires a rule number",
-                                          cmd2char(CMD_REPLACE));
-                       break;
-
-               case 'I':
-                       add_command(&command, CMD_INSERT, CMD_NONE, invert);
-                       chain = optarg;
-                       if (xs_has_arg(argc, argv))
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else rulenum = 1;
-                       break;
-
-               case 'L':
-                       add_command(&command, CMD_LIST,
-                                   CMD_ZERO | CMD_ZERO_NUM, invert);
-                       if (optarg) chain = optarg;
-                       else if (xs_has_arg(argc, argv))
-                               chain = argv[optind++];
-                       if (xs_has_arg(argc, argv))
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       break;
-
-               case 'S':
-                       add_command(&command, CMD_LIST_RULES,
-                                   CMD_ZERO | CMD_ZERO_NUM, invert);
-                       if (optarg) chain = optarg;
-                       else if (xs_has_arg(argc, argv))
-                               chain = argv[optind++];
-                       if (xs_has_arg(argc, argv))
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       break;
-
-               case 'F':
-                       add_command(&command, CMD_FLUSH, CMD_NONE, invert);
-                       if (optarg) chain = optarg;
-                       else if (xs_has_arg(argc, argv))
-                               chain = argv[optind++];
-                       break;
-
-               case 'Z':
-                       add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (xs_has_arg(argc, argv))
-                               chain = argv[optind++];
-                       if (xs_has_arg(argc, argv)) {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_ZERO_NUM;
-                       }
-                       break;
-
-               case 'N':
-                       parse_chain(optarg);
-                       add_command(&command, CMD_NEW_CHAIN, CMD_NONE, invert);
-                       chain = optarg;
-                       break;
-
-               case 'X':
-                       add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (xs_has_arg(argc, argv))
-                               chain = argv[optind++];
-                       break;
-
-               case 'E':
-                       add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (xs_has_arg(argc, argv))
-                               newname = argv[optind++];
-                       else
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
-                                          "new-chain-name",
-                                           cmd2char(CMD_RENAME_CHAIN));
-                       break;
-
-               case 'P':
-                       add_command(&command, CMD_SET_POLICY, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (xs_has_arg(argc, argv))
-                               policy = argv[optind++];
-                       else
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "-%c requires a chain and a policy",
-                                          cmd2char(CMD_SET_POLICY));
-                       break;
-
-               case 'h':
-                       if (!optarg)
-                               optarg = argv[optind];
-
-                       /* ip6tables -p icmp -h */
-                       if (!cs.matches && cs.protocol)
-                               xtables_find_match(cs.protocol, XTF_TRY_LOAD,
-                                       &cs.matches);
-
-                       exit_printhelp(cs.matches);
-
-                       /*
-                        * Option selection
-                        */
-               case 'p':
-                       set_option(&cs.options, OPT_PROTOCOL, &invflags,
-                                  invert);
-
-                       /* Canonicalize into lower case */
-                       for (cs.protocol = optarg; *cs.protocol; cs.protocol++)
-                               *cs.protocol = tolower(*cs.protocol);
-
-                       cs.protocol = optarg;
-                       cs.fw6.ipv6.proto = xtables_parse_protocol(cs.protocol);
-                       cs.fw6.ipv6.flags |= IP6T_F_PROTO;
-
-                       if (cs.fw6.ipv6.proto == 0 && (invflags & XT_INV_PROTO))
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "rule would never match protocol");
-
-                       if (is_exthdr(cs.fw6.ipv6.proto)
-                           && (invflags & XT_INV_PROTO) == 0)
-                               fprintf(stderr,
-                                       "Warning: never matched protocol: %s. "
-                                       "use extension match instead.\n",
-                                       cs.protocol);
-                       break;
-
-               case 's':
-                       set_option(&cs.options, OPT_SOURCE, &invflags, invert);
-                       shostnetworkmask = optarg;
-                       break;
-
-               case 'd':
-                       set_option(&cs.options, OPT_DESTINATION, &invflags,
-                                  invert);
-                       dhostnetworkmask = optarg;
-                       break;
-
-#ifdef IP6T_F_GOTO
-               case 'g':
-                       set_option(&cs.options, OPT_JUMP, &invflags, invert);
-                       cs.fw6.ipv6.flags |= IP6T_F_GOTO;
-                       cs.jumpto = xt_parse_target(optarg);
-                       break;
-#endif
-
-               case 'j':
-                       set_option(&cs.options, OPT_JUMP, &invflags, invert);
-                       command_jump(&cs, optarg);
-                       break;
-
 
-               case 'i':
-                       if (*optarg == '\0')
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "Empty interface is likely to be "
-                                       "undesired");
-                       set_option(&cs.options, OPT_VIANAMEIN, &invflags,
-                                  invert);
-                       xtables_parse_interface(optarg,
-                                       cs.fw6.ipv6.iniface,
-                                       cs.fw6.ipv6.iniface_mask);
-                       break;
-
-               case 'o':
-                       if (*optarg == '\0')
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "Empty interface is likely to be "
-                                       "undesired");
-                       set_option(&cs.options, OPT_VIANAMEOUT, &invflags,
-                                  invert);
-                       xtables_parse_interface(optarg,
-                                       cs.fw6.ipv6.outiface,
-                                       cs.fw6.ipv6.outiface_mask);
-                       break;
-
-               case 'v':
-                       if (!verbose)
-                               set_option(&cs.options, OPT_VERBOSE,
-                                          &invflags, invert);
-                       verbose++;
-                       break;
-
-               case 'w':
-                       if (restore) {
-                               xtables_error(PARAMETER_PROBLEM,
-                                             "You cannot use `-w' from "
-                                             "ip6tables-restore");
-                       }
-                       wait = parse_wait_time(argc, argv);
-                       break;
-
-               case 'W':
-                       if (restore) {
-                               xtables_error(PARAMETER_PROBLEM,
-                                             "You cannot use `-W' from "
-                                             "ip6tables-restore");
-                       }
-                       parse_wait_interval(argc, argv, &wait_interval);
-                       wait_interval_set = true;
-                       break;
-
-               case 'm':
-                       command_match(&cs, invert);
-                       break;
-
-               case 'n':
-                       set_option(&cs.options, OPT_NUMERIC, &invflags, invert);
-                       break;
-
-               case 't':
-                       if (invert)
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --table");
-                       if (restore && table_set)
-                               xtables_error(PARAMETER_PROBLEM,
-                                             "The -t option cannot be used in %s.\n",
-                                             xt_params->program_name);
-                       *table = optarg;
-                       table_set = true;
-                       break;
-
-               case 'x':
-                       set_option(&cs.options, OPT_EXPANDED, &invflags,
-                                  invert);
-                       break;
-
-               case 'V':
-                       if (invert)
-                               printf("Not %s ;-)\n", prog_vers);
-                       else
-                               printf("%s v%s\n",
-                                      prog_name, prog_vers);
-                       exit(0);
-
-               case '0':
-                       set_option(&cs.options, OPT_LINENUMBERS, &invflags,
-                                  invert);
-                       break;
-
-               case 'M':
-                       xtables_modprobe_program = optarg;
-                       break;
-
-               case 'c':
-
-                       set_option(&cs.options, OPT_COUNTERS, &invflags,
-                                  invert);
-                       pcnt = optarg;
-                       bcnt = strchr(pcnt + 1, ',');
-                       if (bcnt)
-                           bcnt++;
-                       if (!bcnt && xs_has_arg(argc, argv))
-                               bcnt = argv[optind++];
-                       if (!bcnt)
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "-%c requires packet and byte counter",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(pcnt, "%llu", &cnt) != 1)
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "-%c packet counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       cs.fw6.counters.pcnt = cnt;
-
-                       if (sscanf(bcnt, "%llu", &cnt) != 1)
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "-%c byte counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       cs.fw6.counters.bcnt = cnt;
-                       break;
-
-               case '4':
-                       /* This is not the IPv4 iptables */
-                       if (line != -1)
-                               return 1; /* success: line ignored */
-                       fprintf(stderr, "This is the IPv6 version of ip6tables.\n");
-                       exit_tryhelp(2, line);
-
-               case '6':
-                       /* This is indeed the IPv6 ip6tables */
-                       break;
-
-               case 1: /* non option */
-                       if (optarg[0] == '!' && optarg[1] == '\0') {
-                               if (invert)
-                                       xtables_error(PARAMETER_PROBLEM,
-                                                  "multiple consecutive ! not"
-                                                  " allowed");
-                               invert = true;
-                               optarg[0] = '\0';
-                               continue;
-                       }
-                       fprintf(stderr, "Bad argument `%s'\n", optarg);
-                       exit_tryhelp(2, line);
-
-               default:
-                       if (command_default(&cs, &ip6tables_globals, invert))
-                               /*
-                                * If new options were loaded, we must retry
-                                * getopt immediately and not allow
-                                * invert=false to be executed.
-                                */
-                               continue;
-                       break;
-               }
-               invert = false;
-       }
-
-       if (!wait && wait_interval_set)
-               xtables_error(PARAMETER_PROBLEM,
-                             "--wait-interval only makes sense with --wait\n");
-
-       if (strcmp(*table, "nat") == 0 &&
-           ((policy != NULL && strcmp(policy, "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");
-
-       for (matchp = cs.matches; matchp; matchp = matchp->next)
-               xtables_option_mfcall(matchp->match);
-       if (cs.target != NULL)
-               xtables_option_tfcall(cs.target);
-
-       /* Fix me: must put inverse options checking here --MN */
-
-       if (optind < argc)
-               xtables_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (!command)
-               xtables_error(PARAMETER_PROBLEM, "no command specified");
-       if (invert)
-               xtables_error(PARAMETER_PROBLEM,
-                          "nothing appropriate following !");
-
-       cs.fw6.ipv6.invflags = invflags;
-
-       if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-               if (!(cs.options & OPT_DESTINATION))
-                       dhostnetworkmask = "::0/0";
-               if (!(cs.options & OPT_SOURCE))
-                       shostnetworkmask = "::0/0";
-       }
-
-       if (shostnetworkmask)
-               xtables_ip6parse_multiple(shostnetworkmask, &saddrs,
-                                         &smasks, &nsaddrs);
-
-       if (dhostnetworkmask)
-               xtables_ip6parse_multiple(dhostnetworkmask, &daddrs,
-                                         &dmasks, &ndaddrs);
-
-       if ((nsaddrs > 1 || ndaddrs > 1) &&
-           (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
-               xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-                          " source or destination IP addresses");
-
-       if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-               xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
-                          "specify a unique address");
-
-       generic_opt_check(command, cs.options);
+       do_parse(argc, argv, &p, &cs, &args);
+
+       command         = p.command;
+       chain           = p.chain;
+       *table          = p.table;
+       rulenum         = p.rulenum;
+       policy          = p.policy;
+       newname         = p.newname;
+       verbose         = p.verbose;
+       wait            = args.wait;
+       wait_interval   = args.wait_interval;
+       nsaddrs         = args.s.naddrs;
+       ndaddrs         = args.d.naddrs;
+       saddrs          = args.s.addr.v6;
+       daddrs          = args.d.addr.v6;
+       smasks          = args.s.mask.v6;
+       dmasks          = args.d.mask.v6;
 
        /* Attempt to acquire the xtables lock */
        if (!restore)
@@ -1182,26 +769,6 @@ int do_command6(int argc, char *argv[], char **table,
            || command == CMD_CHECK
            || command == CMD_INSERT
            || command == CMD_REPLACE) {
-               if (strcmp(chain, "PREROUTING") == 0
-                   || strcmp(chain, "INPUT") == 0) {
-                       /* -o not valid with incoming packets. */
-                       if (cs.options & OPT_VIANAMEOUT)
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEOUT),
-                                          chain);
-               }
-
-               if (strcmp(chain, "POSTROUTING") == 0
-                   || strcmp(chain, "OUTPUT") == 0) {
-                       /* -i not valid with outgoing packets */
-                       if (cs.options & OPT_VIANAMEIN)
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEIN),
-                                          chain);
-               }
-
                if (cs.target && ip6tc_is_chain(cs.jumpto, *handle)) {
                        fprintf(stderr,
                                "Warning: using chain %s, not extension\n",
@@ -1337,6 +904,9 @@ int do_command6(int argc, char *argv[], char **table,
        case CMD_SET_POLICY:
                ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw6.counters : NULL, *handle);
                break;
+       case CMD_NONE:
+               /* do_parse ignored the line (eg: -4 with ip6tables-restore) */
+               break;
        default:
                /* We should never reach this... */
                exit_tryhelp(2, line);
index 8d94fcd592453d4ef607404a55b63d8d4079b063..c5a93290be427943563b36c7083385ae0471de3c 100644 (file)
@@ -1836,6 +1836,10 @@ void ipv6_proto_parse(struct iptables_command_state *cs,
        cs->fw6.ipv6.proto = args->proto;
        cs->fw6.ipv6.invflags = args->invflags;
 
+       /* this is needed for ip6tables-legacy only */
+       args->flags |= IP6T_F_PROTO;
+       cs->fw6.ipv6.flags |= IP6T_F_PROTO;
+
        if (is_exthdr(cs->fw6.ipv6.proto)
            && (cs->fw6.ipv6.invflags & XT_INV_PROTO) == 0)
                fprintf(stderr,