• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ip6tables match extension for limiting packets per destination
2  *
3  * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
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   <devivie@info.enserb.u-bordeaux.fr>
9  * Hervé Eychenne    <rv@wallfire.org>
10  *
11  * Error corections by nmalykh@bilim.com (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")\n",
360 					tmp, max);
361 
362 	tmp = bytes_to_cost(tmp);
363 	if (tmp == 0)
364 		xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", 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\"\n", 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 = strdup(option_arg);
512 
513 	if (!arg)
514 		return -1;
515 
516 	for (tok = strtok(arg, ",|");
517 	     tok;
518 	     tok = strtok(NULL, ",|")) {
519 		if (!strcmp(tok, "dstip"))
520 			*mode |= XT_HASHLIMIT_HASH_DIP;
521 		else if (!strcmp(tok, "srcip"))
522 			*mode |= XT_HASHLIMIT_HASH_SIP;
523 		else if (!strcmp(tok, "srcport"))
524 			*mode |= XT_HASHLIMIT_HASH_SPT;
525 		else if (!strcmp(tok, "dstport"))
526 			*mode |= XT_HASHLIMIT_HASH_DPT;
527 		else {
528 			free(arg);
529 			return -1;
530 		}
531 	}
532 	free(arg);
533 	return 0;
534 }
535 
hashlimit_parse(struct xt_option_call * cb)536 static void hashlimit_parse(struct xt_option_call *cb)
537 {
538 	struct xt_hashlimit_info *info = cb->data;
539 
540 	xtables_option_parse(cb);
541 	switch (cb->entry->id) {
542 	case O_UPTO:
543 		if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
544 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
545 			          "--hashlimit-upto", cb->arg);
546 		break;
547 	case O_MODE:
548 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
549 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
550 			          "--hashlimit-mode", cb->arg);
551 		break;
552 	}
553 }
554 
hashlimit_mt_parse_v1(struct xt_option_call * cb)555 static void hashlimit_mt_parse_v1(struct xt_option_call *cb)
556 {
557 	struct xt_hashlimit_mtinfo1 *info = cb->data;
558 
559 	xtables_option_parse(cb);
560 	switch (cb->entry->id) {
561 	case O_BURST:
562 		info->cfg.burst = parse_burst(cb->arg, 1);
563 		break;
564 	case O_UPTO:
565 		if (cb->invert)
566 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
567 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
568 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
569 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
570 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
571 			          "--hashlimit-upto", cb->arg);
572 		break;
573 	case O_ABOVE:
574 		if (!cb->invert)
575 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
576 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
577 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
578 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
579 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
580 			          "--hashlimit-above", cb->arg);
581 		break;
582 	case O_MODE:
583 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
584 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
585 			          "--hashlimit-mode", cb->arg);
586 		break;
587 	case O_SRCMASK:
588 		info->cfg.srcmask = cb->val.hlen;
589 		break;
590 	case O_DSTMASK:
591 		info->cfg.dstmask = cb->val.hlen;
592 		break;
593 	}
594 }
595 
hashlimit_mt_parse_v2(struct xt_option_call * cb)596 static void hashlimit_mt_parse_v2(struct xt_option_call *cb)
597 {
598 	struct xt_hashlimit_mtinfo2 *info = cb->data;
599 
600 	xtables_option_parse(cb);
601 	switch (cb->entry->id) {
602 	case O_BURST:
603 		info->cfg.burst = parse_burst(cb->arg, 2);
604 		break;
605 	case O_UPTO:
606 		if (cb->invert)
607 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
608 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
609 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
610 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
611 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
612 			          "--hashlimit-upto", cb->arg);
613 		break;
614 	case O_ABOVE:
615 		if (!cb->invert)
616 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
617 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
618 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
619 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
620 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
621 			          "--hashlimit-above", cb->arg);
622 		break;
623 	case O_MODE:
624 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
625 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
626 			          "--hashlimit-mode", cb->arg);
627 		break;
628 	case O_SRCMASK:
629 		info->cfg.srcmask = cb->val.hlen;
630 		break;
631 	case O_DSTMASK:
632 		info->cfg.dstmask = cb->val.hlen;
633 		break;
634 	}
635 }
636 
hashlimit_mt_parse(struct xt_option_call * cb)637 static void hashlimit_mt_parse(struct xt_option_call *cb)
638 {
639 	struct xt_hashlimit_mtinfo3 *info = cb->data;
640 
641 	xtables_option_parse(cb);
642 	switch (cb->entry->id) {
643 	case O_BURST:
644 		info->cfg.burst = parse_burst(cb->arg, 2);
645 		break;
646 	case O_UPTO:
647 		if (cb->invert)
648 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
649 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
650 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
651 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
652 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
653 			          "--hashlimit-upto", cb->arg);
654 		break;
655 	case O_ABOVE:
656 		if (!cb->invert)
657 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
658 		if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
659 			info->cfg.mode |= XT_HASHLIMIT_BYTES;
660 		else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
661 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
662 			          "--hashlimit-above", cb->arg);
663 		break;
664 	case O_MODE:
665 		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
666 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
667 			          "--hashlimit-mode", cb->arg);
668 		break;
669 	case O_SRCMASK:
670 		info->cfg.srcmask = cb->val.hlen;
671 		break;
672 	case O_DSTMASK:
673 		info->cfg.dstmask = cb->val.hlen;
674 		break;
675 	case O_RATEMATCH:
676 		info->cfg.mode |= XT_HASHLIMIT_RATE_MATCH;
677 		break;
678 	case O_INTERVAL:
679 		if (!parse_interval(cb->arg, &info->cfg.interval))
680 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
681 				"--hashlimit-rate-interval", cb->arg);
682 	}
683 }
684 
hashlimit_check(struct xt_fcheck_call * cb)685 static void hashlimit_check(struct xt_fcheck_call *cb)
686 {
687 	const struct hashlimit_mt_udata *udata = cb->udata;
688 	struct xt_hashlimit_info *info = cb->data;
689 
690 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
691 		xtables_error(PARAMETER_PROBLEM,
692 				"You have to specify --hashlimit");
693 	if (!(cb->xflags & F_HTABLE_EXPIRE))
694 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
695 }
696 
hashlimit_mt_check_v1(struct xt_fcheck_call * cb)697 static void hashlimit_mt_check_v1(struct xt_fcheck_call *cb)
698 {
699 	const struct hashlimit_mt_udata *udata = cb->udata;
700 	struct xt_hashlimit_mtinfo1 *info = cb->data;
701 
702 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
703 		xtables_error(PARAMETER_PROBLEM,
704 				"You have to specify --hashlimit");
705 	if (!(cb->xflags & F_HTABLE_EXPIRE))
706 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
707 
708 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
709 		uint32_t burst = 0;
710 		if (cb->xflags & F_BURST) {
711 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
712 				xtables_error(PARAMETER_PROBLEM,
713 					"burst cannot be smaller than %"PRIu64"b",
714 					cost_to_bytes(info->cfg.avg));
715 
716 			burst = info->cfg.burst;
717 			burst /= cost_to_bytes(info->cfg.avg);
718 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
719 				burst++;
720 			if (!(cb->xflags & F_HTABLE_EXPIRE))
721 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
722 		}
723 		info->cfg.burst = burst;
724 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX_v1)
725 		burst_error_v1();
726 }
727 
hashlimit_mt_check_v2(struct xt_fcheck_call * cb)728 static void hashlimit_mt_check_v2(struct xt_fcheck_call *cb)
729 {
730 	const struct hashlimit_mt_udata *udata = cb->udata;
731 	struct xt_hashlimit_mtinfo2 *info = cb->data;
732 
733 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
734 		xtables_error(PARAMETER_PROBLEM,
735 				"You have to specify --hashlimit");
736 	if (!(cb->xflags & F_HTABLE_EXPIRE))
737 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
738 
739 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
740 		uint32_t burst = 0;
741 		if (cb->xflags & F_BURST) {
742 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
743 				xtables_error(PARAMETER_PROBLEM,
744 					"burst cannot be smaller than %"PRIu64"b",
745 					cost_to_bytes(info->cfg.avg));
746 
747 			burst = info->cfg.burst;
748 			burst /= cost_to_bytes(info->cfg.avg);
749 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
750 				burst++;
751 			if (!(cb->xflags & F_HTABLE_EXPIRE))
752 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
753 		}
754 		info->cfg.burst = burst;
755 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
756 		burst_error();
757 }
758 
hashlimit_mt_check(struct xt_fcheck_call * cb)759 static void hashlimit_mt_check(struct xt_fcheck_call *cb)
760 {
761 	const struct hashlimit_mt_udata *udata = cb->udata;
762 	struct xt_hashlimit_mtinfo3 *info = cb->data;
763 
764 	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
765 		xtables_error(PARAMETER_PROBLEM,
766 				"You have to specify --hashlimit");
767 	if (!(cb->xflags & F_HTABLE_EXPIRE))
768 		info->cfg.expire = udata->mult * 1000; /* from s to msec */
769 
770 	if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
771 		uint32_t burst = 0;
772 		if (cb->xflags & F_BURST) {
773 			if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
774 				xtables_error(PARAMETER_PROBLEM,
775 					"burst cannot be smaller than %"PRIu64"b", cost_to_bytes(info->cfg.avg));
776 
777 			burst = info->cfg.burst;
778 			burst /= cost_to_bytes(info->cfg.avg);
779 			if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
780 				burst++;
781 			if (!(cb->xflags & F_HTABLE_EXPIRE))
782 				info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
783 		}
784 		info->cfg.burst = burst;
785 	} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
786 		burst_error();
787 
788 	if (cb->xflags & F_RATEMATCH) {
789 		if (!(info->cfg.mode & XT_HASHLIMIT_BYTES))
790 			info->cfg.avg /= udata->mult;
791 
792 		if (info->cfg.interval == 0) {
793 			if (info->cfg.mode & XT_HASHLIMIT_BYTES)
794 				info->cfg.interval = 1;
795 			else
796 				info->cfg.interval = udata->mult;
797 		}
798 	}
799 }
800 
801 struct rates {
802 	const char *name;
803 	uint64_t mult;
804 } rates_v1[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
805 		 { "hour", XT_HASHLIMIT_SCALE*60*60 },
806 		 { "min", XT_HASHLIMIT_SCALE*60 },
807 		 { "sec", XT_HASHLIMIT_SCALE } };
808 
809 static const struct rates rates[] = {
810 	{ "day", XT_HASHLIMIT_SCALE_v2*24*60*60 },
811 	{ "hour", XT_HASHLIMIT_SCALE_v2*60*60 },
812 	{ "min", XT_HASHLIMIT_SCALE_v2*60 },
813 	{ "sec", XT_HASHLIMIT_SCALE_v2 } };
814 
print_rate(uint64_t period,int revision)815 static uint32_t print_rate(uint64_t period, int revision)
816 {
817 	unsigned int i;
818 	const struct rates *_rates = (revision == 1) ? rates_v1 : rates;
819 	uint64_t scale = (revision == 1) ? XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
820 
821 	if (period == 0) {
822 		printf(" %f", INFINITY);
823 		return 0;
824 	}
825 
826 	for (i = 1; i < ARRAY_SIZE(rates); ++i)
827 		if (period > _rates[i].mult
828             || _rates[i].mult/period < _rates[i].mult%period)
829 			break;
830 
831 	printf(" %"PRIu64"/%s", _rates[i-1].mult / period, _rates[i-1].name);
832 	/* return in msec */
833 	return _rates[i-1].mult / scale * 1000;
834 }
835 
836 static const struct {
837 	const char *name;
838 	uint32_t thresh;
839 } units[] = {
840 	{ "m", 1024 * 1024 },
841 	{ "k", 1024 },
842 	{ "", 1 },
843 };
844 
print_bytes(uint64_t avg,uint64_t burst,const char * prefix)845 static uint32_t print_bytes(uint64_t avg, uint64_t burst, const char *prefix)
846 {
847 	unsigned int i;
848 	unsigned long long r;
849 
850 	r = cost_to_bytes(avg);
851 
852 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
853 		if (r >= units[i].thresh &&
854 		    bytes_to_cost(r & ~(units[i].thresh - 1)) == avg)
855 			break;
856 	printf(" %llu%sb/s", r/units[i].thresh, units[i].name);
857 
858 	if (burst == 0)
859 		return XT_HASHLIMIT_BYTE_EXPIRE * 1000;
860 
861 	r *= burst;
862 	printf(" %s", prefix);
863 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
864 		if (r >= units[i].thresh)
865 			break;
866 
867 	printf("burst %llu%sb", r / units[i].thresh, units[i].name);
868 	return XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
869 }
870 
print_mode(unsigned int mode,char separator)871 static void print_mode(unsigned int mode, char separator)
872 {
873 	bool prevmode = false;
874 
875 	putchar(' ');
876 	if (mode & XT_HASHLIMIT_HASH_SIP) {
877 		fputs("srcip", stdout);
878 		prevmode = 1;
879 	}
880 	if (mode & XT_HASHLIMIT_HASH_SPT) {
881 		if (prevmode)
882 			putchar(separator);
883 		fputs("srcport", stdout);
884 		prevmode = 1;
885 	}
886 	if (mode & XT_HASHLIMIT_HASH_DIP) {
887 		if (prevmode)
888 			putchar(separator);
889 		fputs("dstip", stdout);
890 		prevmode = 1;
891 	}
892 	if (mode & XT_HASHLIMIT_HASH_DPT) {
893 		if (prevmode)
894 			putchar(separator);
895 		fputs("dstport", stdout);
896 	}
897 }
898 
hashlimit_print(const void * ip,const struct xt_entry_match * match,int numeric)899 static void hashlimit_print(const void *ip,
900                             const struct xt_entry_match *match, int numeric)
901 {
902 	const struct xt_hashlimit_info *r = (const void *)match->data;
903 	uint32_t quantum;
904 
905 	fputs(" limit: avg", stdout);
906 	quantum = print_rate(r->cfg.avg, 1);
907 	printf(" burst %u", r->cfg.burst);
908 	fputs(" mode", stdout);
909 	print_mode(r->cfg.mode, '-');
910 	if (r->cfg.size)
911 		printf(" htable-size %u", r->cfg.size);
912 	if (r->cfg.max)
913 		printf(" htable-max %u", r->cfg.max);
914 	if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
915 		printf(" htable-gcinterval %u", r->cfg.gc_interval);
916 	if (r->cfg.expire != quantum)
917 		printf(" htable-expire %u", r->cfg.expire);
918 }
919 
920 static void
hashlimit_mt_print(const struct hashlimit_cfg3 * cfg,unsigned int dmask,int revision)921 hashlimit_mt_print(const struct hashlimit_cfg3 *cfg, unsigned int dmask, int revision)
922 {
923 	uint64_t quantum;
924 	uint64_t period;
925 
926 	if (cfg->mode & XT_HASHLIMIT_INVERT)
927 		fputs(" limit: above", stdout);
928 	else
929 		fputs(" limit: up to", stdout);
930 
931 	if (cfg->mode & XT_HASHLIMIT_BYTES) {
932 		quantum = print_bytes(cfg->avg, cfg->burst, "");
933 	} else {
934 		if (revision == 3) {
935 			period = cfg->avg;
936 			if (cfg->interval != 0)
937 				period *= cfg->interval;
938 
939 			quantum = print_rate(period, revision);
940 		} else {
941 			quantum = print_rate(cfg->avg, revision);
942 		}
943 		printf(" burst %llu", cfg->burst);
944 	}
945 	if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
946 	    XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
947 		fputs(" mode", stdout);
948 		print_mode(cfg->mode, '-');
949 	}
950 	if (cfg->size != 0)
951 		printf(" htable-size %u", cfg->size);
952 	if (cfg->max != 0)
953 		printf(" htable-max %u", cfg->max);
954 	if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
955 		printf(" htable-gcinterval %u", cfg->gc_interval);
956 	if (cfg->expire != quantum)
957 		printf(" htable-expire %u", cfg->expire);
958 
959 	if (cfg->srcmask != dmask)
960 		printf(" srcmask %u", cfg->srcmask);
961 	if (cfg->dstmask != dmask)
962 		printf(" dstmask %u", cfg->dstmask);
963 
964 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
965 		printf(" rate-match");
966 
967 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
968 		if (cfg->interval != 1)
969 			printf(" rate-interval %u", cfg->interval);
970 }
971 
972 static void
hashlimit_mt4_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)973 hashlimit_mt4_print_v1(const void *ip, const struct xt_entry_match *match,
974                    int numeric)
975 {
976 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
977 	struct hashlimit_cfg3 cfg;
978 	int ret;
979 
980 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
981 
982 	if (ret)
983 		xtables_error(OTHER_PROBLEM, "unknown revision");
984 
985 	hashlimit_mt_print(&cfg, 32, 1);
986 }
987 
988 static void
hashlimit_mt6_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)989 hashlimit_mt6_print_v1(const void *ip, const struct xt_entry_match *match,
990                    int numeric)
991 {
992 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
993 	struct hashlimit_cfg3 cfg;
994 	int ret;
995 
996 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
997 
998 	if (ret)
999 		xtables_error(OTHER_PROBLEM, "unknown revision");
1000 
1001 	hashlimit_mt_print(&cfg, 128, 1);
1002 }
1003 
1004 static void
hashlimit_mt4_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)1005 hashlimit_mt4_print_v2(const void *ip, const struct xt_entry_match *match,
1006                    int numeric)
1007 {
1008 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1009 	struct hashlimit_cfg3 cfg;
1010 	int ret;
1011 
1012 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1013 
1014 	if (ret)
1015 		xtables_error(OTHER_PROBLEM, "unknown revision");
1016 
1017 	hashlimit_mt_print(&cfg, 32, 2);
1018 }
1019 
1020 static void
hashlimit_mt6_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)1021 hashlimit_mt6_print_v2(const void *ip, const struct xt_entry_match *match,
1022                    int numeric)
1023 {
1024 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1025 	struct hashlimit_cfg3 cfg;
1026 	int ret;
1027 
1028 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1029 
1030 	if (ret)
1031 		xtables_error(OTHER_PROBLEM, "unknown revision");
1032 
1033 	hashlimit_mt_print(&cfg, 128, 2);
1034 }
1035 static void
hashlimit_mt4_print(const void * ip,const struct xt_entry_match * match,int numeric)1036 hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
1037                    int numeric)
1038 {
1039 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1040 
1041 	hashlimit_mt_print(&info->cfg, 32, 3);
1042 }
1043 
1044 static void
hashlimit_mt6_print(const void * ip,const struct xt_entry_match * match,int numeric)1045 hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
1046                    int numeric)
1047 {
1048 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1049 
1050 	hashlimit_mt_print(&info->cfg, 128, 3);
1051 }
1052 
hashlimit_save(const void * ip,const struct xt_entry_match * match)1053 static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
1054 {
1055 	const struct xt_hashlimit_info *r = (const void *)match->data;
1056 	uint32_t quantum;
1057 
1058 	fputs(" --hashlimit", stdout);
1059 	quantum = print_rate(r->cfg.avg, 1);
1060 	printf(" --hashlimit-burst %u", r->cfg.burst);
1061 
1062 	fputs(" --hashlimit-mode", stdout);
1063 	print_mode(r->cfg.mode, ',');
1064 
1065 	printf(" --hashlimit-name %s", r->name);
1066 
1067 	if (r->cfg.size)
1068 		printf(" --hashlimit-htable-size %u", r->cfg.size);
1069 	if (r->cfg.max)
1070 		printf(" --hashlimit-htable-max %u", r->cfg.max);
1071 	if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
1072 		printf(" --hashlimit-htable-gcinterval %u", r->cfg.gc_interval);
1073 	if (r->cfg.expire != quantum)
1074 		printf(" --hashlimit-htable-expire %u", r->cfg.expire);
1075 }
1076 
1077 static void
hashlimit_mt_save(const struct hashlimit_cfg3 * cfg,const char * name,unsigned int dmask,int revision)1078 hashlimit_mt_save(const struct hashlimit_cfg3 *cfg, const char* name, unsigned int dmask, int revision)
1079 {
1080 	uint32_t quantum;
1081 
1082 	if (cfg->mode & XT_HASHLIMIT_INVERT)
1083 		fputs(" --hashlimit-above", stdout);
1084 	else
1085 		fputs(" --hashlimit-upto", stdout);
1086 
1087 	if (cfg->mode & XT_HASHLIMIT_BYTES) {
1088 		quantum = print_bytes(cfg->avg, cfg->burst, "--hashlimit-");
1089 	} else {
1090 		quantum = print_rate(cfg->avg, revision);
1091 		printf(" --hashlimit-burst %llu", cfg->burst);
1092 	}
1093 
1094 	if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
1095 	    XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
1096 		fputs(" --hashlimit-mode", stdout);
1097 		print_mode(cfg->mode, ',');
1098 	}
1099 
1100 	printf(" --hashlimit-name %s", name);
1101 
1102 	if (cfg->size != 0)
1103 		printf(" --hashlimit-htable-size %u", cfg->size);
1104 	if (cfg->max != 0)
1105 		printf(" --hashlimit-htable-max %u", cfg->max);
1106 	if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
1107 		printf(" --hashlimit-htable-gcinterval %u", cfg->gc_interval);
1108 	if (cfg->expire != quantum)
1109 		printf(" --hashlimit-htable-expire %u", cfg->expire);
1110 
1111 	if (cfg->srcmask != dmask)
1112 		printf(" --hashlimit-srcmask %u", cfg->srcmask);
1113 	if (cfg->dstmask != dmask)
1114 		printf(" --hashlimit-dstmask %u", cfg->dstmask);
1115 
1116 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
1117 		printf(" --hashlimit-rate-match");
1118 
1119 	if ((revision == 3) && (cfg->mode & XT_HASHLIMIT_RATE_MATCH))
1120 		if (cfg->interval != 1)
1121 			printf(" --hashlimit-rate-interval %u", cfg->interval);
1122 }
1123 
1124 static void
hashlimit_mt4_save_v1(const void * ip,const struct xt_entry_match * match)1125 hashlimit_mt4_save_v1(const void *ip, const struct xt_entry_match *match)
1126 {
1127 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
1128 	struct hashlimit_cfg3 cfg;
1129 	int ret;
1130 
1131 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
1132 
1133 	if (ret)
1134 		xtables_error(OTHER_PROBLEM, "unknown revision");
1135 
1136 	hashlimit_mt_save(&cfg, info->name, 32, 1);
1137 }
1138 
1139 static void
hashlimit_mt6_save_v1(const void * ip,const struct xt_entry_match * match)1140 hashlimit_mt6_save_v1(const void *ip, const struct xt_entry_match *match)
1141 {
1142 	const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
1143 	struct hashlimit_cfg3 cfg;
1144 	int ret;
1145 
1146 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
1147 
1148 	if (ret)
1149 		xtables_error(OTHER_PROBLEM, "unknown revision");
1150 
1151 	hashlimit_mt_save(&cfg, info->name, 128, 1);
1152 }
1153 
1154 static void
hashlimit_mt4_save_v2(const void * ip,const struct xt_entry_match * match)1155 hashlimit_mt4_save_v2(const void *ip, const struct xt_entry_match *match)
1156 {
1157 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1158 	struct hashlimit_cfg3 cfg;
1159 	int ret;
1160 
1161 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1162 
1163 	if (ret)
1164 		xtables_error(OTHER_PROBLEM, "unknown revision");
1165 
1166 	hashlimit_mt_save(&cfg, info->name, 32, 2);
1167 }
1168 
1169 static void
hashlimit_mt6_save_v2(const void * ip,const struct xt_entry_match * match)1170 hashlimit_mt6_save_v2(const void *ip, const struct xt_entry_match *match)
1171 {
1172 	const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
1173 	struct hashlimit_cfg3 cfg;
1174 	int ret;
1175 
1176 	ret = cfg_copy(&cfg, (const void *)&info->cfg, 2);
1177 
1178 	if (ret)
1179 		xtables_error(OTHER_PROBLEM, "unknown revision");
1180 
1181 	hashlimit_mt_save(&cfg, info->name, 128, 2);
1182 }
1183 
1184 static void
hashlimit_mt4_save(const void * ip,const struct xt_entry_match * match)1185 hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
1186 {
1187 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1188 
1189 	hashlimit_mt_save(&info->cfg, info->name, 32, 3);
1190 }
1191 
1192 static void
hashlimit_mt6_save(const void * ip,const struct xt_entry_match * match)1193 hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
1194 {
1195 	const struct xt_hashlimit_mtinfo3 *info = (const void *)match->data;
1196 
1197 	hashlimit_mt_save(&info->cfg, info->name, 128, 3);
1198 }
1199 
1200 static const struct rates rates_v1_xlate[] = {
1201 	{ "day", XT_HASHLIMIT_SCALE * 24 * 60 * 60 },
1202 	{ "hour", XT_HASHLIMIT_SCALE * 60 * 60 },
1203 	{ "minute", XT_HASHLIMIT_SCALE * 60 },
1204 	{ "second", XT_HASHLIMIT_SCALE } };
1205 
1206 static const struct rates rates_xlate[] = {
1207 	{ "day", XT_HASHLIMIT_SCALE_v2 * 24 * 60 * 60 },
1208 	{ "hour", XT_HASHLIMIT_SCALE_v2 * 60 * 60 },
1209 	{ "minute", XT_HASHLIMIT_SCALE_v2 * 60 },
1210 	{ "second", XT_HASHLIMIT_SCALE_v2 } };
1211 
print_packets_rate_xlate(struct xt_xlate * xl,uint64_t avg,int revision)1212 static void print_packets_rate_xlate(struct xt_xlate *xl, uint64_t avg,
1213 				     int revision)
1214 {
1215 	unsigned int i;
1216 	const struct rates *_rates = (revision == 1) ?
1217 		rates_v1_xlate : rates_xlate;
1218 
1219 	for (i = 1; i < ARRAY_SIZE(rates); ++i)
1220 		if (avg > _rates[i].mult ||
1221 		    _rates[i].mult / avg < _rates[i].mult % avg)
1222 			break;
1223 
1224 	xt_xlate_add(xl, " %" PRIu64 "/%s ",
1225 		     _rates[i-1].mult / avg, _rates[i-1].name);
1226 }
1227 
print_bytes_rate_xlate(struct xt_xlate * xl,const struct hashlimit_cfg3 * cfg)1228 static void print_bytes_rate_xlate(struct xt_xlate *xl,
1229 				   const struct hashlimit_cfg3 *cfg)
1230 {
1231 	unsigned int i;
1232 	unsigned long long r;
1233 
1234 	r = cost_to_bytes(cfg->avg);
1235 
1236 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
1237 		if (r >= units[i].thresh &&
1238 		    bytes_to_cost(r & ~(units[i].thresh - 1)) == cfg->avg)
1239 			break;
1240 
1241 	xt_xlate_add(xl, " %llu %sbytes/second", r / units[i].thresh,
1242 		     units[i].name);
1243 
1244 	r *= cfg->burst;
1245 	for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
1246 		if (r >= units[i].thresh)
1247 			break;
1248 
1249 	if (cfg->burst > 0)
1250 		xt_xlate_add(xl, " burst %llu %sbytes", r / units[i].thresh,
1251 			     units[i].name);
1252 }
1253 
hashlimit_print_subnet_xlate(struct xt_xlate * xl,uint32_t nsub,int family)1254 static void hashlimit_print_subnet_xlate(struct xt_xlate *xl,
1255 					 uint32_t nsub, int family)
1256 {
1257 	char sep = (family == NFPROTO_IPV4) ? '.' : ':';
1258 	char *fmt = (family == NFPROTO_IPV4) ? "%u" : "%04x";
1259 	unsigned int nblocks = (family == NFPROTO_IPV4) ? 4 : 8;
1260 	unsigned int nbits = (family == NFPROTO_IPV4) ? 8 : 16;
1261 	unsigned int acm, i;
1262 
1263 	xt_xlate_add(xl, " and ");
1264 	while (nblocks--) {
1265 		acm = 0;
1266 
1267 		for (i = 0; i < nbits; i++) {
1268 			acm <<= 1;
1269 
1270 			if (nsub > 0) {
1271 				acm++;
1272 				nsub--;
1273 			}
1274 		}
1275 
1276 		xt_xlate_add(xl, fmt, acm);
1277 		if (nblocks > 0)
1278 			xt_xlate_add(xl, "%c", sep);
1279 	}
1280 }
1281 
1282 static const char *const hashlimit_modes4_xlate[] = {
1283 	[XT_HASHLIMIT_HASH_DIP]	= "ip daddr",
1284 	[XT_HASHLIMIT_HASH_DPT]	= "tcp dport",
1285 	[XT_HASHLIMIT_HASH_SIP]	= "ip saddr",
1286 	[XT_HASHLIMIT_HASH_SPT]	= "tcp sport",
1287 };
1288 
1289 static const char *const hashlimit_modes6_xlate[] = {
1290 	[XT_HASHLIMIT_HASH_DIP]	= "ip6 daddr",
1291 	[XT_HASHLIMIT_HASH_DPT]	= "tcp dport",
1292 	[XT_HASHLIMIT_HASH_SIP]	= "ip6 saddr",
1293 	[XT_HASHLIMIT_HASH_SPT]	= "tcp sport",
1294 };
1295 
hashlimit_mode_xlate(struct xt_xlate * xl,uint32_t mode,int family,unsigned int nsrc,unsigned int ndst)1296 static int hashlimit_mode_xlate(struct xt_xlate *xl,
1297 				uint32_t mode, int family,
1298 				unsigned int nsrc, unsigned int ndst)
1299 {
1300 	const char * const *_modes = (family == NFPROTO_IPV4) ?
1301 		hashlimit_modes4_xlate : hashlimit_modes6_xlate;
1302 	bool prevopt = false;
1303 	unsigned int mask;
1304 
1305 	mode &= ~XT_HASHLIMIT_INVERT & ~XT_HASHLIMIT_BYTES;
1306 
1307 	for (mask = 1; mode > 0; mask <<= 1) {
1308 		if (!(mode & mask))
1309 			continue;
1310 
1311 		if (!prevopt) {
1312 			xt_xlate_add(xl, " ");
1313 			prevopt = true;
1314 		}
1315 		else {
1316 			xt_xlate_add(xl, " . ");
1317 		}
1318 
1319 		xt_xlate_add(xl, "%s", _modes[mask]);
1320 
1321 		if (mask == XT_HASHLIMIT_HASH_DIP &&
1322 		    ((family == NFPROTO_IPV4 && ndst != 32) ||
1323 		     (family == NFPROTO_IPV6 && ndst != 128)))
1324 			hashlimit_print_subnet_xlate(xl, ndst, family);
1325 		else if (mask == XT_HASHLIMIT_HASH_SIP &&
1326 			 ((family == NFPROTO_IPV4 && nsrc != 32) ||
1327 			  (family == NFPROTO_IPV6 && nsrc != 128)))
1328 			hashlimit_print_subnet_xlate(xl, nsrc, family);
1329 
1330 		mode &= ~mask;
1331 	}
1332 
1333 	return prevopt;
1334 }
1335 
hashlimit_mt_xlate(struct xt_xlate * xl,const char * name,const struct hashlimit_cfg3 * cfg,int revision,int family)1336 static int hashlimit_mt_xlate(struct xt_xlate *xl, const char *name,
1337 			      const struct hashlimit_cfg3 *cfg,
1338 			      int revision, int family)
1339 {
1340 	int ret = 1;
1341 
1342 	xt_xlate_add(xl, "meter %s {", name);
1343 	ret = hashlimit_mode_xlate(xl, cfg->mode, family,
1344 				   cfg->srcmask, cfg->dstmask);
1345 	if (cfg->expire != 1000)
1346 		xt_xlate_add(xl, " timeout %us", cfg->expire / 1000);
1347 	xt_xlate_add(xl, " limit rate");
1348 
1349 	if (cfg->mode & XT_HASHLIMIT_INVERT)
1350 		xt_xlate_add(xl, " over");
1351 
1352 	if (cfg->mode & XT_HASHLIMIT_BYTES)
1353 		print_bytes_rate_xlate(xl, cfg);
1354 	else {
1355 		print_packets_rate_xlate(xl, cfg->avg, revision);
1356 		if (cfg->burst != XT_HASHLIMIT_BURST)
1357 			xt_xlate_add(xl, "burst %" PRIu64 " packets", (uint64_t)cfg->burst);
1358 
1359 	}
1360 	xt_xlate_add(xl, "}");
1361 
1362 	return ret;
1363 }
1364 
hashlimit_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1365 static int hashlimit_xlate(struct xt_xlate *xl,
1366 			   const struct xt_xlate_mt_params *params)
1367 {
1368 	const struct xt_hashlimit_info *info = (const void *)params->match->data;
1369 	int ret = 1;
1370 
1371 	xt_xlate_add(xl, "meter %s {", info->name);
1372 	ret = hashlimit_mode_xlate(xl, info->cfg.mode, NFPROTO_IPV4, 32, 32);
1373 	xt_xlate_add(xl, " timeout %us limit rate", info->cfg.expire / 1000);
1374 	print_packets_rate_xlate(xl, info->cfg.avg, 1);
1375 	xt_xlate_add(xl, " burst %u packets", info->cfg.burst);
1376 	xt_xlate_add(xl, "}");
1377 
1378 	return ret;
1379 }
1380 
hashlimit_mt4_xlate_v1(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1381 static int hashlimit_mt4_xlate_v1(struct xt_xlate *xl,
1382 				  const struct xt_xlate_mt_params *params)
1383 {
1384 	const struct xt_hashlimit_mtinfo1 *info =
1385 		(const void *)params->match->data;
1386 	struct hashlimit_cfg3 cfg;
1387 
1388 	if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
1389 		xtables_error(OTHER_PROBLEM, "unknown revision");
1390 
1391 	return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV4);
1392 }
1393 
hashlimit_mt6_xlate_v1(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1394 static int hashlimit_mt6_xlate_v1(struct xt_xlate *xl,
1395 				  const struct xt_xlate_mt_params *params)
1396 {
1397 	const struct xt_hashlimit_mtinfo1 *info =
1398 		(const void *)params->match->data;
1399 	struct hashlimit_cfg3 cfg;
1400 
1401 	if (cfg_copy(&cfg, (const void *)&info->cfg, 1))
1402 		xtables_error(OTHER_PROBLEM, "unknown revision");
1403 
1404 	return hashlimit_mt_xlate(xl, info->name, &cfg, 1, NFPROTO_IPV6);
1405 }
1406 
hashlimit_mt4_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1407 static int hashlimit_mt4_xlate_v2(struct xt_xlate *xl,
1408 				  const struct xt_xlate_mt_params *params)
1409 {
1410 	const struct xt_hashlimit_mtinfo2 *info =
1411 		(const void *)params->match->data;
1412 	struct hashlimit_cfg3 cfg;
1413 
1414 	if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
1415 		xtables_error(OTHER_PROBLEM, "unknown revision");
1416 
1417 	return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV4);
1418 }
1419 
hashlimit_mt6_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1420 static int hashlimit_mt6_xlate_v2(struct xt_xlate *xl,
1421 				  const struct xt_xlate_mt_params *params)
1422 {
1423 	const struct xt_hashlimit_mtinfo2 *info =
1424 		(const void *)params->match->data;
1425 	struct hashlimit_cfg3 cfg;
1426 
1427 	if (cfg_copy(&cfg, (const void *)&info->cfg, 2))
1428 		xtables_error(OTHER_PROBLEM, "unknown revision");
1429 
1430 	return hashlimit_mt_xlate(xl, info->name, &cfg, 2, NFPROTO_IPV6);
1431 }
1432 
hashlimit_mt4_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1433 static int hashlimit_mt4_xlate(struct xt_xlate *xl,
1434 			       const struct xt_xlate_mt_params *params)
1435 {
1436 	const struct xt_hashlimit_mtinfo3 *info =
1437 		(const void *)params->match->data;
1438 
1439 	return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV4);
1440 }
1441 
hashlimit_mt6_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)1442 static int hashlimit_mt6_xlate(struct xt_xlate *xl,
1443 			       const struct xt_xlate_mt_params *params)
1444 {
1445 	const struct xt_hashlimit_mtinfo3 *info =
1446 		(const void *)params->match->data;
1447 
1448 	return hashlimit_mt_xlate(xl, info->name, &info->cfg, 3, NFPROTO_IPV6);
1449 }
1450 
1451 static struct xtables_match hashlimit_mt_reg[] = {
1452 	{
1453 		.family        = NFPROTO_UNSPEC,
1454 		.name          = "hashlimit",
1455 		.version       = XTABLES_VERSION,
1456 		.revision      = 0,
1457 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_info)),
1458 		.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
1459 		.help          = hashlimit_help,
1460 		.init          = hashlimit_init,
1461 		.x6_parse      = hashlimit_parse,
1462 		.x6_fcheck     = hashlimit_check,
1463 		.print         = hashlimit_print,
1464 		.save          = hashlimit_save,
1465 		.x6_options    = hashlimit_opts,
1466 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1467 		.xlate         = hashlimit_xlate,
1468 	},
1469 	{
1470 		.version       = XTABLES_VERSION,
1471 		.name          = "hashlimit",
1472 		.revision      = 1,
1473 		.family        = NFPROTO_IPV4,
1474 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
1475 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
1476 		.help          = hashlimit_mt_help,
1477 		.init          = hashlimit_mt4_init_v1,
1478 		.x6_parse      = hashlimit_mt_parse_v1,
1479 		.x6_fcheck     = hashlimit_mt_check_v1,
1480 		.print         = hashlimit_mt4_print_v1,
1481 		.save          = hashlimit_mt4_save_v1,
1482 		.x6_options    = hashlimit_mt_opts_v1,
1483 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1484 		.xlate         = hashlimit_mt4_xlate_v1,
1485 	},
1486 	{
1487 		.version       = XTABLES_VERSION,
1488 		.name          = "hashlimit",
1489 		.revision      = 1,
1490 		.family        = NFPROTO_IPV6,
1491 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
1492 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
1493 		.help          = hashlimit_mt_help,
1494 		.init          = hashlimit_mt6_init_v1,
1495 		.x6_parse      = hashlimit_mt_parse_v1,
1496 		.x6_fcheck     = hashlimit_mt_check_v1,
1497 		.print         = hashlimit_mt6_print_v1,
1498 		.save          = hashlimit_mt6_save_v1,
1499 		.x6_options    = hashlimit_mt_opts_v1,
1500 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1501 		.xlate         = hashlimit_mt6_xlate_v1,
1502 	},
1503 	{
1504 		.version       = XTABLES_VERSION,
1505 		.name          = "hashlimit",
1506 		.revision      = 2,
1507 		.family        = NFPROTO_IPV4,
1508 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
1509 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
1510 		.help          = hashlimit_mt_help,
1511 		.init          = hashlimit_mt4_init_v2,
1512 		.x6_parse      = hashlimit_mt_parse_v2,
1513 		.x6_fcheck     = hashlimit_mt_check_v2,
1514 		.print         = hashlimit_mt4_print_v2,
1515 		.save          = hashlimit_mt4_save_v2,
1516 		.x6_options    = hashlimit_mt_opts_v2,
1517 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1518 		.xlate         = hashlimit_mt4_xlate_v2,
1519 	},
1520 	{
1521 		.version       = XTABLES_VERSION,
1522 		.name          = "hashlimit",
1523 		.revision      = 2,
1524 		.family        = NFPROTO_IPV6,
1525 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
1526 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
1527 		.help          = hashlimit_mt_help,
1528 		.init          = hashlimit_mt6_init_v2,
1529 		.x6_parse      = hashlimit_mt_parse_v2,
1530 		.x6_fcheck     = hashlimit_mt_check_v2,
1531 		.print         = hashlimit_mt6_print_v2,
1532 		.save          = hashlimit_mt6_save_v2,
1533 		.x6_options    = hashlimit_mt_opts_v2,
1534 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1535 		.xlate         = hashlimit_mt6_xlate_v2,
1536 	},
1537 	{
1538 		.version       = XTABLES_VERSION,
1539 		.name          = "hashlimit",
1540 		.revision      = 3,
1541 		.family        = NFPROTO_IPV4,
1542 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
1543 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
1544 		.help          = hashlimit_mt_help_v3,
1545 		.init          = hashlimit_mt4_init,
1546 		.x6_parse      = hashlimit_mt_parse,
1547 		.x6_fcheck     = hashlimit_mt_check,
1548 		.print         = hashlimit_mt4_print,
1549 		.save          = hashlimit_mt4_save,
1550 		.x6_options    = hashlimit_mt_opts,
1551 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1552 		.xlate         = hashlimit_mt4_xlate,
1553 	},
1554 	{
1555 		.version       = XTABLES_VERSION,
1556 		.name          = "hashlimit",
1557 		.revision      = 3,
1558 		.family        = NFPROTO_IPV6,
1559 		.size          = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo3)),
1560 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo3, hinfo),
1561 		.help          = hashlimit_mt_help_v3,
1562 		.init          = hashlimit_mt6_init,
1563 		.x6_parse      = hashlimit_mt_parse,
1564 		.x6_fcheck     = hashlimit_mt_check,
1565 		.print         = hashlimit_mt6_print,
1566 		.save          = hashlimit_mt6_save,
1567 		.x6_options    = hashlimit_mt_opts,
1568 		.udata_size    = sizeof(struct hashlimit_mt_udata),
1569 		.xlate         = hashlimit_mt6_xlate,
1570 	},
1571 };
1572 
_init(void)1573 void _init(void)
1574 {
1575 	xtables_register_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
1576 }
1577