From 764b1a003c21fcc11e38ac70502f94fe243d833b Mon Sep 17 00:00:00 2001 From: Perry Lorier Date: Sun, 30 Apr 2000 12:00:07 +0000 Subject: [PATCH] Author: ZenShadow Log message: Change the IPcheck API. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@222 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 20 +++++- RELEASE.NOTES | 1 - include/IPcheck.h | 22 ++++--- ircd/IPcheck.c | 163 ++++++++++++---------------------------------- ircd/ircd.c | 2 +- ircd/m_nick.c | 6 +- ircd/s_auth.c | 2 +- ircd/s_bsd.c | 60 ++++++++--------- ircd/s_conf.c | 2 +- ircd/s_misc.c | 8 +-- ircd/s_serv.c | 2 +- ircd/s_user.c | 12 ++-- ircd/whocmds.c | 1 - 13 files changed, 116 insertions(+), 185 deletions(-) diff --git a/ChangeLog b/ChangeLog index c25a313..4055cc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ - rewrite of setuid/chroot code. - server will no longer run as root - -DPROFIL compile option removed + - Fixed IPcheck API calls * config/config-sh.in - Fixed up chroot compile options @@ -24,11 +25,28 @@ * ircd/ircd_signal.c - Removed -DPROFIL + * include/IPcheck.h + - Removed old API prototypes, added new ones + * ircd/IPcheck.c - Readability cleanups (well, I -think-...) - Changed IPRegistryEntry.last_connect to a time_t. The previously used unsigned short was probably causing interesting things after a client had been connected longer than about 65,535 seconds... + - Removed old API functions. + + * ircd/whocmds.c + - Removed IPcheck.h include + + * Additionally modified IPcheck API calls in: + - ircd/m_nick.c + - ircd/m_auth.c + - ircd/s_bsd.c + - ircd/s_conf.c + - ircd/s_misc.c + - ircd/s_serv.c + - ircd/s_user.c + 2000-04-30 Perry Lorier * ircd/s_bsd.c: Sigh. :) @@ -1028,7 +1046,7 @@ # # ChangeLog for ircu2.10.11 # -# $Id: ChangeLog,v 1.119 2000-04-30 11:39:24 isomer Exp $ +# $Id: ChangeLog,v 1.120 2000-04-30 12:00:06 isomer Exp $ # # Insert new changes at beginning of the change list. # diff --git a/RELEASE.NOTES b/RELEASE.NOTES index 98daf15..47c4f2b 100644 --- a/RELEASE.NOTES +++ b/RELEASE.NOTES @@ -89,7 +89,6 @@ debugging *only*. It lets you connect up to 255 clients from one host with no time conciderations. If this is enabled on a production server I will personally drive your server into the ground. You have been warned. --DIPCHECKDEBUG Debugging statements with IPcheck. Operating System and Kernel Requirements: If you plan allowing more than 1000 clients on your server, you diff --git a/include/IPcheck.h b/include/IPcheck.h index f26e222..fe27795 100644 --- a/include/IPcheck.h +++ b/include/IPcheck.h @@ -17,15 +17,19 @@ struct Client; -/* +/*---------------------------------------------------------------------------- * Prototypes - */ -extern int IPcheck_local_connect(struct in_addr ip, time_t* next_target_out); -extern void IPcheck_connect_fail(struct in_addr ip); -extern void IPcheck_connect_succeeded(struct Client *cptr); -extern int IPcheck_remote_connect(struct Client *cptr, int is_burst); -extern void IPcheck_disconnect(struct Client *cptr); -extern unsigned short IPcheck_nr(struct Client *cptr); -extern void IPcheck_expire(); + *--------------------------------------------------------------------------*/ +extern int ip_registry_check_local (unsigned int addr, + time_t *next_target_out); +extern void ip_registry_local_connect(struct Client *cptr); +extern void ip_registry_connect_fail (unsigned int addr); +extern void ip_registry_expire (void); +extern void ip_registry_disconnect (struct Client *cptr); +extern int ip_registry_count (unsigned int addr); +extern int ip_registry_check_remote (struct Client *cptr, + int is_burst); +extern void ip_registry_connect_succeeded(struct Client *cptr); #endif /* INCLUDED_ipcheck_h */ + diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c index 48fe044..6a5b558 100644 --- a/ircd/IPcheck.c +++ b/ircd/IPcheck.c @@ -75,7 +75,7 @@ typedef struct IPRegistryEntry { #define IPCHECK_CLONE_LIMIT 2 #define IPCHECK_CLONE_PERIOD 20 -#define IPCHECK_CLONE_DELAY 1 +#define IPCHECK_CLONE_DELAY 600 /*---------------------------------------------------------------------------- @@ -235,11 +235,16 @@ static void ip_registry_expire_entry(ip_reg_entry_t *entry) { /*---------------------------------------------------------------------------- * ip_registry_expire: Expire all of the needed entries in the hash table *--------------------------------------------------------------------------*/ -static void ip_registry_expire(void) { +void ip_registry_expire(void) { ip_reg_entry_t *entry; ip_reg_entry_t *entry_next; + static time_t next_expire = 0; int i; + /* Only do this if we're ready to */ + if (next_expire >= CurrentTime) + return; + for (i = 0; i < IP_REGISTRY_TABLE_SIZE; ++i) { for (entry = hashTable[i]; entry; entry = entry_next) { entry_next = entry->next; @@ -247,6 +252,8 @@ static void ip_registry_expire(void) { ip_registry_expire_entry(entry); } } + + next_expire = CurrentTime + 60; } @@ -282,6 +289,8 @@ int ip_registry_check_local(unsigned int addr, time_t *next_target_out) ip_reg_entry_t *entry = ip_registry_find(addr); unsigned int free_targets = STARTTARGETS; + assert(0 != next_target_out); + if (0 == entry) { entry = ip_registry_new_entry(addr, 1); return 1; @@ -315,6 +324,18 @@ int ip_registry_check_local(unsigned int addr, time_t *next_target_out) } +/*---------------------------------------------------------------------------- + * ip_registry_local_connect + * + * Does anything that needs to be done once we actually have a client + * structure to play with on a local connection that passed the IPcheck test. + *--------------------------------------------------------------------------*/ +void ip_registry_local_connect(struct Client *cptr) { + assert(0 != cptr); + SetIPChecked(cptr); +} + + /*---------------------------------------------------------------------------- * IPcheck_remote_connect * @@ -327,7 +348,11 @@ int ip_registry_check_local(unsigned int addr, time_t *next_target_out) * Return 0 on failure, 1 on success. *--------------------------------------------------------------------------*/ int ip_registry_check_remote(struct Client* cptr, int is_burst) { - ip_reg_entry_t *entry = ip_registry_find(cptr->ip.s_addr); + ip_reg_entry_t *entry; + + assert(cptr); + + entry = ip_registry_find(cptr->ip.s_addr); SetIPChecked(cptr); @@ -384,7 +409,11 @@ void ip_registry_connect_fail(unsigned int addr) { void ip_registry_connect_succeeded(struct Client *cptr) { const char *tr = ""; unsigned int free_targets = STARTTARGETS; - ip_reg_entry_t *entry = ip_registry_find(cptr->ip.s_addr); + ip_reg_entry_t *entry; + + assert(cptr); + + entry = ip_registry_find(cptr->ip.s_addr); if (!entry) { Debug((DEBUG_ERROR, "Missing registry entry for: %s", cptr->sock_ip)); @@ -415,7 +444,14 @@ void ip_registry_connect_succeeded(struct Client *cptr) { * that belongs to this clients IP number. *--------------------------------------------------------------------------*/ void ip_registry_disconnect(struct Client *cptr) { - ip_reg_entry_t *entry = ip_registry_find(cptr->ip.s_addr); + ip_reg_entry_t *entry; + + assert(0 != cptr); + + if (!IsIPChecked(cptr)) + return; + + entry = ip_registry_find(cptr->ip.s_addr); /* Entry is probably a server if this happens. */ if (0 == entry) @@ -486,123 +522,6 @@ int ip_registry_count(unsigned int addr) { } -/*---------------------------------------------------------------------------- - * IPcheck_local_connect - * - * Event: - * A new connection was accept()-ed with IP number `cptr->ip.s_addr'. - * - * Action: - * Update the IPcheck registry. - * Return: - * 1 : You're allowed to connect. - * 0 : You're not allowed to connect. - * - * Throttling: - * - * A connection should be rejected when a connection from the same IP number was - * received IPCHECK_CLONE_LIMIT times before this connect attempt, with - * reconnect intervals of IPCHECK_CLONE_PERIOD seconds or less. - * - * Free target inheritance: - * - * When the client is accepted, then the number of Free Targets - * of the cptr is set to the value stored in the found IPregistry - * structure, or left at STARTTARGETS. This can be done by changing - * cptr->nexttarget to be `now - (TARGET_DELAY * (FREE_TARGETS - 1))', - * where FREE_TARGETS may range from 0 till STARTTARGETS. - *--------------------------------------------------------------------------*/ -int IPcheck_local_connect(struct in_addr a, time_t* next_target_out) { - assert(0 != next_target_out); - return ip_registry_check_local(a.s_addr, next_target_out); -} - - -/*---------------------------------------------------------------------------- - * IPcheck_remote_connect - * - * Event: - * A remote client connected to Undernet, with IP number `cptr->ip.s_addr' - * and hostname `hostname'. - * - * Action: - * Update the IPcheck registry. - * Return 0 on failure, 1 on success. - *--------------------------------------------------------------------------*/ -int IPcheck_remote_connect(struct Client *cptr, int is_burst) { - assert(0 != cptr); - return ip_registry_check_remote(cptr, is_burst); -} - - -/*---------------------------------------------------------------------------- - * IPcheck_connect_fail - * - * Event: - * This local client failed to connect due to legal reasons. - * - * Action: - * Neutralize the effect of calling IPcheck_local_connect, in such - * a way that the client won't be penalized when trying to reconnect - * again. - *--------------------------------------------------------------------------*/ -void IPcheck_connect_fail(struct in_addr a) { - ip_registry_connect_fail(a.s_addr); -} - - -/*---------------------------------------------------------------------------- - * IPcheck_connect_succeeded - * - * Event: - * A client succeeded to finish the registration. - * - * Finish IPcheck registration of a successfully, locally connected client. - *--------------------------------------------------------------------------*/ -void IPcheck_connect_succeeded(struct Client *cptr) { - assert(0 != cptr); - ip_registry_connect_succeeded(cptr); -} - - -/*---------------------------------------------------------------------------- - * IPcheck_disconnect - * - * Event: - * A local client disconnected or a remote client left Undernet. - * - * Action: - * Update the IPcheck registry. - * Remove all expired IPregistry structures from the hash bucket - * that belongs to this clients IP number. - *--------------------------------------------------------------------------*/ -void IPcheck_disconnect(struct Client *cptr) { - assert(0 != cptr); - ip_registry_disconnect(cptr); -} - - -/*---------------------------------------------------------------------------- - * IPcheck_nr - * - * Returns number of clients with the same IP number - *--------------------------------------------------------------------------*/ -unsigned short IPcheck_nr(struct Client *cptr) { - assert(0 != cptr); - return ip_registry_count(cptr->ip.s_addr); -} -/*---------------------------------------------------------------------------- - * IPcheck_expire - * - * Expire old entries - *--------------------------------------------------------------------------*/ -void IPcheck_expire() { - static time_t next_expire = 0; - if (next_expire < CurrentTime) { - ip_registry_expire(); - next_expire = CurrentTime + 60; - } -} diff --git a/ircd/ircd.c b/ircd/ircd.c index 6012ea5..ededf24 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -495,7 +495,7 @@ static void event_loop(void) { /* timeout pending queries that haven't been responded to */ timeout_auth_queries(CurrentTime); - IPcheck_expire(); + ip_registry_expire(); if (GlobalRehashFlag) { rehash(&me, 1); diff --git a/ircd/m_nick.c b/ircd/m_nick.c index 945e3a9..fe02d16 100644 --- a/ircd/m_nick.c +++ b/ircd/m_nick.c @@ -217,7 +217,7 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) */ if (IsUnknown(acptr) && MyConnect(acptr)) { ++ServerStats->is_ref; - IPcheck_connect_fail(acptr->ip); + ip_registry_connect_fail(acptr->ip.s_addr); exit_client(cptr, acptr, &me, "Overridden by other sign on"); return set_nick_name(cptr, sptr, nick, parc, parv); } @@ -382,7 +382,7 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) */ if (IsUnknown(acptr) && MyConnect(acptr)) { ++ServerStats->is_ref; - IPcheck_connect_fail(acptr->ip); + ip_registry_connect_fail(acptr->ip.s_addr); exit_client(cptr, acptr, &me, "Overridden by other sign on"); return set_nick_name(cptr, sptr, nick, parc, parv); } @@ -665,7 +665,7 @@ int m_nick(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (IsUnknown(acptr) && MyConnect(acptr)) { ++ServerStats->is_ref; - IPcheck_connect_fail(acptr->ip); + ip_registry_connect_fail(acptr->ip.s_addr); exit_client(cptr, acptr, &me, "Overridden by other sign on"); return set_nick_name(cptr, sptr, nick, parc, parv); } diff --git a/ircd/s_auth.c b/ircd/s_auth.c index c687917..ebb1dd6 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -177,7 +177,7 @@ static void auth_kill_client(struct AuthRequest* auth) if (IsDNSPending(auth)) delete_resolver_queries(auth); - IPcheck_disconnect(auth->client); + ip_registry_disconnect(auth->client); Count_unknowndisconnects(UserStats); free_client(auth->client); free_auth_request(auth); diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index b7d7b46..2d82dbb 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -547,63 +547,60 @@ int net_close_unregistered_connections(struct Client* source) return count; } -/* +/*---------------------------------------------------------------------------- + * add_connection + * * Creates a client which has just connected to us on the given fd. * The sockhost field is initialized with the ip# of the host. * The client is not added to the linked list of clients, it is * passed off to the auth handler for dns and ident queries. - */ -void add_connection(struct Listener* listener, int fd) -{ + *--------------------------------------------------------------------------*/ +void add_connection(struct Listener* listener, int fd) { struct sockaddr_in addr; - struct Client* new_client; + struct Client *new_client; time_t next_target = 0; + const char* const throttle_message = "ERROR: Your host is trying to (re)connect too fast -- throttled\r\n"; /* 12345678901234567890123456789012345679012345678901234567890123456 */ assert(0 != listener); + /* - * Removed preliminary access check. Full check is performed in - * m_server and m_user instead. Also connection time out help to - * get rid of unwanted connections. + * Removed preliminary access check. Full check is performed in m_server and + * m_user instead. Also connection time out help to get rid of unwanted + * connections. */ if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) { ++ServerStats->is_ref; close(fd); return; } + + /* * Add this local client to the IPcheck registry. + * * If it is a connection to a user port and if the site has been throttled, * reject the user. */ - if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server) { -#ifdef IPCHECKDEBUG - char buff[512]; - snprintf(buff,512,"\n\rNOTICE * :IPCheck=%i connections active\n\r%s", - IPcheck_nr(cptr), - throttle_message); - buff[511]=0; - send(fd,buff,strlen(buff),0); -#else - /* - * strlen(throttle_message) == 66 - * - * strlen is slow, so we use the constant here. - */ + if (!ip_registry_check_local(addr.sin_addr.s_addr, &next_target) && + !listener->server) { send(fd, throttle_message, 66, 0); -#endif close(fd); ++ServerStats->is_ref; return; } - new_client = make_client(0, - (listener->server) ? STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER); + new_client = make_client(0, ((listener->server) ? + STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER)); + + if (!listener->server) + ip_registry_local_connect(new_client); + /* - * Copy ascii address to 'sockhost' just in case. Then we - * have something valid to put into error messages... + * Copy ascii address to 'sockhost' just in case. Then we have something + * valid to put into error messages... */ ircd_ntoa_r(new_client->sock_ip, (const char*) &addr.sin_addr); strcpy(new_client->sockhost, new_client->sock_ip); @@ -614,19 +611,16 @@ void add_connection(struct Listener* listener, int fd) new_client->nexttarget = next_target; new_client->fd = fd; - - if (!listener->server) - SetIPChecked(new_client); new_client->listener = listener; ++listener->ref_count; Count_newunknown(UserStats); - /* - * if we've made it this far we can put the client on the auth query pile - */ + + /* if we've made it this far we can put the client on the auth query pile */ start_auth(new_client); } + /* * read_packet * diff --git a/ircd/s_conf.c b/ircd/s_conf.c index ec96c49..a28b545 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -498,7 +498,7 @@ check_limit_and_attach(struct Client* cptr, struct ConfItem* aconf) * clients connected with the same IP number */ unsigned short nr = *aconf->passwd - '0'; - if (IPcheck_nr(cptr) > nr) + if (ip_registry_count(cptr->ip.s_addr) > nr) return ACR_TOO_MANY_FROM_IP; /* Already got nr with that ip# */ } #ifdef USEONE diff --git a/ircd/s_misc.c b/ircd/s_misc.c index a5b122c..82fb064 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -277,11 +277,9 @@ static void exit_one_client(struct Client* bcptr, const char* comment) else if (IsUnknown(bcptr) || IsConnecting(bcptr) || IsHandshake(bcptr)) Count_unknowndisconnects(UserStats); - /* - * Update IPregistry - */ - if (IsIPChecked(bcptr)) - IPcheck_disconnect(bcptr); + /* Update IPregistry */ + ip_registry_disconnect(bcptr); + /* * Remove from serv->client_list diff --git a/ircd/s_serv.c b/ircd/s_serv.c index cd7e826..96958ed 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -138,7 +138,7 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf) * XXX - if this comes from a server port, it will not have been added * to the IP check registry, see add_connection in s_bsd.c */ - IPcheck_connect_fail(cptr->ip); + ip_registry_connect_fail(cptr->ip.s_addr); } det_confs_butmask(cptr, CONF_LEAF | CONF_HUB | CONF_SERVER | CONF_UWORLD); diff --git a/ircd/s_user.c b/ircd/s_user.c index a7c0c03..ff7cb11 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -457,7 +457,7 @@ int register_user(struct Client *cptr, struct Client *sptr, get_client_name(sptr, HIDE_IP)); } ++ServerStats->is_ref; - IPcheck_connect_fail(sptr->ip); + ip_registry_connect_fail(sptr->ip.s_addr); return exit_client(cptr, sptr, &me, "Sorry, your connection class is full - try " "again later or try another server"); @@ -476,7 +476,7 @@ int register_user(struct Client *cptr, struct Client *sptr, /* Can this ever happen? */ case ACR_BAD_SOCKET: ++ServerStats->is_ref; - IPcheck_connect_fail(sptr->ip); + ip_registry_connect_fail(sptr->ip.s_addr); return exit_client(cptr, sptr, &me, "Unknown error -- Try again"); } ircd_strncpy(user->host, sptr->sockhost, HOSTLEN); @@ -498,7 +498,7 @@ int register_user(struct Client *cptr, struct Client *sptr, && strcmp(sptr->passwd, aconf->passwd)) { ServerStats->is_ref++; - IPcheck_connect_fail(sptr->ip); + ip_registry_connect_fail(sptr->ip.s_addr); send_reply(sptr, ERR_PASSWDMISMATCH); return exit_client(cptr, sptr, &me, "Bad Password"); } @@ -508,7 +508,7 @@ int register_user(struct Client *cptr, struct Client *sptr, */ if (find_kill(sptr)) { ServerStats->is_ref++; - IPcheck_connect_fail(sptr->ip); + ip_registry_connect_fail(sptr->ip.s_addr); return exit_client(cptr, sptr, &me, "K-lined"); } /* @@ -627,7 +627,7 @@ int register_user(struct Client *cptr, struct Client *sptr, nextping = CurrentTime; if (sptr->snomask & SNO_NOISY) set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD); - IPcheck_connect_succeeded(sptr); + ip_registry_connect_succeeded(sptr); } else /* if (IsServer(cptr)) */ @@ -656,7 +656,7 @@ int register_user(struct Client *cptr, struct Client *sptr, if (IsBurst(acptr) || Protocol(acptr) < 10) break; } - if (!IPcheck_remote_connect(sptr, (acptr != &me))) + if (!ip_registry_check_remote(sptr, (acptr != &me))) /* * We ran out of bits to count this */ diff --git a/ircd/whocmds.c b/ircd/whocmds.c index c06a3af..47f774f 100644 --- a/ircd/whocmds.c +++ b/ircd/whocmds.c @@ -23,7 +23,6 @@ * $Id$ */ #include "whocmds.h" -#include "IPcheck.h" #include "channel.h" #include "client.h" #include "hash.h" -- 2.20.1