]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Proper fix for "unknown argument" error message
authorPhil Sutter <phil@nwl.cc>
Wed, 25 Jan 2023 00:51:43 +0000 (01:51 +0100)
committerPhil Sutter <phil@nwl.cc>
Tue, 31 Jan 2023 15:29:26 +0000 (16:29 +0100)
While commit 1b8210f848631 kind of fixed the corner-case of invalid
short-options packed with others, it broke error reporting for
long-options. Revert it and deploy a proper solution:

When passing an invalid short-option, e.g. 'iptables -vaL', getopt_long
sets the variable 'optopt' to the invalid character's value. Use it for
reporting instead of optind if set.

To distinguish between invalid options and missing option arguments,
ebtables-translate optstring needs adjustment.

Fixes: 1b8210f848631 ("ebtables: Fix error message for invalid parameters")
Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/tests/shell/testcases/iptables/0009-unknown-arg_0 [new file with mode: 0755]
iptables/xshared.c
iptables/xtables-eb-translate.c
iptables/xtables-eb.c

diff --git a/iptables/tests/shell/testcases/iptables/0009-unknown-arg_0 b/iptables/tests/shell/testcases/iptables/0009-unknown-arg_0
new file mode 100755 (executable)
index 0000000..ac6e743
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+rc=0
+
+check() {
+       local cmd="$1"
+       local msg="$2"
+
+       $XT_MULTI $cmd 2>&1 | grep -q "$msg" || {
+               echo "cmd: $XT_MULTI $1"
+               echo "exp: $msg"
+               echo "res: $($XT_MULTI $cmd 2>&1)"
+               rc=1
+       }
+}
+
+cmds="iptables ip6tables"
+[[ $XT_MULTI == *xtables-nft-multi ]] && {
+       cmds+=" ebtables"
+       cmds+=" iptables-translate"
+       cmds+=" ip6tables-translate"
+       cmds+=" ebtables-translate"
+}
+
+for cmd in $cmds; do
+       check "${cmd} --foo" 'unknown option "--foo"'
+       check "${cmd} -A" 'option "-A" requires an argument'
+       check "${cmd} -aL" 'unknown option "-a"'
+done
+
+exit $rc
index f93529b11a3190ba02cc4ccad89dad2951d1c494..ac51fac5ce9ed1272e978f640c32c791e66c8564 100644 (file)
@@ -192,9 +192,12 @@ static int command_default(struct iptables_command_state *cs,
        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]);
+       if (cs->c == '?') {
+               char optoptstr[3] = {'-', optopt, '\0'};
+
+               xtables_error(PARAMETER_PROBLEM, "unknown option \"%s\"",
+                             optopt ? optoptstr : cs->argv[optind - 1]);
+       }
        xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
 }
 
index 13b6b864a5f243f4a3dad6db9456081077097d30..0c35272051752e714eb4acfcac103d05b17d4147 100644 (file)
@@ -201,7 +201,7 @@ static int do_commandeb_xlate(struct nft_handle *h, int argc, char *argv[], char
        printf("nft ");
        /* Getopt saves the day */
        while ((c = getopt_long(argc, argv,
-          "-A:D:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", opts, NULL)) != -1) {
+          "-:A:D:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", opts, NULL)) != -1) {
                cs.c = c;
                switch (c) {
                case 'A': /* Add a rule */
@@ -491,11 +491,7 @@ print_zero:
                        continue;
                default:
                        ebt_check_inverse2(optarg, argc, argv);
-
-                       if (ebt_command_default(&cs))
-                               xtables_error(PARAMETER_PROBLEM,
-                                             "Unknown argument: '%s'",
-                                             argv[optind - 1]);
+                       ebt_command_default(&cs);
 
                        if (command != 'A' && command != 'I' &&
                            command != 'D')
index 7214a767ffe964290c946b580923b110020a5b3d..412b5cccdc46a43dd76940b06d283252f7a8166c 100644 (file)
@@ -640,7 +640,16 @@ int ebt_command_default(struct iptables_command_state *cs)
                        return 0;
                }
        }
-       return 1;
+       if (cs->c == ':')
+               xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
+                             "requires an argument", cs->argv[optind - 1]);
+       if (cs->c == '?') {
+               char optoptstr[3] = {'-', optopt, '\0'};
+
+               xtables_error(PARAMETER_PROBLEM, "unknown option \"%s\"",
+                             optopt ? optoptstr : cs->argv[optind - 1]);
+       }
+       xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
 }
 
 int nft_init_eb(struct nft_handle *h, const char *pname)
@@ -1084,11 +1093,7 @@ print_zero:
                        continue;
                default:
                        ebt_check_inverse2(optarg, argc, argv);
-
-                       if (ebt_command_default(&cs))
-                               xtables_error(PARAMETER_PROBLEM,
-                                             "Unknown argument: '%s'",
-                                             argv[optind]);
+                       ebt_command_default(&cs);
 
                        if (command != 'A' && command != 'I' &&
                            command != 'D' && command != 'C' && command != 14)