]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xshared: Fix parsing of option arguments in same word
authorPhil Sutter <phil@nwl.cc>
Fri, 28 Apr 2023 12:41:08 +0000 (14:41 +0200)
committerPhil Sutter <phil@nwl.cc>
Fri, 28 Apr 2023 13:05:45 +0000 (15:05 +0200)
When merging commandline parsers, a decision between 'argv[optind - 1]'
and 'optarg' had to be made in some spots. While the implementation of
check_inverse() required the former, use of the latter allows for the
common syntax of '--opt=arg' or even '-oarg' as 'optarg' will point at
the suffix while 'argv[optind - 1]' will just point at the following
option.

Fix the mess by making check_inverse() update optarg pointer if needed
so calling code may refer to and always correct 'optarg'.

Fixes: 0af80a91b0a98 ("nft: Merge xtables-arp-standalone.c into xtables-standalone.c")
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1677
Signed-off-by: Phil Sutter <phil@nwl.cc>
extensions/libarpt_standard.t
extensions/libxt_standard.t
iptables/xshared.c

index e84a00b780488df06ee2143ec9c2420cf35ffe73..007fa2b8335e872341c53930d2210571cc84d54b 100644 (file)
@@ -12,3 +12,5 @@
 -i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK
 --source-mac Unicast;--src-mac 00:00:00:00:00:00/01:00:00:00:00:00;OK
 ! --src-mac Multicast;! --src-mac 01:00:00:00:00:00/01:00:00:00:00:00;OK
+--src-mac=01:02:03:04:05:06 --dst-mac=07:08:09:0A:0B:0C --h-length=6 --opcode=Request --h-type=Ethernet --proto-type=ipv4;--src-mac 01:02:03:04:05:06 --dst-mac 07:08:09:0a:0b:0c --opcode 1 --proto-type 0x800;OK
+--src-mac ! 01:02:03:04:05:06 --dst-mac ! 07:08:09:0A:0B:0C --h-length ! 6 --opcode ! Request --h-type ! Ethernet --proto-type ! ipv4;! --src-mac 01:02:03:04:05:06 ! --dst-mac 07:08:09:0a:0b:0c ! --h-length 6 ! --opcode 1 ! --h-type 1 ! --proto-type 0x800;OK
index 56d6da2e5884e1977ac6d85bb0c738d565caf5ec..6ed978e442b80fe4ec57beaef63fb236e2f7b6d6 100644 (file)
@@ -21,3 +21,6 @@
 -s 10.11.12.13/255.128.0.0;-s 10.0.0.0/9;OK
 -s 10.11.12.13/255.0.255.0;-s 10.0.12.0/255.0.255.0;OK
 -s 10.11.12.13/255.0.12.0;-s 10.0.12.0/255.0.12.0;OK
