blob: 6b9bb16f4eda0ab26c38692705b95ade7f9d3a67 [file] [log] [blame]
Arturo Borreroaf72a052015-03-04 19:49:02 +01001/* 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
Arturo Borrero Gonzalez4bf10c62016-10-18 14:12:57 +020011 * Arturo Borrero Gonzalez <arturo@debian.org>
Arturo Borreroaf72a052015-03-04 19:49:02 +010012 */
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
32static 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
39static 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
50static 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
85static 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
93static 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
126struct rates
127{
128 const char *name;
129 uint32_t mult;
130};
131
132static 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
140static 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
152static 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
162static 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
176void _init(void)
177{
178 xtables_register_match(&brlimit_match);
179}