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