xref: /aosp_15_r20/external/iptables/extensions/libxt_connbytes.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1*a71a9546SAutomerger Merge Worker #include <stdio.h>
2*a71a9546SAutomerger Merge Worker #include <string.h>
3*a71a9546SAutomerger Merge Worker #include <xtables.h>
4*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_connbytes.h>
5*a71a9546SAutomerger Merge Worker 
6*a71a9546SAutomerger Merge Worker enum {
7*a71a9546SAutomerger Merge Worker 	O_CONNBYTES = 0,
8*a71a9546SAutomerger Merge Worker 	O_CONNBYTES_DIR,
9*a71a9546SAutomerger Merge Worker 	O_CONNBYTES_MODE,
10*a71a9546SAutomerger Merge Worker };
11*a71a9546SAutomerger Merge Worker 
connbytes_help(void)12*a71a9546SAutomerger Merge Worker static void connbytes_help(void)
13*a71a9546SAutomerger Merge Worker {
14*a71a9546SAutomerger Merge Worker 	printf(
15*a71a9546SAutomerger Merge Worker "connbytes match options:\n"
16*a71a9546SAutomerger Merge Worker " [!] --connbytes from:[to]\n"
17*a71a9546SAutomerger Merge Worker "     --connbytes-dir [original, reply, both]\n"
18*a71a9546SAutomerger Merge Worker "     --connbytes-mode [packets, bytes, avgpkt]\n");
19*a71a9546SAutomerger Merge Worker }
20*a71a9546SAutomerger Merge Worker 
21*a71a9546SAutomerger Merge Worker static const struct xt_option_entry connbytes_opts[] = {
22*a71a9546SAutomerger Merge Worker 	{.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC,
23*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_MAND | XTOPT_INVERT},
24*a71a9546SAutomerger Merge Worker 	{.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING,
25*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_MAND},
26*a71a9546SAutomerger Merge Worker 	{.name = "connbytes-mode", .id = O_CONNBYTES_MODE,
27*a71a9546SAutomerger Merge Worker 	 .type = XTTYPE_STRING, .flags = XTOPT_MAND},
28*a71a9546SAutomerger Merge Worker 	XTOPT_TABLEEND,
29*a71a9546SAutomerger Merge Worker };
30*a71a9546SAutomerger Merge Worker 
connbytes_parse(struct xt_option_call * cb)31*a71a9546SAutomerger Merge Worker static void connbytes_parse(struct xt_option_call *cb)
32*a71a9546SAutomerger Merge Worker {
33*a71a9546SAutomerger Merge Worker 	struct xt_connbytes_info *sinfo = cb->data;
34*a71a9546SAutomerger Merge Worker 	unsigned long long i;
35*a71a9546SAutomerger Merge Worker 
36*a71a9546SAutomerger Merge Worker 	xtables_option_parse(cb);
37*a71a9546SAutomerger Merge Worker 	switch (cb->entry->id) {
38*a71a9546SAutomerger Merge Worker 	case O_CONNBYTES:
39*a71a9546SAutomerger Merge Worker 		sinfo->count.from = cb->val.u64_range[0];
40*a71a9546SAutomerger Merge Worker 		sinfo->count.to   = UINT64_MAX;
41*a71a9546SAutomerger Merge Worker 		if (cb->nvals == 2)
42*a71a9546SAutomerger Merge Worker 			sinfo->count.to = cb->val.u64_range[1];
43*a71a9546SAutomerger Merge Worker 
44*a71a9546SAutomerger Merge Worker 		if (sinfo->count.to < sinfo->count.from)
45*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
46*a71a9546SAutomerger Merge Worker 					(unsigned long long)sinfo->count.from,
47*a71a9546SAutomerger Merge Worker 					(unsigned long long)sinfo->count.to);
48*a71a9546SAutomerger Merge Worker 		if (cb->invert) {
49*a71a9546SAutomerger Merge Worker 			i = sinfo->count.from;
50*a71a9546SAutomerger Merge Worker 			sinfo->count.from = sinfo->count.to;
51*a71a9546SAutomerger Merge Worker 			sinfo->count.to = i;
52*a71a9546SAutomerger Merge Worker 		}
53*a71a9546SAutomerger Merge Worker 		break;
54*a71a9546SAutomerger Merge Worker 	case O_CONNBYTES_DIR:
55*a71a9546SAutomerger Merge Worker 		if (strcmp(cb->arg, "original") == 0)
56*a71a9546SAutomerger Merge Worker 			sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
57*a71a9546SAutomerger Merge Worker 		else if (strcmp(cb->arg, "reply") == 0)
58*a71a9546SAutomerger Merge Worker 			sinfo->direction = XT_CONNBYTES_DIR_REPLY;
59*a71a9546SAutomerger Merge Worker 		else if (strcmp(cb->arg, "both") == 0)
60*a71a9546SAutomerger Merge Worker 			sinfo->direction = XT_CONNBYTES_DIR_BOTH;
61*a71a9546SAutomerger Merge Worker 		else
62*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM,
63*a71a9546SAutomerger Merge Worker 				   "Unknown --connbytes-dir `%s'", cb->arg);
64*a71a9546SAutomerger Merge Worker 		break;
65*a71a9546SAutomerger Merge Worker 	case O_CONNBYTES_MODE:
66*a71a9546SAutomerger Merge Worker 		if (strcmp(cb->arg, "packets") == 0)
67*a71a9546SAutomerger Merge Worker 			sinfo->what = XT_CONNBYTES_PKTS;
68*a71a9546SAutomerger Merge Worker 		else if (strcmp(cb->arg, "bytes") == 0)
69*a71a9546SAutomerger Merge Worker 			sinfo->what = XT_CONNBYTES_BYTES;
70*a71a9546SAutomerger Merge Worker 		else if (strcmp(cb->arg, "avgpkt") == 0)
71*a71a9546SAutomerger Merge Worker 			sinfo->what = XT_CONNBYTES_AVGPKT;
72*a71a9546SAutomerger Merge Worker 		else
73*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM,
74*a71a9546SAutomerger Merge Worker 				   "Unknown --connbytes-mode `%s'", cb->arg);
75*a71a9546SAutomerger Merge Worker 		break;
76*a71a9546SAutomerger Merge Worker 	}
77*a71a9546SAutomerger Merge Worker }
78*a71a9546SAutomerger Merge Worker 
print_mode(const struct xt_connbytes_info * sinfo)79*a71a9546SAutomerger Merge Worker static void print_mode(const struct xt_connbytes_info *sinfo)
80*a71a9546SAutomerger Merge Worker {
81*a71a9546SAutomerger Merge Worker 	switch (sinfo->what) {
82*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_PKTS:
83*a71a9546SAutomerger Merge Worker 			fputs(" packets", stdout);
84*a71a9546SAutomerger Merge Worker 			break;
85*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_BYTES:
86*a71a9546SAutomerger Merge Worker 			fputs(" bytes", stdout);
87*a71a9546SAutomerger Merge Worker 			break;
88*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_AVGPKT:
89*a71a9546SAutomerger Merge Worker 			fputs(" avgpkt", stdout);
90*a71a9546SAutomerger Merge Worker 			break;
91*a71a9546SAutomerger Merge Worker 		default:
92*a71a9546SAutomerger Merge Worker 			fputs(" unknown", stdout);
93*a71a9546SAutomerger Merge Worker 			break;
94*a71a9546SAutomerger Merge Worker 	}
95*a71a9546SAutomerger Merge Worker }
96*a71a9546SAutomerger Merge Worker 
print_direction(const struct xt_connbytes_info * sinfo)97*a71a9546SAutomerger Merge Worker static void print_direction(const struct xt_connbytes_info *sinfo)
98*a71a9546SAutomerger Merge Worker {
99*a71a9546SAutomerger Merge Worker 	switch (sinfo->direction) {
100*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_DIR_ORIGINAL:
101*a71a9546SAutomerger Merge Worker 			fputs(" original", stdout);
102*a71a9546SAutomerger Merge Worker 			break;
103*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_DIR_REPLY:
104*a71a9546SAutomerger Merge Worker 			fputs(" reply", stdout);
105*a71a9546SAutomerger Merge Worker 			break;
106*a71a9546SAutomerger Merge Worker 		case XT_CONNBYTES_DIR_BOTH:
107*a71a9546SAutomerger Merge Worker 			fputs(" both", stdout);
108*a71a9546SAutomerger Merge Worker 			break;
109*a71a9546SAutomerger Merge Worker 		default:
110*a71a9546SAutomerger Merge Worker 			fputs(" unknown", stdout);
111*a71a9546SAutomerger Merge Worker 			break;
112*a71a9546SAutomerger Merge Worker 	}
113*a71a9546SAutomerger Merge Worker }
114*a71a9546SAutomerger Merge Worker 
print_from_to(const struct xt_connbytes_info * sinfo,const char * prefix)115*a71a9546SAutomerger Merge Worker static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix)
116*a71a9546SAutomerger Merge Worker {
117*a71a9546SAutomerger Merge Worker 	unsigned long long from, to;
118*a71a9546SAutomerger Merge Worker 
119*a71a9546SAutomerger Merge Worker 	if (sinfo->count.from > sinfo->count.to) {
120*a71a9546SAutomerger Merge Worker 		fputs(" !", stdout);
121*a71a9546SAutomerger Merge Worker 		from = sinfo->count.to;
122*a71a9546SAutomerger Merge Worker 		to = sinfo->count.from;
123*a71a9546SAutomerger Merge Worker 	} else {
124*a71a9546SAutomerger Merge Worker 		to = sinfo->count.to;
125*a71a9546SAutomerger Merge Worker 		from = sinfo->count.from;
126*a71a9546SAutomerger Merge Worker 	}
127*a71a9546SAutomerger Merge Worker 	printf(" %sconnbytes %llu", prefix, from);
128*a71a9546SAutomerger Merge Worker 	if (to && to < UINT64_MAX)
129*a71a9546SAutomerger Merge Worker 		printf(":%llu", to);
130*a71a9546SAutomerger Merge Worker }
131*a71a9546SAutomerger Merge Worker 
132*a71a9546SAutomerger Merge Worker static void
connbytes_print(const void * ip,const struct xt_entry_match * match,int numeric)133*a71a9546SAutomerger Merge Worker connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
134*a71a9546SAutomerger Merge Worker {
135*a71a9546SAutomerger Merge Worker 	const struct xt_connbytes_info *sinfo = (const void *)match->data;
136*a71a9546SAutomerger Merge Worker 
137*a71a9546SAutomerger Merge Worker 	print_from_to(sinfo, "");
138*a71a9546SAutomerger Merge Worker 
139*a71a9546SAutomerger Merge Worker 	fputs(" connbytes mode", stdout);
140*a71a9546SAutomerger Merge Worker 	print_mode(sinfo);
141*a71a9546SAutomerger Merge Worker 
142*a71a9546SAutomerger Merge Worker 	fputs(" connbytes direction", stdout);
143*a71a9546SAutomerger Merge Worker 	print_direction(sinfo);
144*a71a9546SAutomerger Merge Worker }
145*a71a9546SAutomerger Merge Worker 
connbytes_save(const void * ip,const struct xt_entry_match * match)146*a71a9546SAutomerger Merge Worker static void connbytes_save(const void *ip, const struct xt_entry_match *match)
147*a71a9546SAutomerger Merge Worker {
148*a71a9546SAutomerger Merge Worker 	const struct xt_connbytes_info *sinfo = (const void *)match->data;
149*a71a9546SAutomerger Merge Worker 
150*a71a9546SAutomerger Merge Worker 	print_from_to(sinfo, "--");
151*a71a9546SAutomerger Merge Worker 
152*a71a9546SAutomerger Merge Worker 	fputs(" --connbytes-mode", stdout);
153*a71a9546SAutomerger Merge Worker 	print_mode(sinfo);
154*a71a9546SAutomerger Merge Worker 
155*a71a9546SAutomerger Merge Worker 	fputs(" --connbytes-dir", stdout);
156*a71a9546SAutomerger Merge Worker 	print_direction(sinfo);
157*a71a9546SAutomerger Merge Worker }
158*a71a9546SAutomerger Merge Worker 
159*a71a9546SAutomerger Merge Worker 
connbytes_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)160*a71a9546SAutomerger Merge Worker static int connbytes_xlate(struct xt_xlate *xl,
161*a71a9546SAutomerger Merge Worker 			   const struct xt_xlate_mt_params *params)
162*a71a9546SAutomerger Merge Worker {
163*a71a9546SAutomerger Merge Worker 	const struct xt_connbytes_info *info = (void *)params->match->data;
164*a71a9546SAutomerger Merge Worker 	unsigned long long from, to;
165*a71a9546SAutomerger Merge Worker 	bool invert = false;
166*a71a9546SAutomerger Merge Worker 
167*a71a9546SAutomerger Merge Worker 	xt_xlate_add(xl, "ct ");
168*a71a9546SAutomerger Merge Worker 
169*a71a9546SAutomerger Merge Worker 	switch (info->direction) {
170*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_DIR_ORIGINAL:
171*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "original ");
172*a71a9546SAutomerger Merge Worker 		break;
173*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_DIR_REPLY:
174*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "reply ");
175*a71a9546SAutomerger Merge Worker 		break;
176*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_DIR_BOTH:
177*a71a9546SAutomerger Merge Worker 		break;
178*a71a9546SAutomerger Merge Worker 	default:
179*a71a9546SAutomerger Merge Worker 		return 0;
180*a71a9546SAutomerger Merge Worker 	}
181*a71a9546SAutomerger Merge Worker 
182*a71a9546SAutomerger Merge Worker 	switch (info->what) {
183*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_PKTS:
184*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "packets ");
185*a71a9546SAutomerger Merge Worker 		break;
186*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_BYTES:
187*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "bytes ");
188*a71a9546SAutomerger Merge Worker 		break;
189*a71a9546SAutomerger Merge Worker 	case XT_CONNBYTES_AVGPKT:
190*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "avgpkt ");
191*a71a9546SAutomerger Merge Worker 		break;
192*a71a9546SAutomerger Merge Worker 	default:
193*a71a9546SAutomerger Merge Worker 		return 0;
194*a71a9546SAutomerger Merge Worker 	}
195*a71a9546SAutomerger Merge Worker 
196*a71a9546SAutomerger Merge Worker 	if (info->count.from > info->count.to) {
197*a71a9546SAutomerger Merge Worker 		invert = true;
198*a71a9546SAutomerger Merge Worker 		from = info->count.to;
199*a71a9546SAutomerger Merge Worker 		to = info->count.from;
200*a71a9546SAutomerger Merge Worker 	} else {
201*a71a9546SAutomerger Merge Worker 		to = info->count.to;
202*a71a9546SAutomerger Merge Worker 		from = info->count.from;
203*a71a9546SAutomerger Merge Worker 	}
204*a71a9546SAutomerger Merge Worker 
205*a71a9546SAutomerger Merge Worker 	if (from == to)
206*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "%llu", from);
207*a71a9546SAutomerger Merge Worker 	else if (to == UINT64_MAX)
208*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "%s %llu", invert ? "lt" : "ge", from);
209*a71a9546SAutomerger Merge Worker 	else
210*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "%s%llu-%llu", invert ? "!= " : "", from, to);
211*a71a9546SAutomerger Merge Worker 	return 1;
212*a71a9546SAutomerger Merge Worker }
213*a71a9546SAutomerger Merge Worker 
214*a71a9546SAutomerger Merge Worker static struct xtables_match connbytes_match = {
215*a71a9546SAutomerger Merge Worker 	.family		= NFPROTO_UNSPEC,
216*a71a9546SAutomerger Merge Worker 	.name 		= "connbytes",
217*a71a9546SAutomerger Merge Worker 	.version 	= XTABLES_VERSION,
218*a71a9546SAutomerger Merge Worker 	.size 		= XT_ALIGN(sizeof(struct xt_connbytes_info)),
219*a71a9546SAutomerger Merge Worker 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connbytes_info)),
220*a71a9546SAutomerger Merge Worker 	.help		= connbytes_help,
221*a71a9546SAutomerger Merge Worker 	.print		= connbytes_print,
222*a71a9546SAutomerger Merge Worker 	.save 		= connbytes_save,
223*a71a9546SAutomerger Merge Worker 	.x6_parse	= connbytes_parse,
224*a71a9546SAutomerger Merge Worker 	.x6_options	= connbytes_opts,
225*a71a9546SAutomerger Merge Worker 	.xlate		= connbytes_xlate,
226*a71a9546SAutomerger Merge Worker };
227*a71a9546SAutomerger Merge Worker 
_init(void)228*a71a9546SAutomerger Merge Worker void _init(void)
229*a71a9546SAutomerger Merge Worker {
230*a71a9546SAutomerger Merge Worker 	xtables_register_match(&connbytes_match);
231*a71a9546SAutomerger Merge Worker }
232