From 54015b5fea2584a35aa605ebe37217010b448cff Mon Sep 17 00:00:00 2001 From: jilles Date: Mon, 14 May 2007 15:21:16 -0700 Subject: [PATCH] [svn] Apply ratbox flood fix. --- ChangeLog | 9 +++++++ doc/example.conf | 3 ++- doc/reference.conf | 7 +++++- include/client.h | 5 +++- include/reject.h | 6 ++++- include/s_conf.h | 3 ++- include/serno.h | 2 +- src/client.c | 4 ++- src/listener.c | 5 +++- src/newconf.c | 3 ++- src/packet.c | 15 ++++++----- src/reject.c | 63 +++++++++++++++++++++++++++++++++++++++++++--- src/s_conf.c | 3 ++- src/s_serv.c | 4 ++- src/s_user.c | 3 ++- 15 files changed, 114 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3967173..0f7716f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +nenolod 2007/05/09 00:32:08 UTC (20070509-3444) + Log: + - fix a bug here + + + Changes: Modified: + +5 -1 trunk/libcharybdis/epoll.c (File Modified) + + nenolod 2007/05/07 02:57:50 UTC (20070507-3442) Log: - regen configure diff --git a/doc/example.conf b/doc/example.conf index 983fa87..0a0927f 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -4,7 +4,7 @@ * Copyright (C) 2002-2005 ircd-ratbox development team * Copyright (C) 2005-2006 charybdis development team * - * $Id: example.conf 3390 2007-04-05 00:12:55Z jilles $ + * $Id: example.conf 3446 2007-05-14 22:21:16Z jilles $ * * See reference.conf for more information. */ @@ -429,6 +429,7 @@ general { reject_ban_time = 1 minute; reject_after_count = 3; reject_duration = 5 minutes; + max_unknown_ip = 2; }; modules { diff --git a/doc/reference.conf b/doc/reference.conf index 06ec89e..be0c3a1 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -6,7 +6,7 @@ * * Written by ejb, wcampbel, db, leeh and others * - * $Id: reference.conf 3390 2007-04-05 00:12:55Z jilles $ + * $Id: reference.conf 3446 2007-05-14 22:21:16Z jilles $ */ /* IMPORTANT NOTES: @@ -1119,6 +1119,11 @@ general { /* reject duration: the amount of time to cache the rejection */ reject_duration = 5 minutes; + + /* max_unknown_ip: maximum number of pending connections to the server + * that are allowed per IP address + */ + max_unknown_ip = 2; }; modules { diff --git a/include/client.h b/include/client.h index 5a3e041..a52f686 100644 --- a/include/client.h +++ b/include/client.h @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: client.h 2023 2006-09-02 23:47:27Z jilles $ + * $Id: client.h 3446 2007-05-14 22:21:16Z jilles $ */ #ifndef INCLUDED_client_h @@ -431,6 +431,7 @@ struct exit_client_hook #define FLAGS_SERVICE 0x400000 /* network service */ #define FLAGS_TGCHANGE 0x800000 /* we're allowed to clear something */ #define FLAGS_DYNSPOOF 0x1000000 /* dynamic spoof, only opers see ip */ +#define FLAGS_EXUNKNOWN 0x2000000 /* too many unknowns exit.. */ /* umodes, settable flags */ /* lots of this moved to snomask -- jilles */ @@ -512,6 +513,8 @@ struct exit_client_hook #define IsDynSpoof(x) ((x)->flags & FLAGS_DYNSPOOF) #define SetDynSpoof(x) ((x)->flags |= FLAGS_DYNSPOOF) #define ClearDynSpoof(x) ((x)->flags &= ~FLAGS_DYNSPOOF) +#define IsExUnknown(x) ((x)->flags & FLAGS_EXUNKNOWN) +#define SetExUnknown(x) ((x)->flags |= FLAGS_EXUNKNOWN) /* oper flags */ #define MyOper(x) (MyConnect(x) && IsOper(x)) diff --git a/include/reject.h b/include/reject.h index 4e1bc41..5a4210c 100644 --- a/include/reject.h +++ b/include/reject.h @@ -21,7 +21,7 @@ * USA * * - * $Id: reject.h 6 2005-09-10 01:02:21Z nenolod $ + * $Id: reject.h 3446 2007-05-14 22:21:16Z jilles $ */ #ifndef INCLUDED_reject_h #define INCLUDED_reject_h @@ -36,5 +36,9 @@ int check_reject(struct Client *); void add_reject(struct Client *); void flush_reject(void); int remove_reject(const char *ip); + +int add_unknown_ip(struct Client *client_p); +void del_unknown_ip(struct Client *client_p); + #endif diff --git a/include/s_conf.h b/include/s_conf.h index 63f47b3..29bc389 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: s_conf.h 3257 2007-03-13 16:09:28Z jilles $ + * $Id: s_conf.h 3446 2007-05-14 22:21:16Z jilles $ */ #ifndef INCLUDED_s_conf_h @@ -250,6 +250,7 @@ struct config_file_entry int default_umodes; int global_snotices; int operspy_dont_care_user_info; + int max_unknown_ip; }; struct config_channel_entry diff --git a/include/serno.h b/include/serno.h index b03706e..b82f811 100644 --- a/include/serno.h +++ b/include/serno.h @@ -1 +1 @@ -#define SERNO "20070507-3442" +#define SERNO "20070509-3444" diff --git a/src/client.c b/src/client.c index 2d64947..ae8ce9c 100644 --- a/src/client.c +++ b/src/client.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: client.c 3412 2007-04-15 16:49:56Z jilles $ + * $Id: client.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" #include "config.h" @@ -58,6 +58,7 @@ #include "msg.h" #include "monitor.h" #include "blacklist.h" +#include "reject.h" #define DEBUG_EXITED_CLIENTS @@ -1419,6 +1420,7 @@ exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Cli { delete_auth_queries(source_p); client_flush_input(source_p); + del_unknown_ip(source_p); dlinkDelete(&source_p->localClient->tnode, &unknown_list); if(!IsIOError(source_p)) diff --git a/src/listener.c b/src/listener.c index d261c90..7b92a6c 100644 --- a/src/listener.c +++ b/src/listener.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: listener.c 3354 2007-04-03 09:21:31Z nenolod $ + * $Id: listener.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -477,6 +477,9 @@ add_connection(listener_t *listener, int fd, struct sockaddr *sai) if(check_reject(new_client)) return; + if(add_unknown_ip(new_client)) + return; + start_auth(new_client); } diff --git a/src/newconf.c b/src/newconf.c index 81c26ab..98b831f 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -1,5 +1,5 @@ /* This code is in the public domain. - * $Id: newconf.c 3257 2007-03-13 16:09:28Z jilles $ + * $Id: newconf.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -2053,6 +2053,7 @@ static struct ConfEntry conf_general_table[] = { "max_nick_time", CF_TIME, NULL, 0, &ConfigFileEntry.max_nick_time }, { "max_nick_changes", CF_INT, NULL, 0, &ConfigFileEntry.max_nick_changes }, { "max_targets", CF_INT, NULL, 0, &ConfigFileEntry.max_targets }, + { "max_unknown_ip", CF_INT, NULL, 0, &ConfigFileEntry.max_unknown_ip }, { "min_nonwildcard", CF_INT, NULL, 0, &ConfigFileEntry.min_nonwildcard }, { "nick_delay", CF_TIME, NULL, 0, &ConfigFileEntry.nick_delay }, { "no_oper_flood", CF_YESNO, NULL, 0, &ConfigFileEntry.no_oper_flood }, diff --git a/src/packet.c b/src/packet.c index 7c8c87f..5e06c80 100644 --- a/src/packet.c +++ b/src/packet.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: packet.c 262 2005-09-22 00:38:45Z jilles $ + * $Id: packet.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" #include "tools.h" @@ -56,12 +56,9 @@ parse_client_queued(struct Client *client_p) if(IsUnknown(client_p)) { - int i = 0; - for (;;) { - /* rate unknown clients at MAX_FLOOD per loop */ - if(i >= MAX_FLOOD) + if(client_p->localClient->sent_parsed >= client_p->localClient->allow_read) break; dolen = linebuf_get(&client_p->localClient-> @@ -72,7 +69,7 @@ parse_client_queued(struct Client *client_p) break; client_dopacket(client_p, readBuf, dolen); - i++; + client_p->localClient->sent_parsed++; /* He's dead cap'n */ if(IsAnyDead(client_p)) @@ -81,7 +78,13 @@ parse_client_queued(struct Client *client_p) * to the parsing for their appropriate status. --fl */ if(!IsUnknown(client_p)) + { + /* reset their flood limits, they're now + * graced to flood + */ + client_p->localClient->sent_parsed = 0; break; + } } } diff --git a/src/reject.c b/src/reject.c index 13d1d31..3dd3406 100644 --- a/src/reject.c +++ b/src/reject.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: reject.c 849 2006-02-15 01:33:43Z jilles $ + * $Id: reject.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -38,6 +38,8 @@ static patricia_tree_t *reject_tree; dlink_list delay_exit; static dlink_list reject_list; +static patricia_tree_t *unknown_tree; + struct reject_data { dlink_node rnode; @@ -45,6 +47,8 @@ struct reject_data unsigned int count; }; +static patricia_tree_t *unknown_tree; + static void reject_exit(void *unused) { @@ -67,8 +71,12 @@ reject_exit(void *unused) * ircu message suggests --jilles */ if(!IsIOError(client_p)) - sendto_one(client_p, "ERROR :Closing Link: %s (*** Banned (cache))", client_p->host); - + { + if(IsExUnknown(client_p)) + sendto_one(client_p, "ERROR :Closing Link: %s (*** Too many unknown connections)", client_p->host); + else + sendto_one(client_p, "ERROR :Closing Link: %s (*** Banned (cache))", client_p->host); + } close_connection(client_p); SetDead(client_p); dlinkAddAlloc(client_p, &dead_list); @@ -103,6 +111,7 @@ void init_reject(void) { reject_tree = New_Patricia(PATRICIA_BITS); + unknown_tree = New_Patricia(PATRICIA_BITS); eventAdd("reject_exit", reject_exit, NULL, DELAYED_EXIT_TIME); eventAdd("reject_expires", reject_expires, NULL, 60); } @@ -208,3 +217,51 @@ remove_reject(const char *ip) return 0; } + +int +add_unknown_ip(struct Client *client_p) +{ + patricia_node_t *pnode; + + if((pnode = match_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip)) == NULL) + { + int bitlen = 32; +#ifdef IPV6 + if(client_p->localClient->ip.ss_family == AF_INET6) + bitlen = 128; +#endif + pnode = make_and_lookup_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen); + pnode->data = (void *)0; + } + + if((unsigned long)pnode->data >= ConfigFileEntry.max_unknown_ip) + { + SetExUnknown(client_p); + SetReject(client_p); + comm_setselect(client_p->localClient->fd, FDLIST_NONE, COMM_SELECT_WRITE | COMM_SELECT_READ, NULL, NULL, 0); + SetClosing(client_p); + dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &delay_exit); + return 1; + } + + pnode->data = (void *)((unsigned long)pnode->data + 1); + + return 0; +} + +void +del_unknown_ip(struct Client *client_p) +{ + patricia_node_t *pnode; + + if((pnode = match_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL) + { + pnode->data = (void *)((unsigned long)pnode->data - 1); + if((unsigned long)pnode->data <= 0) + { + patricia_remove(unknown_tree, pnode); + } + } + /* well..this shouldn't happen */ + s_assert(0); +} diff --git a/src/s_conf.c b/src/s_conf.c index 19c1593..6d452c4 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: s_conf.c 3390 2007-04-05 00:12:55Z jilles $ + * $Id: s_conf.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -850,6 +850,7 @@ set_default_conf(void) ConfigFileEntry.reject_after_count = 5; ConfigFileEntry.reject_ban_time = 300; ConfigFileEntry.reject_duration = 120; + ConfigFileEntry.max_unknown_ip = 2; ServerInfo.max_clients = comm_get_maxconnections() - MAX_BUFFER; } diff --git a/src/s_serv.c b/src/s_serv.c index 86b4bfe..9768d9b 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: s_serv.c 3354 2007-04-03 09:21:31Z nenolod $ + * $Id: s_serv.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -57,6 +57,7 @@ #include "channel.h" /* chcap_usage_counts stuff... */ #include "hook.h" #include "msg.h" +#include "reject.h" extern char *crypt(); @@ -1103,6 +1104,7 @@ server_estab(struct Client *client_p) set_chcap_usage_counts(client_p); dlinkAdd(client_p, &client_p->lnode, &me.serv->servers); + del_unknown_ip(client_p); dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &serv_list); dlinkAddTailAlloc(client_p, &global_serv_list); diff --git a/src/s_user.c b/src/s_user.c index 91f30dd..44683b9 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: s_user.c 3414 2007-04-15 16:54:50Z jilles $ + * $Id: s_user.c 3446 2007-05-14 22:21:16Z jilles $ */ #include "stdinc.h" @@ -528,6 +528,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char Count.invisi++; s_assert(!IsClient(source_p)); + del_unknown_ip(source_p); dlinkMoveNode(&source_p->localClient->tnode, &unknown_list, &lclient_list); SetClient(source_p);