#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <stdio.h>
#include "../lib/sstring.h"
#include "../core/hooks.h"
#include "../core/nsmalloc.h"
#include "../lib/irc_string.h"
+#include "../irc/irc.h"
#include "trusts.h"
trustgroup *tglist;
void th_dbupdatecounts(trusthost *);
void tg_dbupdatecounts(trustgroup *);
+static trusthost *th_getnextchildbyhost(trusthost *, trusthost *);
+
void trusts_freeall(void) {
trustgroup *tg, *ntg;
trusthost *th, *nth;
nsfree(POOL_TRUSTS, th);
}
+static void th_updatechildren(trusthost *th) {
+ trusthost *nth = NULL;
+
+ th->children = NULL;
+
+ for(;;) {
+ nth = th_getnextchildbyhost(th, nth);
+ if(!nth)
+ break;
+
+ nth->nextbychild = th->children;
+ th->children = nth;
+ }
+}
+
+void th_linktree(void) {
+ trustgroup *tg;
+ trusthost *th;
+
+ /* ugh */
+ for(tg=tglist;tg;tg=tg->next)
+ for(th=tg->hosts;th;th=th->next)
+ th->parent = th_getsmallestsupersetbyhost(&th->ip, th->bits);
+
+ for(tg=tglist;tg;tg=tg->next)
+ for(th=tg->hosts;th;th=th->next)
+ if(th->parent)
+ th_updatechildren(th->parent);
+}
+
trusthost *th_add(trusthost *ith) {
trusthost *th;
th->users = NULL;
th->count = 0;
+ th->parent = NULL;
+ th->children = NULL;
+
+ th->marker = 0;
+
th->next = th->group->hosts;
th->group->hosts = th;
}
tg->hosts = NULL;
+ tg->marker = 0;
tg->count = 0;
memset(tg->exts, 0, sizeof(tg->exts));
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);
+/* NOT reentrant obviously */
+static trusthost *th_getnextchildbyhost(trusthost *orig, trusthost *th) {
+ if(!th) {
+ trustgroup *tg;
+
+ for(tg=tglist;tg;tg=tg->next) {
+ th = tg->hosts;
+ if(th)
+ break;
+ }
+
+ /* INVARIANT: tg => th */
+ if(!tg)
+ return NULL;
+
+ if(th->parent == orig)
+ return th;
+ }
+
+ for(;;) {
+ if(th->next) {
+ th = th->next;
+ } else {
+ trustgroup *tg = th->group;
+
+ do {
+ tg = tg->next;
+ } while (tg && !tg->hosts);
+
+ if(!tg)
+ return NULL;
+
+ th = tg->hosts;
+ }
+
+ if(th->parent == orig)
+ return th;
+ }
+}
+
+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 *)) {
trustgroup *tg;
trusthost *th;
- time_t t = time(NULL);
+ time_t t = getnettime();
for(tg=tglist;tg;tg=tg->next) {
if(tg->count > 0)
}
for(tg=tglist;tg;tg=tg->next)
- if(!strcmp(name, tg->name->content))
+ if(!strcasecmp(name, tg->name->content))
return tg;
return NULL;
}
void th_adjusthosts(trusthost *th, trusthost *superset, trusthost *subset) {
+ struct irc_in_addr ipaddress_canonical;
+
/*
* First and foremost, CIDR doesn't allow hosts to cross boundaries, i.e. everything with a smaller prefix
* is entirely contained with the prefix that is one smaller.
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) {
+ ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
+ if(ipmask_check(&ipaddress_canonical, &th->ip, th->bits)) {
trusts_lostnick(np, 1);
trusts_newnick(np, 1);
}
nick *np;
int i;
- 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_ipaddr) & th->mask) == th->ip))
+ for(i=0;i<NICKHASHSIZE;i++) {
+ for(np=nicktable[i];np;np=np->next) {
+ ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
+ if(!gettrusthost(np) && ipmask_check(&ipaddress_canonical, &th->ip, th->bits))
trusts_newnick(np, 1);
+ }
+ }
+ }
+}
+
+unsigned int nexttgmarker(void) {
+ static unsigned int tgmarker = 0;
+ trustgroup *tg;
+
+ tgmarker++;
+ if(!tgmarker) {
+ /* If we wrapped to zero, zap the marker on all groups */
+ for(tg=tglist;tg;tg=tg->next)
+ tg->marker=0;
+
+ tgmarker++;
}
+
+ return tgmarker;
+}
+
+unsigned int nextthmarker(void) {
+ static unsigned int thmarker = 0;
+ trustgroup *tg;
+ trusthost *th;
+
+ thmarker++;
+ if(!thmarker) {
+ /* If we wrapped to zero, zap the marker on all hosts */
+ for(tg=tglist;tg;tg=tg->next)
+ for(th=tg->hosts;th;th=th->next)
+ th->marker=0;
+
+ thmarker++;
+ }
+
+ return thmarker;
}
trusthost *th_getbyid(unsigned int id) {
/* id remains the same, count/hosts/marker/next/exts are ignored */
vnewtg.trustedfor = newtg->trustedfor;
- vnewtg.mode = newtg->mode;
+ vnewtg.flags = newtg->flags;
vnewtg.maxperident = newtg->maxperident;
vnewtg.maxusage = newtg->maxusage;
vnewtg.expires = newtg->expires;
return 1;
}
+
+int th_modify(trusthost *oldth, trusthost *newth) {
+ oldth->maxpernode = newth->maxpernode;
+ oldth->nodebits = newth->nodebits;
+
+ return 1;
+}
+