xt_quota2: support packet counting; add manpage

This commit is contained in:
Jan Engelhardt
2008-07-07 01:19:10 +02:00
parent e987e2118c
commit e456c864c1
4 changed files with 66 additions and 15 deletions

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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 <jengelh@medozas.de>, 2008
*
* Sam Johnston <samj@samj.net>
* Originally based on xt_quota.c:
* netfilter module to enforce network quotas
* Sam Johnston <samj@samj.net>
*/
#include <linux/list.h>
#include <linux/proc_fs.h>
@@ -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 */

View File

@@ -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,
};