1
0
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:
Bram Matthys
2024-09-14 20:11:56 +02:00
parent 710afe7cc7
commit 2ef39497c7
7 changed files with 220 additions and 172 deletions
-7
View File
@@ -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
*/
-9
View File
@@ -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
View File
@@ -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);
}
}
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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)
{
-44
View File
@@ -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;
}