libxt_quota2.c revision 92556c7047257284cc8659c769b800219cff47a5
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
19enum {
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
27enum {
28	O_QUOTA     = 0,
29	O_NAME,
30	O_GROW,
31	O_PACKET,
32	O_NO_CHANGE,
33};
34
35
36static 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
48static 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
60static 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
84static void
85quota_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
102static 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
124static 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
138void _init(void)
139{
140	xtables_register_match(&quota_mt2_reg);
141}
142