4 * Tom Marshall <tommy@home.tig-grr.com>
6 * Mostly copied from iptables' limit match.
16 #include "../include/ebtables_u.h"
17 #include <linux/netfilter_bridge/ebt_limit.h>
19 #define EBT_LIMIT_AVG "3/hour"
20 #define EBT_LIMIT_BURST 5
22 static int string_to_number(const char *s
, unsigned int min
, unsigned int max
,
29 number
= strtol(s
, &end
, 0);
30 if (*end
== '\0' && end
!= s
) {
31 if (errno
!= ERANGE
&& min
<= number
&& number
<= max
) {
39 #define FLAG_LIMIT 0x01
40 #define FLAG_LIMIT_BURST 0x02
42 #define ARG_LIMIT_BURST '2'
44 static struct option opts
[] =
46 { "limit", required_argument
, 0, ARG_LIMIT
},
47 { "limit-burst", required_argument
, 0, ARG_LIMIT_BURST
},
51 static void print_help(void)
55 "--limit avg : max average match rate: default "EBT_LIMIT_AVG
"\n"
56 " [Packets per second unless followed by \n"
57 " /sec /minute /hour /day postfixes]\n"
58 "--limit-burst number : number to match in a burst, -1 < number < 10001,\n"
59 " default %u\n", EBT_LIMIT_BURST
);
62 static int parse_rate(const char *rate
, u_int32_t
*val
)
66 u_int32_t mult
= 1; /* Seconds by default. */
68 delim
= strchr(rate
, '/');
70 if (strlen(delim
+1) == 0)
73 if (strncasecmp(delim
+1, "second", strlen(delim
+1)) == 0)
75 else if (strncasecmp(delim
+1, "minute", strlen(delim
+1)) == 0)
77 else if (strncasecmp(delim
+1, "hour", strlen(delim
+1)) == 0)
79 else if (strncasecmp(delim
+1, "day", strlen(delim
+1)) == 0)
88 /* This would get mapped to infinite (1/day is minimum they
89 can specify, so we're ok at that end). */
90 if (r
/ mult
> EBT_LIMIT_SCALE
)
93 *val
= EBT_LIMIT_SCALE
* mult
/ r
;
97 /* Initialize the match. */
98 static void init(struct ebt_entry_match
*m
)
100 struct ebt_limit_info
*r
= (struct ebt_limit_info
*)m
->data
;
102 parse_rate(EBT_LIMIT_AVG
, &r
->avg
);
103 r
->burst
= EBT_LIMIT_BURST
;
106 /* FIXME: handle overflow:
107 if (r->avg*r->burst/r->burst != r->avg)
108 exit_error(PARAMETER_PROBLEM,
109 "Sorry: burst too large for that avg rate.\n");
112 static int parse(int c
, char **argv
, int argc
,
113 const struct ebt_u_entry
*entry
,
115 struct ebt_entry_match
**match
)
117 struct ebt_limit_info
*r
= (struct ebt_limit_info
*)(*match
)->data
;
122 ebt_check_option2(flags
, FLAG_LIMIT
);
123 if (ebt_check_inverse2(optarg
))
124 ebt_print_error2("Unexpected `!' after --limit");
125 if (!parse_rate(optarg
, &r
->avg
))
126 ebt_print_error2("bad rate `%s'", optarg
);
129 case ARG_LIMIT_BURST
:
130 ebt_check_option2(flags
, FLAG_LIMIT_BURST
);
131 if (ebt_check_inverse2(optarg
))
132 ebt_print_error2("Unexpected `!' after --limit-burst");
133 if (string_to_number(optarg
, 0, 10000, &num
) == -1)
134 ebt_print_error2("bad --limit-burst `%s'", optarg
);
145 static void final_check(const struct ebt_u_entry
*entry
,
146 const struct ebt_entry_match
*match
, const char *name
,
147 unsigned int hookmask
, unsigned int time
)
157 static struct rates g_rates
[] =
159 { "day", EBT_LIMIT_SCALE
*24*60*60 },
160 { "hour", EBT_LIMIT_SCALE
*60*60 },
161 { "min", EBT_LIMIT_SCALE
*60 },
162 { "sec", EBT_LIMIT_SCALE
}
165 static void print_rate(u_int32_t period
)
169 for (i
= 1; i
< sizeof(g_rates
)/sizeof(struct rates
); i
++)
170 if (period
> g_rates
[i
].mult
||
171 g_rates
[i
].mult
/period
< g_rates
[i
].mult
%period
)
174 printf("%u/%s ", g_rates
[i
-1].mult
/ period
, g_rates
[i
-1].name
);
177 static void print(const struct ebt_u_entry
*entry
,
178 const struct ebt_entry_match
*match
)
180 struct ebt_limit_info
*r
= (struct ebt_limit_info
*)match
->data
;
184 printf("--limit-burst %u ", r
->burst
);
187 static int compare(const struct ebt_entry_match
* m1
,
188 const struct ebt_entry_match
*m2
)
190 struct ebt_limit_info
* li1
= (struct ebt_limit_info
*)m1
->data
;
191 struct ebt_limit_info
* li2
= (struct ebt_limit_info
*)m2
->data
;
193 if (li1
->avg
!= li2
->avg
)
196 if (li1
->burst
!= li2
->burst
)
202 static struct ebt_u_match limit_match
=
205 .size
= sizeof(struct ebt_limit_info
),
209 .final_check
= final_check
,
217 ebt_register_match(&limit_match
);