summaryrefslogtreecommitdiffstats
path: root/iptables/xshared.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2023-04-28 14:41:08 +0200
committerPhil Sutter <phil@nwl.cc>2023-04-28 15:05:45 +0200
commit90a7a183a208b691810b8519cc57d3d9d3b7eb60 (patch)
tree4ba88802d9d4a1fa41f4022f4fd48ce52fb8f4b1 /iptables/xshared.c
parent79f93b0943fa0e46ba29bb476362634509eb594e (diff)
xshared: Fix parsing of option arguments in same word
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>
Diffstat (limited to 'iptables/xshared.c')
-rw-r--r--iptables/xshared.c61
1 files changed, 30 insertions, 31 deletions
diff --git a/iptables/xshared.c b/iptables/xshared.c
index ac51fac5..17aed04e 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -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;