1 /*
2 * "quota2" match extension for iptables
3 * Sam Johnston <samj [at] samj net>
4 * Jan Engelhardt <jengelh [at] medozas de>, 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_NAME,
30 O_GROW,
31 O_PACKET,
32 O_NO_CHANGE,
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 switch (cb->entry->id) {
66 case O_GROW:
67 info->flags |= XT_QUOTA_GROW;
68 break;
69 case O_NO_CHANGE:
70 info->flags |= XT_QUOTA_NO_CHANGE;
71 break;
72 case O_NAME:
73 break;
74 case O_PACKET:
75 info->flags |= XT_QUOTA_PACKET;
76 break;
77 case O_QUOTA:
78 if (cb->invert)
79 info->flags |= XT_QUOTA_INVERT;
80 break;
81 }
82 }
83
84 static void
quota_mt2_save(const void * ip,const struct xt_entry_match * match)85 quota_mt2_save(const void *ip, const struct xt_entry_match *match)
86 {
87 const struct xt_quota_mtinfo2 *q = (void *)match->data;
88
89 if (q->flags & XT_QUOTA_INVERT)
90 printf(" !");
91 if (q->flags & XT_QUOTA_GROW)
92 printf(" --grow ");
93 if (q->flags & XT_QUOTA_NO_CHANGE)
94 printf(" --no-change ");
95 if (q->flags & XT_QUOTA_PACKET)
96 printf(" --packets ");
97 if (*q->name != '\0')
98 printf(" --name %s ", q->name);
99 printf(" --quota %llu ", (unsigned long long)q->quota);
100 }
101
quota_mt2_print(const void * ip,const struct xt_entry_match * match,int numeric)102 static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
103 int numeric)
104 {
105 const struct xt_quota_mtinfo2 *q = (const void *)match->data;
106
107 if (q->flags & XT_QUOTA_INVERT)
108 printf(" !");
109 if (q->flags & XT_QUOTA_GROW)
110 printf(" counter");
111 else
112 printf(" quota");
113 if (*q->name != '\0')
114 printf(" %s:", q->name);
115 printf(" %llu ", (unsigned long long)q->quota);
116 if (q->flags & XT_QUOTA_PACKET)
117 printf("packets ");
118 else
119 printf("bytes ");
120 if (q->flags & XT_QUOTA_NO_CHANGE)
121 printf("(no-change mode) ");
122 }
123
124 static struct xtables_match quota_mt2_reg = {
125 .family = NFPROTO_UNSPEC,
126 .revision = 3,
127 .name = "quota2",
128 .version = XTABLES_VERSION,
129 .size = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
130 .userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
131 .help = quota_mt2_help,
132 .x6_parse = quota_mt2_parse,
133 .print = quota_mt2_print,
134 .save = quota_mt2_save,
135 .x6_options = quota_mt2_opts,
136 };
137
_init(void)138 void _init(void)
139 {
140 xtables_register_match("a_mt2_reg);
141 }
142