X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2FIPcheck.c;h=67b34851cb8fe0bbe4ce905040c4ff1179e81c83;hb=894ccd3b8d5acb0067562d26bf72228d3e617203;hp=af94d8cc50ba4a8484fdc778ff65ccfb87cfa32c;hpb=54e02ed6d1a4b45c942c277a98360479a047d30a;p=ircu2.10.12-pk.git diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c index af94d8c..67b3485 100644 --- a/ircd/IPcheck.c +++ b/ircd/IPcheck.c @@ -27,11 +27,11 @@ #include "ircd.h" #include "match.h" #include "msg.h" -#include "numnicks.h" /* NumNick, NumServ (GODMODE) */ #include "ircd_alloc.h" #include "ircd_events.h" #include "ircd_features.h" #include "ircd_log.h" +#include "ircd_string.h" /* ircd_ntoa */ #include "s_debug.h" /* Debug */ #include "s_user.h" /* TARGET_DELAY */ #include "send.h" @@ -120,8 +120,8 @@ static struct IPRegistryEntry* ip_registry_find(const struct irc_in_addr *ip) ip_registry_canonicalize(&canon, ip); entry = hashTable[ip_registry_hash(&canon)]; for ( ; entry; entry = entry->next) { - int bits = (ip->in6_16[0] == ntohs(0x2002)) ? 48 : 64; - if (ipmask_check(ip, &entry->addr, bits)) + int bits = (canon.in6_16[0] == htons(0x2002)) ? 48 : 64; + if (ipmask_check(&canon, &entry->addr, bits)) break; } return entry; @@ -160,7 +160,7 @@ static void ip_registry_remove(struct IPRegistryEntry* entry) * For members that have a sensible default value, that is used. * @return Newly allocated registry entry. */ -static struct IPRegistryEntry* ip_registry_new_entry() +static struct IPRegistryEntry* ip_registry_new_entry(void) { struct IPRegistryEntry* entry = freeList; if (entry) @@ -219,6 +219,7 @@ static void ip_registry_expire_entry(struct IPRegistryEntry* entry) /* * expired */ + Debug((DEBUG_DNS, "IPcheck expiring registry for %s (no clients connected).", ircd_ntoa(&entry->addr))); ip_registry_remove(entry); ip_registry_delete_entry(entry); } @@ -275,16 +276,17 @@ int ip_registry_check_local(const struct irc_in_addr *addr, time_t* next_target_ entry = ip_registry_new_entry(); ip_registry_canonicalize(&entry->addr, addr); ip_registry_add(entry); + Debug((DEBUG_DNS, "IPcheck added new registry for local connection from %s.", ircd_ntoa(&entry->addr))); return 1; } - /* Note that this also connects server connects. + /* Note that this also counts server connects. * It is hard and not interesting, to change that. - * - * Don't allow more then 255 connects from one IP number, ever + * Refuse connection if it would overflow the counter. */ if (0 == ++entry->connected) { entry->connected--; + Debug((DEBUG_DNS, "IPcheck refusing local connection from %s: counter overflow.", ircd_ntoa(&entry->addr))); return 0; } @@ -302,17 +304,17 @@ int ip_registry_check_local(const struct irc_in_addr *addr, time_t* next_target_ *next_target_out = CurrentTime - (TARGET_DELAY * free_targets - 1); } else if ((CurrentTime - cli_since(&me)) > IPCHECK_CLONE_DELAY) { - /* + /* * Don't refuse connection when we just rebooted the server */ -#ifdef NOTHROTTLE - return 1; -#else +#ifndef NOTHROTTLE assert(entry->connected > 0); --entry->connected; + Debug((DEBUG_DNS, "IPcheck refusing local connection from %s: too fast.", ircd_ntoa(&entry->addr))); return 0; -#endif +#endif } + Debug((DEBUG_DNS, "IPcheck accepting local connection from %s.", ircd_ntoa(&entry->addr))); return 1; } @@ -332,8 +334,10 @@ int ip_registry_check_remote(struct Client* cptr, int is_burst) * Mark that we did add/update an IPregistry entry */ SetIPChecked(cptr); - if (!irc_in_addr_valid(&cli_ip(cptr))) + if (!irc_in_addr_valid(&cli_ip(cptr))) { + Debug((DEBUG_DNS, "IPcheck accepting remote connection from invalid %s.", ircd_ntoa(&cli_ip(cptr)))); return 1; + } entry = ip_registry_find(&cli_ip(cptr)); if (0 == entry) { entry = ip_registry_new_entry(); @@ -341,27 +345,27 @@ int ip_registry_check_remote(struct Client* cptr, int is_burst) if (is_burst) entry->attempts = 0; ip_registry_add(entry); + Debug((DEBUG_DNS, "IPcheck added new registry for remote connection from %s.", ircd_ntoa(&entry->addr))); + return 1; } - else { - if (0 == ++entry->connected) { - /* - * Don't allow more then 255 connects from one IP number, ever + /* Avoid overflowing the connection counter. */ + if (0 == ++entry->connected) { + Debug((DEBUG_DNS, "IPcheck refusing remote connection from %s: counter overflow.", ircd_ntoa(&entry->addr))); + return 0; + } + if (CONNECTED_SINCE(entry->last_connect) > IPCHECK_CLONE_PERIOD) + entry->attempts = 0; + if (!is_burst) { + if (0 == ++entry->attempts) { + /* + * Check for overflow */ - return 0; - } - if (CONNECTED_SINCE(entry->last_connect) > IPCHECK_CLONE_PERIOD) - entry->attempts = 0; - if (!is_burst) { - if (0 == ++entry->attempts) { - /* - * Check for overflow - */ - --entry->attempts; - } - ip_registry_update_free_targets(entry); - entry->last_connect = NOW; + --entry->attempts; } + ip_registry_update_free_targets(entry); + entry->last_connect = NOW; } + Debug((DEBUG_DNS, "IPcheck counting remote connection from %s.", ircd_ntoa(&entry->addr))); return 1; } @@ -369,14 +373,20 @@ int ip_registry_check_remote(struct Client* cptr, int is_burst) * of their own. This "undoes" the effect of ip_registry_check_local() * so the client's address is not penalized for the failure. * @param[in] addr Address of rejected client. + * @param[in] disconnect If true, also count the client as disconnecting. */ -void ip_registry_connect_fail(const struct irc_in_addr *addr) +void ip_registry_connect_fail(const struct irc_in_addr *addr, int disconnect) { struct IPRegistryEntry* entry = ip_registry_find(addr); - if (entry) - { - if (0 == --entry->attempts) + if (entry) { + if (0 == --entry->attempts) { + Debug((DEBUG_DNS, "IPcheck noting local connection failure for %s.", ircd_ntoa(&entry->addr))); ++entry->attempts; + } + if (disconnect) { + assert(entry->connected > 0); + entry->connected--; + } } } @@ -392,15 +402,13 @@ void ip_registry_connect_succeeded(struct Client *cptr) unsigned int free_targets = STARTTARGETS; struct IPRegistryEntry* entry = ip_registry_find(&cli_ip(cptr)); - if (!entry) { - Debug((DEBUG_ERROR, "Missing registry entry for: %s", cli_sock_ip(cptr))); - return; - } + assert(entry); if (entry->target) { memcpy(cli_targets(cptr), entry->target->targets, MAXTARGETS); free_targets = entry->target->count; tr = " tr"; } + Debug((DEBUG_DNS, "IPcheck noting local connection success for %s.", ircd_ntoa(&entry->addr))); sendcmdto_one(&me, CMD_NOTICE, cptr, "%C :on %u ca %u(%u) ft %u(%u)%s", cptr, entry->connected, entry->attempts, IPCHECK_CLONE_LIMIT, free_targets, STARTTARGETS, tr); @@ -414,21 +422,20 @@ void ip_registry_connect_succeeded(struct Client *cptr) void ip_registry_disconnect(struct Client *cptr) { struct IPRegistryEntry* entry = ip_registry_find(&cli_ip(cptr)); - if (0 == entry) { - /* - * trying to find an entry for a server causes this to happen, - * servers should never have FLAG_IPCHECK set - */ + if (!irc_in_addr_valid(&cli_ip(cptr))) { + Debug((DEBUG_DNS, "IPcheck noting dicconnect from invalid %s.", ircd_ntoa(&cli_ip(cptr)))); return; } + assert(entry); + assert(entry->connected > 0); + Debug((DEBUG_DNS, "IPcheck noting disconnect from %s.", ircd_ntoa(&entry->addr))); /* * If this was the last one, set `last_connect' to disconnect time (used for expiration) */ - /* assert(entry->connected > 0); */ if (0 == --entry->connected) { if (CONNECTED_SINCE(entry->last_connect) > IPCHECK_CLONE_LIMIT * IPCHECK_CLONE_PERIOD) { /* - * Otherwise we'd penetalize for this old value if the client reconnects within 20 seconds + * Otherwise we'd penalize for this old value if the client reconnects within 20 seconds */ entry->attempts = 0; } @@ -450,7 +457,7 @@ void ip_registry_disconnect(struct Client *cptr) /* * This calculation can be pretty unfair towards large multi-user hosts, but * there is "nothing" we can do without also allowing spam bots to send more - * messages or by drastically increasing the ammount of memory used in the IPregistry. + * messages or by drastically increasing the amount of memory used in the IPregistry. * * The problem is that when a client disconnects, leaving no free targets, then * the next client from that IP number has to pay for it (getting no free targets). @@ -477,7 +484,7 @@ void ip_registry_disconnect(struct Client *cptr) */ free_targets += (CurrentTime - cli_firsttime(cptr) - 600) / TARGET_DELAY; /* - * Finally, store smallest value for Judgement Day + * Finally, store smallest value for Judgment Day */ if (free_targets < entry->target->count) entry->target->count = free_targets; @@ -513,17 +520,20 @@ int IPcheck_local_connect(const struct irc_in_addr *a, time_t* next_target_out) int IPcheck_remote_connect(struct Client *cptr, int is_burst) { assert(0 != cptr); + assert(!IsIPChecked(cptr)); return ip_registry_check_remote(cptr, is_burst); } /** Handle a client being rejected during connection through no fault * of their own. This "undoes" the effect of ip_registry_check_local() * so the client's address is not penalized for the failure. - * @param[in] a Address of rejected client. + * @param[in] cptr Client who has been rejected. + * @param[in] disconnect If true, also count the client as disconnecting. */ -void IPcheck_connect_fail(const struct irc_in_addr *a) +void IPcheck_connect_fail(const struct Client *cptr, int disconnect) { - ip_registry_connect_fail(a); + assert(IsIPChecked(cptr)); + ip_registry_connect_fail(&cli_ip(cptr), disconnect); } /** Handle a client that has successfully connected. @@ -535,6 +545,7 @@ void IPcheck_connect_fail(const struct irc_in_addr *a) void IPcheck_connect_succeeded(struct Client *cptr) { assert(0 != cptr); + assert(IsIPChecked(cptr)); ip_registry_connect_succeeded(cptr); } @@ -546,6 +557,7 @@ void IPcheck_connect_succeeded(struct Client *cptr) void IPcheck_disconnect(struct Client *cptr) { assert(0 != cptr); + assert(IsIPChecked(cptr)); ip_registry_disconnect(cptr); }