--string-icase is registered as a no_argument option, so getopt_long always sets optarg to NULL when it is parsed. The ebt_check_inverse2() macro contains a mandatory-argument guard: if (!optarg) { __ebt_print_error("Option without (mandatory) argument"); return -1; } so every use of --string-icase aborts parsing with the misleading error "Option without (mandatory) argument." and XT_STRING_FLAG_IGNORECASE can never be set. The option has been broken since it was added in commit b1cdae8 ("extensions: Add string filter to ebtables"). Reproducer (no privileges required): $ ebtables-legacy --string-icase Option without (mandatory) argument. Use ebt_check_inverse() instead: it tolerates a NULL optarg and returns the current ebt_invert state, which the main option loop resets to 0 after every option, so the flag is set as intended and the "Unexpected '!'" diagnostic is kept. This fix was originally carried in the Kylin Linux SRPM since 2022; the commit message has been rewritten to describe the actual failure mode observed on current master. Signed-off-by: YuPeng --- v2: Use ebt_check_inverse() instead of removing the check entirely, as suggested by Florian Westphal. No other changes. extensions/ebt_string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ebt_string.c b/extensions/ebt_string.c index 97fbe19..cbbe103 100644 --- a/extensions/ebt_string.c +++ b/extensions/ebt_string.c @@ -174,7 +174,7 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, break; case STRING_ICASE: ebt_check_option2(flags, OPT_STRING_ICASE); - if (ebt_check_inverse2(optarg)) + if (ebt_check_inverse(optarg)) ebt_print_error2("Unexpected `!' after --string-icase"); info->u.v1.flags |= XT_STRING_FLAG_IGNORECASE; break; -- 2.39.5