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