+:FORWARD
+--protocol=tcp --source=1.2.3.4 --destination=5.6.7.8/32 --in-interface=eth0 --out-interface=eth1 --jump=ACCEPT;-s 1.2.3.4/32 -d 5.6.7.8/32 -i eth0 -o eth1 -p tcp -j ACCEPT;OK
+-ptcp -s1.2.3.4 -d5.6.7.8/32 -ieth0 -oeth1 -jACCEPT;-s 1.2.3.4/32 -d 5.6.7.8/32 -i eth0 -o eth1 -p tcp -j ACCEPT;OK
index ac51fac5ce9ed1272e978f640c32c791e66c8564..17aed04e02b0905f0ad72aaaa62bf523e5ac88b6 100644 (file)
@@ -1318,7 +1318,7 @@ static void check_empty_interface(struct xtables_args *args, const char *arg)
 }
 
 static void check_inverse(struct xtables_args *args, const char option[],
-                         bool *invert, int *optidx, int argc)
+                         bool *invert, int argc, char **argv)
 {
        switch (args->family) {
        case NFPROTO_ARP:
@@ -1337,12 +1337,11 @@ static void check_inverse(struct xtables_args *args, const char option[],
                xtables_error(PARAMETER_PROBLEM,
                              "Multiple `!' flags not allowed");
        *invert = true;
-       if (optidx) {
-               *optidx = *optidx + 1;
-               if (argc && *optidx > argc)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "no argument following `!'");
-       }
+       optind++;
+       if (optind > argc)
+               xtables_error(PARAMETER_PROBLEM, "no argument following `!'");
+
+       optarg = argv[optind - 1];
 }
 
 static const char *optstring_lookup(int family)
@@ -1555,16 +1554,16 @@ void do_parse(int argc, char *argv[],
                         * Option selection
                         */
                case 'p':
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_PROTOCOL,
                                   &args->invflags, invert);
 
                        /* Canonicalize into lower case */
-                       for (cs->protocol = argv[optind - 1];
+                       for (cs->protocol = optarg;
                             *cs->protocol; cs->protocol++)
                                *cs->protocol = tolower(*cs->protocol);
 
-                       cs->protocol = argv[optind - 1];
+                       cs->protocol = optarg;
                        args->proto = xtables_parse_protocol(cs->protocol);
 
                        if (args->proto == 0 &&
@@ -1578,17 +1577,17 @@ void do_parse(int argc, char *argv[],
                        break;
 
                case 's':
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_SOURCE,
                                   &args->invflags, invert);
-                       args->shostnetworkmask = argv[optind - 1];
+                       args->shostnetworkmask = optarg;
                        break;
 
                case 'd':
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_DESTINATION,
                                   &args->invflags, invert);
-                       args->dhostnetworkmask = argv[optind - 1];
+                       args->dhostnetworkmask = optarg;
                        break;
 
 #ifdef IPT_F_GOTO
@@ -1601,71 +1600,71 @@ void do_parse(int argc, char *argv[],
 #endif
 
                case 2:/* src-mac */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_S_MAC, &args->invflags,
                                   invert);
-                       args->src_mac = argv[optind - 1];
+                       args->src_mac = optarg;
                        break;
 
                case 3:/* dst-mac */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_D_MAC, &args->invflags,
                                   invert);
-                       args->dst_mac = argv[optind - 1];
+                       args->dst_mac = optarg;
                        break;
 
                case 'l':/* hardware length */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
                                   invert);
-                       args->arp_hlen = argv[optind - 1];
+                       args->arp_hlen = optarg;
                        break;
 
                case 8: /* was never supported, not even in arptables-legacy */
                        xtables_error(PARAMETER_PROBLEM, "not supported");
                case 4:/* opcode */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_OPCODE, &args->invflags,
                                   invert);
-                       args->arp_opcode = argv[optind - 1];
+                       args->arp_opcode = optarg;
                        break;
 
                case 5:/* h-type */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_H_TYPE, &args->invflags,
                                   invert);
-                       args->arp_htype = argv[optind - 1];
+                       args->arp_htype = optarg;
                        break;
 
                case 6:/* proto-type */
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_P_TYPE, &args->invflags,
                                   invert);
-                       args->arp_ptype = argv[optind - 1];
+                       args->arp_ptype = optarg;
                        break;
 
                case 'j':
                        set_option(&cs->options, OPT_JUMP, &args->invflags,
                                   invert);
-                       command_jump(cs, argv[optind - 1]);
+                       command_jump(cs, optarg);
                        break;
 
                case 'i':
                        check_empty_interface(args, optarg);
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_VIANAMEIN,
                                   &args->invflags, invert);
-                       xtables_parse_interface(argv[optind - 1],
+                       xtables_parse_interface(optarg,
                                                args->iniface,
                                                args->iniface_mask);
                        break;
 
                case 'o':
                        check_empty_interface(args, optarg);
-                       check_inverse(args, optarg, &invert, &optind, argc);
+                       check_inverse(args, optarg, &invert, argc, argv);
                        set_option(&cs->options, OPT_VIANAMEOUT,
                                   &args->invflags, invert);
-                       xtables_parse_interface(argv[optind - 1],
+                       xtables_parse_interface(optarg,
                                                args->outiface,
                                                args->outiface_mask);
                        break;