aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2013-12-10 14:45:18 -0700
committerMathieu Poirier <mathieu.poirier@linaro.org>2014-01-27 08:51:10 -0700
commitbd136a90279f7020af56ecd2cabea12e05be44e6 (patch)
tree6eee4e01af3ff31f935e201de3a342b7d3dd9da8
parenta0e224be48300b308a02f7bf898f0838463a7305 (diff)
extensions: add quota to nfacct matchHEADmaster
This patch adds necessairy support for quota enhancement to the nfacct module. It can be used as such: nfacct add icmp-packet-limit iptables -I OUTPUT -p icmp -m nfacct --nfacct-name nfacct add icmp-packet-limit --packets --quota 200 --REJECT Without the '--packets' option, quotas are treated as byte. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
-rw-r--r--extensions/libxt_nfacct.c102
-rw-r--r--include/linux/netfilter/xt_nfacct.h17
2 files changed, 110 insertions, 9 deletions
diff --git a/extensions/libxt_nfacct.c b/extensions/libxt_nfacct.c
index 2ad59d5..506f6f5 100644
--- a/extensions/libxt_nfacct.c
+++ b/extensions/libxt_nfacct.c
@@ -18,6 +18,8 @@
enum {
O_NAME = 0,
+ O_QUOTA,
+ O_PACKET,
};
#define s struct xt_nfacct_match_info
@@ -28,10 +30,30 @@ static const struct xt_option_entry nfacct_opts[] = {
};
#undef s
+#define s1 struct xt_nfacct_match_info_v1
+static const struct xt_option_entry nfacct_opts_v1[] = {
+ {.name = "nfacct-name", .id = O_NAME, .type = XTTYPE_STRING,
+ .min = 1, .flags = XTOPT_MAND|XTOPT_PUT, XTOPT_POINTER(s1, name)},
+ {.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
+ .flags = XTOPT_PUT,
+ XTOPT_POINTER(s1, quota)},
+ {.name = "packets", .id = O_PACKET, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+#undef s1
+
static void nfacct_help(void)
{
printf("nfacct match options:\n"
- " --nfacct-name STRING Name of accouting area\n");
+ " --nfacct-name STRING Name of accounting area\n");
+}
+
+static void nfacct_help_v1(void)
+{
+ printf("nfacct match options:\n"
+ " --nfacct-name STRING Name of accounting area\n"
+ " --quota quota Initial quota (byte or packets)\n"
+ " --packets Count packets instead of bytes\n");
}
static void nfacct_parse(struct xt_option_call *cb)
@@ -46,20 +68,55 @@ static void nfacct_parse(struct xt_option_call *cb)
}
}
+static void nfacct_parse_v1(struct xt_option_call *cb)
+{
+ struct xt_nfacct_match_info_v1 *info =
+ (struct xt_nfacct_match_info_v1 *)cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_NAME:
+ if (strchr(cb->arg, '\n') != NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Newlines not allowed in --nfacct-name");
+ break;
+ case O_PACKET:
+ info->flags |= XT_NFACCT_QUOTA_PKTS;
+ break;
+ case O_QUOTA:
+ info->flags |= XT_NFACCT_QUOTA;
+ break;
+ }
+}
+
static void
-nfacct_print_name(const struct xt_nfacct_match_info *info, char *name)
+nfacct_print_name(const char *info_name, char *name)
{
printf(" %snfacct-name ", name);
- xtables_save_string(info->name);
+ xtables_save_string(info_name);
}
-static void nfacct_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
+static void nfacct_print(const void *ip,
+ const struct xt_entry_match *match, int numeric)
{
const struct xt_nfacct_match_info *info =
(struct xt_nfacct_match_info *)match->data;
- nfacct_print_name(info, "");
+ nfacct_print_name(info->name, "");
+}
+
+static void nfacct_print_v1(const void *ip,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_nfacct_match_info_v1 *info =
+ (struct xt_nfacct_match_info_v1 *)match->data;
+
+ nfacct_print_name(info->name, "");
+ if (info->flags & XT_NFACCT_QUOTA) {
+ if (info->flags & XT_NFACCT_QUOTA_PKTS)
+ printf(" packets");
+ printf(" quota: %llu", (unsigned long long)info->quota);
+ }
}
static void nfacct_save(const void *ip, const struct xt_entry_match *match)
@@ -67,10 +124,24 @@ static void nfacct_save(const void *ip, const struct xt_entry_match *match)
const struct xt_nfacct_match_info *info =
(struct xt_nfacct_match_info *)match->data;
- nfacct_print_name(info, "--");
+ nfacct_print_name(info->name, "--");
}
-static struct xtables_match nfacct_match = {
+static void nfacct_save_v1(const void *ip,
+ const struct xt_entry_match *match)
+{
+ const struct xt_nfacct_match_info_v1 *info =
+ (struct xt_nfacct_match_info_v1 *)match->data;
+
+ nfacct_print_name(info->name, "--");
+ if (info->flags & XT_NFACCT_QUOTA) {
+ if (info->flags & XT_NFACCT_QUOTA_PKTS)
+ printf(" --packets");
+ printf(" --quota %llu", (unsigned long long)info->quota);
+ }
+}
+static struct xtables_match nfacct_matches[] = {
+{
.family = NFPROTO_UNSPEC,
.name = "nfacct",
.version = XTABLES_VERSION,
@@ -81,9 +152,22 @@ static struct xtables_match nfacct_match = {
.print = nfacct_print,
.save = nfacct_save,
.x6_options = nfacct_opts,
+},{
+ .family = NFPROTO_UNSPEC,
+ .revision = 1,
+ .name = "nfacct",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_nfacct_match_info_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_nfacct_match_info_v1)),
+ .help = nfacct_help_v1,
+ .x6_parse = nfacct_parse_v1,
+ .print = nfacct_print_v1,
+ .save = nfacct_save_v1,
+ .x6_options = nfacct_opts_v1,
+},
};
void _init(void)
{
- xtables_register_match(&nfacct_match);
+ xtables_register_matches(nfacct_matches, ARRAY_SIZE(nfacct_matches));
}
diff --git a/include/linux/netfilter/xt_nfacct.h b/include/linux/netfilter/xt_nfacct.h
index 59ab00d..2c6b24b 100644
--- a/include/linux/netfilter/xt_nfacct.h
+++ b/include/linux/netfilter/xt_nfacct.h
@@ -7,11 +7,28 @@
#define NFACCT_NAME_MAX 32
#endif
+enum xt_quota_flags {
+ XT_NFACCT_QUOTA_PKTS = 1 << 0,
+ XT_NFACCT_QUOTA = 1 << 1,
+};
+
struct nf_acct;
+struct nf_acct_quota;
struct xt_nfacct_match_info {
+ char name[NFACCT_NAME_MAX];
+ struct nf_acct *nfacct;
+};
+
+struct xt_nfacct_match_info_v1 {
char name[NFACCT_NAME_MAX];
struct nf_acct *nfacct;
+
+ __u32 flags;
+ __aligned_u64 quota;
+
+ /* used internally by kernel */
+ struct nf_acct_quota *priv __attribute__((aligned(8)));
};
#endif /* _XT_NFACCT_MATCH_H */