1 /* Shared library add-on to iptables to add limit support.
3 * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
4 * Hervé Eychenne <rv@wallfire.org>
11 #include <ip6tables.h>
13 #include <linux/netfilter_ipv6/ip6_tables.h>
14 #include <linux/netfilter_ipv6/ip6t_limit.h>
16 #define IP6T_LIMIT_AVG "3/hour"
17 #define IP6T_LIMIT_BURST 5
19 /* Function which prints out usage message. */
24 "limit v%s options:\n"
25 "--limit avg max average match rate: default "IP6T_LIMIT_AVG"\n"
26 " [Packets per second unless followed by \n"
27 " /sec /minute /hour /day postfixes]\n"
28 "--limit-burst number number to match in a burst, default %u\n"
29 "\n", IPTABLES_VERSION, IP6T_LIMIT_BURST);
32 static struct option opts[] = {
33 { "limit", 1, 0, '%' },
34 { "limit-burst", 1, 0, '$' },
39 int parse_rate(const char *rate, u_int32_t *val)
43 u_int32_t mult = 1; /* Seconds by default. */
45 delim = strchr(rate, '/');
47 if (strlen(delim+1) == 0)
50 if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
52 else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
54 else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
56 else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
65 /* This would get mapped to infinite (1/day is minimum they
66 can specify, so we're ok at that end). */
67 if (r / mult > IP6T_LIMIT_SCALE)
68 exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
70 *val = IP6T_LIMIT_SCALE * mult / r;
74 /* Initialize the match. */
76 init(struct ip6t_entry_match *m, unsigned int *nfcache)
78 struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)m->data;
80 parse_rate(IP6T_LIMIT_AVG, &r->avg);
81 r->burst = IP6T_LIMIT_BURST;
83 /* Can't cache this */
84 *nfcache |= NFC_UNKNOWN;
87 /* FIXME: handle overflow:
88 if (r->avg*r->burst/r->burst != r->avg)
89 exit_error(PARAMETER_PROBLEM,
90 "Sorry: burst too large for that avg rate.\n");
93 /* Function which parses command options; returns true if it
96 parse(int c, char **argv, int invert, unsigned int *flags,
97 const struct ip6t_entry *entry,
98 unsigned int *nfcache,
99 struct ip6t_entry_match **match)
101 struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)(*match)->data;
106 if (check_inverse(optarg, &invert, NULL, 0))
107 exit_error(PARAMETER_PROBLEM,
108 "Unexpected `!' after --limit");
109 if (!parse_rate(optarg, &r->avg))
110 exit_error(PARAMETER_PROBLEM,
111 "bad rate `%s'", optarg);
115 if (check_inverse(optarg, &invert, NULL, 0))
116 exit_error(PARAMETER_PROBLEM,
117 "Unexpected `!' after --limit-burst");
119 if (string_to_number(optarg, 0, 10000, &num) == -1)
120 exit_error(PARAMETER_PROBLEM,
121 "bad --limit-burst `%s'", optarg);
132 /* Final check; nothing. */
133 static void final_check(unsigned int flags)
141 } rates[] = { { "day", IP6T_LIMIT_SCALE*24*60*60 },
142 { "hour", IP6T_LIMIT_SCALE*60*60 },
143 { "min", IP6T_LIMIT_SCALE*60 },
144 { "sec", IP6T_LIMIT_SCALE } };
146 static void print_rate(u_int32_t period)
150 for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
151 if (period > rates[i].mult
152 || rates[i].mult % period != 0)
156 printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
159 /* Prints out the matchinfo. */
161 print(const struct ip6t_ip6 *ip,
162 const struct ip6t_entry_match *match,
165 struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)match->data;
166 printf("limit: avg "); print_rate(r->avg);
167 printf("burst %u ", r->burst);
170 /* FIXME: Make minimalist: only print rate if not default --RR */
171 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
173 struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)match->data;
175 printf("--limit "); print_rate(r->avg);
176 if (r->burst != IP6T_LIMIT_BURST)
177 printf("--limit-burst %u ", r->burst);
181 struct ip6tables_match limit
185 IP6T_ALIGN(sizeof(struct ip6t_rateinfo)),
186 offsetof(struct ip6t_rateinfo, prev),
198 register_match6(&limit);