diff --git a/include/struct.h b/include/struct.h index a25b98c55..92f20ba04 100644 --- a/include/struct.h +++ b/include/struct.h @@ -861,10 +861,11 @@ typedef void (*OverrideCmdFunc)(CommandOverride *ovr, Client *client, MessageTag /* these are not real tkl types, but only used for exceptions: */ #define TKL_BLACKLIST 0x0001000 #define TKL_CONNECT_FLOOD 0x0002000 -#define TKL_UNKNOWN_DATA_FLOOD 0x0004000 -#define TKL_ANTIRANDOM 0x0008000 -#define TKL_ANTIMIXEDUTF8 0x0010000 -#define TKL_BAN_VERSION 0x0020000 +#define TKL_MAXPERIP 0x0004000 +#define TKL_UNKNOWN_DATA_FLOOD 0x0008000 +#define TKL_ANTIRANDOM 0x0010000 +#define TKL_ANTIMIXEDUTF8 0x0020000 +#define TKL_BAN_VERSION 0x0040000 #define TKLIsServerBan(tkl) ((tkl)->type & (TKL_KILL|TKL_ZAP|TKL_SHUN)) #define TKLIsServerBanType(tpe) ((tpe) & (TKL_KILL|TKL_ZAP|TKL_SHUN)) diff --git a/src/modules/nick.c b/src/modules/nick.c index 6ab75ffc5..d825a8bd3 100644 --- a/src/modules/nick.c +++ b/src/modules/nick.c @@ -1258,6 +1258,27 @@ int check_init(Client *client, char *sockn, size_t size) return 1; } +/** Returns 1 if allow::maxperip is exceeded by 'client' */ +int exceeds_maxperip(Client *client, ConfigItem_allow *aconf) +{ + Client *acptr; + int cnt = 1; + + if (find_tkl_exception(TKL_MAXPERIP, client)) + return 0; /* exempt */ + + list_for_each_entry(acptr, &lclient_list, lclient_node) + { + if (IsUser(acptr) && !strcmp(GetIP(acptr), GetIP(client))) + { + cnt++; + if (cnt > aconf->maxperip) + return 1; + } + } + return 0; +} + /** Allow or reject the client based on allow { } blocks and all other restrictions. * @param client Client to check (local) * @param username Username, for some reason... @@ -1365,25 +1386,13 @@ int AllowClient(Client *client, char *username) strlcpy(uhost, sockhost, sizeof(uhost)); set_sockhost(client, uhost); - if (aconf->maxperip) + if (aconf->maxperip && exceeds_maxperip(client, aconf)) { - Client *acptr, *acptr2; - int cnt = 1; - - list_for_each_entry_safe(acptr, acptr2, &lclient_list, lclient_node) - { - if (!strcmp(GetIP(acptr), GetIP(client))) - { - cnt++; - if (cnt > aconf->maxperip) - { - /* Already got too many with that ip# */ - exit_client(client, NULL, iConf.reject_message_too_many_connections); - return 0; - } - } - } + /* Already got too many with that ip# */ + exit_client(client, NULL, iConf.reject_message_too_many_connections); + return 0; } + if (aconf->auth && !Auth_Check(client, aconf->auth, client->local->passwd)) { /* Always continue if password was wrong. */ diff --git a/src/modules/tkl.c b/src/modules/tkl.c index 334d0496f..909c7fb44 100644 --- a/src/modules/tkl.c +++ b/src/modules/tkl.c @@ -124,6 +124,7 @@ TKLTypeTable tkl_types[] = { { "local-exception", 'f', TKL_SPAMF, "Local Spamfilter", 1, 0 }, { "blacklist", 'b', TKL_BLACKLIST, "Blacklist", 0, 1 }, { "connect-flood", 'c', TKL_CONNECT_FLOOD, "Connect flood", 0, 1 }, + { "maxperip", 'm', TKL_MAXPERIP, "Max-per-IP", 0, 1 }, { "unknown-data-flood", 'd', TKL_UNKNOWN_DATA_FLOOD, "Unknown data flood", 0, 1 }, { "antirandom", 'r', TKL_ANTIRANDOM, "Antirandom", 0, 1 }, { "antimixedutf8", '8', TKL_ANTIMIXEDUTF8, "Antimixedutf8", 0, 1 }, @@ -1361,6 +1362,7 @@ void eline_syntax(Client *client) sendnotice(client, "b: Blacklist checking"); sendnotice(client, "c: Connect flood (bypass set::anti-flood::connect-flood))"); sendnotice(client, "d: Unknown data flood (no ZLINE on too much data before registration)"); + sendnotice(client, "m: Bypass allow::maxperip restriction"); sendnotice(client, "r: Bypass antirandom module"); sendnotice(client, "8: Bypass antimixedutf8 module"); sendnotice(client, "v: Bypass ban version { } blocks");