]>
jfr.im git - irc/rqf/shadowircd.git/blob - src/reject.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * $Id: reject.c 3456 2007-05-18 19:14:18Z jilles $
38 static patricia_tree_t
*reject_tree
;
39 dlink_list delay_exit
;
40 static dlink_list reject_list
;
42 static patricia_tree_t
*unknown_tree
;
52 static patricia_tree_t
*unknown_tree
;
55 reject_exit(void *unused
)
57 struct Client
*client_p
;
58 dlink_node
*ptr
, *ptr_next
;
60 DLINK_FOREACH_SAFE(ptr
, ptr_next
, delay_exit
.head
)
66 /* this MUST be here, to prevent the possibility
67 * sendto_one() generates a write error, and then a client
68 * ends up on the dead_list and the abort_list --fl
70 * new disconnect notice stolen from ircu --nenolod
71 * no, this only happens when someone's IP has some
72 * ban on it and rejects them rather longer than the
73 * ircu message suggests --jilles
75 if(!IsIOError(client_p
))
77 if(IsExUnknown(client_p
))
78 sendto_one(client_p
, "ERROR :Closing Link: %s (*** Too many unknown connections)", client_p
->host
);
80 sendto_one(client_p
, "ERROR :Closing Link: %s (*** Banned (cache))", client_p
->host
);
82 close_connection(client_p
);
84 dlinkAddAlloc(client_p
, &dead_list
);
87 delay_exit
.head
= delay_exit
.tail
= NULL
;
88 delay_exit
.length
= 0;
92 reject_expires(void *unused
)
94 dlink_node
*ptr
, *next
;
95 patricia_node_t
*pnode
;
96 struct reject_data
*rdata
;
98 DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
103 if(rdata
->time
+ ConfigFileEntry
.reject_duration
> CurrentTime
)
106 dlinkDelete(ptr
, &reject_list
);
108 patricia_remove(reject_tree
, pnode
);
115 reject_tree
= New_Patricia(PATRICIA_BITS
);
116 unknown_tree
= New_Patricia(PATRICIA_BITS
);
117 eventAdd("reject_exit", reject_exit
, NULL
, DELAYED_EXIT_TIME
);
118 eventAdd("reject_expires", reject_expires
, NULL
, 60);
123 add_reject(struct Client
*client_p
, const char *mask1
, const char *mask2
)
125 patricia_node_t
*pnode
;
126 struct reject_data
*rdata
;
129 /* Reject is disabled */
130 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_ban_time
== 0)
135 hashv
^= fnv_hash_upper(mask1
, 32);
137 hashv
^= fnv_hash_upper(mask2
, 32);
139 if((pnode
= match_ip(reject_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
)) != NULL
)
142 rdata
->time
= CurrentTime
;
149 if(client_p
->localClient
->ip
.ss_family
== AF_INET6
)
152 pnode
= make_and_lookup_ip(reject_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
, bitlen
);
153 pnode
->data
= rdata
= MyMalloc(sizeof(struct reject_data
));
154 dlinkAddTail(pnode
, &rdata
->rnode
, &reject_list
);
155 rdata
->time
= CurrentTime
;
158 rdata
->mask_hashv
= hashv
;
162 check_reject(struct Client
*client_p
)
164 patricia_node_t
*pnode
;
165 struct reject_data
*rdata
;
167 /* Reject is disabled */
168 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_ban_time
== 0 ||
169 ConfigFileEntry
.reject_duration
== 0)
172 pnode
= match_ip(reject_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
);
177 rdata
->time
= CurrentTime
;
178 if(rdata
->count
> ConfigFileEntry
.reject_after_count
)
180 ServerStats
->is_rej
++;
182 rb_setselect(client_p
->localClient
->F
->fd
, FDLIST_NONE
, COMM_SELECT_WRITE
| COMM_SELECT_READ
, NULL
, NULL
, 0);
183 SetClosing(client_p
);
184 dlinkMoveNode(&client_p
->localClient
->tnode
, &unknown_list
, &delay_exit
);
188 /* Caller does what it wants */
195 dlink_node
*ptr
, *next
;
196 patricia_node_t
*pnode
;
197 struct reject_data
*rdata
;
199 DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
203 dlinkDelete(ptr
, &reject_list
);
205 patricia_remove(reject_tree
, pnode
);
210 remove_reject_ip(const char *ip
)
212 patricia_node_t
*pnode
;
214 /* Reject is disabled */
215 if(ConfigFileEntry
.reject_after_count
== 0 || ConfigFileEntry
.reject_ban_time
== 0 ||
216 ConfigFileEntry
.reject_duration
== 0)
219 if((pnode
= match_string(reject_tree
, ip
)) != NULL
)
221 struct reject_data
*rdata
= pnode
->data
;
222 dlinkDelete(&rdata
->rnode
, &reject_list
);
224 patricia_remove(reject_tree
, pnode
);
231 remove_reject_mask(const char *mask1
, const char *mask2
)
233 dlink_node
*ptr
, *next
;
234 patricia_node_t
*pnode
;
235 struct reject_data
*rdata
;
241 hashv
^= fnv_hash_upper(mask1
, 32);
243 hashv
^= fnv_hash_upper(mask2
, 32);
244 DLINK_FOREACH_SAFE(ptr
, next
, reject_list
.head
)
248 if (rdata
->mask_hashv
== hashv
)
250 dlinkDelete(ptr
, &reject_list
);
252 patricia_remove(reject_tree
, pnode
);
261 add_unknown_ip(struct Client
*client_p
)
263 patricia_node_t
*pnode
;
265 if((pnode
= match_ip(unknown_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
)) == NULL
)
269 if(client_p
->localClient
->ip
.ss_family
== AF_INET6
)
272 pnode
= make_and_lookup_ip(unknown_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
, bitlen
);
273 pnode
->data
= (void *)0;
276 if((unsigned long)pnode
->data
>= ConfigFileEntry
.max_unknown_ip
)
278 SetExUnknown(client_p
);
280 rb_setselect(client_p
->localClient
->F
->fd
, FDLIST_NONE
, COMM_SELECT_WRITE
| COMM_SELECT_READ
, NULL
, NULL
, 0);
281 SetClosing(client_p
);
282 dlinkMoveNode(&client_p
->localClient
->tnode
, &unknown_list
, &delay_exit
);
286 pnode
->data
= (void *)((unsigned long)pnode
->data
+ 1);
292 del_unknown_ip(struct Client
*client_p
)
294 patricia_node_t
*pnode
;
296 if((pnode
= match_ip(unknown_tree
, (struct sockaddr
*)&client_p
->localClient
->ip
)) != NULL
)
298 pnode
->data
= (void *)((unsigned long)pnode
->data
- 1);
299 if((unsigned long)pnode
->data
<= 0)
301 patricia_remove(unknown_tree
, pnode
);
304 /* this can happen due to m_webirc.c's manipulations, for example */