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->mask);
+
+ 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(trustgroup *tg, unsigned int id, char *host, unsigned int maxusage, time_t lastseen) {
- u_int32_t ip, mask;
+ uint32_t ip, mask;
trusthost *th;
if(!trusts_str2cidr(host, &ip, &mask))
th->group = tg;
th->count = 0;
+ th->parent = NULL;
+ th->children = NULL;
+
th->next = tg->hosts;
tg->hosts = th;
return NULL;
}
+/* NOT reentrant obviously */
+static trusthost *th_getnextchildbyhost(trusthost *orig, trusthost *th) {
+ if(!th) {
+ trustgroup *tg;
+
+ tg = tglist;
+ 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 {
+ if(!th->group->next)
+ return NULL;
+ th = th->group->next->hosts;
+ }
+
+ if(th->parent == orig)
+ return th;
+ }
+}
+
void th_getsuperandsubsets(uint32_t ip, uint32_t mask, trusthost **superset, trusthost **subset) {
*superset = th_getsmallestsupersetbyhost(ip, mask);
*subset = th_getsubsetbyhost(ip, mask);
unsigned int count;
+ struct trusthost *parent, *children;
+ struct trusthost *nextbychild;
+
struct trusthost *next;
} trusthost;
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, uint32_t);
+trusthost *th_getsubsetbyhost(uint32_t ip, uint32_t mask);
+trusthost *th_getnextsubsetbyhost(trusthost *th, uint32_t ip, uint32_t mask);
+void th_linktree(void);
/* migration.c */
typedef void (*TrustMigrationGroup)(void *, unsigned int, char *, unsigned int, unsigned int, unsigned int, unsigned int, time_t, time_t, time_t, char *, char *, char *);
#include <stdio.h>
+#include <string.h>
#include "../control/control.h"
#include "../lib/irc_string.h"
+#include "../lib/strlfunc.h"
#include "trusts.h"
int trusts_migration_start(TrustDBMigrationCallback, void *);
return CMD_OK;
}
+void calculatespaces(int spaces, char *str, char **_prebuf, char **_postbuf) {
+ static char prebuf[512], postbuf[512];
+ int spacelen;
+
+ if(spaces + 5 >= sizeof(prebuf)) {
+ prebuf[0] = prebuf[1] = '\0';
+ } else {
+ memset(prebuf, ' ', spaces);
+ prebuf[spaces] = '\0';
+ }
+
+ spacelen = 21 - (strlen(str) + spaces);
+ if(spacelen <= 0 || spacelen + 5 >= sizeof(postbuf)) {
+ postbuf[0] = postbuf[1] = '\0';
+ } else {
+ memset(postbuf, ' ', spacelen);
+ postbuf[spacelen] = '\0';
+ }
+
+ *_prebuf = prebuf;
+ *_postbuf = postbuf;
+}
+
+#define MODE_PARENT 0
+#define MODE_CURRENT 1
+#define MODE_CHILDREN 2
+
+static int __replytrusthosts(nick *sender, trusthost *th, int mode, int childdepth) {
+ char parentbuf[512], *postspacebuf, *prespacebuf, *cidrstr;
+ int depth;
+
+ if(mode != MODE_CHILDREN) {
+ /* find all parents of this node */
+ if(th->parent) {
+ depth = __replytrusthosts(sender, th->parent, MODE_PARENT, 0) + 1;
+ } else {
+ depth = 1;
+ }
+ } else {
+ depth = childdepth;
+ }
+
+ cidrstr = trusts_cidr2str(th->ip, th->mask);
+ calculatespaces(depth, cidrstr, &prespacebuf, &postspacebuf);
+
+ if(mode == MODE_CURRENT) {
+ /* prefix the hosts in the current group with > */
+
+ if(!prespacebuf[0])
+ prespacebuf[1] = '\0';
+ prespacebuf[0] = '>';
+
+ parentbuf[0] = '\0';
+ } else {
+ /* show the ids of other groups */
+
+ snprintf(parentbuf, sizeof(parentbuf), "%-10d %s", th->id, th->group->name->content);
+ }
+
+ controlreply(sender, "%s%s%s %-10d %-10d %-20s%s", prespacebuf, cidrstr, postspacebuf, th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"), parentbuf);
+
+ /* find all children of this node */
+ if(mode != MODE_PARENT) {
+ trusthost *cth;
+ for(cth=th->children;cth;cth=cth->nextbychild)
+ __replytrusthosts(sender, cth, MODE_CHILDREN, depth + 1);
+ }
+
+ return depth;
+}
+
+static void replytrusthosts(nick *sender, trusthost *th) {
+ __replytrusthosts(sender, th, MODE_CURRENT, 0);
+}
+
static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) {
nick *sender = source;
trustgroup *tg;
controlreply(sender, "Max usage : %d", tg->maxusage);
controlreply(sender, "Last max reset : %s", tg->lastmaxuserreset?trusts_timetostr(tg->lastmaxuserreset):"(never)");
- controlreply(sender, "Host Current Max Last seen");
+ controlreply(sender, "Host Current Max Last seen Group ID Group name");
for(th=tg->hosts;th;th=th->next)
- controlreply(sender, " %-20s %-10d %-10d %s", trusts_cidr2str(th->ip, th->mask), th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"));
+ replytrusthosts(sender, th);
controlreply(sender, "End of list.");