• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ebt_limit
2  *
3  * Authors:
4  * Tom Marshall <tommy@home.tig-grr.com>
5  *
6  * Mostly copied from iptables' limit match.
7  *
8  * September, 2003
9  *
10  * Translated to use libxtables for ebtables-compat in 2015 by
11  * Arturo Borrero Gonzalez <arturo@debian.org>
12  */
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <getopt.h>
18 #include <errno.h>
19 #include <xtables.h>
20 #include <linux/netfilter_bridge/ebt_limit.h>
21 #include "iptables/nft.h"
22 #include "iptables/nft-bridge.h"
23 
24 #define EBT_LIMIT_AVG	"3/hour"
25 #define EBT_LIMIT_BURST	5
26 
27 #define FLAG_LIMIT		0x01
28 #define FLAG_LIMIT_BURST	0x02
29 #define ARG_LIMIT		'1'
30 #define ARG_LIMIT_BURST		'2'
31 
32 static struct option brlimit_opts[] =
33 {
34 	{ .name = "limit",	.has_arg = true,	.val = ARG_LIMIT },
35 	{ .name = "limit-burst",.has_arg = true,	.val = ARG_LIMIT_BURST },
36 	XT_GETOPT_TABLEEND,
37 };
38 
brlimit_print_help(void)39 static void brlimit_print_help(void)
40 {
41 	printf(
42 "limit options:\n"
43 "--limit avg                   : max average match rate: default "EBT_LIMIT_AVG"\n"
44 "                                [Packets per second unless followed by \n"
45 "                                /sec /minute /hour /day postfixes]\n"
46 "--limit-burst number          : number to match in a burst, -1 < number < 10001,\n"
47 "                                default %u\n", EBT_LIMIT_BURST);
48 }
49 
parse_rate(const char * rate,uint32_t * val)50 static int parse_rate(const char *rate, uint32_t *val)
51 {
52 	const char *delim;
53 	uint32_t r;
54 	uint32_t mult = 1;  /* Seconds by default. */
55 
56 	delim = strchr(rate, '/');
57 	if (delim) {
58 		if (strlen(delim+1) == 0)
59 			return 0;
60 
61 		if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
62 			mult = 1;
63 		else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
64 			mult = 60;
65 		else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
66 			mult = 60*60;
67 		else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
68 			mult = 24*60*60;
69 		else
70 			return 0;
71 	}
72 	r = atoi(rate);
73 	if (!r)
74 		return 0;
75 
76 	/* This would get mapped to infinite (1/day is minimum they
77 	   can specify, so we're ok at that end). */
78 	if (r / mult > EBT_LIMIT_SCALE)
79 		return 0;
80 
81 	*val = EBT_LIMIT_SCALE * mult / r;
82 	return 1;
83 }
84 
brlimit_init(struct xt_entry_match * match)85 static void brlimit_init(struct xt_entry_match *match)
86 {
87 	struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
88 
89 	parse_rate(EBT_LIMIT_AVG, &r->avg);
90 	r->burst = EBT_LIMIT_BURST;
91 }
92 
brlimit_parse(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_match ** match)93 static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
94 			 const void *entry, struct xt_entry_match **match)
95 {
96 	struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data;
97 	uintmax_t num;
98 
99 	switch (c) {
100 	case ARG_LIMIT:
101 		EBT_CHECK_OPTION(flags, FLAG_LIMIT);
102 		if (invert)
103 			xtables_error(PARAMETER_PROBLEM,
104 				      "Unexpected `!' after --limit");
105 		if (!parse_rate(optarg, &r->avg))
106 			xtables_error(PARAMETER_PROBLEM,
107 				      "bad rate `%s'", optarg);
108 		break;
109 	case ARG_LIMIT_BURST:
110 		EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST);
111 		if (invert)
112 			xtables_error(PARAMETER_PROBLEM,
113 				      "Unexpected `!' after --limit-burst");
114 		if (!xtables_strtoul(optarg, NULL, &num, 0, 10000))
115 			xtables_error(PARAMETER_PROBLEM,
116 				      "bad --limit-burst `%s'", optarg);
117 		r->burst = num;
118 		break;
119 	default:
120 		return 0;
121 	}
122 
123 	return 1;
124 }
125 
126 struct rates
127 {
128 	const char	*name;
129 	uint32_t	mult;
130 };
131 
132 static struct rates g_rates[] =
133 {
134 	{ "day",	EBT_LIMIT_SCALE*24*60*60 },
135 	{ "hour",	EBT_LIMIT_SCALE*60*60 },
136 	{ "min",	EBT_LIMIT_SCALE*60 },
137 	{ "sec",	EBT_LIMIT_SCALE }
138 };
139 
print_rate(uint32_t period)140 static void print_rate(uint32_t period)
141 {
142 	unsigned int i;
143 
144 	for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++)
145 		if (period > g_rates[i].mult ||
146 		    g_rates[i].mult/period < g_rates[i].mult%period)
147 			break;
148 
149 	printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name);
150 }
151 
brlimit_print(const void * ip,const struct xt_entry_match * match,int numeric)152 static void brlimit_print(const void *ip, const struct xt_entry_match *match,
153 			  int numeric)
154 {
155 	struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
156 
157 	printf("--limit ");
158 	print_rate(r->avg);
159 	printf("--limit-burst %u ", r->burst);
160 }
161 
162 static struct xtables_match brlimit_match = {
163 	.name		= "limit",
164 	.revision	= 0,
165 	.version	= XTABLES_VERSION,
166 	.family		= NFPROTO_BRIDGE,
167 	.size		= XT_ALIGN(sizeof(struct ebt_limit_info)),
168 	.userspacesize	= offsetof(struct ebt_limit_info, prev),
169 	.init		= brlimit_init,
170 	.help		= brlimit_print_help,
171 	.parse		= brlimit_parse,
172 	.print		= brlimit_print,
173 	.extra_opts	= brlimit_opts,
174 };
175 
_init(void)176 void _init(void)
177 {
178 	xtables_register_match(&brlimit_match);
179 }
180