diff options
author | Mathieu Poirier <mathieu.poirier@linaro.org> | 2013-12-10 14:45:18 -0700 |
---|---|---|
committer | Mathieu Poirier <mathieu.poirier@linaro.org> | 2014-01-27 08:51:10 -0700 |
commit | bd136a90279f7020af56ecd2cabea12e05be44e6 (patch) | |
tree | 6eee4e01af3ff31f935e201de3a342b7d3dd9da8 | |
parent | a0e224be48300b308a02f7bf898f0838463a7305 (diff) |
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.c | 102 | ||||
-rw-r--r-- | include/linux/netfilter/xt_nfacct.h | 17 |
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 */ |