]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xshared: Support for ebtables' --change-counters command
authorPhil Sutter <phil@nwl.cc>
Fri, 24 Nov 2023 17:13:00 +0000 (18:13 +0100)
committerPhil Sutter <phil@nwl.cc>
Tue, 5 Dec 2023 15:35:37 +0000 (16:35 +0100)
This is tricky because the short-option clashes with the --check
command. OTOH, ebtables supports --check as well (though without
short-option), so making do_parse() detect ebtables based on struct
xtables_args::family is probably still the least messy option.

Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft-cmd.h
iptables/xshared.c
iptables/xshared.h

index 8163b82c3511fc3b3d8fb6cd06ae36fee3be377f..00ecc80249f0d05329fb24ca5ae0b5acc4bdc014 100644 (file)
@@ -7,13 +7,6 @@
 
 struct nftnl_rule;
 
-enum {
-       CTR_OP_INC_PKTS = 1 << 0,
-       CTR_OP_DEC_PKTS = 1 << 1,
-       CTR_OP_INC_BYTES = 1 << 2,
-       CTR_OP_DEC_BYTES = 1 << 3,
-};
-
 struct nft_cmd {
        struct list_head                head;
        int                             command;
index 62ae4141325ed02bc62621b2aa766e6c4b047d3e..50f23757d4aff3ebc31881cbb2ec32da850da85b 100644 (file)
@@ -937,7 +937,7 @@ static void parse_rule_range(struct xt_cmd_parse *p, const char *argv)
 
 /* list the commands an option is allowed with */
 #define CMD_IDRAC      CMD_INSERT | CMD_DELETE | CMD_REPLACE | \
-                       CMD_APPEND | CMD_CHECK
+                       CMD_APPEND | CMD_CHECK | CMD_CHANGE_COUNTERS
 static const unsigned int options_v_commands[NUMBER_OF_OPT] = {
 /*OPT_NUMERIC*/                CMD_LIST,
 /*OPT_SOURCE*/         CMD_IDRAC,
@@ -1392,10 +1392,58 @@ static void parse_interface(const char *arg, char *iface)
        strcpy(iface, arg);
 }
 
+static bool
+parse_signed_counter(char *argv, unsigned long long *val, uint8_t *ctr_op,
+                    uint8_t flag_inc, uint8_t flag_dec)
+{
+       char *endptr, *p = argv;
+
+       switch (*p) {
+       case '+':
+               *ctr_op |= flag_inc;
+               p++;
+               break;
+       case '-':
+               *ctr_op |= flag_dec;
+               p++;
+               break;
+       }
+       *val = strtoull(p, &endptr, 10);
+       return *endptr == '\0';
+}
+
+static void parse_change_counters_rule(int argc, char **argv,
+                                      struct xt_cmd_parse *p,
+                                      struct xtables_args *args)
+{
+       if (optind + 1 >= argc ||
+           (argv[optind][0] == '-' && !isdigit(argv[optind][1])) ||
+           (argv[optind + 1][0] == '-' && !isdigit(argv[optind + 1][1])))
+               xtables_error(PARAMETER_PROBLEM,
+                             "The command -C needs at least 2 arguments");
+       if (optind + 2 < argc &&
+           (argv[optind + 2][0] != '-' || isdigit(argv[optind + 2][1]))) {
+               if (optind + 3 != argc)
+                       xtables_error(PARAMETER_PROBLEM,
+                                     "No extra options allowed with -C start_nr[:end_nr] pcnt bcnt");
+               parse_rule_range(p, argv[optind++]);
+       }
+
+       if (!parse_signed_counter(argv[optind++], &args->pcnt_cnt,
+                                 &args->counter_op,
+                                 CTR_OP_INC_PKTS, CTR_OP_DEC_PKTS) ||
+           !parse_signed_counter(argv[optind++], &args->bcnt_cnt,
+                                 &args->counter_op,
+                                 CTR_OP_INC_BYTES, CTR_OP_DEC_BYTES))
+               xtables_error(PARAMETER_PROBLEM,
+                             "Packet counter '%s' invalid", argv[optind - 1]);
+}
+
 void do_parse(int argc, char *argv[],
              struct xt_cmd_parse *p, struct iptables_command_state *cs,
              struct xtables_args *args)
 {
+       bool family_is_bridge = args->family == NFPROTO_BRIDGE;
        struct xtables_match *m;
        struct xtables_rule_match *matchp;
        bool wait_interval_set = false;
@@ -1435,6 +1483,13 @@ void do_parse(int argc, char *argv[],
                        break;
 
                case 'C':
+                       if (family_is_bridge) {
+                               add_command(&p->command, CMD_CHANGE_COUNTERS,
+                                           CMD_NONE, invert);
+                               p->chain = optarg;
+                               parse_change_counters_rule(argc, argv, p, args);
+                               break;
+                       }
                        add_command(&p->command, CMD_CHECK, CMD_NONE, invert);
                        p->chain = optarg;
                        break;
index 2fd15c725faafe09cb8f53bf538817c08c5c7a29..68acfb4b406fba2023a2b29b73f584d608490705 100644 (file)
@@ -69,8 +69,9 @@ enum {
        CMD_LIST_RULES          = 1 << 12,
        CMD_ZERO_NUM            = 1 << 13,
        CMD_CHECK               = 1 << 14,
+       CMD_CHANGE_COUNTERS     = 1 << 15, /* ebtables only */
 };
-#define NUMBER_OF_CMD          16
+#define NUMBER_OF_CMD          17
 
 struct xtables_globals;
 struct xtables_rule_match;
@@ -247,6 +248,13 @@ struct addr_mask {
        } mask;
 };
 
+enum {
+       CTR_OP_INC_PKTS = 1 << 0,
+       CTR_OP_DEC_PKTS = 1 << 1,
+       CTR_OP_INC_BYTES = 1 << 2,
+       CTR_OP_DEC_BYTES = 1 << 3,
+};
+
 struct xtables_args {
        int             family;
        uint8_t         flags;
@@ -261,6 +269,7 @@ struct xtables_args {
        const char      *arp_hlen, *arp_opcode;
        const char      *arp_htype, *arp_ptype;
        unsigned long long pcnt_cnt, bcnt_cnt;
+       uint8_t         counter_op;
        int             wait;
 };