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(&quota_mt2_reg);
141 }
142