1766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera#include <stdio.h>
2766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera#include <string.h>
36aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI#include <xtables.h>
46aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI#include <linux/netfilter/xt_connbytes.h>
5766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
609631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardtenum {
709631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	O_CONNBYTES = 0,
809631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	O_CONNBYTES_DIR,
909631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	O_CONNBYTES_MODE,
1009631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt};
1109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt
12181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void connbytes_help(void)
13766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera{
14766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera	printf(
158b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"connbytes match options:\n"
16766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera" [!] --connbytes from:[to]\n"
1793f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte"     --connbytes-dir [original, reply, both]\n"
188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"     --connbytes-mode [packets, bytes, avgpkt]\n");
19766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera}
20766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
2109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardtstatic const struct xt_option_entry connbytes_opts[] = {
2209631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	{.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC,
2309631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	 .flags = XTOPT_MAND | XTOPT_INVERT},
2409631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	{.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING,
2509631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	 .flags = XTOPT_MAND},
2609631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	{.name = "connbytes-mode", .id = O_CONNBYTES_MODE,
2709631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	 .type = XTTYPE_STRING, .flags = XTOPT_MAND},
2809631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	XTOPT_TABLEEND,
29766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera};
30766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
3109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardtstatic void connbytes_parse(struct xt_option_call *cb)
32766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera{
3309631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	struct xt_connbytes_info *sinfo = cb->data;
3409631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	unsigned long long i;
3509631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt
3609631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	xtables_option_parse(cb);
3709631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	switch (cb->entry->id) {
3809631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	case O_CONNBYTES:
3909631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		sinfo->count.from = cb->val.u64_range[0];
4009631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		sinfo->count.to   = cb->val.u64_range[0];
4109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		if (cb->nvals == 2)
4209631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt			sinfo->count.to = cb->val.u64_range[1];
4309631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		if (cb->invert) {
4493f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			i = sinfo->count.from;
457dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte			sinfo->count.from = sinfo->count.to;
4693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			sinfo->count.to = i;
47766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera		}
48766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera		break;
4909631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	case O_CONNBYTES_DIR:
5009631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		if (strcmp(cb->arg, "original") == 0)
516aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
5209631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		else if (strcmp(cb->arg, "reply") == 0)
536aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->direction = XT_CONNBYTES_DIR_REPLY;
5409631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		else if (strcmp(cb->arg, "both") == 0)
556aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->direction = XT_CONNBYTES_DIR_BOTH;
5693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte		else
571829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt			xtables_error(PARAMETER_PROBLEM,
5809631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt				   "Unknown --connbytes-dir `%s'", cb->arg);
5993f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte		break;
6009631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	case O_CONNBYTES_MODE:
6109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		if (strcmp(cb->arg, "packets") == 0)
626aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->what = XT_CONNBYTES_PKTS;
6309631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		else if (strcmp(cb->arg, "bytes") == 0)
646aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->what = XT_CONNBYTES_BYTES;
6509631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt		else if (strcmp(cb->arg, "avgpkt") == 0)
666aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI			sinfo->what = XT_CONNBYTES_AVGPKT;
6793f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte		else
681829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt			xtables_error(PARAMETER_PROBLEM,
6909631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt				   "Unknown --connbytes-mode `%s'", cb->arg);
701c0f2365ab7a884cc3e1aaed487ecdc2109fe0e2Piotrek Kaczmarek		break;
71766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera	}
7293f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte}
7393f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
7469f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardtstatic void print_mode(const struct xt_connbytes_info *sinfo)
7593f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte{
7693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	switch (sinfo->what) {
776aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_PKTS:
7873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" packets", stdout);
7993f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
806aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_BYTES:
8173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" bytes", stdout);
8293f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
836aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_AVGPKT:
8473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" avgpkt", stdout);
8593f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
867dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte		default:
8773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" unknown", stdout);
887dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte			break;
8993f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	}
9093f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte}
9193f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
9269f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardtstatic void print_direction(const struct xt_connbytes_info *sinfo)
9393f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte{
9493f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	switch (sinfo->direction) {
956aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_DIR_ORIGINAL:
9673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" original", stdout);
9793f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
986aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_DIR_REPLY:
9973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" reply", stdout);
10093f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
1016aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI		case XT_CONNBYTES_DIR_BOTH:
10273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" both", stdout);
1037dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte			break;
1047dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte		default:
10573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			fputs(" unknown", stdout);
10693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte			break;
10793f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	}
108766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera}
109766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
110766113ac7457f4e14014d2accd5344a03bb6854fMartin Deverastatic void
111181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtconnbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
112766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera{
11369f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_connbytes_info *sinfo = (const void *)match->data;
114766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
1157dc57e2933f0d6eeefb7c6d937c56655e5d1c9eaHarald Welte	if (sinfo->count.from > sinfo->count.to)
11673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" connbytes ! %llu:%llu",
117c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.to,
118c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.from);
119766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera	else
12073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" connbytes %llu:%llu",
121c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.from,
122c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.to);
12393f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
12473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	fputs(" connbytes mode", stdout);
12593f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	print_mode(sinfo);
12693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
12773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	fputs(" connbytes direction", stdout);
12893f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	print_direction(sinfo);
129766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera}
130766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
131181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void connbytes_save(const void *ip, const struct xt_entry_match *match)
132766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera{
13369f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_connbytes_info *sinfo = (const void *)match->data;
134766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
13593f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	if (sinfo->count.from > sinfo->count.to)
13673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" ! --connbytes %llu:%llu",
137c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.to,
138c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.from);
139766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera	else
14073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" --connbytes %llu:%llu",
141c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.from,
142c329d6a7085e3123f3d5ca98a8e0ab37edca2dccPatrick McHardy			(unsigned long long)sinfo->count.to);
14393f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
14473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	fputs(" --connbytes-mode", stdout);
14593f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	print_mode(sinfo);
14693f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte
14773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	fputs(" --connbytes-dir", stdout);
14893f4a3d72ad082ea42d67787d43e25343890dcdcHarald Welte	print_direction(sinfo);
149766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera}
150766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
151181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match connbytes_match = {
152c5e85736c207f211d82d2878a5781f512327dfceJan Engelhardt	.family		= NFPROTO_UNSPEC,
1536aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI	.name 		= "connbytes",
1548b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version 	= XTABLES_VERSION,
1556aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI	.size 		= XT_ALIGN(sizeof(struct xt_connbytes_info)),
1566aac50010e50aa42b42089110c8cf4d80b224f14Yasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_connbytes_info)),
157181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= connbytes_help,
158181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= connbytes_print,
159181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save 		= connbytes_save,
16009631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	.x6_parse	= connbytes_parse,
16109631dc60ce41bc484a42fcf4d4ddf7036820bd1Jan Engelhardt	.x6_options	= connbytes_opts,
162766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera};
163766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera
164766113ac7457f4e14014d2accd5344a03bb6854fMartin Deveravoid _init(void)
165766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera{
166181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&connbytes_match);
167766113ac7457f4e14014d2accd5344a03bb6854fMartin Devera}
168