libxt_connbytes.c revision 09631dc60ce41bc484a42fcf4d4ddf7036820bd1
1#include <stdio.h>
2#include <string.h>
3#include <xtables.h>
4#include <linux/netfilter/xt_connbytes.h>
5
6enum {
7	O_CONNBYTES = 0,
8	O_CONNBYTES_DIR,
9	O_CONNBYTES_MODE,
10};
11
12static void connbytes_help(void)
13{
14	printf(
15"connbytes match options:\n"
16" [!] --connbytes from:[to]\n"
17"     --connbytes-dir [original, reply, both]\n"
18"     --connbytes-mode [packets, bytes, avgpkt]\n");
19}
20
21static const struct xt_option_entry connbytes_opts[] = {
22	{.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC,
23	 .flags = XTOPT_MAND | XTOPT_INVERT},
24	{.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING,
25	 .flags = XTOPT_MAND},
26	{.name = "connbytes-mode", .id = O_CONNBYTES_MODE,
27	 .type = XTTYPE_STRING, .flags = XTOPT_MAND},
28	XTOPT_TABLEEND,
29};
30
31static void connbytes_parse(struct xt_option_call *cb)
32{
33	struct xt_connbytes_info *sinfo = cb->data;
34	unsigned long long i;
35
36	xtables_option_parse(cb);
37	switch (cb->entry->id) {
38	case O_CONNBYTES:
39		sinfo->count.from = cb->val.u64_range[0];
40		sinfo->count.to   = cb->val.u64_range[0];
41		if (cb->nvals == 2)
42			sinfo->count.to = cb->val.u64_range[1];
43		if (cb->invert) {
44			i = sinfo->count.from;
45			sinfo->count.from = sinfo->count.to;
46			sinfo->count.to = i;
47		}
48		break;
49	case O_CONNBYTES_DIR:
50		if (strcmp(cb->arg, "original") == 0)
51			sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
52		else if (strcmp(cb->arg, "reply") == 0)
53			sinfo->direction = XT_CONNBYTES_DIR_REPLY;
54		else if (strcmp(cb->arg, "both") == 0)
55			sinfo->direction = XT_CONNBYTES_DIR_BOTH;
56		else
57			xtables_error(PARAMETER_PROBLEM,
58				   "Unknown --connbytes-dir `%s'", cb->arg);
59		break;
60	case O_CONNBYTES_MODE:
61		if (strcmp(cb->arg, "packets") == 0)
62			sinfo->what = XT_CONNBYTES_PKTS;
63		else if (strcmp(cb->arg, "bytes") == 0)
64			sinfo->what = XT_CONNBYTES_BYTES;
65		else if (strcmp(cb->arg, "avgpkt") == 0)
66			sinfo->what = XT_CONNBYTES_AVGPKT;
67		else
68			xtables_error(PARAMETER_PROBLEM,
69				   "Unknown --connbytes-mode `%s'", cb->arg);
70		break;
71	}
72}
73
74static void print_mode(const struct xt_connbytes_info *sinfo)
75{
76	switch (sinfo->what) {
77		case XT_CONNBYTES_PKTS:
78			fputs(" packets", stdout);
79			break;
80		case XT_CONNBYTES_BYTES:
81			fputs(" bytes", stdout);
82			break;
83		case XT_CONNBYTES_AVGPKT:
84			fputs(" avgpkt", stdout);
85			break;
86		default:
87			fputs(" unknown", stdout);
88			break;
89	}
90}
91
92static void print_direction(const struct xt_connbytes_info *sinfo)
93{
94	switch (sinfo->direction) {
95		case XT_CONNBYTES_DIR_ORIGINAL:
96			fputs(" original", stdout);
97			break;
98		case XT_CONNBYTES_DIR_REPLY:
99			fputs(" reply", stdout);
100			break;
101		case XT_CONNBYTES_DIR_BOTH:
102			fputs(" both", stdout);
103			break;
104		default:
105			fputs(" unknown", stdout);
106			break;
107	}
108}
109
110static void
111connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
112{
113	const struct xt_connbytes_info *sinfo = (const void *)match->data;
114
115	if (sinfo->count.from > sinfo->count.to)
116		printf(" connbytes ! %llu:%llu",
117			(unsigned long long)sinfo->count.to,
118			(unsigned long long)sinfo->count.from);
119	else
120		printf(" connbytes %llu:%llu",
121			(unsigned long long)sinfo->count.from,
122			(unsigned long long)sinfo->count.to);
123
124	fputs(" connbytes mode", stdout);
125	print_mode(sinfo);
126
127	fputs(" connbytes direction", stdout);
128	print_direction(sinfo);
129}
130
131static void connbytes_save(const void *ip, const struct xt_entry_match *match)
132{
133	const struct xt_connbytes_info *sinfo = (const void *)match->data;
134
135	if (sinfo->count.from > sinfo->count.to)
136		printf(" ! --connbytes %llu:%llu",
137			(unsigned long long)sinfo->count.to,
138			(unsigned long long)sinfo->count.from);
139	else
140		printf(" --connbytes %llu:%llu",
141			(unsigned long long)sinfo->count.from,
142			(unsigned long long)sinfo->count.to);
143
144	fputs(" --connbytes-mode", stdout);
145	print_mode(sinfo);
146
147	fputs(" --connbytes-dir", stdout);
148	print_direction(sinfo);
149}
150
151static struct xtables_match connbytes_match = {
152	.family		= NFPROTO_UNSPEC,
153	.name 		= "connbytes",
154	.version 	= XTABLES_VERSION,
155	.size 		= XT_ALIGN(sizeof(struct xt_connbytes_info)),
156	.userspacesize	= XT_ALIGN(sizeof(struct xt_connbytes_info)),
157	.help		= connbytes_help,
158	.print		= connbytes_print,
159	.save 		= connbytes_save,
160	.x6_parse	= connbytes_parse,
161	.x6_options	= connbytes_opts,
162};
163
164void _init(void)
165{
166	xtables_register_match(&connbytes_match);
167}
168