From e456c864c1403954e7162f4933b9b376554af70d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 7 Jul 2008 01:19:10 +0200 Subject: [PATCH] xt_quota2: support packet counting; add manpage --- extensions/libxt_quota2.c | 31 +++++++++++++++++++++++-------- extensions/libxt_quota2.man | 31 +++++++++++++++++++++++++++++++ extensions/xt_quota2.c | 12 ++++++++---- extensions/xt_quota2.h | 7 ++++--- 4 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 extensions/libxt_quota2.man diff --git a/extensions/libxt_quota2.c b/extensions/libxt_quota2.c index 47193d2..71ee70c 100644 --- a/extensions/libxt_quota2.c +++ b/extensions/libxt_quota2.c @@ -13,15 +13,17 @@ #include "xt_quota2.h" enum { - FL_QUOTA = 1 << 0, - FL_NAME = 1 << 1, - FL_GROW = 1 << 2, + FL_QUOTA = 1 << 0, + FL_NAME = 1 << 1, + FL_GROW = 1 << 2, + FL_PACKET = 1 << 3, }; 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 = "grow", .has_arg = false, .val = 'g'}, + {.name = "name", .has_arg = true, .val = 'n'}, + {.name = "quota", .has_arg = true, .val = 'q'}, + {.name = "packets", .has_arg = true, .val = 'p'}, {NULL}, }; @@ -31,7 +33,8 @@ static void quota_mt2_help(void) "quota match options:\n" " --grow provide an increasing counter\n" " --name name name for the file in sysfs\n" - "[!] --quota quota quota (bytes)\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, strncpy(info->name, optarg, sizeof(info->name)); *flags |= FL_NAME; return true; + case 'p': + param_act(P_ONLY_ONCE, "quota", "--packets", *flags & FL_PACKETS); + param_act(P_NO_INVERT, "quota", "--packets", invert); + info->flags |= XT_QUOTA_PACKET; + *flags |= FL_PACKET; + return true; case 'q': param_act(P_ONLY_ONCE, "quota", "--quota", *flags & FL_QUOTA); if (invert) @@ -79,6 +88,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_PACKET) + printf("--packets "); if (*q->name != '\0') printf("--name %s ", q->name); printf("--quota %llu ", (unsigned long long)q->quota); @@ -97,7 +108,11 @@ static void quota_mt2_print(const void *ip, const struct xt_entry_match *match, printf("quota"); if (*q->name != '\0') printf(" %s:", q->name); - printf(" %llu bytes", (unsigned long long)q->quota); + printf(" %llu ", (unsigned long long)q->quota); + if (q->flags & XT_QUOTA_PACKET) + printf("packets "); + else + printf("bytes "); } static struct xtables_match quota_mt2_reg = { diff --git a/extensions/libxt_quota2.man b/extensions/libxt_quota2.man new file mode 100644 index 0000000..e18c681 --- /dev/null +++ b/extensions/libxt_quota2.man @@ -0,0 +1,31 @@ +The "quota2" implements a named counter which can be increased or decreased +on a per-match basis. Available modes are packet counting or byte counting. +The value of the counter can be read and reset through procfs, thereby making +this match a minimalist accounting tool. +.PP +When counting down from the initial quota, the counter will stop at 0 and +the match will return false, just like the original "quota" match. In growing +(upcounting) mode, it will always return true. +.TP +\fB--grow\fP +Count upwards instead of downwards. +.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 +prohibited. +.TP +[\fB!\fP] \fB--quota\fP \fIiq\fP +Specify the initial quota for this counter. If the counter already exists, +it is not reset. An "!" may be used to invert the result of the match. The +negation has no effect when \fB--grow\fP is used. +.TP +\fB--packets\fP +Count packets instead of bytes that passed the quota2 match. +.PP +Because counters in quota2 can be shared, you can combine them for various +purposes, for example, a bytebucket filter that only lets as much traffic go +out as has come in: +.PP +-A INPUT -p tcp --dport 6881 -m quota --name bt --grow +-A OUTPUT -p tcp --sport 6881 -m quota --name bt diff --git a/extensions/xt_quota2.c b/extensions/xt_quota2.c index 2e719ff..78dc677 100644 --- a/extensions/xt_quota2.c +++ b/extensions/xt_quota2.c @@ -1,7 +1,11 @@ /* - * netfilter module to enforce network quotas + * xt_quota2 - enhanced xt_quota that can count upwards and in packets + * as a minimal accounting match. + * by Jan Engelhardt , 2008 * - * Sam Johnston + * Originally based on xt_quota.c: + * netfilter module to enforce network quotas + * Sam Johnston */ #include #include @@ -167,14 +171,14 @@ quota_mt2(const struct sk_buff *skb, const struct net_device *in, if (q->flags & XT_QUOTA_GROW) { spin_lock_bh(&e->lock); - e->quota += skb->len; + e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; q->quota = e->quota; spin_unlock_bh(&e->lock); ret = true; } else { spin_lock_bh(&e->lock); if (e->quota >= skb->len) { - e->quota -= skb->len; + 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 1b68ae2..cb13c79 100644 --- a/extensions/xt_quota2.h +++ b/extensions/xt_quota2.h @@ -2,9 +2,10 @@ #define _XT_QUOTA_H enum xt_quota_flags { - XT_QUOTA_INVERT = 0x1, - XT_QUOTA_GROW = 0x2, - XT_QUOTA_MASK = 0x3, + XT_QUOTA_INVERT = 1 << 0, + XT_QUOTA_GROW = 1 << 1, + XT_QUOTA_PACKET = 1 << 2, + XT_QUOTA_MASK = 0x7, XT_QUOTA_COUNTER_NAME_LENGTH = 31, };