1 /*
2 * "quota2" match extension for iptables
3 * Sam Johnston <samj [at] samj net>
4 * Jan Engelhardt, 2008
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License; either
8 * version 2 of the License, or any later version, as published by the
9 * Free Software Foundation.
10 */
11 #include <getopt.h>
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <xtables.h>
17 #include <linux/netfilter/xt_quota2.h>
18
19 enum {
20 FL_QUOTA = 1 << 0,
21 FL_NAME = 1 << 1,
22 FL_GROW = 1 << 2,
23 FL_PACKET = 1 << 3,
24 FL_NO_CHANGE = 1 << 4,
25 };
26
27 enum {
28 O_QUOTA = 0,
29 O_GROW,
30 O_PACKET,
31 O_NO_CHANGE,
32 O_NAME,
33 };
34
35
36 static const struct xt_option_entry quota_mt2_opts[] = {
37 {.name = "grow", .id = O_GROW, .type = XTTYPE_NONE},
38 {.name = "no-change", .id = O_NO_CHANGE, .type = XTTYPE_NONE},
39 {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
40 .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_quota_mtinfo2, name)},
41 {.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
42 .flags = XTOPT_INVERT | XTOPT_PUT,
43 XTOPT_POINTER(struct xt_quota_mtinfo2, quota)},
44 {.name = "packets", .id = O_PACKET, .type = XTTYPE_NONE},
45 XTOPT_TABLEEND,
46 };
47
quota_mt2_help(void)48 static void quota_mt2_help(void)
49 {
50 printf(
51 "quota match options:\n"
52 " --grow provide an increasing counter\n"
53 " --no-change never change counter/quota value for matching packets\n"
54 " --name name name for the file in sysfs\n"
55 "[!] --quota quota initial quota (bytes or packets)\n"
56 " --packets count packets instead of bytes\n"
57 );
58 }
59
quota_mt2_parse(struct xt_option_call * cb)60 static void quota_mt2_parse(struct xt_option_call *cb)
61 {
62 struct xt_quota_mtinfo2 *info = cb->data;
63
64 xtables_option_parse(cb);
65 if (cb->entry->id == O_NAME || (cb->entry->id == O_QUOTA && !cb->invert))
66 return;
67 else
68 info->flags |= 1 << (int)cb->entry->id;
69 }
70
71 static void
quota_mt2_save(const void * ip,const struct xt_entry_match * match)72 quota_mt2_save(const void *ip, const struct xt_entry_match *match)
73 {
74 const struct xt_quota_mtinfo2 *q = (void *)match->data;
75
76 if (q->flags & XT_QUOTA_INVERT)
77 printf(" !");
78 if (q->flags & XT_QUOTA_GROW)
79 printf(" --grow ");
80 if (q->flags & XT_QUOTA_NO_CHANGE)
81 printf(" --no-change ");
82 if (q->flags & XT_QUOTA_PACKET)
83 printf(" --packets ");
84 if (*q->name != '\0')
85 printf(" --name %s ", q->name);
86 printf(" --quota %llu ", (unsigned long long)q->quota);
87 }
88
quota_mt2_print(const void * ip,const struct xt_entry_match * match,int numeric)89 static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
90 int numeric)
91 {
92 printf(" -m quota");
93 quota_mt2_save(ip, match);
94 }
95
96 static struct xtables_match quota_mt2_reg = {
97 .family = NFPROTO_UNSPEC,
98 .revision = 3,
99 .name = "quota2",
100 .version = XTABLES_VERSION,
101 .size = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
102 .userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
103 .help = quota_mt2_help,
104 .x6_parse = quota_mt2_parse,
105 .print = quota_mt2_print,
106 .save = quota_mt2_save,
107 .x6_options = quota_mt2_opts,
108 };
109
_init(void)110 void _init(void)
111 {
112 xtables_register_match("a_mt2_reg);
113 }
114