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