diff --git a/extensions/libxt_quota2.c b/extensions/libxt_quota2.c index db144f9..211b64f 100644 --- a/extensions/libxt_quota2.c +++ b/extensions/libxt_quota2.c @@ -17,17 +17,19 @@ #include "xt_quota2.h" enum { - FL_QUOTA = 1 << 0, - FL_NAME = 1 << 1, - FL_GROW = 1 << 2, - FL_PACKET = 1 << 3, + FL_QUOTA = 1 << 0, + FL_NAME = 1 << 1, + FL_GROW = 1 << 2, + FL_PACKET = 1 << 3, + FL_NO_CHANGE = 1 << 4, }; static const struct option quota_mt2_opts[] = { - {.name = "grow", .has_arg = false, .val = 'g'}, - {.name = "name", .has_arg = true, .val = 'n'}, - {.name = "quota", .has_arg = true, .val = 'q'}, - {.name = "packets", .has_arg = false, .val = 'p'}, + {.name = "grow", .has_arg = false, .val = 'g'}, + {.name = "no-change", .has_arg = false, .val = 'c'}, + {.name = "name", .has_arg = true, .val = 'n'}, + {.name = "quota", .has_arg = true, .val = 'q'}, + {.name = "packets", .has_arg = false, .val = 'p'}, {NULL}, }; @@ -36,6 +38,7 @@ static void quota_mt2_help(void) printf( "quota match options:\n" " --grow provide an increasing counter\n" + " --no-change never change counter/quota value for matching packets\n" " --name name name for the file in sysfs\n" "[!] --quota quota initial quota (bytes or packets)\n" " --packets count packets instead of bytes\n" @@ -56,6 +59,12 @@ quota_mt2_parse(int c, char **argv, int invert, unsigned int *flags, info->flags |= XT_QUOTA_GROW; *flags |= FL_GROW; return true; + case 'c': /* no-change */ + xtables_param_act(XTF_ONLY_ONCE, "quota", "--no-change", *flags & FL_NO_CHANGE); + xtables_param_act(XTF_NO_INVERT, "quota", "--no-change", invert); + info->flags |= XT_QUOTA_NO_CHANGE; + *flags |= FL_NO_CHANGE; + return true; case 'n': /* zero termination done on behalf of the kernel module */ xtables_param_act(XTF_ONLY_ONCE, "quota", "--name", *flags & FL_NAME); @@ -92,6 +101,8 @@ quota_mt2_save(const void *ip, const struct xt_entry_match *match) printf("! "); if (q->flags & XT_QUOTA_GROW) printf("--grow "); + if (q->flags & XT_QUOTA_NO_CHANGE) + printf("--no-change "); if (q->flags & XT_QUOTA_PACKET) printf("--packets "); if (*q->name != '\0') @@ -117,6 +128,8 @@ static void quota_mt2_print(const void *ip, const struct xt_entry_match *match, printf("packets "); else printf("bytes "); + if (q->flags & XT_QUOTA_NO_CHANGE) + printf("(no-change mode) "); } static struct xtables_match quota_mt2_reg = { diff --git a/extensions/libxt_quota2.man b/extensions/libxt_quota2.man index affa32f..c2e6b44 100644 --- a/extensions/libxt_quota2.man +++ b/extensions/libxt_quota2.man @@ -10,6 +10,12 @@ the match will return false, just like the original "quota" match. In growing \fB\-\-grow\fP Count upwards instead of downwards. .TP +\fB\-\-no\-change\fP +Makes it so the counter or quota amount is never changed by packets matching +this rule. This is only really useful in "quota" mode, as it will allow you to +use complex prerouting rules in association with the quota system, without +counting a packet twice. +.TP \fB\-\-name\fP \fIname\fP Assign the counter a specific name. This option must be present, as an empty name is not allowed. Names starting with a dot or names containing a slash are diff --git a/extensions/xt_quota2.Kconfig b/extensions/xt_quota2.Kconfig index 74744af..e2a1b1c 100644 --- a/extensions/xt_quota2.Kconfig +++ b/extensions/xt_quota2.Kconfig @@ -5,4 +5,5 @@ config NETFILTER_XT_MATCH_QUOTA2 This option adds the "quota2" match which is an advanced form of xt_quota that also allows counting upwards, and where the counter can be set through procfs. This allows for simple interfacing of - accounting information. + accounting information. It also allows for a test mode without changing + the quota value. diff --git a/extensions/xt_quota2.c b/extensions/xt_quota2.c index fbc8aab..f530b8b 100644 --- a/extensions/xt_quota2.c +++ b/extensions/xt_quota2.c @@ -199,12 +199,19 @@ quota_mt2(const struct sk_buff *skb, const struct xt_match_param *par) spin_lock_bh(&e->lock); if (q->flags & XT_QUOTA_GROW) { - e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; - q->quota = e->quota; + /* + * While no_change is pointless in "grow" mode, we will + * implement it here simply to have a consistent behavior. + */ + if (!(q->flags & XT_QUOTA_NO_CHANGE)) { + e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; + q->quota = e->quota; + } ret = true; } else { if (e->quota >= skb->len) { - e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; + if (!(q->flags & XT_QUOTA_NO_CHANGE)) + e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; ret = !ret; } else { /* we do not allow even small packets from now on */ diff --git a/extensions/xt_quota2.h b/extensions/xt_quota2.h index 05e3e20..eadc690 100644 --- a/extensions/xt_quota2.h +++ b/extensions/xt_quota2.h @@ -2,10 +2,11 @@ #define _XT_QUOTA_H enum xt_quota_flags { - XT_QUOTA_INVERT = 1 << 0, - XT_QUOTA_GROW = 1 << 1, - XT_QUOTA_PACKET = 1 << 2, - XT_QUOTA_MASK = 0x7, + XT_QUOTA_INVERT = 1 << 0, + XT_QUOTA_GROW = 1 << 1, + XT_QUOTA_PACKET = 1 << 2, + XT_QUOTA_NO_CHANGE = 1 << 3, + XT_QUOTA_MASK = 0x0F, }; struct xt_quota_counter;