2 * ircd-ratbox: A slightly useful ircd
3 * reject.c: reject users with prejudice
5 * Copyright (C) 2003 Aaron Sethman <androsyn@ratbox.org>
6 * Copyright (C) 2003-2005 ircd-ratbox development team
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.
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.
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
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
23 * $Id: reject.c 25119 2008-03-13 16:57:05Z androsyn $
39 static rb_patricia_tree_t
*reject_tree
;
40 static rb_dlink_list delay_exit
;
41 static rb_dlink_list reject_list
;
42 static rb_dlink_list throttle_list
;
43 static rb_patricia_tree_t
*throttle_tree
;
44 static void throttle_expires(void *unused
);
47 typedef struct _reject_data
55 typedef struct _delay_data
61 typedef struct _throttle
69 delay_exit_length(void)
71 return rb_dlink_list_length(&delay_exit
);
75 reject_exit(void *unused
)
77 rb_dlink_node
*ptr
, *ptr_next
;
79 static const char *errbuf
= "ERROR :Closing Link: (*** Banned (cache))\r\n";
81 RB_DLINK_FOREACH_SAFE(ptr
, ptr_next
, delay_exit
.head
)
85 rb_write(ddata
->F
, errbuf
, strlen(errbuf
));
90 delay_exit
.head
= delay_exit
.tail
= NULL
;
91 delay_exit
.length
= 0;
95 reject_expires(void *unused
)
97 rb_dlink_node
*ptr
, *next
;
98 rb_patricia_node_t
*pnode
;
101 RB_DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
106 if(rdata
->time
+ ConfigFileEntry
.reject_duration
> rb_current_time())
109 rb_dlinkDelete(ptr
, &reject_list
);
111 rb_patricia_remove(reject_tree
, pnode
);
118 reject_tree
= rb_new_patricia(PATRICIA_BITS
);
119 throttle_tree
= rb_new_patricia(PATRICIA_BITS
);
120 rb_event_add("reject_exit", reject_exit
, NULL
, DELAYED_EXIT_TIME
);
121 rb_event_add("reject_expires", reject_expires
, NULL
, 60);
122 rb_event_add("throttle_expires", throttle_expires
, NULL
, 10);
130 rb_patricia_node_t
*pnode
;
134 RB_DLINK_FOREACH(ptr
, throttle_list
.head
)
138 if (t
->count
> ConfigFileEntry
.throttle_count
)
146 add_reject(struct Client
*client_p
, const char *mask1
, const char *mask2
)
148 rb_patricia_node_t
*pnode
;
152 /* Reject is disabled */
153 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_duration
== 0)
158 hashv
^= fnv_hash_upper((const unsigned char *)mask1
, 32);
160 hashv
^= fnv_hash_upper((const unsigned char *)mask2
, 32);
162 if((pnode
= rb_match_ip(reject_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
)) != NULL
)
165 rdata
->time
= rb_current_time();
172 if(GET_SS_FAMILY(&client_p
->localClient
->ip
) == AF_INET6
)
175 pnode
= make_and_lookup_ip(reject_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
, bitlen
);
176 pnode
->data
= rdata
= rb_malloc(sizeof(reject_t
));
177 rb_dlinkAddTail(pnode
, &rdata
->rnode
, &reject_list
);
178 rdata
->time
= rb_current_time();
181 rdata
->mask_hashv
= hashv
;
185 check_reject(rb_fde_t
*F
, struct sockaddr
*addr
)
187 rb_patricia_node_t
*pnode
;
190 /* Reject is disabled */
191 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_duration
== 0)
194 pnode
= rb_match_ip(reject_tree
, addr
);
199 rdata
->time
= rb_current_time();
200 if(rdata
->count
> (unsigned long)ConfigFileEntry
.reject_after_count
)
202 ddata
= rb_malloc(sizeof(delay_t
));
203 ServerStats
.is_rej
++;
204 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
206 rb_dlinkAdd(ddata
, &ddata
->node
, &delay_exit
);
210 /* Caller does what it wants */
215 is_reject_ip(struct sockaddr
*addr
)
217 rb_patricia_node_t
*pnode
;
221 /* Reject is disabled */
222 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_duration
== 0)
225 pnode
= rb_match_ip(reject_tree
, addr
);
230 if(rdata
->count
> (unsigned long)ConfigFileEntry
.reject_after_count
)
232 duration
= rdata
->time
+ ConfigFileEntry
.reject_duration
- rb_current_time();
233 return duration
> 0 ? duration
: 1;
242 rb_dlink_node
*ptr
, *next
;
243 rb_patricia_node_t
*pnode
;
246 RB_DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
250 rb_dlinkDelete(ptr
, &reject_list
);
252 rb_patricia_remove(reject_tree
, pnode
);
257 remove_reject_ip(const char *ip
)
259 rb_patricia_node_t
*pnode
;
261 /* Reject is disabled */
262 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_duration
== 0)
265 if((pnode
= rb_match_string(reject_tree
, ip
)) != NULL
)
267 reject_t
*rdata
= pnode
->data
;
268 rb_dlinkDelete(&rdata
->rnode
, &reject_list
);
270 rb_patricia_remove(reject_tree
, pnode
);
277 remove_reject_mask(const char *mask1
, const char *mask2
)
279 rb_dlink_node
*ptr
, *next
;
280 rb_patricia_node_t
*pnode
;
287 hashv
^= fnv_hash_upper((const unsigned char *)mask1
, 32);
289 hashv
^= fnv_hash_upper((const unsigned char *)mask2
, 32);
290 RB_DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
294 if (rdata
->mask_hashv
== hashv
)
296 rb_dlinkDelete(ptr
, &reject_list
);
298 rb_patricia_remove(reject_tree
, pnode
);
306 throttle_add(struct sockaddr
*addr
)
309 rb_patricia_node_t
*pnode
;
311 if((pnode
= rb_match_ip(throttle_tree
, addr
)) != NULL
)
315 if(t
->count
> ConfigFileEntry
.throttle_count
)
317 ServerStats
.is_thr
++;
320 /* Stop penalizing them after they've been throttled */
321 t
->last
= rb_current_time();
327 if(GET_SS_FAMILY(addr
) == AF_INET6
)
330 t
= rb_malloc(sizeof(throttle_t
));
331 t
->last
= rb_current_time();
333 pnode
= make_and_lookup_ip(throttle_tree
, addr
, bitlen
);
335 rb_dlinkAdd(pnode
, &t
->node
, &throttle_list
);
341 is_throttle_ip(struct sockaddr
*addr
)
344 rb_patricia_node_t
*pnode
;
347 if((pnode
= rb_match_ip(throttle_tree
, addr
)) != NULL
)
350 if(t
->count
> ConfigFileEntry
.throttle_count
)
352 duration
= t
->last
+ ConfigFileEntry
.throttle_duration
- rb_current_time();
353 return duration
> 0 ? duration
: 1;
362 rb_dlink_node
*ptr
, *next
;
363 rb_patricia_node_t
*pnode
;
366 RB_DLINK_FOREACH_SAFE(ptr
, next
, throttle_list
.head
)
371 rb_dlinkDelete(ptr
, &throttle_list
);
373 rb_patricia_remove(throttle_tree
, pnode
);
378 throttle_expires(void *unused
)
380 rb_dlink_node
*ptr
, *next
;
381 rb_patricia_node_t
*pnode
;
384 RB_DLINK_FOREACH_SAFE(ptr
, next
, throttle_list
.head
)
389 if(t
->last
+ ConfigFileEntry
.throttle_duration
> rb_current_time())
392 rb_dlinkDelete(ptr
, &throttle_list
);
394 rb_patricia_remove(throttle_tree
, pnode
);