registerhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
registerhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
- registerhook(HOOK_NICK_MOVENODE, &pn_hook_movenodeuser);
+ registerhook(HOOK_NICK_MOVENODE, &pn_hook_nodemoveuser);
registercontrolhelpcmd("nodeuserlist", NO_OPER, 1, &pn_cmd_nodeuserlist, "Usage: nodeuserlist <ipv4|ipv6|cidr4|cidr6>\nLists all users on a given IP address or CIDR range.");
}
deregisterhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
deregisterhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
- deregisterhook(HOOK_NICK_MOVENODE, &pn_hook_movenodeuser);
+ deregisterhook(HOOK_NICK_MOVENODE, &pn_hook_nodemoveuser);
deregistercontrolcmd("nodeuserlist", &pn_cmd_nodeuserlist);
}
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 pn_hook_nodemoveuser(int hook, void *arg);
void addnicktonode(patricia_node_t *node, nick *nick);
void deletenickfromnode(patricia_node_t *node, nick *nick);
/* ugh */
for(tg=tglist;tg;tg=tg->next)
for(th=tg->hosts;th;th=th->next)
- th->parent = th_getsmallestsupersetbyhost(th->ip, th->mask);
+ th->parent = th_getsmallestsupersetbyhost(&th->ip, th->bits);
for(tg=tglist;tg;tg=tg->next)
for(th=tg->hosts;th;th=th->next)
th->users = NULL;
th->count = 0;
- th->maxpernode = 0;
- th->nodebits = 128;
-
th->parent = NULL;
th->children = NULL;
return tg;
}
-trusthost *th_getbyhost(uint32_t ip) {
+trusthost *th_getbyhost(struct irc_in_addr *ip) {
trustgroup *tg;
trusthost *th, *result = NULL;
- uint32_t mask;
+ uint32_t bits;
for(tg=tglist;tg;tg=tg->next) {
for(th=tg->hosts;th;th=th->next) {
- if((ip & th->mask) == th->ip) {
- if(!result || (th->mask > mask)) {
- mask = th->mask;
+ if(ipmask_check(ip, &th->ip, th->bits)) {
+ if(!result || (th->bits > bits)) {
+ bits = th->bits;
result = th;
}
}
return result;
}
-trusthost *th_getbyhostandmask(uint32_t ip, uint32_t mask) {
+trusthost *th_getbyhostandmask(struct irc_in_addr *ip, uint32_t bits) {
trustgroup *tg;
trusthost *th;
for(tg=tglist;tg;tg=tg->next)
for(th=tg->hosts;th;th=th->next)
- if((th->ip == ip) && (th->mask == mask))
+ if(ipmask_check(ip, &th->ip, 128) && th->bits == bits)
return th;
return NULL;
}
/* returns the ip with the smallest prefix that is still a superset of the given host */
-trusthost *th_getsmallestsupersetbyhost(uint32_t ip, uint32_t mask) {
+trusthost *th_getsmallestsupersetbyhost(struct irc_in_addr *ip, uint32_t bits) {
trustgroup *tg;
trusthost *th, *result = NULL;
- uint32_t smask;
+ uint32_t sbits;
for(tg=tglist;tg;tg=tg->next) {
for(th=tg->hosts;th;th=th->next) {
- if(th->ip == (ip & th->mask)) {
- if((th->mask < mask) && (!result || (th->mask > smask))) {
- smask = th->mask;
+ if(ipmask_check(ip, &th->ip, th->bits)) {
+ if((th->bits < bits) && (!result || (th->bits > sbits))) {
+ sbits = th->bits;
result = th;
}
}
}
/* returns the first ip that is a subset it comes across */
-trusthost *th_getsubsetbyhost(uint32_t ip, uint32_t mask) {
+trusthost *th_getsubsetbyhost(struct irc_in_addr *ip, uint32_t bits) {
trustgroup *tg;
trusthost *th;
for(tg=tglist;tg;tg=tg->next)
for(th=tg->hosts;th;th=th->next)
- if((th->ip & mask) == ip)
- if(th->mask > mask)
+ if(ipmask_check(ip, &th->ip, th->bits))
+ if(th->bits > bits)
return th;
return NULL;
}
}
-void th_getsuperandsubsets(uint32_t ip, uint32_t mask, trusthost **superset, trusthost **subset) {
- *superset = th_getsmallestsupersetbyhost(ip, mask);
- *subset = th_getsubsetbyhost(ip, mask);
+void th_getsuperandsubsets(struct irc_in_addr *ip, uint32_t bits, trusthost **superset, trusthost **subset) {
+ *superset = th_getsmallestsupersetbyhost(ip, bits);
+ *subset = th_getsubsetbyhost(ip, bits);
}
void trusts_flush(void (*thflush)(trusthost *), void (*tgflush)(trustgroup *)) {
nick *np, *nnp;
for(np=superset->users;np;np=nnp) {
nnp = nextbytrust(np);
- if((irc_in_addr_v4_to_int(&np->p_nodeaddr) & th->mask) == th->ip) {
+ if(ipmask_check(&np->p_nodeaddr, &th->ip, th->bits)) {
trusts_lostnick(np, 1);
trusts_newnick(np, 1);
}
for(i=0;i<NICKHASHSIZE;i++)
for(np=nicktable[i];np;np=np->next)
- if(!gettrusthost(np) && ((irc_in_addr_v4_to_int(&np->p_nodeaddr) & th->mask) == th->ip))
+ if(!gettrusthost(np) && ipmask_check(&np->p_nodeaddr, &th->ip, th->bits))
trusts_newnick(np, 1);
}
}
static void __counthandler(int hooknum, void *arg);
void trusts_newnick(nick *sender, int moving) {
- uint32_t host;
trusthost *th;
void *arg[2];
struct irc_in_addr ipaddress;
ip_canonicalize_6to4(&ipaddress, &sender->p_ipaddr);
- if (irc_in_addr_is_ipv4(&ipaddress)) {
- host = irc_in_addr_v4_to_int(&ipaddress);
- th = th_getbyhost(host);
- } else
- th = NULL;
+ th = th_getbyhost(&ipaddress);
settrusthost(sender, th);
if(!th) {
#include "../lib/strlfunc.h"
#include "trusts.h"
-int trusts_parsecidr(const char *host, uint32_t *ip, short *mask) {
- unsigned int octet1 = 0, octet2 = 0, octet3 = 0, octet4 = 0, umask = 32;
-
- if(sscanf(host, "%u.%u.%u.%u/%u", &octet1, &octet2, &octet3, &octet4, &umask) != 5)
- if(sscanf(host, "%u.%u.%u/%u", &octet1, &octet2, &octet3, &umask) != 4)
- if(sscanf(host, "%u.%u/%u", &octet1, &octet2, &umask) != 3)
- if(sscanf(host, "%u/%u", &octet1, &umask) != 2)
- if(sscanf(host, "%u.%u.%u.%u", &octet1, &octet2, &octet3, &octet4) != 4)
- return 0;
-
- if(octet1 > 255 || octet2 > 255 || octet3 > 255 || octet4 > 255 || umask > 32)
- return 0;
-
- *ip = (octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4;
- *mask = umask;
-
- return 1;
-}
-
-/* returns mask pre-anded */
-int trusts_str2cidr(const char *host, uint32_t *ip, uint32_t *mask) {
- uint32_t result;
- short smask;
-
- if(!trusts_parsecidr(host, &result, &smask))
- return 0;
-
- if(smask == 0) {
- *mask = 0;
- } else {
- *mask = 0xffffffff << (32 - smask);
- }
- *ip = result & *mask;
-
- return 1;
-}
-
-char *trusts_cidr2str(uint32_t ip, uint32_t mask) {
+char *trusts_cidr2str(struct irc_in_addr *ip, unsigned char bits) {
static char buf[100];
- char maskbuf[10];
-
- if(mask != 0) {
- /* count number of trailing zeros */
- float f = (float)(mask & -mask);
-
- mask = 32 - ((*(unsigned int *)&f >> 23) - 0x7f);
- }
-
- if(mask < 32) {
- snprintf(maskbuf, sizeof(maskbuf), "/%u", mask);
- } else {
- maskbuf[0] = '\0';
- }
- snprintf(buf, sizeof(buf), "%u.%u.%u.%u%s", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, maskbuf);
+ snprintf(buf, sizeof(buf), "%s/%u", IPtostr(*ip), (irc_in_addr_is_ipv4(ip))?bits-96:bits);
return buf;
}
static char buf[512];
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);
+ snprintf(buf, sizeof(buf), "#%u,%s/%u,%u,%u,%jd", th->group->id, IPtostr(th->ip), (unsigned int)th->bits, th->count, th->maxusage, (intmax_t)th->lastseen);
} else {
- 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);
+ snprintf(buf, sizeof(buf), "%u,%s/%u,%u,%u,%jd,%jd,%u,%u", th->group->id, IPtostr(th->ip), (unsigned int)th->bits, th->id, th->maxusage, (intmax_t)th->lastseen, (intmax_t)th->created, th->maxpernode, th->nodebits);
}
return buf;
return 0;
*line++ = '\0';
- if(!trusts_str2cidr(ip, &th->ip, &th->mask))
+ if(!ipmask_parse(ip, &th->ip, &th->bits))
return 0;
if(oformat) {
typedef struct trusthost {
unsigned int id;
- uint32_t ip, mask;
+ struct irc_in_addr ip;
+ unsigned char bits;
unsigned int maxusage;
time_t created;
time_t lastseen;
/* formats.c */
char *trusts_timetostr(time_t);
-int trusts_parsecidr(const char *, uint32_t *, short *);
-int trusts_str2cidr(const char *, uint32_t *, uint32_t *);
-char *trusts_cidr2str(uint32_t, uint32_t);
+char *trusts_cidr2str(struct irc_in_addr *ip, unsigned char);
char *dumpth(trusthost *, int);
char *dumptg(trustgroup *, int);
int parseth(char *, trusthost *, unsigned int *, int);
trusthost *th_add(trusthost *);
void tg_free(trustgroup *, int);
trustgroup *tg_add(trustgroup *);
-trusthost *th_getbyhost(uint32_t);
-trusthost *th_getbyhostandmask(uint32_t, uint32_t);
-trusthost *th_getsmallestsupersetbyhost(uint32_t, uint32_t);
+trusthost *th_getbyhost(struct irc_in_addr *);
+trusthost *th_getbyhostandmask(struct irc_in_addr *, uint32_t);
+trusthost *th_getsmallestsupersetbyhost(struct irc_in_addr *, uint32_t);
trustgroup *tg_strtotg(char *);
void th_adjusthosts(trusthost *th, trusthost *, trusthost *);
-void th_getsuperandsubsets(uint32_t, uint32_t, trusthost **, trusthost **);
-trusthost *th_getsubsetbyhost(uint32_t ip, uint32_t mask);
-trusthost *th_getnextsubsetbyhost(trusthost *th, uint32_t ip, uint32_t mask);
+void th_getsuperandsubsets(struct irc_in_addr *, uint32_t, trusthost **, trusthost **);
+trusthost *th_getsubsetbyhost(struct irc_in_addr *ip, uint32_t mask);
+trusthost *th_getnextsubsetbyhost(trusthost *th, struct irc_in_addr *ip, uint32_t mask);
void th_linktree(void);
unsigned int nexttgmarker(void);
unsigned int nextthmarker(void);
+#include <stdio.h>
#include <../nick/nick.h>
#include "../irc/irc.h"
#include "trusts.h"
int count = 0;
for(th=tg->hosts;th;th=th->next) {
- char *cidrstr = trusts_cidr2str(th->ip, th->mask);
+ char *cidrstr = trusts_cidr2str(&th->ip, th->bits);
irc_send("%s GL * +%s@%s %d %jd :%s", mynumeric->content, ident, cidrstr, duration, (intmax_t)getnettime(), reason);
count++;
}
int count = 0;
for(th=tg->hosts;th;th=th->next) {
- char *cidrstr = trusts_cidr2str(th->ip, th->mask);
+ char *cidrstr = trusts_cidr2str(&th->ip, th->bits);
irc_send("%s GL * +%s@%s %d %jd :%s", mynumeric->content, ident, cidrstr, duration, (intmax_t)getnettime(), reason);
count++;
}
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;
- cidrstr = trusts_cidr2str(th->ip, th->mask);
+ cidrstr = trusts_cidr2str(&th->ip, th->bits);
calculatespaces(depth + 1, 20 + 1, cidrstr, &prespacebuf, &postspacebuf);
if(th->group == originalgroup) {
snprintf(parentbuf, sizeof(parentbuf), "%-10d %s", th->group->id, th->group->name->content);
}
- /*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);
+ 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, (irc_in_addr_is_ipv4(&th->ip))?(th->nodebits - 96):th->nodebits, parentbuf);
for(th=th->children;th;th=th->nextbychild)
outputtree(np, marker, originalgroup, th, depth + 1);
int found = 0, remaining = 50;
char *name;
trusthost *th;
- uint32_t ip;
- short mask;
+ struct irc_in_addr ip;
+ unsigned char bits;
if(cargc < 1)
return CMD_USAGE;
return CMD_OK;
}
- if(trusts_parsecidr(name, &ip, &mask)) {
- th = th_getbyhost(ip);
+ if(ipmask_parse(name, &ip, &bits)) {
+ th = th_getbyhost(&ip);
if(!th) {
controlreply(sender, "Specified IP address is not trusted.");
}
host = result->get(result, 2);
- if(!trusts_str2cidr(host, &th.ip, &th.mask)) {
+ if(!ipmask_parse(host, &th.ip, &th.bits)) {
Error("trusts", ERR_WARNING, "Error parsing cidr for host: %s", host);
continue;
}
trustsdb_insertth("hosts", th, th->group->id);
- th_getsuperandsubsets(ith->ip, ith->mask, &superset, &subset);
+ th_getsuperandsubsets(&ith->ip, ith->bits, &superset, &subset);
th_adjusthosts(th, superset, subset);
th_linktree();
trusthost *th_new(trustgroup *tg, char *host) {
trusthost *th, nth;
- if(!trusts_str2cidr(host, &nth.ip, &nth.mask))
+ if(!ipmask_parse(host, &nth.ip, &nth.bits))
return NULL;
nth.group = tg;
nth.lastseen = 0;
nth.maxusage = 0;
+ nth.maxpernode = 0;
+ nth.nodebits = (irc_in_addr_is_ipv4(&nth.ip))?128:64;
+
th = th_copy(&nth);
if(!th)
return NULL;
void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) {
trustsdb->squery(trustsdb,
"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
+ "Tuusuutuu", table, th->id, groupid, trusts_cidr2str(&th->ip, th->bits), th->maxusage, th->created, th->lastseen, th->maxpernode, th->nodebits
);
}
trustgroup *tg;
nick *sender = source;
char *host;
- uint32_t ip, mask;
+ struct irc_in_addr ip;
+ unsigned char bits;
trusthost *th, *superset, *subset;
if(cargc < 2)
}
host = cargv[1];
- if(!trusts_str2cidr(host, &ip, &mask)) {
+ if(!ipmask_parse(host, &ip, &bits)) {
controlreply(sender, "Invalid host.");
return CMD_ERROR;
}
*/
for(th=tg->hosts;th;th=th->next) {
- if(th->ip == (ip & th->mask)) {
+ if(ipmask_check(&ip, &th->ip, th->bits)) {
controlreply(sender, "This host (or part of it) is already covered in the given group.");
return CMD_ERROR;
}
}
- if(th_getbyhostandmask(ip, mask)) {
+ if(th_getbyhostandmask(&ip, bits)) {
controlreply(sender, "This host already exists in another group with the same mask.");
return CMD_ERROR;
}
/* this function will set both to NULL if it's equal, hence the check above */
- th_getsuperandsubsets(ip, mask, &superset, &subset);
+ th_getsuperandsubsets(&ip, bits, &superset, &subset);
if(superset) {
/* a superset exists for us, we will be more specific than one existing host */
static int trusts_cmdtrustdel(void *source, int cargc, char **cargv) {
trustgroup *tg;
trusthost *th;
- uint32_t ip, mask;
+ struct irc_in_addr ip;
+ unsigned char bits;
nick *sender = source;
char *host;
}
host = cargv[1];
- if(!trusts_str2cidr(host, &ip, &mask)) {
+ if(!ipmask_parse(host, &ip, &bits)) {
controlreply(sender, "Invalid IP/mask.");
return CMD_ERROR;
}
for(th=tg->hosts;th;th=th->next)
- if((th->ip == ip) && (th->mask == mask))
+ if(ipmask_check(&ip, &th->ip, th->bits) && th->bits == bits)
break;
if(!th) {
triggerhook(HOOK_TRUSTS_DELHOST, th);
th_delete(th);
- cidrstr = trusts_cidr2str(th->ip, th->mask);
+ cidrstr = trusts_cidr2str(&th->ip, th->bits);
trustlog(tg, "cleanuptrusts", "Removed host '%s' because it was unused for %d days.", cidrstr, CLEANUP_TH_INACTIVE);
thcount++;
if(!th)
return;
- if(th->maxpernode > np->ipnode->usercount) {
+ tg = th->group;
+
+ if(th->maxpernode && np->ipnode->usercount > th->maxpernode) {
if(np->ipnode->usercount > 5)
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;
}
- tg = th->group;
/*
* the purpose of this logic is to avoid spam like this:
* WARNING: tgX exceeded limit: 11 connected vs 10 max