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