xref: /aosp_15_r20/external/iptables/extensions/libxt_hashlimit.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1 /* ip6tables match extension for limiting packets per destination
2  *
3  * (C) 2003-2004 by Harald Welte <[email protected]>
4  *
5  * Development of this code was funded by Astaro AG, http://www.astaro.com/
6  *
7  * Based on ipt_limit.c by
8  * Jérôme de Vivie   <[email protected]>
9  * Hervé Eychenne    <[email protected]>
10  *
11  * Error corections by [email protected] (22.01.2005)
12  */
13 #define _BSD_SOURCE 1
14 #define _DEFAULT_SOURCE 1
15 #define _ISOC99_SOURCE 1
16 #include <inttypes.h>
17 #include <math.h>
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <xtables.h>
24 #include <linux/netfilter/x_tables.h>
25 #include <linux/netfilter/xt_hashlimit.h>
26 
27 #define XT_HASHLIMIT_BURST	5
28 #define XT_HASHLIMIT_BURST_MAX_v1	10000
29 #define XT_HASHLIMIT_BURST_MAX		1000000
30 
31 #define XT_HASHLIMIT_BYTE_EXPIRE	15
32 #define XT_HASHLIMIT_BYTE_EXPIRE_BURST	60
33 
34 /* miliseconds */
35 #define XT_HASHLIMIT_GCINTERVAL	1000
36 
37 struct hashlimit_mt_udata {
38 	uint32_t mult;
39 };
40 
hashlimit_help(void)41 static void hashlimit_help(void)
42 {
43 	printf(
44 "hashlimit match options:\n"
45 "--hashlimit <avg>		max average match rate\n"
46 "                                [Packets per second unless followed by \n"
47 "                                /sec /minute /hour /day postfixes]\n"
48 "--hashlimit-mode <mode>		mode is a comma-separated list of\n"
49 "					dstip,srcip,dstport,srcport\n"
50 "--hashlimit-name <name>		name for /proc/net/ipt_hashlimit/\n"
51 "[--hashlimit-burst <num>]	number to match in a burst, default %u\n"
52 "[--hashlimit-htable-size <num>]	number of hashtable buckets\n"
53 "[--hashlimit-htable-max <num>]	number of hashtable entries\n"
54 "[--hashlimit-htable-gcinterval]	interval between garbage collection runs\n"
55 "[--hashlimit-htable-expire]	after which time are idle entries expired?\n",
56 XT_HASHLIMIT_BURST);
57 }
58 
59 enum {
60 	O_UPTO = 0,
61 	O_ABOVE,
62 	O_LIMIT,
63 	O_MODE,
64 	O_SRCMASK,
65 	O_DSTMASK,
66 	O_NAME,
67 	O_BURST,
68 	O_HTABLE_SIZE,
69 	O_HTABLE_MAX,
70 	O_HTABLE_GCINT,
71 	O_HTABLE_EXPIRE,
72 	O_RATEMATCH,
73 	O_INTERVAL,
74 	F_BURST         = 1 << O_BURST,
75 	F_UPTO          = 1 << O_UPTO,
76 	F_ABOVE         = 1 << O_ABOVE,
77 	F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE,
78 	F_RATEMATCH	= 1 << O_RATEMATCH,
79 };
80 
hashlimit_mt_help(void)81 static void hashlimit_mt_help(void)
82 {
83 	printf(
84 "hashlimit match options:\n"
85 "  --hashlimit-upto <avg>           max average match rate\n"
86 "                                   [Packets per second unless followed by \n"
87 "                                   /sec /minute /hour /day postfixes]\n"
88 "  --hashlimit-above <avg>          min average match rate\n"
89 "  --hashlimit-mode <mode>          mode is a comma-separated list of\n"
90 "                                   dstip,srcip,dstport,srcport (or none)\n"
91 "  --hashlimit-srcmask <length>     source address grouping prefix length\n"
92 "  --hashlimit-dstmask <length>     destination address grouping prefix length\n"
93 "  --hashlimit-name <name>          name for /proc/net/ipt_hashlimit\n"
94 "  --hashlimit-burst <num>	    number to match in a burst, default %u\n"
95 "  --hashlimit-htable-size <num>    number of hashtable buckets\n"
96 "  --hashlimit-htable-max <num>     number of hashtable entries\n"
97 "  --hashlimit-htable-gcinterval    interval between garbage collection runs\n"
98 "  --hashlimit-htable-expire        after which time are idle entries expired?\n"
99 "\n", XT_HASHLIMIT_BURST);
100 }
101 
hashlimit_mt_help_v3(void)102 static void hashlimit_mt_help_v3(void)
103 {
104 	printf(
105 "hashlimit match options:\n"
106 "  --hashlimit-upto <avg>           max average match rate\n"
107 "                                   [Packets per second unless followed by \n"
108 "                                   /sec /minute /hour /day postfixes]\n"
109 "  --hashlimit-above <avg>          min average match rate\n"
110 "  --hashlimit-mode <mode>          mode is a comma-separated list of\n"
111 "                                   dstip,srcip,dstport,srcport (or none)\n"
112 "  --hashlimit-srcmask <length>     source address grouping prefix length\n"
113 "  --hashlimit-dstmask <length>     destination address grouping prefix length\n"
114 "  --hashlimit-name <name>          name for /proc/net/ipt_hashlimit\n"
115 "  --hashlimit-burst <num>	    number to match in a burst, default %u\n"
116 "  --hashlimit-htable-size <num>    number of hashtable buckets\n"
117 "  --hashlimit-htable-max <num>     number of hashtable entries\n"
118 "  --hashlimit-htable-gcinterval    interval between garbage collection runs\n"
119 "  --hashlimit-htable-expire        after which time are idle entries expired?\n"
120 "  --hashlimit-rate-match           rate match the flow without rate-limiting it\n"
121 "  --hashlimit-rate-interval        interval in seconds for hashlimit-rate-match\n"
122 "\n", XT_HASHLIMIT_BURST);
123 }
124 
125 #define s struct xt_hashlimit_info
126 static const struct xt_option_entry hashlimit_opts[] = {
127 	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
128 	 .type = XTTYPE_STRING},
129 	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
130 	 .min = 1, .max = XT_HASHLIMIT_BURST_MAX_v1, .flags = XTOPT_PUT,
131 	 XTOPT_POINTER(s, cfg.burst)},
132 	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
133 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
134 	 XTOPT_POINTER(s, cfg.size)},
135 	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
136 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
137 	 XTOPT_POINTER(s, cfg.max)},
138 	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
139 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
140 	 XTOPT_POINTER(s, cfg.gc_interval)},
141 	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
142 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
143 	 XTOPT_POINTER(s, cfg.expire)},
144 	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING,
145 	 .flags = XTOPT_MAND},
146 	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
147 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
148 	XTOPT_TABLEEND,
149 };
150 #undef s
151 
152 #define s struct xt_hashlimit_mtinfo1
153 static const struct xt_option_entry hashlimit_mt_opts_v1[] = {
154 	{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
155 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
156 	{.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
157 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
158 	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
159 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
160 	{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
161 	{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
162 	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
163 	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
164 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
165 	 XTOPT_POINTER(s, cfg.size)},
166 	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
167 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
168 	 XTOPT_POINTER(s, cfg.max)},
169 	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
170 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
171 	 XTOPT_POINTER(s, cfg.gc_interval)},
172 	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
173 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
174 	 XTOPT_POINTER(s, cfg.expire)},
175 	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
176 	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
177 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
178 	XTOPT_TABLEEND,
179 };
180 #undef s
181 
182 #define s struct xt_hashlimit_mtinfo2
183 static const struct xt_option_entry hashlimit_mt_opts_v2[] = {
184 	{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
185 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
186 	{.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
187 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
188 	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
189 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
190 	{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
191 	{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
192 	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
193 	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
194 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
195 	 XTOPT_POINTER(s, cfg.size)},
196 	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
197 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
198 	 XTOPT_POINTER(s, cfg.max)},
199 	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
200 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
201 	 XTOPT_POINTER(s, cfg.gc_interval)},
202 	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
203 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
204 	 XTOPT_POINTER(s, cfg.expire)},
205 	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
206 	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
207 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
208 	XTOPT_TABLEEND,
209 };
210 #undef s
211 
212 #define s struct xt_hashlimit_mtinfo3
213 static const struct xt_option_entry hashlimit_mt_opts[] = {
214 	{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
215 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
216 	{.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
217 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
218 	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
219 	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
220 	{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
221 	{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
222 	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
223 	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
224 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
225 	 XTOPT_POINTER(s, cfg.size)},
226 	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
227 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
228 	 XTOPT_POINTER(s, cfg.max)},
229 	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
230 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
231 	 XTOPT_POINTER(s, cfg.gc_interval)},
232 	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
233 	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
234 	 XTOPT_POINTER(s, cfg.expire)},
235 	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
236 	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
237 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
238 	{.name = "hashlimit-rate-match", .id = O_RATEMATCH, .type = XTTYPE_NONE},
239 	{.name = "hashlimit-rate-interval", .id = O_INTERVAL, .type = XTTYPE_STRING},
240 	XTOPT_TABLEEND,
241 };
242 #undef s
243 
244 static int
cfg_copy(struct hashlimit_cfg3 * to,const void * from,int revision)245 cfg_copy(struct hashlimit_cfg3 *to, const void *from, int revision)
246 {
247 	if (revision == 1) {
248 		struct hashlimit_cfg1 *cfg = (struct hashlimit_cfg1 *)from;
249 
250 		to->mode = cfg->mode;
251 		to->avg = cfg->avg;
252 		to->burst = cfg->burst;
253 		to->size = cfg->size;
254 		to->max = cfg->max;
255 		to->gc_interval = cfg->gc_interval;
256 		to->expire = cfg->expire;
257 		to->srcmask = cfg->srcmask;
258 		to->dstmask = cfg->dstmask;
259 	} else if (revision == 2) {
260 		struct hashlimit_cfg2 *cfg = (struct hashlimit_cfg2 *)from;
261 
262 		to->mode = cfg->mode;
263 		to->avg = cfg->avg;
264 		to->burst = cfg->burst;
265 		to->size = cfg->size;
266 		to->max = cfg->max;
267 		to->gc_interval = cfg->gc_interval;
268 		to->expire = cfg->expire;
269 		to->srcmask = cfg->srcmask;
270 		to->dstmask = cfg->dstmask;
271 	} else if (revision == 3) {
272 		memcpy(to, from, sizeof(struct hashlimit_cfg3));
273 	} else {
274 		return -EINVAL;
275 	}
276 
277 	return 0;
278 }
279 
cost_to_bytes(uint64_t cost)280 static uint64_t cost_to_bytes(uint64_t cost)
281 {
282 	uint64_t r;
283 
284 	r = cost ? UINT32_MAX / cost : UINT32_MAX;
285 	r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
286 	return r;
287 }
288 
bytes_to_cost(uint64_t bytes)289 static uint64_t bytes_to_cost(uint64_t bytes)
290 {
291 	uint32_t r = bytes >> XT_HASHLIMIT_BYTE_SHIFT;
292 	return UINT32_MAX / (r+1);
293 }
294 
get_factor(int chr)295 static uint32_t get_factor(int chr)
296 {
297 	switch (chr) {
298 	case 'm': return 1024 * 1024;
299 	case 'k': return 1024;
300 	}
301 	return 1;
302 }
303 
burst_error_v1(void)304 static void burst_error_v1(void)
305 {
306 	xtables_error(PARAMETER_PROBLEM, "bad value for option "
307 			"\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX_v1);
308 }
309 
burst_error(void)310 static void burst_error(void)
311 {
312 	xtables_error(PARAMETER_PROBLEM, "bad value for option "
313 			"\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX);
314 }
315 
parse_burst(const char * burst,int revision)316 static uint64_t parse_burst(const char *burst, int revision)
317 {
318 	uintmax_t v;
319 	char *end;
320 	uint64_t max = (revision == 1) ? UINT32_MAX : UINT64_MAX;
321 	uint64_t burst_max = (revision == 1) ?
322 			      XT_HASHLIMIT_BURST_MAX_v1 : XT_HASHLIMIT_BURST_MAX;
323 
324 	if (!xtables_strtoul(burst, &end, &v, 1, max) ||
325 		(*end == 0 && v > burst_max)) {
326 		if (revision == 1)
327 			burst_error_v1();
328 		else
329 			burst_error();
330 	}
331 
332 	v *= get_factor(*end);
333 	if (v > max)
334 		xtables_error(PARAMETER_PROBLEM, "bad value for option "
335 			"\"--hashlimit-burst\", value \"%s\" too large "
336 				"(max %"PRIu64"mb).", burst, max/1024/1024);
337 	return v;
338 }
339 
parse_bytes(const char * rate,void * val,struct hashlimit_mt_udata * ud,int revision)340 static bool parse_bytes(const char *rate, void *val, struct hashlimit_mt_udata *ud, int revision)
341 {
342 	unsigned int factor = 1;
343 	uint64_t tmp, r;
344 	const char *mode = strstr(rate, "b/s");
345 	uint64_t max = (revision == 1) ? UINT32_MAX : UINT64_MAX;
346 
347 	if (!mode || mode == rate)
348 		return false;
349 
350 	mode--;
351 	r = atoll(rate);
352 	if (r == 0)
353 		return false;
354 
355 	factor = get_factor(*mode);
356 	tmp = (uint64_t) r * factor;
357 	if (tmp > max)
358 		xtables_error(PARAMETER_PROBLEM,
359 			      "Rate value too large \"%"PRIu64"\" (max %"PRIu64")",
360 			      tmp, max);
361 
362 	tmp = bytes_to_cost(tmp);
363 	if (tmp == 0)
364 		xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"", rate);
365 
366 	ud->mult = XT_HASHLIMIT_BYTE_EXPIRE;
367 
368 	if(revision == 1)
369 		*((uint32_t*)val) = tmp;
370 	else
371 		*((uint64_t*)val) = tmp;
372 
373 	return true;
374 }
375 
376 static
parse_rate(const char * rate,void * val,struct hashlimit_mt_udata * ud,int revision)377 int parse_rate(const char *rate, void *val, struct hashlimit_mt_udata *ud, int revision)
378 {
379 	const char *delim;
380 	uint64_t tmp, r;
381 	uint64_t scale = (revision == 1) ? XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
382 
383 	ud->mult = 1;  /* Seconds by default. */
384 	delim = strchr(rate, '/');
385 	if (delim) {
386 		if (strlen(delim+1) == 0)
387 			return 0;
388 
389 		if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
390 			ud->mult = 1;
391 		else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
392 			ud->mult = 60;
393 		else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
394 			ud->mult = 60*60;
395 		else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
396 			ud->mult = 24*60*60;
397 		else
398 			return 0;
399 	}
400 	r = atoll(rate);
401 	if (!r)
402 		return 0;
403 
404 	tmp = scale * ud->mult / r;
405 	if (tmp == 0)
406 		/*
407 		 * The rate maps to infinity. (1/day is the minimum they can
408 		 * specify, so we are ok at that end).
409 		 */
410 		xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"", rate);
411 
412 	if(revision == 1)
413 		*((uint32_t*)val) = tmp;
414 	else
415 		*((uint64_t*)val) = tmp;
416 
417 	return 1;
418 }
419 
parse_interval(const char * rate,uint32_t * val)420 static int parse_interval(const char *rate, uint32_t *val)
421 {
422 	int r = atoi(rate);
423 	if (r <= 0)
424 		return 0;
425 
426 	*val = r;
427 	return 1;
428 }
429 
hashlimit_init(struct xt_entry_match * m)430 static void hashlimit_init(struct xt_entry_match *m)
431 {
432 	struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
433 
434 	r->cfg.burst = XT_HASHLIMIT_BURST;
435 	r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
436 
437 }
438 
hashlimit_mt4_init_v1(struct xt_entry_match * match)439 static void hashlimit_mt4_init_v1(struct xt_entry_match *match)
440 {
441 	struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
442 
443 	info->cfg.mode        = 0;
444 	info->cfg.burst       = XT_HASHLIMIT_BURST;
445 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
446 	info->cfg.srcmask     = 32;
447 	info->cfg.dstmask     = 32;
448 }
449 
hashlimit_mt6_init_v1(struct xt_entry_match * match)450 static void hashlimit_mt6_init_v1(struct xt_entry_match *match)
451 {
452 	struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
453 
454 	info->cfg.mode        = 0;
455 	info->cfg.burst       = XT_HASHLIMIT_BURST;
456 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
457 	info->cfg.srcmask     = 128;
458 	info->cfg.dstmask     = 128;
459 }
460 
hashlimit_mt4_init_v2(struct xt_entry_match * match)461 static void hashlimit_mt4_init_v2(struct xt_entry_match *match)
462 {
463 	struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
464 
465 	info->cfg.mode        = 0;
466 	info->cfg.burst       = XT_HASHLIMIT_BURST;
467 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
468 	info->cfg.srcmask     = 32;
469 	info->cfg.dstmask     = 32;
470 }
471 
hashlimit_mt6_init_v2(struct xt_entry_match * match)472 static void hashlimit_mt6_init_v2(struct xt_entry_match *match)
473 {
474 	struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
475 
476 	info->cfg.mode        = 0;
477 	info->cfg.burst       = XT_HASHLIMIT_BURST;
478 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
479 	info->cfg.srcmask     = 128;
480 	info->cfg.dstmask     = 128;
481 }
482 
hashlimit_mt4_init(struct xt_entry_match * match)483 static void hashlimit_mt4_init(struct xt_entry_match *match)
484 {
485 	struct xt_hashlimit_mtinfo3 *info = (void *)match->data;
486 
487 	info->cfg.mode        = 0;
488 	info->cfg.burst       = XT_HASHLIMIT_BURST;
489 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
490 	info->cfg.srcmask     = 32;
491 	info->cfg.dstmask     = 32;
492 	info->cfg.interval    = 0;
493 }
494 
hashlimit_mt6_init(struct xt_entry_match * match)495 static void hashlimit_mt6_init(struct xt_entry_match *match)
496 {
497 	struct xt_hashlimit_mtinfo3 *info = (void *)match->data;
498 
499 	info->cfg.mode        = 0;
500 	info->cfg.burst       = XT_HASHLIMIT_BURST;
501 	info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
502 	info->cfg.srcmask     = 128;
503 	info->cfg.dstmask     = 128;
504 	info->cfg.interval    = 0;
505 }
506 
507 /* Parse a 'mode' parameter into the required bitmask */
parse_mode(uint32_t * mode,const char * option_arg)508 static int parse_mode(uint32_t *mode, const char *option_arg)
509 {
510 	char *tok;
511 	char *arg = xtables_strdup(option_arg);
512 
513 	for (tok = strtok(arg, ",|");
514 	     tok;
515 	     tok = strtok(NULL, ",|")) {
516 		if (!strcmp(tok, "dstip"))
517 			*mode |= XT_HASHLIMIT_HASH_DIP;
518 		else if (!strcmp(tok, "srcip"))
519 			*mode |= XT_HASHLIMIT_HASH_SIP;
520 		else if (!strcmp(tok, "srcport"))
521 			*mode |= XT_HASHLIMIT_HASH_SPT;
522 		else if (!strcmp(tok, "dstport"))
523 			*mode |= XT_HASHLIMIT_HASH_DPT;
524 		else {
525 			free(arg);
526 			return -1;
527 		}
528 	}
529 	free(arg);
530 	return 0;
531 }
532 
hashlimit_parse(struct xt_option_call * cb)533 static void hashlimit_parse(struct xt_option_call *cb)
534 {
535 	struct xt_hashlimit_info *info = cb->data;
536 
537 	xtables_option_parse(cb);
538 	switch (cb->entry->id) {
539 	case O_UPTO:
540 		if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
541 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
542 			          "--hashlimit-upto", cb->arg);
543 		break;
544 	case O_MODE:
545 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
546 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
547 			          "--hashlimit-mode", cb->arg);
548 		break;
549 	}
550 }
551 
hashlimit_mt_parse_v1(struct xt_option_call * cb)552 static void hashlimit_mt_parse_v1(struct xt_option_call *cb)
553 {
554 	struct xt_hashlimit_mtinfo1 *info = cb->data;
555 
556 	xtables_option_parse(cb);
557 	switch (cb->entry->id) {
558 	case O_BURST:
559 		info->cfg.burst = parse_burst(cb->arg, 1);
560 		break;
561 	case O_UPTO:
562 		if (cb->invert)
563 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
564 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
565 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
566 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
567 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
568 			          "--hashlimit-upto", cb->arg);
569 		break;
570 	case O_ABOVE:
571 		if (!cb->invert)
572 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
573 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
574 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
575 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
576 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
577 			          "--hashlimit-above", cb->arg);
578 		break;
579 	case O_MODE:
580 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
581 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
582 			          "--hashlimit-mode", cb->arg);
583 		break;
584 	case O_SRCMASK:
585 		info->cfg.srcmask = cb->val.hlen;
586 		break;
587 	case O_DSTMASK:
588 		info->cfg.dstmask = cb->val.hlen;
589 		break;
590 	}
591 }
592 
hashlimit_mt_parse_v2(struct xt_option_call * cb)593 static void hashlimit_mt_parse_v2(struct xt_option_call *cb)
594 {
595 	struct xt_hashlimit_mtinfo2 *info = cb->data;
596 
597 	xtables_option_parse(cb);
598 	switch (cb->entry->id) {
599 	case O_BURST:
600 		info->cfg.burst = parse_burst(cb->arg, 2);
601 		break;
602 	case O_UPTO:
603 		if (cb->invert)
604 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
605 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
606 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
607 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
608 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
609 			          "--hashlimit-upto", cb->arg);
610 		break;
611 	case O_ABOVE:
612 		if (!cb->invert)
613 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
614 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
615 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
616 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
617 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
618 			          "--hashlimit-above", cb->arg);
619 		break;
620 	case O_MODE:
621 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
622 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
623 			          "--hashlimit-mode", cb->arg);
624 		break;
625 	case O_SRCMASK:
626 		info->cfg.srcmask = cb->val.hlen;
627 		break;
628 	case O_DSTMASK:
629 		info->cfg.dstmask = cb->val.hlen;
630 		break;
631 	}
632 }
633 
hashlimit_mt_parse(struct xt_option_call * cb)634 static void hashlimit_mt_parse(struct xt_option_call *cb)
635 {
636 	struct xt_hashlimit_mtinfo3 *info = cb->data;
637 
638 	xtables_option_parse(cb);
639 	switch (cb->entry->id) {
640 	case O_BURST:
641 		info->cfg.burst = parse_burst(cb->arg, 2);
642 		break;
643 	case O_UPTO:
644 		if (cb->invert)
645 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
646 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
647 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
648 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
649 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
650 			          "--hashlimit-upto", cb->arg);
651 		break;
652 	case O_ABOVE:
653 		if (!cb->invert)
654 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
655 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
656 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
657 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
658 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
659 			          "--hashlimit-above", cb->arg);
660 		break;
661 	case O_MODE:
662 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
663 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
664 			          "--hashlimit-mode", cb->arg);
665 		break;
666 	case O_SRCMASK:
667 		info->cfg.srcmask = cb->val.hlen;
668 		break;
669 	case O_DSTMASK:
670 		info->cfg.dstmask = cb->val.hlen;
671 		break;
672 	case O_RATEMATCH:
673 		info->cfg.mode |= XT_HASHLIMIT_RATE_MATCH;
674 		break;
675 	case O_INTERVAL:
676 		if (!parse_interval(cb->arg, &info->cfg.interval))
677 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
678 				"--hashlimit-rate-interval", cb->arg);
679 	}
680 }
681 
hashlimit_check(struct xt_fcheck_call * cb)682 static void hashlimit_check(struct xt_fcheck_call *cb)
683 {
684 	const struct hashlimit_mt_udata *udata = cb->udata;
685 	struct xt_hashlimit_info *info = cb->data;
686 
687 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
688 		xtables_error(PARAMETER_PROBLEM,
689 				"You have to specify --hashlimit");
690 	if (!(cb->xflags & F_HTABLE_EXPIRE))
691 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
692 }
693 
hashlimit_mt_check_v1(struct xt_fcheck_call * cb)694 static void hashlimit_mt_check_v1(struct xt_fcheck_call *cb)
695 {
696 	const struct hashlimit_mt_udata *udata = cb->udata;
697 	struct xt_hashlimit_mtinfo1 *info = cb->data;
698 
699 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
700 		xtables_error(PARAMETER_PROBLEM,
701 				"You have to specify --hashlimit");
702 	if (!(cb->xflags & F_HTABLE_EXPIRE))
703 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
704 
705 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
706 		uint32_t burst = 0;
707 		if (cb->xflags & F_BURST) {
708 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
709 				xtables_error(PARAMETER_PROBLEM,
710 					"burst cannot be smaller than %"PRIu64"b",
711 					cost_to_bytes(info->cfg.avg));
712 
713 			burst = info->cfg.burst;
714 			burst /= cost_to_bytes(info->cfg.avg);
715 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
716 				burst++;
717 			if (!(cb->xflags & F_HTABLE_EXPIRE))
718 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
719 		}
720 		info->cfg.burst = burst;
721 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX_v1)
722 		burst_error_v1();
723 }
724 
hashlimit_mt_check_v2(struct xt_fcheck_call * cb)725 static void hashlimit_mt_check_v2(struct xt_fcheck_call *cb)
726 {
727 	const struct hashlimit_mt_udata *udata = cb->udata;
728 	struct xt_hashlimit_mtinfo2 *info = cb->data;
729 
730 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
731 		xtables_error(PARAMETER_PROBLEM,
732 				"You have to specify --hashlimit");
733 	if (!(cb->xflags & F_HTABLE_EXPIRE))
734 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
735 
736 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
737 		uint32_t burst = 0;
738 		if (cb->xflags & F_BURST) {
739 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
740 				xtables_error(PARAMETER_PROBLEM,
741 					"burst cannot be smaller than %"PRIu64"b",
742 					cost_to_bytes(info->cfg.avg));
743 
744 			burst = info->cfg.burst;
745 			burst /= cost_to_bytes(info->cfg.avg);
746 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
747 				burst++;
748 			if (!(cb->xflags & F_HTABLE_EXPIRE))
749 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
750 		}
751 		info->cfg.burst = burst;
752 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
753 		burst_error();
754 }
755 
hashlimit_mt_check(struct xt_fcheck_call * cb)756 static void hashlimit_mt_check(struct xt_fcheck_call *cb)
757 {
758 	const struct hashlimit_mt_udata *udata = cb->udata;
759 	struct xt_hashlimit_mtinfo3 *info = cb->data;
760 
761 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
762 		xtables_error(PARAMETER_PROBLEM,
763 				"You have to specify --hashlimit");
764 	if (!(cb->xflags & F_HTABLE_EXPIRE))
765 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
766 
767 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
768 		uint32_t burst = 0;
769 		if (cb->xflags & F_BURST) {
770 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
771 				xtables_error(PARAMETER_PROBLEM,
772 					"burst cannot be smaller than %"PRIu64"b", cost_to_bytes(info->cfg.avg));
773 
774 			burst = info->cfg.burst;
775 			burst /= cost_to_bytes(info->cfg.avg);
776 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
777 				burst++;
778 			if (!(cb->xflags & F_HTABLE_EXPIRE))
779 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
780 		}
781 		info->cfg.burst = burst;
782 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
783 		burst_error();
784 
785 	if (cb->xflags & F_RATEMATCH) {
786 		if (!(info->cfg.mode & XT_HASHLIMIT_BYTES))
787 			info->cfg.avg /= udata->mult;
788 
789 		if (info->cfg.interval == 0) {
790 			if (info->cfg.mode & XT_HASHLIMIT_BYTES)
791 				info->cfg.interval = 1;
792 			else
793 				info->cfg.interval = udata->mult;
794 		}
795 	}
796 }
797 
798 struct rates {
799 	const char *name;
800 	uint64_t mult;
801 } rates_v1[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
802 		 { "hour", XT_HASHLIMIT_SCALE*60*60 },
803 		 { "min", XT_HASHLIMIT_SCALE*60 },
804 		 { "sec", XT_HASHLIMIT_SCALE } };
805 
806 static const struct rates rates[] = {
807 	{ "day", XT_HASHLIMIT_SCALE_v2*24*60*60 },
808 	{ "hour", XT_HASHLIMIT_SCALE_v2*60*60 },
809 	{ "min", XT_HASHLIMIT_SCALE_v2*60 },
810 	{ "sec", XT_HASHLIMIT_SCALE_v2 } };
811 
print_rate(uint64_t period,int revision)812 static uint32_t print_rate(uint64_t period, int revision)
813 {
814 	unsigned int i;
815 	const struct rates *_rates = (revision == 1) ? rates_v1 : rates;
816 	uint64_t scale = (revision == 1) ? XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
817 
818 	if (period == 0) {
819 		printf(" %f", INFINITY);
820 		return 0;
821 	}
822 
823 	for (i = 1; i < ARRAY_SIZE(rates); ++i)
824 		if (period > _rates[i].mult
825             || _rates[i].mult/period < _rates[i].mult%period)
826 			break;
827 
828 	printf(" %"PRIu64"/%s", _rates[i-1].mult / period, _rates[i-1].name);
829 	/* return in msec */
830 	return _rates[i-1].mult / scale * 1000;
831 }
832 
833 static const struct {
834 	const char *name;
835 	uint32_t thresh;
836 } units[] = {
837 	{ "m", 1024 * 1024 },
838 	{ "k", 1024 },
839 	{ "", 1 },
840 };
841 
print_bytes(uint64_t avg,uint64_t burst,const char * prefix)842 static uint32_t print_bytes(uint64_t avg, uint64_t burst, const char *prefix)
843 {
844 	unsigned int i;
845 	unsigned long long r;
846 
847 	r = cost_to_bytes(avg);
848 
849 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
850 		if (r >= units[i].thresh &&
851 		    bytes_to_cost(r & ~(units[i].thresh - 1)) == avg)
852 			break;
853 	printf(" %llu%sb/s", r/units[i].thresh, units[i].name);
854 
855 	if (burst == 0)
856 		return XT_HASHLIMIT_BYTE_EXPIRE * 1000;
857 
858 	r *= burst;
859 	printf(" %s", prefix);
860 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
861 		if (r >= units[i].thresh)
862 			break;
863 
864 	printf("burst %llu%sb", r / units[i].thresh, units[i].name);
865 	return XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
866 }
867 
print_mode(unsigned int mode,char separator)868 static void print_mode(unsigned int mode, char separator)
869 {
870 	bool prevmode = false;
871 
872 	putchar(' ');
873 	if (mode & XT_HASHLIMIT_HASH_SIP) {
874 		fputs("srcip", stdout);
875 		prevmode = 1;
876 	}
877 	if (mode & XT_HASHLIMIT_HASH_SPT) {
878 		if (prevmode)
879 			putchar(separator);
880 		fputs("srcport", stdout);
881 		prevmode = 1;
882 	}
883 	if (mode & XT_HASHLIMIT_HASH_DIP) {
884 		if (prevmode)
885 			putchar(separator);
886 		fputs("dstip", stdout);
887 		prevmode = 1;
888 	}
889 	if (mode & XT_HASHLIMIT_HASH_DPT) {
890 		if (prevmode)
891 			putchar(separator);
892 		fputs("dstport", stdout);
893 	}
894 }
895 
hashlimit_print(const void * ip,const struct xt_entry_match * match,int numeric)896 static void hashlimit_print(const void *ip,
897                             const struct xt_entry_match *match, int numeric)
898 {
899 	const struct xt_hashlimit_info *r = (const void *)match->data;
900 	uint32_t quantum;
901 
902 	fputs(" limit: avg", stdout);
903 	quantum = print_rate(r->cfg.avg, 1);
904 	printf(" burst %u", r->cfg.burst);
905 	fputs(" mode", stdout);
906 	print_mode(r->cfg.mode, '-');
907 	if (r->cfg.size)
908 		printf(" htable-size %u", r->cfg.size);
909 	if (r->cfg.max)
910 		printf(" htable-max %u", r->cfg.max);
911 	if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
912 		printf(" htable-gcinterval %u", r->cfg.gc_interval);
913 	if (r->cfg.expire != quantum)
914 		printf(" htable-expire %u", r->cfg.expire);
915 }
916 
917 static void
hashlimit_mt_print(const struct hashlimit_cfg3 * cfg,unsigned int dmask,int revision)918 hashlimit_mt_print(const struct hashlimit_cfg3 *cfg, unsigned int dmask, int revision)
919 {
920 	uint64_t quantum;
921 	uint64_t period;
922 
923 	if (cfg->mode & XT_HASHLIMIT_INVERT)
924 		fputs(" limit: above", stdout);
925 	else
926 		fputs(" limit: up to", stdout);
927 
928 	if (cfg->mode & XT_HASHLIMIT_BYTES) {
929 		quantum = print_bytes(cfg->avg, cfg->burst, "");
930 	} else {
931 		if (revision == 3) {
932 			period = cfg->avg;
933 			if (cfg->interval != 0)
934 				period *= cfg->interval;
935 
936 			quantum = print_rate(period, revision);
937 		} else {
938 			quantum = print_rate(cfg->avg, revision);
939 		}
940 		printf(" burst %llu", cfg->burst);
941 	}
942 	if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
943 	    XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
944 		fputs(" mode", stdout);
945 		print_mode(cfg->mode, '-');
946 	}
947 	if (cfg->size != 0)
948 		printf(" htable-size %u", cfg->size);
949 	if (cfg->max != 0)
950 		printf(" htable-max %u", cfg->max);
951 	if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
952 		printf(" htable-gcinterval %u", cfg->gc_interval);
953 	if (cfg->expire != quantum)
954 		printf(" htable-expire %u", cfg->expire);
955 
956 	if (cfg->srcmask != dmask)
957 		printf(" srcmask %u", cfg->srcmask);
958 	if (cfg->dstmask != dmask)
959 		printf(" dstmask %u", cfg->dstmask);
960 
961 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
962 		printf(" rate-match");
963 
964 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
965 		if (cfg->interval != 1)
966 			printf(" rate-interval %u", cfg->interval);
967 }
968 
969 static void
hashlimit_mt4_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)970 hashlimit_mt4_print_v1(const void *ip, const struct xt_entry_match *match,
971                    int numeric)
972 {
973 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
974 	struct hashlimit_cfg3 cfg;
975 	int ret;
976 
977 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
978 
979 	if (ret)
980 		xtables_error(OTHER_PROBLEM, "unknown revision");
981 
982 	hashlimit_mt_print(&cfg, 32, 1);
983 }
984 
985 static void
hashlimit_mt6_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)986 hashlimit_mt6_print_v1(const void *ip, const struct xt_entry_match *match,
987                    int numeric)
988 {
989 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
990 	struct hashlimit_cfg3 cfg;
991 	int ret;
992 
993 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
994 
995 	if (ret)
996 		xtables_error(OTHER_PROBLEM, "unknown revision");
997 
998 	hashlimit_mt_print(&cfg, 128, 1);
999 }
1000 
1001 static void
hashlimit_mt4_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)1002 hashlimit_mt4_print_v2(const void *ip, const struct xt_entry_match *match,
1003                    int numeric)
1004 {
1005 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1006 	struct hashlimit_cfg3 cfg;
1007 	int ret;
1008 
1009 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1010 
1011 	if (ret)
1012 		xtables_error(OTHER_PROBLEM, "unknown revision");
1013 
1014 	hashlimit_mt_print(&cfg, 32, 2);
1015 }
1016 
1017 static void
hashlimit_mt6_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)1018 hashlimit_mt6_print_v2(const void *ip, const struct xt_entry_match *match,
1019                    int numeric)
1020 {
1021 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1022 	struct hashlimit_cfg3 cfg;
1023 	int ret;
1024 
1025 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1026 
1027 	if (ret)
1028 		xtables_error(OTHER_PROBLEM, "unknown revision");
1029 
1030 	hashlimit_mt_print(&cfg, 128, 2);
1031 }
1032 static void
hashlimit_mt4_print(const void * ip,const struct xt_entry_match * match,int numeric)1033 hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
1034                    int numeric)
1035 {
1036 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1037 
1038 	hashlimit_mt_print(&info->cfg, 32, 3);
1039 }
1040 
1041 static void
hashlimit_mt6_print(const void * ip,const struct xt_entry_match * match,int numeric)1042 hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
1043                    int numeric)
1044 {
1045 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1046 
1047 	hashlimit_mt_print(&info->cfg, 128, 3);
1048 }
1049 
hashlimit_save(const void * ip,const struct xt_entry_match * match)1050 static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
1051 {
1052 	const struct xt_hashlimit_info *r = (const void *)match->data;
1053 	uint32_t quantum;
1054 
1055 	fputs(" --hashlimit", stdout);
1056 	quantum = print_rate(r->cfg.avg, 1);
1057 	printf(" --hashlimit-burst %u", r->cfg.burst);
1058 
1059 	fputs(" --hashlimit-mode", stdout);
1060 	print_mode(r->cfg.mode, ',');
1061 
1062 	printf(" --hashlimit-name %s", r->name);
1063 
1064 	if (r->cfg.size)
1065 		printf(" --hashlimit-htable-size %u", r->cfg.size);
1066 	if (r->cfg.max)
1067 		printf(" --hashlimit-htable-max %u", r->cfg.max);
1068 	if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
1069 		printf(" --hashlimit-htable-gcinterval %u", r->cfg.gc_interval);
1070 	if (r->cfg.expire != quantum)
1071 		printf(" --hashlimit-htable-expire %u", r->cfg.expire);
1072 }
1073 
1074 static void
hashlimit_mt_save(const struct hashlimit_cfg3 * cfg,const char * name,unsigned int dmask,int revision)1075 hashlimit_mt_save(const struct hashlimit_cfg3 *cfg, const char* name, unsigned int dmask, int revision)
1076 {
1077 	uint32_t quantum;
1078 
1079 	if (cfg->mode & XT_HASHLIMIT_INVERT)
1080 		fputs(" --hashlimit-above", stdout);
1081 	else
1082 		fputs(" --hashlimit-upto", stdout);
1083 
1084 	if (cfg->mode & XT_HASHLIMIT_BYTES) {
1085 		quantum = print_bytes(cfg->avg, cfg->burst, "--hashlimit-");
1086 	} else {
1087 		quantum = print_rate(cfg->avg, revision);
1088 		printf(" --hashlimit-burst %llu", cfg->burst);
1089 	}
1090 
1091 	if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
1092 	    XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
1093 		fputs(" --hashlimit-mode", stdout);
1094 		print_mode(cfg->mode, ',');
1095 	}
1096 
1097 	printf(" --hashlimit-name %s", name);
1098 
1099 	if (cfg->size != 0)
1100 		printf(" --hashlimit-htable-size %u", cfg->size);
1101 	if (cfg->max != 0)
1102 		printf(" --hashlimit-htable-max %u", cfg->max);
1103 	if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
1104 		printf(" --hashlimit-htable-gcinterval %u", cfg->gc_interval);
1105 	if (cfg->expire != quantum)
1106 		printf(" --hashlimit-htable-expire %u", cfg->expire);
1107 
1108 	if (cfg->srcmask != dmask)
1109 		printf(" --hashlimit-srcmask %u", cfg->srcmask);
1110 	if (cfg->dstmask != dmask)
1111 		printf(" --hashlimit-dstmask %u", cfg->dstmask);
1112 
1113 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
1114 		printf(" --hashlimit-rate-match");
1115 
1116 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
1117 		if (cfg->interval != 1)
1118 			printf(" --hashlimit-rate-interval %u", cfg->interval);
1119 }
1120 
1121 static void
hashlimit_mt4_save_v1(const void * ip,const struct xt_entry_match * match)1122 hashlimit_mt4_save_v1(const void *ip, const struct xt_entry_match *match)
1123 {
1124 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
1125 	struct hashlimit_cfg3 cfg;
1126 	int ret;
1127 
1128 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
1129 
1130 	if (ret)
1131 		xtables_error(OTHER_PROBLEM, "unknown revision");
1132 
1133 	hashlimit_mt_save(&cfg, info->name, 32, 1);
1134 }
1135 
1136 static void
hashlimit_mt6_save_v1(const void * ip,const struct xt_entry_match * match)1137 hashlimit_mt6_save_v1(const void *ip, const struct xt_entry_match *match)
1138 {
1139 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
1140 	struct hashlimit_cfg3 cfg;
1141 	int ret;
1142 
1143 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
1144 
1145 	if (ret)
1146 		xtables_error(OTHER_PROBLEM, "unknown revision");
1147 
1148 	hashlimit_mt_save(&cfg, info->name, 128, 1);
1149 }
1150 
1151 static void
hashlimit_mt4_save_v2(const void * ip,const struct xt_entry_match * match)1152 hashlimit_mt4_save_v2(const void *ip, const struct xt_entry_match *match)
1153 {
1154 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1155 	struct hashlimit_cfg3 cfg;
1156 	int ret;
1157 
1158 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1159 
1160 	if (ret)
1161 		xtables_error(OTHER_PROBLEM, "unknown revision");
1162 
1163 	hashlimit_mt_save(&cfg, info->name, 32, 2);
1164 }
1165 
1166 static void
hashlimit_mt6_save_v2(const void * ip,const struct xt_entry_match * match)1167 hashlimit_mt6_save_v2(const void *ip, const struct xt_entry_match *match)
1168 {
1169 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1170 	struct hashlimit_cfg3 cfg;
1171 	int ret;
1172 
1173 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1174 
1175 	if (ret)
1176 		xtables_error(OTHER_PROBLEM, "unknown revision");
1177 
1178 	hashlimit_mt_save(&cfg, info->name, 128, 2);
1179 }
1180 
1181 static void
hashlimit_mt4_save(const void * ip,const struct xt_entry_match * match)1182 hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
1183 {
1184 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1185 
1186 	hashlimit_mt_save(&info->cfg, info->name, 32, 3);
1187 }
1188 
1189 static void
hashlimit_mt6_save(const void * ip,const struct xt_entry_match * match)1190 hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
1191 {
1192 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1193 
1194 	hashlimit_mt_save(&info->cfg, info->name, 128, 3);
1195 }
1196 
1197 static const struct rates rates_v1_xlate[] = {
1198 	{ "day", XT_HASHLIMIT_SCALE * 24 * 60 * 60 },
1199 	{ "hour", XT_HASHLIMIT_SCALE * 60 * 60 },
1200 	{ "minute", XT_HASHLIMIT_SCALE * 60 },
1201 	{ "second", XT_HASHLIMIT_SCALE } };
1202 
1203 static const struct rates rates_xlate[] = {
1204 	{ "day", XT_HASHLIMIT_SCALE_v2 * 24 * 60 * 60 },
1205 	{ "hour", XT_HASHLIMIT_SCALE_v2 * 60 * 60 },
1206 	{ "minute", XT_HASHLIMIT_SCALE_v2 * 60 },
1207 	{ "second", XT_HASHLIMIT_SCALE_v2 } };
1208 
print_packets_rate_xlate(struct xt_xlate * xl,uint64_t avg,int revision)1209 static void print_packets_rate_xlate(struct xt_xlate *xl, uint64_t avg,
1210 				     int revision)
1211 {
1212 	unsigned int i;
1213 	const struct rates *_rates = (revision == 1) ?
1214 		rates_v1_xlate : rates_xlate;
1215 
1216 	for (i = 1; i < ARRAY_SIZE(rates); ++i)
1217 		if (avg > _rates[i].mult ||
1218 		    _rates[i].mult / avg < _rates[i].mult % avg)
1219 			break;
1220 
1221 	xt_xlate_add(xl, " %" PRIu64 "/%s ",
1222 		     _rates[i-1].mult / avg, _rates[i-1].name);
1223 }
1224 
print_bytes_rate_xlate(struct xt_xlate * xl,const struct hashlimit_cfg3 * cfg)1225 static void print_bytes_rate_xlate(struct xt_xlate *xl,
1226 				   const struct hashlimit_cfg3 *cfg)
1227 {
1228 	unsigned int i;
1229 	unsigned long long r;
1230 
1231 	r = cost_to_bytes(cfg->avg);
1232 
1233 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
1234 		if (r >= units[i].thresh &&
1235 		    bytes_to_cost(r & ~(units[i].thresh - 1)) == cfg->avg)
1236 			break;
1237 
1238 	xt_xlate_add(xl, " %llu %sbytes/second", r / units[i].thresh,
1239 		     units[i].name);
1240 
1241 	r *= cfg->burst;
1242 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
1243 		if (r >= units[i].thresh)
1244 			break;
1245 
1246 	if (cfg->burst > 0)
1247 		xt_xlate_add(xl, " burst %llu %sbytes", r / units[i].thresh,
1248 			     units[i].name);
1249 }
1250 
hashlimit_print_subnet_xlate(struct xt_xlate * xl,uint32_t nsub,int family)1251 static void hashlimit_print_subnet_xlate(struct xt_xlate *xl,
1252 					 uint32_t nsub, int family)
1253 {
1254 	char sep = (family == NFPROTO_IPV4) ? '.' : ':';
1255 	char *fmt = (family == NFPROTO_IPV4) ? "%u" : "%04x";
1256 	unsigned int nblocks = (family == NFPROTO_IPV4) ? 4 : 8;
1257 	unsigned int nbits = (family == NFPROTO_IPV4) ? 8 : 16;
1258 	unsigned int acm, i;
1259 
1260 	xt_xlate_add(xl, " and ");
1261 	while (nblocks--) {
1262 		acm = 0;
1263 
1264 		for (i = 0; i < nbits; i++) {
1265 			acm <<= 1;
1266 
1267 			if (nsub > 0) {
1268 				acm++;
1269 				nsub--;
1270 			}
1271 		}
1272 
1273 		xt_xlate_add_nospc(xl, fmt, acm);
1274 		if (nblocks > 0)
1275 			xt_xlate_add(xl, "%c", sep);
1276 	}
1277 }
1278 
1279 static const char *const hashlimit_modes4_xlate[] = {
1280 	[XT_HASHLIMIT_HASH_DIP]	= "ip daddr",
1281 	[XT_HASHLIMIT_HASH_DPT]	= "tcp dport",
1282 	[XT_HASHLIMIT_HASH_SIP]	= "ip saddr",
1283 	[XT_HASHLIMIT_HASH_SPT]	= "tcp sport",
1284 };
1285 
1286 static const char *const hashlimit_modes6_xlate[] = {
1287 	[XT_HASHLIMIT_HASH_DIP]	= "ip6 daddr",
1288 	[XT_HASHLIMIT_HASH_DPT]	= "tcp dport",
1289 	[XT_HASHLIMIT_HASH_SIP]	= "ip6 saddr",
1290 	[XT_HASHLIMIT_HASH_SPT]	= "tcp sport",
1291 };
1292 
hashlimit_mode_xlate(struct xt_xlate * xl,uint32_t mode,int family,unsigned int nsrc,unsigned int ndst)1293 static int hashlimit_mode_xlate(struct xt_xlate *xl,
1294 				uint32_t mode, int family,
1295 				unsigned int nsrc, unsigned int ndst)
1296 {
1297 	const char * const *_modes = (family == NFPROTO_IPV4) ?
1298 		hashlimit_modes4_xlate : hashlimit_modes6_xlate;
1299 	bool prevopt = false;
1300 	unsigned int mask;
1301 
1302 	mode &= ~XT_HASHLIMIT_INVERT & ~XT_HASHLIMIT_BYTES;
1303 
1304 	for (mask = 1; mode > 0; mask <<= 1) {
1305 		if (!(mode & mask))
1306 			continue;
1307 
1308 		if (!prevopt) {
1309 			xt_xlate_add(xl, " ");
1310 			prevopt = true;
1311 		}
1312 		else {
1313 			xt_xlate_add(xl, " . ");
1314 		}
1315 
1316 		xt_xlate_add(xl, "%s", _modes[mask]);
1317 
1318 		if (mask == XT_HASHLIMIT_HASH_DIP &&
1319 		    ((family == NFPROTO_IPV4 && ndst != 32) ||
1320 		     (family == NFPROTO_IPV6 && ndst != 128)))
1321 			hashlimit_print_subnet_xlate(xl, ndst, family);
1322 		else if (mask == XT_HASHLIMIT_HASH_SIP &&
1323 			 ((family == NFPROTO_IPV4 && nsrc != 32) ||
1324 			  (family == NFPROTO_IPV6 && nsrc != 128)))
1325 			hashlimit_print_subnet_xlate(xl, nsrc, family);
1326 
1327 		mode &= ~mask;
1328 	}
1329 
1330 	return prevopt;
1331 }
1332 
hashlimit_mt_xlate(struct xt_xlate * xl,const char * name,const struct hashlimit_cfg3 * cfg,int revision,int family)1333 static int hashlimit_mt_xlate(struct xt_xlate *xl, const char *name,
1334 			      const struct hashlimit_cfg3 *cfg,
1335 			      int revision, int family)
1336 {
1337 	int ret = 1;
1338 
1339 	xt_xlate_add(xl, "meter %s {", name);
1340 	ret = hashlimit_mode_xlate(xl, cfg->mode, family,
1341 				   cfg->srcmask, cfg->dstmask);
1342 	if (cfg->expire != 1000)
1343 		xt_xlate_add(xl, " timeout %us", cfg->expire / 1000);
1344 	xt_xlate_add(xl, " limit rate");
1345 
1346 	if (cfg->mode & XT_HASHLIMIT_INVERT)
1347 		xt_xlate_add(xl, " over");
1348 
1349 	if (cfg->mode & XT_HASHLIMIT_BYTES)
1350 		print_bytes_rate_xlate(xl, cfg);
1351 	else {
1352 		print_packets_rate_xlate(xl, cfg->avg, revision);
1353 		if (cfg->burst != XT_HASHLIMIT_BURST)
1354 			xt_xlate_add(xl, "burst %" PRIu64 " packets", (uint64_t)cfg->burst);
1355 
1356 	}
1357 	xt_xlate_add(xl, "}");
1358 
1359 	return ret;
1360 }
1361 
hashlimit_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1362 static int hashlimit_xlate(struct xt_xlate *xl,
1363 			   const struct xt_xlate_mt_params *params)
1364 {
1365 	const struct xt_hashlimit_info *info = (const void *)params->match->data;
1366 	int ret = 1;
1367 
1368 	xt_xlate_add(xl, "meter %s {", info->name);
1369 	ret = hashlimit_mode_xlate(xl, info->cfg.mode, NFPROTO_IPV4, 32, 32);
1370 	xt_xlate_add(xl, " timeout %us limit rate", info->cfg.expire / 1000);
1371 	print_packets_rate_xlate(xl, info->cfg.avg, 1);
1372 	xt_xlate_add(xl, " burst %u packets", info->cfg.burst);
1373 	xt_xlate_add(xl, "}");
1374 
1375 	return ret;
1376 }
1377 
hashlimit_mt4_xlate_v1(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1378 static int hashlimit_mt4_xlate_v1(struct xt_xlate *xl,
1379 				  const struct xt_xlate_mt_params *params)
1380 {
1381 	const struct xt_hashlimit_mtinfo1 *info =
1382 		(const void *)params->match->data;
1383 	struct hashlimit_cfg3 cfg;
1384 
1385 	if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
1386 		xtables_error(OTHER_PROBLEM, "unknown revision");
1387 
1388 	return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV4);
1389 }
1390 
hashlimit_mt6_xlate_v1(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1391 static int hashlimit_mt6_xlate_v1(struct xt_xlate *xl,
1392 				  const struct xt_xlate_mt_params *params)
1393 {
1394 	const struct xt_hashlimit_mtinfo1 *info =
1395 		(const void *)params->match->data;
1396 	struct hashlimit_cfg3 cfg;
1397 
1398 	if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
1399 		xtables_error(OTHER_PROBLEM, "unknown revision");
1400 
1401 	return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV6);
1402 }
1403 
hashlimit_mt4_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1404 static int hashlimit_mt4_xlate_v2(struct xt_xlate *xl,
1405 				  const struct xt_xlate_mt_params *params)
1406 {
1407 	const struct xt_hashlimit_mtinfo2 *info =
1408 		(const void *)params->match->data;
1409 	struct hashlimit_cfg3 cfg;
1410 
1411 	if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
1412 		xtables_error(OTHER_PROBLEM, "unknown revision");
1413 
1414 	return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV4);
1415 }
1416 
hashlimit_mt6_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1417 static int hashlimit_mt6_xlate_v2(struct xt_xlate *xl,
1418 				  const struct xt_xlate_mt_params *params)
1419 {
1420 	const struct xt_hashlimit_mtinfo2 *info =
1421 		(const void *)params->match->data;
1422 	struct hashlimit_cfg3 cfg;
1423 
1424 	if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
1425 		xtables_error(OTHER_PROBLEM, "unknown revision");
1426 
1427 	return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV6);
1428 }
1429 
hashlimit_mt4_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1430 static int hashlimit_mt4_xlate(struct xt_xlate *xl,
1431 			       const struct xt_xlate_mt_params *params)
1432 {
1433 	const struct xt_hashlimit_mtinfo3 *info =
1434 		(const void *)params->match->data;
1435 
1436 	return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV4);
1437 }
1438 
hashlimit_mt6_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1439 static int hashlimit_mt6_xlate(struct xt_xlate *xl,
1440 			       const struct xt_xlate_mt_params *params)
1441 {
1442 	const struct xt_hashlimit_mtinfo3 *info =
1443 		(const void *)params->match->data;
1444 
1445 	return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV6);
1446 }
1447 
1448 static struct xtables_match hashlimit_mt_reg[] = {
1449 	{
1450 		.family        = NFPROTO_UNSPEC,
1451 		.name          = "hashlimit",
1452 		.version       = XTABLES_VERSION,
1453 		.revision      = 0,
1454 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_info)),
1455 		.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
1456 		.help          = hashlimit_help,
1457 		.init          = hashlimit_init,
1458 		.x6_parse      = hashlimit_parse,
1459 		.x6_fcheck     = hashlimit_check,
1460 		.print         = hashlimit_print,
1461 		.save          = hashlimit_save,
1462 		.x6_options    = hashlimit_opts,
1463 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1464 		.xlate         = hashlimit_xlate,
1465 	},
1466 	{
1467 		.version       = XTABLES_VERSION,
1468 		.name          = "hashlimit",
1469 		.revision      = 1,
1470 		.family        = NFPROTO_IPV4,
1471 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
1472 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
1473 		.help          = hashlimit_mt_help,
1474 		.init          = hashlimit_mt4_init_v1,
1475 		.x6_parse      = hashlimit_mt_parse_v1,
1476 		.x6_fcheck     = hashlimit_mt_check_v1,
1477 		.print         = hashlimit_mt4_print_v1,
1478 		.save          = hashlimit_mt4_save_v1,
1479 		.x6_options    = hashlimit_mt_opts_v1,
1480 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1481 		.xlate         = hashlimit_mt4_xlate_v1,
1482 	},
1483 	{
1484 		.version       = XTABLES_VERSION,
1485 		.name          = "hashlimit",
1486 		.revision      = 1,
1487 		.family        = NFPROTO_IPV6,
1488 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
1489 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
1490 		.help          = hashlimit_mt_help,
1491 		.init          = hashlimit_mt6_init_v1,
1492 		.x6_parse      = hashlimit_mt_parse_v1,
1493 		.x6_fcheck     = hashlimit_mt_check_v1,
1494 		.print         = hashlimit_mt6_print_v1,
1495 		.save          = hashlimit_mt6_save_v1,
1496 		.x6_options    = hashlimit_mt_opts_v1,
1497 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1498 		.xlate         = hashlimit_mt6_xlate_v1,
1499 	},
1500 	{
1501 		.version       = XTABLES_VERSION,
1502 		.name          = "hashlimit",
1503 		.revision      = 2,
1504 		.family        = NFPROTO_IPV4,
1505 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
1506 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
1507 		.help          = hashlimit_mt_help,
1508 		.init          = hashlimit_mt4_init_v2,
1509 		.x6_parse      = hashlimit_mt_parse_v2,
1510 		.x6_fcheck     = hashlimit_mt_check_v2,
1511 		.print         = hashlimit_mt4_print_v2,
1512 		.save          = hashlimit_mt4_save_v2,
1513 		.x6_options    = hashlimit_mt_opts_v2,
1514 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1515 		.xlate         = hashlimit_mt4_xlate_v2,
1516 	},
1517 	{
1518 		.version       = XTABLES_VERSION,
1519 		.name          = "hashlimit",
1520 		.revision      = 2,
1521 		.family        = NFPROTO_IPV6,
1522 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
1523 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
1524 		.help          = hashlimit_mt_help,
1525 		.init          = hashlimit_mt6_init_v2,
1526 		.x6_parse      = hashlimit_mt_parse_v2,
1527 		.x6_fcheck     = hashlimit_mt_check_v2,
1528 		.print         = hashlimit_mt6_print_v2,
1529 		.save          = hashlimit_mt6_save_v2,
1530 		.x6_options    = hashlimit_mt_opts_v2,
1531 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1532 		.xlate         = hashlimit_mt6_xlate_v2,
1533 	},
1534 	{
1535 		.version       = XTABLES_VERSION,
1536 		.name          = "hashlimit",
1537 		.revision      = 3,
1538 		.family        = NFPROTO_IPV4,
1539 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
1540 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
1541 		.help          = hashlimit_mt_help_v3,
1542 		.init          = hashlimit_mt4_init,
1543 		.x6_parse      = hashlimit_mt_parse,
1544 		.x6_fcheck     = hashlimit_mt_check,
1545 		.print         = hashlimit_mt4_print,
1546 		.save          = hashlimit_mt4_save,
1547 		.x6_options    = hashlimit_mt_opts,
1548 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1549 		.xlate         = hashlimit_mt4_xlate,
1550 	},
1551 	{
1552 		.version       = XTABLES_VERSION,
1553 		.name          = "hashlimit",
1554 		.revision      = 3,
1555 		.family        = NFPROTO_IPV6,
1556 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
1557 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
1558 		.help          = hashlimit_mt_help_v3,
1559 		.init          = hashlimit_mt6_init,
1560 		.x6_parse      = hashlimit_mt_parse,
1561 		.x6_fcheck     = hashlimit_mt_check,
1562 		.print         = hashlimit_mt6_print,
1563 		.save          = hashlimit_mt6_save,
1564 		.x6_options    = hashlimit_mt_opts,
1565 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1566 		.xlate         = hashlimit_mt6_xlate,
1567 	},
1568 };
1569 
_init(void)1570 void _init(void)
1571 {
1572 	xtables_register_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
1573 }
1574