Home | History | Annotate | Download | only in extensions
      1 /* ebt_limit
      2  *
      3  * Authors:
      4  * Tom Marshall <tommy (at) 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 (at) 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 
     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 
     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 
     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 
     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 
    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 
    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 
    176 void _init(void)
    177 {
    178 	xtables_register_match(&brlimit_match);
    179 }
    180