You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.3 KiB
179 lines
4.3 KiB
/* ebt_limit |
|
* |
|
* Authors: |
|
* Tom Marshall <tommy@home.tig-grr.com> |
|
* |
|
* Mostly copied from iptables' limit match. |
|
* |
|
* September, 2003 |
|
* |
|
* Translated to use libxtables for ebtables-compat in 2015 by |
|
* Arturo Borrero Gonzalez <arturo@debian.org> |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <getopt.h> |
|
#include <errno.h> |
|
#include <xtables.h> |
|
#include <linux/netfilter_bridge/ebt_limit.h> |
|
#include "iptables/nft.h" |
|
#include "iptables/nft-bridge.h" |
|
|
|
#define EBT_LIMIT_AVG "3/hour" |
|
#define EBT_LIMIT_BURST 5 |
|
|
|
#define FLAG_LIMIT 0x01 |
|
#define FLAG_LIMIT_BURST 0x02 |
|
#define ARG_LIMIT '1' |
|
#define ARG_LIMIT_BURST '2' |
|
|
|
static struct option brlimit_opts[] = |
|
{ |
|
{ .name = "limit", .has_arg = true, .val = ARG_LIMIT }, |
|
{ .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST }, |
|
XT_GETOPT_TABLEEND, |
|
}; |
|
|
|
static void brlimit_print_help(void) |
|
{ |
|
printf( |
|
"limit options:\n" |
|
"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n" |
|
" [Packets per second unless followed by \n" |
|
" /sec /minute /hour /day postfixes]\n" |
|
"--limit-burst number : number to match in a burst, -1 < number < 10001,\n" |
|
" default %u\n", EBT_LIMIT_BURST); |
|
} |
|
|
|
static int parse_rate(const char *rate, uint32_t *val) |
|
{ |
|
const char *delim; |
|
uint32_t r; |
|
uint32_t mult = 1; /* Seconds by default. */ |
|
|
|
delim = strchr(rate, '/'); |
|
if (delim) { |
|
if (strlen(delim+1) == 0) |
|
return 0; |
|
|
|
if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0) |
|
mult = 1; |
|
else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0) |
|
mult = 60; |
|
else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0) |
|
mult = 60*60; |
|
else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0) |
|
mult = 24*60*60; |
|
else |
|
return 0; |
|
} |
|
r = atoi(rate); |
|
if (!r) |
|
return 0; |
|
|
|
/* This would get mapped to infinite (1/day is minimum they |
|
can specify, so we're ok at that end). */ |
|
if (r / mult > EBT_LIMIT_SCALE) |
|
return 0; |
|
|
|
*val = EBT_LIMIT_SCALE * mult / r; |
|
return 1; |
|
} |
|
|
|
static void brlimit_init(struct xt_entry_match *match) |
|
{ |
|
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; |
|
|
|
parse_rate(EBT_LIMIT_AVG, &r->avg); |
|
r->burst = EBT_LIMIT_BURST; |
|
} |
|
|
|
static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags, |
|
const void *entry, struct xt_entry_match **match) |
|
{ |
|
struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data; |
|
uintmax_t num; |
|
|
|
switch (c) { |
|
case ARG_LIMIT: |
|
EBT_CHECK_OPTION(flags, FLAG_LIMIT); |
|
if (invert) |
|
xtables_error(PARAMETER_PROBLEM, |
|
"Unexpected `!' after --limit"); |
|
if (!parse_rate(optarg, &r->avg)) |
|
xtables_error(PARAMETER_PROBLEM, |
|
"bad rate `%s'", optarg); |
|
break; |
|
case ARG_LIMIT_BURST: |
|
EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST); |
|
if (invert) |
|
xtables_error(PARAMETER_PROBLEM, |
|
"Unexpected `!' after --limit-burst"); |
|
if (!xtables_strtoul(optarg, NULL, &num, 0, 10000)) |
|
xtables_error(PARAMETER_PROBLEM, |
|
"bad --limit-burst `%s'", optarg); |
|
r->burst = num; |
|
break; |
|
default: |
|
return 0; |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
struct rates |
|
{ |
|
const char *name; |
|
uint32_t mult; |
|
}; |
|
|
|
static struct rates g_rates[] = |
|
{ |
|
{ "day", EBT_LIMIT_SCALE*24*60*60 }, |
|
{ "hour", EBT_LIMIT_SCALE*60*60 }, |
|
{ "min", EBT_LIMIT_SCALE*60 }, |
|
{ "sec", EBT_LIMIT_SCALE } |
|
}; |
|
|
|
static void print_rate(uint32_t period) |
|
{ |
|
unsigned int i; |
|
|
|
for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++) |
|
if (period > g_rates[i].mult || |
|
g_rates[i].mult/period < g_rates[i].mult%period) |
|
break; |
|
|
|
printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name); |
|
} |
|
|
|
static void brlimit_print(const void *ip, const struct xt_entry_match *match, |
|
int numeric) |
|
{ |
|
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; |
|
|
|
printf("--limit "); |
|
print_rate(r->avg); |
|
printf("--limit-burst %u ", r->burst); |
|
} |
|
|
|
static struct xtables_match brlimit_match = { |
|
.name = "limit", |
|
.revision = 0, |
|
.version = XTABLES_VERSION, |
|
.family = NFPROTO_BRIDGE, |
|
.size = XT_ALIGN(sizeof(struct ebt_limit_info)), |
|
.userspacesize = offsetof(struct ebt_limit_info, prev), |
|
.init = brlimit_init, |
|
.help = brlimit_print_help, |
|
.parse = brlimit_parse, |
|
.print = brlimit_print, |
|
.extra_opts = brlimit_opts, |
|
}; |
|
|
|
void _init(void) |
|
{ |
|
xtables_register_match(&brlimit_match); |
|
}
|
|
|