Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding the original quota2 from xtables-addons

The original xt_quota in the kernel is plain broken:
  - counts quota at a per CPU level
    (was written back when ubiquitous SMP was just a dream)
  - provides no way to count across IPV4/IPV6.

This patch is the original unaltered code from:
  http://sourceforge.net/projects/xtables-addons
at commit e84391ce665cef046967f796dd91026851d6bbf3

Change-Id: Ia8b21394ea79ef55514748e96f769e40355a6ccf
Signed-off-by: JP Abgrall <jpa@google.com>
  • Loading branch information...
commit 5caed2aebebf7c72dfa982f247ac35ec67a1b852 1 parent 8b4807f
JP Abgrall authored
View
153 extensions/libxt_quota2.c
@@ -0,0 +1,153 @@
+/*
+ * "quota2" match extension for iptables
+ * Sam Johnston <samj [at] samj net>
+ * Jan Engelhardt <jengelh [at] medozas de>, 2008
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License; either
+ * version 2 of the License, or any later version, as published by the
+ * Free Software Foundation.
+ */
+#include <getopt.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xtables.h>
+#include "xt_quota2.h"
+#include "compat_user.h"
+
+enum {
+ 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 = "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},
+};
+
+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"
+ );
+}
+
+static int
+quota_mt2_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_quota_mtinfo2 *info = (void *)(*match)->data;
+ char *end;
+
+ switch (c) {
+ case 'g':
+ xtables_param_act(XTF_ONLY_ONCE, "quota", "--grow", *flags & FL_GROW);
+ xtables_param_act(XTF_NO_INVERT, "quota", "--grow", invert);
+ 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);
+ xtables_param_act(XTF_NO_INVERT, "quota", "--name", invert);
+ strncpy(info->name, optarg, sizeof(info->name));
+ *flags |= FL_NAME;
+ return true;
+ case 'p':
+ xtables_param_act(XTF_ONLY_ONCE, "quota", "--packets", *flags & FL_PACKET);
+ xtables_param_act(XTF_NO_INVERT, "quota", "--packets", invert);
+ info->flags |= XT_QUOTA_PACKET;
+ *flags |= FL_PACKET;
+ return true;
+ case 'q':
+ xtables_param_act(XTF_ONLY_ONCE, "quota", "--quota", *flags & FL_QUOTA);
+ if (invert)
+ info->flags |= XT_QUOTA_INVERT;
+ info->quota = strtoull(optarg, &end, 0);
+ if (*end != '\0')
+ xtables_error(PARAMETER_PROBLEM, "quota match: "
+ "invalid value for --quota");
+ *flags |= FL_QUOTA;
+ return true;
+ }
+ return false;
+}
+
+static void
+quota_mt2_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_quota_mtinfo2 *q = (void *)match->data;
+
+ if (q->flags & XT_QUOTA_INVERT)
+ 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')
+ printf(" --name %s ", q->name);
+ printf(" --quota %llu ", (unsigned long long)q->quota);
+}
+
+static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_quota_mtinfo2 *q = (const void *)match->data;
+
+ if (q->flags & XT_QUOTA_INVERT)
+ printf(" !");
+ if (q->flags & XT_QUOTA_GROW)
+ printf(" counter");
+ else
+ printf(" quota");
+ if (*q->name != '\0')
+ printf(" %s:", q->name);
+ printf(" %llu ", (unsigned long long)q->quota);
+ if (q->flags & XT_QUOTA_PACKET)
+ printf("packets ");
+ else
+ printf("bytes ");
+ if (q->flags & XT_QUOTA_NO_CHANGE)
+ printf("(no-change mode) ");
+}
+
+static struct xtables_match quota_mt2_reg = {
+ .family = NFPROTO_UNSPEC,
+ .revision = 3,
+ .name = "quota2",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
+ .userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
+ .help = quota_mt2_help,
+ .parse = quota_mt2_parse,
+ .print = quota_mt2_print,
+ .save = quota_mt2_save,
+ .extra_opts = quota_mt2_opts,
+};
+
+static __attribute__((constructor)) void quota2_mt_ldr(void)
+{
+ xtables_register_match(&quota_mt2_reg);
+}
View
37 extensions/libxt_quota2.man
@@ -0,0 +1,37 @@
+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\-\-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
+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
25 include/linux/netfilter/xt_quota2.h
@@ -0,0 +1,25 @@
+#ifndef _XT_QUOTA_H
+#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_NO_CHANGE = 1 << 3,
+ XT_QUOTA_MASK = 0x0F,
+};
+
+struct xt_quota_counter;
+
+struct xt_quota_mtinfo2 {
+ char name[15];
+ u_int8_t flags;
+
+ /* Comparison-invariant */
+ aligned_u64 quota;
+
+ /* Used internally by the kernel */
+ struct xt_quota_counter *master __attribute__((aligned(8)));
+};
+
+#endif /* _XT_QUOTA_H */
Please sign in to comment.
Something went wrong with that request. Please try again.