summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2023-11-24 18:13:00 +0100
committerPhil Sutter <phil@nwl.cc>2023-12-05 16:35:37 +0100
commit9c777205d6464b8af64d7ab2cdfbf2c85e22b3ed (patch)
tree885d95832283b3342ddfb6fc7d3444b95e33352d
parentd5605f44cdc0354ccbbc3cc46346823865c8a5fe (diff)
xshared: Support for ebtables' --change-counters command
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>
-rw-r--r--iptables/nft-cmd.h7
-rw-r--r--iptables/xshared.c57
-rw-r--r--iptables/xshared.h11
3 files changed, 66 insertions, 9 deletions
diff --git a/iptables/nft-cmd.h b/iptables/nft-cmd.h
index 8163b82c..00ecc802 100644
--- a/iptables/nft-cmd.h
+++ b/iptables/nft-cmd.h
@@ -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;
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 62ae4141..50f23757 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -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;
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 2fd15c72..68acfb4b 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -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;
};