]> jfr.im git - irc/rqf/shadowircd.git/blame - src/reject.c
Remove redundant prototypes in src/ircd_lexer.l.
[irc/rqf/shadowircd.git] / src / reject.c
CommitLineData
21c9d815
VY
1/*
2 * ircd-ratbox: A slightly useful ircd
3 * reject.c: reject users with prejudice
4 *
5 * Copyright (C) 2003 Aaron Sethman <androsyn@ratbox.org>
6 * Copyright (C) 2003-2005 ircd-ratbox development team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
d1275a8f 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21c9d815
VY
21 * USA
22 *
21c9d815
VY
23 */
24
25#include "stdinc.h"
21c9d815
VY
26#include "client.h"
27#include "s_conf.h"
28#include "reject.h"
29#include "s_stats.h"
d1275a8f
JT
30#include "ircd.h"
31#include "send.h"
32#include "numeric.h"
33#include "parse.h"
34#include "hostmask.h"
35#include "match.h"
21c9d815
VY
36#include "hash.h"
37
07943cb5 38static rb_patricia_tree_t *reject_tree;
d1275a8f 39static rb_dlink_list delay_exit;
21c9d815 40static rb_dlink_list reject_list;
d1275a8f
JT
41static rb_dlink_list throttle_list;
42static rb_patricia_tree_t *throttle_tree;
43static void throttle_expires(void *unused);
21c9d815 44
21c9d815 45
d1275a8f 46typedef struct _reject_data
21c9d815
VY
47{
48 rb_dlink_node rnode;
49 time_t time;
50 unsigned int count;
51 uint32_t mask_hashv;
d1275a8f
JT
52} reject_t;
53
54typedef struct _delay_data
55{
56 rb_dlink_node node;
57 rb_fde_t *F;
58} delay_t;
59
60typedef struct _throttle
61{
62 rb_dlink_node node;
63 time_t last;
64 int count;
65} throttle_t;
66
67unsigned long
68delay_exit_length(void)
69{
70 return rb_dlink_list_length(&delay_exit);
71}
21c9d815 72
21c9d815
VY
73static void
74reject_exit(void *unused)
75{
21c9d815 76 rb_dlink_node *ptr, *ptr_next;
d1275a8f
JT
77 delay_t *ddata;
78 static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
79
21c9d815
VY
80 RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head)
81 {
d1275a8f
JT
82 ddata = ptr->data;
83
84 rb_write(ddata->F, errbuf, strlen(errbuf));
85 rb_close(ddata->F);
86 rb_free(ddata);
21c9d815
VY
87 }
88
d1275a8f
JT
89 delay_exit.head = delay_exit.tail = NULL;
90 delay_exit.length = 0;
21c9d815
VY
91}
92
93static void
94reject_expires(void *unused)
95{
96 rb_dlink_node *ptr, *next;
07943cb5 97 rb_patricia_node_t *pnode;
d1275a8f 98 reject_t *rdata;
21c9d815
VY
99
100 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
101 {
102 pnode = ptr->data;
103 rdata = pnode->data;
104
105 if(rdata->time + ConfigFileEntry.reject_duration > rb_current_time())
106 continue;
107
108 rb_dlinkDelete(ptr, &reject_list);
109 rb_free(rdata);
07943cb5 110 rb_patricia_remove(reject_tree, pnode);
21c9d815
VY
111 }
112}
113
114void
115init_reject(void)
116{
07943cb5 117 reject_tree = rb_new_patricia(PATRICIA_BITS);
d1275a8f 118 throttle_tree = rb_new_patricia(PATRICIA_BITS);
21c9d815
VY
119 rb_event_add("reject_exit", reject_exit, NULL, DELAYED_EXIT_TIME);
120 rb_event_add("reject_expires", reject_expires, NULL, 60);
d1275a8f 121 rb_event_add("throttle_expires", throttle_expires, NULL, 10);
21c9d815
VY
122}
123
76d49681
JT
124unsigned long
125throttle_size(void)
126{
84bfb8cc
JT
127 unsigned long count;
128 rb_dlink_node *ptr;
129 rb_patricia_node_t *pnode;
130 throttle_t *t;
131
132 count = 0;
133 RB_DLINK_FOREACH(ptr, throttle_list.head)
134 {
135 pnode = ptr->data;
136 t = pnode->data;
137 if (t->count > ConfigFileEntry.throttle_count)
138 count++;
139 }
140
141 return count;
76d49681 142}
21c9d815
VY
143
144void
145add_reject(struct Client *client_p, const char *mask1, const char *mask2)
146{
07943cb5 147 rb_patricia_node_t *pnode;
d1275a8f 148 reject_t *rdata;
21c9d815
VY
149 uint32_t hashv;
150
151 /* Reject is disabled */
d1275a8f 152 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
21c9d815
VY
153 return;
154
155 hashv = 0;
156 if (mask1 != NULL)
d1275a8f 157 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
21c9d815 158 if (mask2 != NULL)
d1275a8f 159 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
21c9d815 160
07943cb5 161 if((pnode = rb_match_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL)
21c9d815
VY
162 {
163 rdata = pnode->data;
164 rdata->time = rb_current_time();
165 rdata->count++;
166 }
167 else
168 {
169 int bitlen = 32;
2c2e0aa9 170#ifdef RB_IPV6
d1275a8f 171 if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6)
21c9d815
VY
172 bitlen = 128;
173#endif
174 pnode = make_and_lookup_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen);
d1275a8f 175 pnode->data = rdata = rb_malloc(sizeof(reject_t));
21c9d815
VY
176 rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
177 rdata->time = rb_current_time();
178 rdata->count = 1;
179 }
180 rdata->mask_hashv = hashv;
181}
182
183int
d1275a8f 184check_reject(rb_fde_t *F, struct sockaddr *addr)
21c9d815 185{
07943cb5 186 rb_patricia_node_t *pnode;
d1275a8f
JT
187 reject_t *rdata;
188 delay_t *ddata;
21c9d815 189 /* Reject is disabled */
d1275a8f 190 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
21c9d815
VY
191 return 0;
192
d1275a8f 193 pnode = rb_match_ip(reject_tree, addr);
21c9d815
VY
194 if(pnode != NULL)
195 {
196 rdata = pnode->data;
197
198 rdata->time = rb_current_time();
d1275a8f 199 if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
21c9d815 200 {
d1275a8f 201 ddata = rb_malloc(sizeof(delay_t));
83251205 202 ServerStats.is_rej++;
d1275a8f
JT
203 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
204 ddata->F = F;
205 rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
21c9d815
VY
206 return 1;
207 }
208 }
209 /* Caller does what it wants */
210 return 0;
211}
212
760ef9e1
JT
213int
214is_reject_ip(struct sockaddr *addr)
215{
216 rb_patricia_node_t *pnode;
217 reject_t *rdata;
218 int duration;
219
220 /* Reject is disabled */
221 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
222 return 0;
223
224 pnode = rb_match_ip(reject_tree, addr);
225 if(pnode != NULL)
226 {
227 rdata = pnode->data;
228
229 if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
230 {
231 duration = rdata->time + ConfigFileEntry.reject_duration - rb_current_time();
232 return duration > 0 ? duration : 1;
233 }
234 }
235 return 0;
236}
237
21c9d815
VY
238void
239flush_reject(void)
240{
241 rb_dlink_node *ptr, *next;
07943cb5 242 rb_patricia_node_t *pnode;
d1275a8f 243 reject_t *rdata;
21c9d815
VY
244
245 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
246 {
247 pnode = ptr->data;
248 rdata = pnode->data;
249 rb_dlinkDelete(ptr, &reject_list);
250 rb_free(rdata);
07943cb5 251 rb_patricia_remove(reject_tree, pnode);
21c9d815
VY
252 }
253}
254
255int
256remove_reject_ip(const char *ip)
257{
07943cb5 258 rb_patricia_node_t *pnode;
21c9d815
VY
259
260 /* Reject is disabled */
d1275a8f 261 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
21c9d815
VY
262 return -1;
263
07943cb5 264 if((pnode = rb_match_string(reject_tree, ip)) != NULL)
21c9d815 265 {
d1275a8f 266 reject_t *rdata = pnode->data;
21c9d815
VY
267 rb_dlinkDelete(&rdata->rnode, &reject_list);
268 rb_free(rdata);
07943cb5 269 rb_patricia_remove(reject_tree, pnode);
21c9d815
VY
270 return 1;
271 }
272 return 0;
273}
274
275int
276remove_reject_mask(const char *mask1, const char *mask2)
277{
278 rb_dlink_node *ptr, *next;
07943cb5 279 rb_patricia_node_t *pnode;
d1275a8f 280 reject_t *rdata;
21c9d815
VY
281 uint32_t hashv;
282 int n = 0;
283
284 hashv = 0;
285 if (mask1 != NULL)
d1275a8f 286 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
21c9d815 287 if (mask2 != NULL)
d1275a8f 288 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
21c9d815
VY
289 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
290 {
291 pnode = ptr->data;
292 rdata = pnode->data;
293 if (rdata->mask_hashv == hashv)
294 {
295 rb_dlinkDelete(ptr, &reject_list);
296 rb_free(rdata);
07943cb5 297 rb_patricia_remove(reject_tree, pnode);
21c9d815
VY
298 n++;
299 }
300 }
301 return n;
302}
303
21c9d815 304int
d1275a8f 305throttle_add(struct sockaddr *addr)
21c9d815 306{
d1275a8f 307 throttle_t *t;
07943cb5 308 rb_patricia_node_t *pnode;
21c9d815 309
d1275a8f 310 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
21c9d815 311 {
d1275a8f
JT
312 t = pnode->data;
313
314 if(t->count > ConfigFileEntry.throttle_count)
76d49681
JT
315 {
316 ServerStats.is_thr++;
317 return 1;
318 }
d1275a8f
JT
319 /* Stop penalizing them after they've been throttled */
320 t->last = rb_current_time();
321 t->count++;
322
323 } else {
21c9d815 324 int bitlen = 32;
2c2e0aa9 325#ifdef RB_IPV6
d1275a8f 326 if(GET_SS_FAMILY(addr) == AF_INET6)
21c9d815
VY
327 bitlen = 128;
328#endif
d1275a8f
JT
329 t = rb_malloc(sizeof(throttle_t));
330 t->last = rb_current_time();
331 t->count = 1;
332 pnode = make_and_lookup_ip(throttle_tree, addr, bitlen);
333 pnode->data = t;
334 rb_dlinkAdd(pnode, &t->node, &throttle_list);
335 }
21c9d815
VY
336 return 0;
337}
338
760ef9e1
JT
339int
340is_throttle_ip(struct sockaddr *addr)
341{
342 throttle_t *t;
343 rb_patricia_node_t *pnode;
344 int duration;
345
346 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
347 {
348 t = pnode->data;
349 if(t->count > ConfigFileEntry.throttle_count)
350 {
351 duration = t->last + ConfigFileEntry.throttle_duration - rb_current_time();
352 return duration > 0 ? duration : 1;
353 }
354 }
355 return 0;
356}
357
0b1e46f5
JT
358void
359flush_throttle(void)
360{
361 rb_dlink_node *ptr, *next;
362 rb_patricia_node_t *pnode;
363 throttle_t *t;
364
365 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
366 {
367 pnode = ptr->data;
368 t = pnode->data;
369
370 rb_dlinkDelete(ptr, &throttle_list);
371 rb_free(t);
372 rb_patricia_remove(throttle_tree, pnode);
373 }
374}
375
d1275a8f
JT
376static void
377throttle_expires(void *unused)
21c9d815 378{
d1275a8f 379 rb_dlink_node *ptr, *next;
07943cb5 380 rb_patricia_node_t *pnode;
d1275a8f
JT
381 throttle_t *t;
382
383 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
21c9d815 384 {
d1275a8f
JT
385 pnode = ptr->data;
386 t = pnode->data;
387
388 if(t->last + ConfigFileEntry.throttle_duration > rb_current_time())
389 continue;
390
391 rb_dlinkDelete(ptr, &throttle_list);
392 rb_free(t);
393 rb_patricia_remove(throttle_tree, pnode);
21c9d815 394 }
21c9d815 395}
d1275a8f 396