From: Gunnar Beutner Date: Mon, 17 Jun 2013 10:22:55 +0000 (+0200) Subject: Implement pernodemax/nodebits for THs. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/cebc4cab58027ae9b510eadebfa27970068af38f Implement pernodemax/nodebits for THs. --HG-- branch : shroudtrusts --- diff --git a/core/hooks.h b/core/hooks.h index 28f961c3..67a3e9ab 100644 --- a/core/hooks.h +++ b/core/hooks.h @@ -41,6 +41,7 @@ #define HOOK_NICK_MODEOPER 307 /* Argument is void*[2] (nick, modes) */ #define HOOK_NICK_KILL 308 /* Argument is void*[2] (nick, reason) */ #define HOOK_NICK_MASKPRIVMSG 309 /* Argument is void*[3] (nick, target, message) ** NICK COULD BE NULL ** */ +#define HOOK_NICK_MOVENODE 310 /* Argument is void*[2] (nick, oldnode) */ #define HOOK_CHANNEL_BURST 400 /* Argument is channel pointer */ #define HOOK_CHANNEL_CREATE 401 /* Argument is void*[2] (channel, nick) */ diff --git a/nick/nick.c b/nick/nick.c index 10203dc6..05fea70c 100644 --- a/nick/nick.c +++ b/nick/nick.c @@ -370,6 +370,31 @@ char *visibleuserhost(nick *np, char *buf) { return buf; } +/* + * setipnodebits: + * Moves the nick to a different ipnode. + */ +void setipnodebits(nick *np, int bits) { + struct irc_in_addr ipaddress; + patricia_node_t *oldnode; + void *harg[2]; + + if(np->ipnode->prefix->bitlen == bits) + return; + + memcpy(&ipaddress, &np->p_nodeaddr, sizeof(ipaddress)); + node_decrement_usercount(np->ipnode); + oldnode = np->ipnode; + np->ipnode = refnode(iptree, &ipaddress, bits); + node_increment_usercount(np->ipnode); + + harg[0] = np; + harg[1] = oldnode; + triggerhook(HOOK_NICK_MOVENODE, harg); + + derefnode(iptree, oldnode); +} + #if 0 /* @@ -423,5 +448,6 @@ nick *getnickbynumericstr(char *numericstr) { return getnickbynumeric(numerictolong(numericstr,5)); } + #endif diff --git a/nick/nick.h b/nick/nick.h index 984d1407..eab487b1 100644 --- a/nick/nick.h +++ b/nick/nick.h @@ -154,6 +154,7 @@ typedef struct nick { } nick; #define p_ipaddr ipaddress +#define p_nodeaddr ipnode->prefix->sin #define NICKHASHSIZE 60000 #define HOSTHASHSIZE 40000 @@ -199,6 +200,7 @@ int findnickext(const char *name); void releasenickext(int index); char *visiblehostmask(nick *np, char *buf); char *visibleuserhost(nick *np, char *buf); +void setipnodebits(nick *np, int bits); /* nickhandlers.c functions */ int handlenickmsg(void *source, int cargc, char **cargv); diff --git a/patricianick/patricianick.c b/patricianick/patricianick.c index 9eca059e..e9e00aa0 100644 --- a/patricianick/patricianick.c +++ b/patricianick/patricianick.c @@ -46,6 +46,7 @@ void _init() { registerhook(HOOK_NICK_NEWNICK, &pn_hook_newuser); registerhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser); + registerhook(HOOK_NICK_MOVENODE, &pn_hook_movenodeuser); registercontrolhelpcmd("nodeuserlist", NO_OPER, 1, &pn_cmd_nodeuserlist, "Usage: nodeuserlist \nLists all users on a given IP address or CIDR range."); } @@ -63,6 +64,7 @@ void _fini() { deregisterhook(HOOK_NICK_NEWNICK, &pn_hook_newuser); deregisterhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser); + deregisterhook(HOOK_NICK_MOVENODE, &pn_hook_movenodeuser); deregistercontrolcmd("nodeuserlist", &pn_cmd_nodeuserlist); } @@ -146,6 +148,14 @@ void pn_hook_lostuser(int hook, void *arg) { deletenickfromnode(np->ipnode, np); } +void pn_hook_nodemoveuser(int hook, void *arg) { + nick *np = ((void **)arg)[0]; + patricia_node_t *oldnode = ((void **)arg)[1]; + + deletenickfromnode(oldnode, np); + addnicktonode(np->ipnode, np); +} + int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv) { nick *np=(nick *)source; struct irc_in_addr sin; diff --git a/patricianick/patricianick.h b/patricianick/patricianick.h index 339c20d1..f89c5c79 100644 --- a/patricianick/patricianick.h +++ b/patricianick/patricianick.h @@ -16,6 +16,7 @@ extern int pnick_ext; void pn_hook_newuser(int hook, void *arg); void pn_hook_lostuser(int hook, void *arg); +void pn_hook_movenodeuser(int hook, void *arg); void addnicktonode(patricia_node_t *node, nick *nick); void deletenickfromnode(patricia_node_t *node, nick *nick); diff --git a/trusts/data.c b/trusts/data.c index eed4c504..f1cc016f 100644 --- a/trusts/data.c +++ b/trusts/data.c @@ -91,6 +91,9 @@ trusthost *th_add(trusthost *ith) { th->users = NULL; th->count = 0; + th->maxpernode = 0; + th->nodebits = 128; + th->parent = NULL; th->children = NULL; @@ -354,7 +357,7 @@ void th_adjusthosts(trusthost *th, trusthost *superset, trusthost *subset) { nick *np, *nnp; for(np=superset->users;np;np=nnp) { nnp = nextbytrust(np); - if((irc_in_addr_v4_to_int(&np->p_ipaddr) & th->mask) == th->ip) { + if((irc_in_addr_v4_to_int(&np->p_nodeaddr) & th->mask) == th->ip) { trusts_lostnick(np, 1); trusts_newnick(np, 1); } @@ -367,7 +370,7 @@ void th_adjusthosts(trusthost *th, trusthost *superset, trusthost *subset) { for(i=0;inext) - if(!gettrusthost(np) && ((irc_in_addr_v4_to_int(&np->p_ipaddr) & th->mask) == th->ip)) + if(!gettrusthost(np) && ((irc_in_addr_v4_to_int(&np->p_nodeaddr) & th->mask) == th->ip)) trusts_newnick(np, 1); } } diff --git a/trusts/events.c b/trusts/events.c index 797fc4ba..ca0efdb9 100644 --- a/trusts/events.c +++ b/trusts/events.c @@ -23,6 +23,7 @@ void trusts_newnick(nick *sender, int moving) { } else { setnextbytrust(sender, th->users); th->users = sender; + setipnodebits(sender, th->nodebits); } arg[0] = sender; diff --git a/trusts/formats.c b/trusts/formats.c index 77167351..d6a15c18 100644 --- a/trusts/formats.c +++ b/trusts/formats.c @@ -79,7 +79,7 @@ char *dumpth(trusthost *th, int oformat) { if(oformat) { snprintf(buf, sizeof(buf), "#%u,%s,%u,%u,%jd", th->group->id, trusts_cidr2str(th->ip, th->mask), th->count, th->maxusage, (intmax_t)th->lastseen); } else { - snprintf(buf, sizeof(buf), "%u,%s,%u,%u,%jd,%jd", th->group->id, trusts_cidr2str(th->ip, th->mask), th->id, th->maxusage, (intmax_t)th->lastseen, (intmax_t)th->created); + snprintf(buf, sizeof(buf), "%u,%s,%u,%u,%jd,%jd,%u,%u", th->group->id, trusts_cidr2str(th->ip, th->mask), th->id, th->maxusage, (intmax_t)th->lastseen, (intmax_t)th->created, th->maxpernode, th->nodebits); } return buf; @@ -189,6 +189,7 @@ int parsetg(char *buf, trustgroup *tg, int oformat) { int parseth(char *line, trusthost *th, unsigned int *tgid, int oformat) { unsigned long lastseen, created; + int maxpernode, nodebits; char *ip, xbuf[1024], *id; /* #id,213.230.192.128/26,20,23,1222732944 @@ -223,12 +224,14 @@ int parseth(char *line, trusthost *th, unsigned int *tgid, int oformat) { return 0; created = time(NULL); } else { - if(sscanf(line, "%u,%u,%lu,%lu", &th->id, &th->maxusage, &lastseen, &created) != 4) + if(sscanf(line, "%u,%u,%lu,%lu,%d,%d", &th->id, &th->maxusage, &lastseen, &created, &maxpernode, &nodebits) != 6) return 0; } th->lastseen = (time_t)lastseen; th->created = (time_t)created; + th->maxpernode = maxpernode; + th->nodebits = nodebits; return 1; } diff --git a/trusts/trusts.h b/trusts/trusts.h index 3a55300a..6898f83e 100644 --- a/trusts/trusts.h +++ b/trusts/trusts.h @@ -35,7 +35,6 @@ struct trusthost; typedef struct trusthost { unsigned int id; - uint32_t ip, mask; unsigned int maxusage; time_t created; @@ -46,6 +45,9 @@ typedef struct trusthost { unsigned int count; + int maxpernode; + int nodebits; + struct trusthost *parent, *children; unsigned int marker; diff --git a/trusts/trusts_commands.c b/trusts/trusts_commands.c index 7a52145b..09af6700 100644 --- a/trusts/trusts_commands.c +++ b/trusts/trusts_commands.c @@ -75,6 +75,7 @@ static void marktree(array *parents, unsigned int marker, trusthost *th) { static void outputtree(nick *np, unsigned int marker, trustgroup *originalgroup, trusthost *th, int depth) { char *cidrstr, *prespacebuf, *postspacebuf, parentbuf[512]; + int mask; if(th->marker != marker) return; @@ -92,7 +93,10 @@ static void outputtree(nick *np, unsigned int marker, trustgroup *originalgroup, snprintf(parentbuf, sizeof(parentbuf), "%-10d %s", th->group->id, th->group->name->content); } - controlreply(np, "%s%s%s %-10d %-10d %-21s%s", prespacebuf, cidrstr, postspacebuf, th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"), trusts_timetostr(th->created), parentbuf); + /*if (!ipv6) */ + mask = th->nodebits - 96; + + controlreply(np, "%s%s%s %-10d %-10d %-21s %-15d /%-14d%s", prespacebuf, cidrstr, postspacebuf, th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"), th->maxpernode, mask, parentbuf); for(th=th->children;th;th=th->nextbychild) outputtree(np, marker, originalgroup, th, depth + 1); @@ -119,7 +123,7 @@ static void displaygroup(nick *sender, trustgroup *tg) { controlreply(sender, "Max usage : %d", tg->maxusage); controlreply(sender, "Last max reset : %s", tg->lastmaxusereset?trusts_timetostr(tg->lastmaxusereset):"(never)"); - controlreply(sender, "Host Current Max Last seen Created Group ID Group name"); + controlreply(sender, "Host Current Max Last seen Max per Node Node Mask Group ID Group name"); marker = nextthmarker(); array_init(&parents, sizeof(trusthost *)); diff --git a/trusts/trusts_db.c b/trusts/trusts_db.c index 1ad9f17e..f49699ac 100644 --- a/trusts/trusts_db.c +++ b/trusts/trusts_db.c @@ -38,7 +38,7 @@ void createtrusttables(int mode) { ); /* I'd like multiple keys here but that's not gonna happen on a cross-database platform :( */ - trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, created INT, lastseen INT)", "Td", hosts, TRUSTHOSTLEN); + trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, created INT, lastseen INT, maxpernode INT, nodebits INT)", "Td", hosts, TRUSTHOSTLEN); trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, groupname VARCHAR(?), ts INT, username VARCHAR(?), message VARCHAR(?))", @@ -80,7 +80,7 @@ static void loadhosts_data(const DBAPIResult *result, void *tag) { return; } - if(result->fields != 6) { + if(result->fields != 8) { Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table."); loaderror = 1; @@ -114,6 +114,8 @@ static void loadhosts_data(const DBAPIResult *result, void *tag) { th.maxusage = strtoul(result->get(result, 3), NULL, 10); th.created = (time_t)strtoul(result->get(result, 4), NULL, 10); th.lastseen = (time_t)strtoul(result->get(result, 5), NULL, 10); + th.maxpernode = strtol(result->get(result, 6), NULL, 10); + th.nodebits = strtol(result->get(result, 7), NULL, 10); if(!th_add(&th)) Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host); @@ -312,8 +314,8 @@ trustgroup *tg_new(trustgroup *itg) { void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) { trustsdb->squery(trustsdb, - "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen) VALUES (?, ?, ?, ?, ?, ?)", - "Tuusuut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->created, th->lastseen + "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen, maxpernode, nodebits) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + "Tuusuutuu", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->created, th->lastseen, th->maxpernode, th->nodebits ); } diff --git a/trusts/trusts_policy.c b/trusts/trusts_policy.c index 32a8ca51..5882a13a 100644 --- a/trusts/trusts_policy.c +++ b/trusts/trusts_policy.c @@ -15,9 +15,12 @@ static void policycheck(int hooknum, void *arg) { if(moving) return; - if(!th) { + if(!th) + return; + + if(th->maxpernode > np->ipnode->usercount) { if(np->ipnode->usercount > 5) - controlwall(NO_OPER, NL_TRUSTS, "Hard connection limit exceeded on IP: %s (untrusted) %d connected, 5 max.", IPtostr(np->p_ipaddr), np->ipnode->usercount); + controlwall(NO_OPER, NL_TRUSTS, "Hard connection limit exceeded on IP: %s (group: %s) %d connected, %d max.", IPtostr(np->p_ipaddr), tg->name->content, np->ipnode->usercount, th->maxpernode); return; }