Accept this for arptables only for now, iptables dropped support for it long time ago. Signed-off-by: Phil Sutter <phil@xxxxxx> --- iptables/xtables.c | 63 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/iptables/xtables.c b/iptables/xtables.c index c77d76c89a543..dba497b85064a 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -262,6 +262,31 @@ list_rules(struct nft_handle *h, const char *chain, const char *table, return nft_cmd_rule_list_save(h, chain, table, rulenum, counters); } +static void check_inverse(struct nft_handle *h, const char option[], + bool *invert, int *optidx, int argc) +{ + switch (h->family) { + case NFPROTO_ARP: + break; + default: + return; + } + + if (!option || strcmp(option, "!")) + return false; + + if (*invert) + 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 `!'"); + } +} + void do_parse(struct nft_handle *h, int argc, char *argv[], struct nft_xt_cmd_parse *p, struct iptables_command_state *cs, struct xtables_args *args) @@ -447,14 +472,16 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], * Option selection */ case 'p': + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_PROTOCOL, &args->invflags, invert); /* Canonicalize into lower case */ - for (cs->protocol = optarg; *cs->protocol; cs->protocol++) + for (cs->protocol = argv[optind - 1]; + *cs->protocol; cs->protocol++) *cs->protocol = tolower(*cs->protocol); - cs->protocol = optarg; + cs->protocol = argv[optind - 1]; args->proto = xtables_parse_protocol(cs->protocol); if (args->proto == 0 && @@ -468,15 +495,17 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], break; case 's': + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_SOURCE, &args->invflags, invert); - args->shostnetworkmask = optarg; + args->shostnetworkmask = argv[optind - 1]; break; case 'd': + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_DESTINATION, &args->invflags, invert); - args->dhostnetworkmask = optarg; + args->dhostnetworkmask = argv[optind - 1]; break; #ifdef IPT_F_GOTO @@ -489,47 +518,53 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], #endif case 2:/* src-mac */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_S_MAC, &args->invflags, invert); - args->src_mac = optarg; + args->src_mac = argv[optind - 1]; break; case 3:/* dst-mac */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_D_MAC, &args->invflags, invert); - args->dst_mac = optarg; + args->dst_mac = argv[optind - 1]; break; case 'l':/* hardware length */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_H_LENGTH, &args->invflags, invert); - args->arp_hlen = optarg; + args->arp_hlen = argv[optind - 1]; break; case 8: /* was never supported, not even in arptables-legacy */ xtables_error(PARAMETER_PROBLEM, "not supported"); case 4:/* opcode */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_OPCODE, &args->invflags, invert); - args->arp_opcode = optarg; + args->arp_opcode = argv[optind - 1]; break; case 5:/* h-type */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_H_TYPE, &args->invflags, invert); - args->arp_htype = optarg; + args->arp_htype = argv[optind - 1]; break; case 6:/* proto-type */ + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_P_TYPE, &args->invflags, invert); - args->arp_ptype = optarg; + args->arp_ptype = argv[optind - 1]; break; case 'j': set_option(&cs->options, OPT_JUMP, &args->invflags, invert); - command_jump(cs, optarg); + command_jump(cs, argv[optind - 1]); break; case 'i': @@ -537,9 +572,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_VIANAMEIN, &args->invflags, invert); - xtables_parse_interface(optarg, + xtables_parse_interface(argv[optind - 1], args->iniface, args->iniface_mask); break; @@ -549,9 +585,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); + check_inverse(h, optarg, &invert, &optind, argc); set_option(&cs->options, OPT_VIANAMEOUT, &args->invflags, invert); - xtables_parse_interface(optarg, + xtables_parse_interface(argv[optind - 1], args->outiface, args->outiface_mask); break; -- 2.33.0