mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-01 16:26:37 +02:00
Similar to previous commit, move maxperip stuff from core to module.
This was in src/hash.c, src/list.c and src/modules/stats.c. Now all in src/modules/nick.c... or should this go into a new module? Again, this needs some more testing, like previous commit.
This commit is contained in:
@@ -436,7 +436,6 @@ extern void del_queries(const char *);
|
||||
#define NICK_HASH_TABLE_SIZE 32768
|
||||
#define CHAN_HASH_TABLE_SIZE 32768
|
||||
#define WHOWAS_HASH_TABLE_SIZE 32768
|
||||
#define IPUSERS_HASH_TABLE_SIZE 8192
|
||||
extern uint64_t siphash(const char *in, const char *k);
|
||||
extern uint64_t siphash_raw(const char *in, size_t len, const char *k);
|
||||
extern uint64_t siphash_nocase(const char *in, const char *k);
|
||||
@@ -462,12 +461,6 @@ extern Client *hash_find_id(const char *, Client *);
|
||||
extern Client *hash_find_nickatserver(const char *, Client *);
|
||||
extern Channel *find_channel(const char *name);
|
||||
extern Client *hash_find_server(const char *, Client *);
|
||||
extern IpUsersBucket *find_ipusers_bucket(Client *client);
|
||||
extern IpUsersBucket *add_ipusers_bucket(Client *client);
|
||||
extern void decrease_ipusers_bucket(Client *client);
|
||||
extern MODVAR IpUsersBucket *IpUsersHash_ipv4[IPUSERS_HASH_TABLE_SIZE];
|
||||
extern MODVAR IpUsersBucket *IpUsersHash_ipv6[IPUSERS_HASH_TABLE_SIZE];
|
||||
|
||||
|
||||
/* Mode externs
|
||||
*/
|
||||
|
||||
@@ -2469,15 +2469,6 @@ extern MODVAR SSL_CTX *ctx_client;
|
||||
|
||||
#define TLS_PROTOCOL_ALL 0xffff
|
||||
|
||||
typedef struct IpUsersBucket IpUsersBucket;
|
||||
struct IpUsersBucket
|
||||
{
|
||||
IpUsersBucket *prev, *next;
|
||||
char rawip[16];
|
||||
int local_clients;
|
||||
int global_clients;
|
||||
};
|
||||
|
||||
typedef struct CoreChannelModeTable CoreChannelModeTable;
|
||||
struct CoreChannelModeTable {
|
||||
long mode; /**< Mode value (which bit will be set) */
|
||||
|
||||
-96
@@ -264,7 +264,6 @@ static Channel *channelTable[CHAN_HASH_TABLE_SIZE];
|
||||
static char siphashkey_nick[SIPHASH_KEY_LENGTH];
|
||||
static char siphashkey_chan[SIPHASH_KEY_LENGTH];
|
||||
static char siphashkey_whowas[SIPHASH_KEY_LENGTH];
|
||||
static char siphashkey_ipusers[SIPHASH_KEY_LENGTH];
|
||||
|
||||
extern char unreallogo[];
|
||||
|
||||
@@ -276,7 +275,6 @@ void init_hash(void)
|
||||
siphash_generate_key(siphashkey_nick);
|
||||
siphash_generate_key(siphashkey_chan);
|
||||
siphash_generate_key(siphashkey_whowas);
|
||||
siphash_generate_key(siphashkey_ipusers);
|
||||
|
||||
for (i = 0; i < NICK_HASH_TABLE_SIZE; i++)
|
||||
INIT_LIST_HEAD(&clientTable[i]);
|
||||
@@ -599,97 +597,3 @@ Client *find_server_by_uid(const char *uid)
|
||||
strlcpy(sid, uid, sizeof(sid));
|
||||
return hash_find_id(sid, NULL);
|
||||
}
|
||||
|
||||
/**** IP users hash table *****/
|
||||
|
||||
MODVAR IpUsersBucket *IpUsersHash_ipv4[IPUSERS_HASH_TABLE_SIZE];
|
||||
MODVAR IpUsersBucket *IpUsersHash_ipv6[IPUSERS_HASH_TABLE_SIZE];
|
||||
|
||||
uint64_t hash_ipusers(const char *ip)
|
||||
{
|
||||
return siphash(ip, siphashkey_ipusers) % IPUSERS_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
IpUsersBucket *find_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash = 0;
|
||||
IpUsersBucket *p;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
for (p = IpUsersHash_ipv6[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 16) == 0)
|
||||
return p;
|
||||
} else {
|
||||
for (p = IpUsersHash_ipv4[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 4) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IpUsersBucket *add_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash;
|
||||
IpUsersBucket *n;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
n = safe_alloc(sizeof(IpUsersBucket));
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
memcpy(n->rawip, client->rawip, 16);
|
||||
AddListItem(n, IpUsersHash_ipv6[hash]);
|
||||
} else {
|
||||
memcpy(n->rawip, client->rawip, 4);
|
||||
AddListItem(n, IpUsersHash_ipv4[hash]);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void decrease_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash = 0;
|
||||
IpUsersBucket *p;
|
||||
|
||||
if (!(client->flags & CLIENT_FLAG_IPUSERS_BUMPED))
|
||||
return; /* nothing to do */
|
||||
|
||||
client->flags &= ~CLIENT_FLAG_IPUSERS_BUMPED;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
for (p = IpUsersHash_ipv6[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 16) == 0)
|
||||
break;
|
||||
} else {
|
||||
for (p = IpUsersHash_ipv4[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 4) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
unreal_log(ULOG_INFO, "user", "BUG_DECREASE_IPUSERS_BUCKET", client,
|
||||
"[BUG] decrease_ipusers_bucket() called but bucket is gone for client $client.details");
|
||||
return;
|
||||
}
|
||||
|
||||
p->global_clients--;
|
||||
if (MyConnect(client))
|
||||
p->local_clients--;
|
||||
|
||||
if ((p->global_clients == 0) && (p->local_clients == 0))
|
||||
{
|
||||
if (IsIPV6(client))
|
||||
DelListItem(p, IpUsersHash_ipv6[hash]);
|
||||
else
|
||||
DelListItem(p, IpUsersHash_ipv4[hash]);
|
||||
safe_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,8 +284,6 @@ void free_user(Client *client)
|
||||
{
|
||||
RunHook(HOOKTYPE_FREE_USER, client);
|
||||
|
||||
decrease_ipusers_bucket(client);
|
||||
|
||||
safe_free(client->user->away);
|
||||
if (client->user->swhois)
|
||||
{
|
||||
|
||||
+13
-13
@@ -65,6 +65,19 @@ MOD_INIT()
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
MOD_LOAD()
|
||||
{
|
||||
add_throttling_timeout_timer(modinfo);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
MOD_UNLOAD()
|
||||
{
|
||||
SavePersistentPointer(modinfo, siphashkey_throttling);
|
||||
SavePersistentPointer(modinfo, ThrottlingHash);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
void siphashkey_throttling_free(ModData *m)
|
||||
{
|
||||
safe_free(siphashkey_throttling);
|
||||
@@ -79,19 +92,6 @@ void throttlinghash_free(ModData *m)
|
||||
m->ptr = NULL;
|
||||
}
|
||||
|
||||
MOD_LOAD()
|
||||
{
|
||||
add_throttling_timeout_timer(modinfo);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
MOD_UNLOAD()
|
||||
{
|
||||
SavePersistentPointer(modinfo, siphashkey_throttling);
|
||||
SavePersistentPointer(modinfo, ThrottlingHash);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
int connect_flood_throttle(Client *client, int exitflags)
|
||||
{
|
||||
int val;
|
||||
|
||||
+207
-1
@@ -45,8 +45,23 @@ ModuleHeader MOD_HEADER
|
||||
*/
|
||||
#define ASSUME_NICK_IN_FLIGHT
|
||||
|
||||
#define IPUSERS_HASH_TABLE_SIZE 8192
|
||||
|
||||
/* Structs */
|
||||
typedef struct IpUsersBucket IpUsersBucket;
|
||||
struct IpUsersBucket
|
||||
{
|
||||
IpUsersBucket *prev, *next;
|
||||
char rawip[16];
|
||||
int local_clients;
|
||||
int global_clients;
|
||||
};
|
||||
|
||||
/* Variables */
|
||||
static char spamfilter_user[NICKLEN + USERLEN + HOSTLEN + REALLEN + 64];
|
||||
IpUsersBucket **IpUsersHash_ipv4 = NULL;
|
||||
IpUsersBucket **IpUsersHash_ipv6 = NULL;
|
||||
char *siphashkey_ipusers = NULL;
|
||||
|
||||
/* Forward declarations */
|
||||
CMD_FUNC(cmd_nick);
|
||||
@@ -57,6 +72,13 @@ int _register_user(Client *client);
|
||||
void nick_collision(Client *cptr, const char *newnick, const char *newid, Client *new, Client *existing, int type);
|
||||
int AllowClient(Client *client);
|
||||
int exceeds_maxperip(Client *client, ConfigItem_allow *aconf);
|
||||
void siphashkey_ipusers_free(ModData *m);
|
||||
void ipusershash_free_4(ModData *m);
|
||||
void ipusershash_free_6(ModData *m);
|
||||
IpUsersBucket *add_ipusers_bucket(Client *client);
|
||||
void decrease_ipusers_bucket(Client *client);
|
||||
int decrease_ipusers_bucket_wrapper(Client *client);
|
||||
int stats_maxperip(Client *client, const char *para);
|
||||
|
||||
MOD_TEST()
|
||||
{
|
||||
@@ -67,9 +89,26 @@ MOD_TEST()
|
||||
|
||||
MOD_INIT()
|
||||
{
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
|
||||
LoadPersistentPointer(modinfo, siphashkey_ipusers, siphashkey_ipusers_free);
|
||||
if (!siphashkey_ipusers)
|
||||
{
|
||||
siphashkey_ipusers = safe_alloc(SIPHASH_KEY_LENGTH);
|
||||
siphash_generate_key(siphashkey_ipusers);
|
||||
}
|
||||
LoadPersistentPointer(modinfo, IpUsersHash_ipv4, ipusershash_free_4);
|
||||
if (!IpUsersHash_ipv4)
|
||||
IpUsersHash_ipv4 = safe_alloc(sizeof(IpUsersBucket *) * IPUSERS_HASH_TABLE_SIZE);
|
||||
LoadPersistentPointer(modinfo, IpUsersHash_ipv6, ipusershash_free_6);
|
||||
if (!IpUsersHash_ipv6)
|
||||
IpUsersHash_ipv6 = safe_alloc(sizeof(IpUsersBucket *) * IPUSERS_HASH_TABLE_SIZE);
|
||||
|
||||
CommandAdd(modinfo->handle, "NICK", cmd_nick, MAXPARA, CMD_USER|CMD_SERVER|CMD_UNREGISTERED);
|
||||
CommandAdd(modinfo->handle, "UID", cmd_uid, MAXPARA, CMD_SERVER);
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
|
||||
HookAdd(modinfo->handle, HOOKTYPE_FREE_USER, 0, decrease_ipusers_bucket_wrapper);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, stats_maxperip);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -80,9 +119,176 @@ MOD_LOAD()
|
||||
|
||||
MOD_UNLOAD()
|
||||
{
|
||||
SavePersistentPointer(modinfo, siphashkey_ipusers);
|
||||
SavePersistentPointer(modinfo, IpUsersHash_ipv4);
|
||||
SavePersistentPointer(modinfo, IpUsersHash_ipv6);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
void siphashkey_ipusers_free(ModData *m)
|
||||
{
|
||||
safe_free(siphashkey_ipusers);
|
||||
m->ptr = NULL;
|
||||
}
|
||||
|
||||
void ipusershash_free_4(ModData *m)
|
||||
{
|
||||
// FIXME: need to free every bucket in a for loop
|
||||
// and then end with this:
|
||||
safe_free(IpUsersHash_ipv4);
|
||||
m->ptr = NULL;
|
||||
}
|
||||
|
||||
void ipusershash_free_6(ModData *m)
|
||||
{
|
||||
// FIXME: need to free every bucket in a for loop
|
||||
// and then end with this:
|
||||
safe_free(IpUsersHash_ipv6);
|
||||
m->ptr = NULL;
|
||||
}
|
||||
|
||||
uint64_t hash_ipusers(const char *ip)
|
||||
{
|
||||
return siphash(ip, siphashkey_ipusers) % IPUSERS_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
IpUsersBucket *find_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash = 0;
|
||||
IpUsersBucket *p;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
for (p = IpUsersHash_ipv6[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 16) == 0)
|
||||
return p;
|
||||
} else {
|
||||
for (p = IpUsersHash_ipv4[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 4) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* (wrapper needed because hook has return type 'int' and function is 'void' */
|
||||
int decrease_ipusers_bucket_wrapper(Client *client)
|
||||
{
|
||||
decrease_ipusers_bucket(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IpUsersBucket *add_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash;
|
||||
IpUsersBucket *n;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
n = safe_alloc(sizeof(IpUsersBucket));
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
memcpy(n->rawip, client->rawip, 16);
|
||||
AddListItem(n, IpUsersHash_ipv6[hash]);
|
||||
} else {
|
||||
memcpy(n->rawip, client->rawip, 4);
|
||||
AddListItem(n, IpUsersHash_ipv4[hash]);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void decrease_ipusers_bucket(Client *client)
|
||||
{
|
||||
int hash = 0;
|
||||
IpUsersBucket *p;
|
||||
|
||||
if (!(client->flags & CLIENT_FLAG_IPUSERS_BUMPED))
|
||||
return; /* nothing to do */
|
||||
|
||||
client->flags &= ~CLIENT_FLAG_IPUSERS_BUMPED;
|
||||
|
||||
hash = hash_ipusers(client->ip);
|
||||
|
||||
if (IsIPV6(client))
|
||||
{
|
||||
for (p = IpUsersHash_ipv6[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 16) == 0)
|
||||
break;
|
||||
} else {
|
||||
for (p = IpUsersHash_ipv4[hash]; p; p = p->next)
|
||||
if (memcmp(p->rawip, client->rawip, 4) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
unreal_log(ULOG_INFO, "user", "BUG_DECREASE_IPUSERS_BUCKET", client,
|
||||
"[BUG] decrease_ipusers_bucket() called but bucket is gone for client $client.details");
|
||||
return;
|
||||
}
|
||||
|
||||
p->global_clients--;
|
||||
if (MyConnect(client))
|
||||
p->local_clients--;
|
||||
|
||||
if ((p->global_clients == 0) && (p->local_clients == 0))
|
||||
{
|
||||
if (IsIPV6(client))
|
||||
DelListItem(p, IpUsersHash_ipv6[hash]);
|
||||
else
|
||||
DelListItem(p, IpUsersHash_ipv4[hash]);
|
||||
safe_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
int stats_maxperip(Client *client, const char *para)
|
||||
{
|
||||
int i;
|
||||
IpUsersBucket *e;
|
||||
char ipbuf[256];
|
||||
const char *ip;
|
||||
|
||||
/* '/STATS 8' or '/STATS maxperip' is for us... */
|
||||
if (strcmp(para, "8") && strcasecmp(para, "maxperip"))
|
||||
return 0;
|
||||
|
||||
if (!ValidatePermissionsForPath("server:info:stats",client,NULL,NULL,NULL))
|
||||
{
|
||||
sendnumeric(client, ERR_NOPRIVILEGES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sendtxtnumeric(client, "MaxPerIp IPv4 hash table:");
|
||||
for (i=0; i < IPUSERS_HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
for (e = IpUsersHash_ipv4[i]; e; e = e->next)
|
||||
{
|
||||
ip = inetntop(AF_INET, e->rawip, ipbuf, sizeof(ipbuf));
|
||||
if (!ip)
|
||||
ip = "<invalid>";
|
||||
sendtxtnumeric(client, "IPv4 #%d %s: %d local / %d global",
|
||||
i, ip, e->local_clients, e->global_clients);
|
||||
}
|
||||
}
|
||||
|
||||
sendtxtnumeric(client, "MaxPerIp IPv6 hash table:");
|
||||
for (i=0; i < IPUSERS_HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
for (e = IpUsersHash_ipv6[i]; e; e = e->next)
|
||||
{
|
||||
ip = inetntop(AF_INET6, e->rawip, ipbuf, sizeof(ipbuf));
|
||||
if (!ip)
|
||||
ip = "<invalid>";
|
||||
sendtxtnumeric(client, "IPv6 #%d %s: %d local / %d global",
|
||||
i, ip, e->local_clients, e->global_clients);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Hmm.. don't we already have such a function? */
|
||||
void set_user_modes_dont_spread(Client *client, const char *umode)
|
||||
{
|
||||
|
||||
@@ -84,7 +84,6 @@ int stats_officialchannels(Client *, const char *);
|
||||
int stats_spamfilter(Client *, const char *);
|
||||
int stats_fdtable(Client *, const char *);
|
||||
int stats_linecache(Client *client, const char *para);
|
||||
int stats_maxperip(Client *, const char *);
|
||||
|
||||
#define SERVER_AS_PARA 0x1
|
||||
#define FLAGS_AS_PARA 0x2
|
||||
@@ -136,7 +135,6 @@ struct statstab StatsTable[] = {
|
||||
{ 'v', "denyver", stats_denyver, 0 },
|
||||
{ 'x', "notlink", stats_notlink, 0 },
|
||||
{ 'y', "class", stats_class, 0 },
|
||||
{ '8', "maxperip", stats_maxperip, 0 },
|
||||
{ '9', "linecache", stats_linecache, 0 },
|
||||
{ 0, NULL, NULL, 0 }
|
||||
};
|
||||
@@ -1081,45 +1079,3 @@ int stats_linecache(Client *client, const char *para)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stats_maxperip(Client *client, const char *para)
|
||||
{
|
||||
int i;
|
||||
IpUsersBucket *e;
|
||||
char ipbuf[256];
|
||||
const char *ip;
|
||||
|
||||
if (!ValidatePermissionsForPath("server:info:stats",client,NULL,NULL,NULL))
|
||||
{
|
||||
sendnumeric(client, ERR_NOPRIVILEGES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sendtxtnumeric(client, "MaxPerIp IPv4 hash table:");
|
||||
for (i=0; i < IPUSERS_HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
for (e = IpUsersHash_ipv4[i]; e; e = e->next)
|
||||
{
|
||||
ip = inetntop(AF_INET, e->rawip, ipbuf, sizeof(ipbuf));
|
||||
if (!ip)
|
||||
ip = "<invalid>";
|
||||
sendtxtnumeric(client, "IPv4 #%d %s: %d local / %d global",
|
||||
i, ip, e->local_clients, e->global_clients);
|
||||
}
|
||||
}
|
||||
|
||||
sendtxtnumeric(client, "MaxPerIp IPv6 hash table:");
|
||||
for (i=0; i < IPUSERS_HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
for (e = IpUsersHash_ipv6[i]; e; e = e->next)
|
||||
{
|
||||
ip = inetntop(AF_INET6, e->rawip, ipbuf, sizeof(ipbuf));
|
||||
if (!ip)
|
||||
ip = "<invalid>";
|
||||
sendtxtnumeric(client, "IPv6 #%d %s: %d local / %d global",
|
||||
i, ip, e->local_clients, e->global_clients);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user