Haven't added functionality for del/groupdel yet though.
#define HOOK_TRUSTS_DELGROUP 907 /* Argument is trustgroup* */
#define HOOK_TRUSTS_ADDHOST 908 /* Argument is trusthost* */
#define HOOK_TRUSTS_DELHOST 909 /* Argument is trusthost* */
+#define HOOK_TRUSTS_MODIFYGROUP 910 /* Argument is trustgroup* */
+#define HOOK_TRUSTS_LOSTHOST 911 /* Argument is trusthost* */
#define PRIORITY_DEFAULT 0
th_free(th);
}
- tg_free(tg);
+ tg_free(tg, 1);
}
tglist = NULL;
}
void th_free(trusthost *th) {
+ triggerhook(HOOK_TRUSTS_LOSTHOST, th);
+
nsfree(POOL_TRUSTS, th);
}
return th;
}
-void tg_free(trustgroup *tg) {
- triggerhook(HOOK_TRUSTS_LOSTGROUP, tg);
+void tg_free(trustgroup *tg, int created) {
+ if(created)
+ triggerhook(HOOK_TRUSTS_LOSTGROUP, tg);
freesstring(tg->name);
freesstring(tg->createdby);
tg->contact = getsstring(tg->contact->content, CONTACTLEN);
tg->comment = getsstring(tg->comment->content, COMMENTLEN);
if(!tg->name || !tg->createdby || !tg->contact || !tg->comment) {
- tg_free(tg);
+ tg_free(tg, 0);
return NULL;
}
return thmarker;
}
-trustgroup *tg_inttotg(unsigned int id) {
+trusthost *th_getbyid(unsigned int id) {
trustgroup *tg;
+ trusthost *th;
for(tg=tglist;tg;tg=tg->next)
- if(tg->id == id)
- return tg;
+ for(th=tg->hosts;th;th=th->next)
+ if(th->id == id)
+ return th;
return NULL;
}
+int tg_modify(trustgroup *oldtg, trustgroup *newtg) {
+ trustgroup vnewtg;
+
+ memcpy(&vnewtg, oldtg, sizeof(trustgroup));
+
+ /* unfortunately we can't just memcpy the new one over */
+
+ vnewtg.name = getsstring(newtg->name->content, TRUSTNAMELEN);
+ vnewtg.createdby = getsstring(newtg->createdby->content, NICKLEN);
+ vnewtg.contact = getsstring(newtg->contact->content, CONTACTLEN);
+ vnewtg.comment = getsstring(newtg->comment->content, COMMENTLEN);
+ if(!vnewtg.name || !vnewtg.createdby || !vnewtg.contact || vnewtg.comment) {
+ freesstring(vnewtg.name);
+ freesstring(vnewtg.createdby);
+ freesstring(vnewtg.contact);
+ freesstring(vnewtg.comment);
+ return 0;
+ }
+
+ /* id remains the same, count/hosts/marker/next/exts are ignored */
+ vnewtg.trustedfor = newtg->trustedfor;
+ vnewtg.mode = newtg->mode;
+ vnewtg.maxperident = newtg->maxperident;
+ vnewtg.maxusage = newtg->maxusage;
+ vnewtg.expires = newtg->expires;
+ vnewtg.lastseen = newtg->lastseen;
+ vnewtg.lastmaxuserreset = newtg->lastmaxuserreset;
+
+ memcpy(oldtg, &vnewtg, sizeof(trustgroup));
+
+ return 1;
+}
#define TRUSTHOSTLEN 100
#define MAXTGEXTS 5
+#define MAXTRUSTEDFOR 50000
+#define MAXDURATION 365 * 86400 * 20
+#define MAXPERIDENT 1000
+
#define TABLES_REGULAR 0
#define TABLES_MIGRATION 1
#define TABLES_REPLICATION 2
void releasetgext(int);
int trusts_fullyonline(void);
-/* db.c */
-extern int trustsdbloaded;
-int trusts_loaddb(void);
-void trusts_closedb(int);
-trustgroup *tg_new(trustgroup *);
-trusthost *th_new(trustgroup *, char *);
-void trustsdb_insertth(char *, trusthost *, unsigned int);
-void trustsdb_inserttg(char *, trustgroup *);
-trustgroup *tg_copy(trustgroup *);
-trusthost *th_copy(trusthost *);
-
/* formats.c */
char *trusts_timetostr(time_t);
int trusts_parsecidr(const char *, uint32_t *, short *);
trustgroup *tg_getbyid(unsigned int);
void th_free(trusthost *);
trusthost *th_add(trusthost *);
-void tg_free(trustgroup *);
+void tg_free(trustgroup *, int);
trustgroup *tg_add(trustgroup *);
trusthost *th_getbyhost(uint32_t);
trusthost *th_getbyhostandmask(uint32_t, uint32_t);
void th_linktree(void);
unsigned int nexttgmarker(void);
unsigned int nextthmarker(void);
-trustgroup *tg_inttotg(unsigned int);
+trusthost *th_getbyid(unsigned int);
+int tg_modify(trustgroup *, trustgroup *);
/* migration.c */
typedef void (*TrustMigrationGroup)(void *, trustgroup *);
typedef void (*TrustMigrationHost)(void *, trusthost *, unsigned int);
typedef void (*TrustMigrationFini)(void *, int);
+/* trusts_db.c */
+extern int trustsdbloaded;
+int trusts_loaddb(void);
+void trusts_closedb(int);
+trustgroup *tg_new(trustgroup *);
+trusthost *th_new(trustgroup *, char *);
+void trustsdb_insertth(char *, trusthost *, unsigned int);
+void trustsdb_inserttg(char *, trustgroup *);
+trustgroup *tg_copy(trustgroup *);
+trusthost *th_copy(trusthost *);
+void tg_update(trustgroup *);
+void tg_delete(trustgroup *);
+void th_delete(trusthost *);
+
typedef struct trustmigration {
int count, cur;
void *schedule;
);
}
+void tg_update(trustgroup *tg) {
+ trustsdb->squery(trustsdb,
+ "UPDATE ? SET name = ?, trustedfor = ?, maxperident = ?, maxusage = ?, expires = ?, lastseen = ?, lastmaxuserreset = ?, createdby = ?, contact = ?, comment = ? WHERE id = ?",
+ "Tsuuuutttsssu", "groups", tg->name->content, tg->trustedfor, tg->mode, tg->maxperident, tg->maxusage, tg->expires, tg->lastseen, tg->lastmaxuserreset, tg->createdby->content, tg->contact->content, tg->comment->content, tg->id
+ );
+}
+
+void tg_delete(trustgroup *tg) {
+ /* TODO */
+}
+
+void th_delete(trusthost *th) {
+ /* TODO */
+}
+
void _init(void) {
trusts_connectdb();
}
#include "../lib/irc_string.h"
#include "../lib/strlfunc.h"
#include "../core/config.h"
+#include "../lib/stringbuf.h"
#include "trusts.h"
static void registercommands(int, void *);
static void deregistercommands(int, void *);
+typedef int (*trustmodificationfn)(trustgroup *, char *arg);
+
+struct trustmodification {
+ char *name;
+ trustmodificationfn fn;
+};
+
static int trusts_cmdtrustadd(void *source, int cargc, char **cargv) {
trustgroup *tg;
nick *sender = source;
name = cargv[0];
howmany = strtoul(cargv[1], NULL, 10);
- if(!howmany || (howmany > 50000)) {
+ if(!howmany || (howmany > MAXTRUSTEDFOR)) {
controlreply(sender, "Bad value maximum number of clients.");
return CMD_ERROR;
}
howlong = durationtolong(cargv[2]);
- if((howlong <= 0) || (howlong > 365 * 86400 * 20)) {
+ if((howlong <= 0) || (howlong > MAXDURATION)) {
controlreply(sender, "Invalid duration supplied.");
return CMD_ERROR;
}
maxperident = strtoul(cargv[3], NULL, 10);
- if(!howmany || (maxperident > 1000)) {
+ if(!howmany || (maxperident > MAXPERIDENT)) {
controlreply(sender, "Bad value for max per ident.");
return CMD_ERROR;
}
return CMD_OK;
}
+static int trusts_cmdtrustgroupdel(void *source, int cargc, char **cargv) {
+ trustgroup *tg;
+ nick *sender = source;
+
+ if(cargc < 1)
+ return CMD_USAGE;
+
+ tg = tg_strtotg(cargv[0]);
+ if(!tg) {
+ controlreply(sender, "Couldn't look up trustgroup.");
+ return CMD_ERROR;
+ }
+
+ if(tg->hosts) {
+ controlreply(sender, "Delete all hosts before deleting the group.");
+ return CMD_ERROR;
+ }
+
+ triggerhook(HOOK_TRUSTS_DELGROUP, tg);
+ tg_delete(tg);
+ controlreply(sender, "Group deleted.");
+
+ /* TODO: controlwall */
+ return CMD_OK;
+}
+
+static int trusts_cmdtrustdel(void *source, int cargc, char **cargv) {
+ trustgroup *tg;
+ trusthost *th;
+ uint32_t ip, mask;
+ nick *sender = source;
+
+ if(cargc < 2)
+ return CMD_USAGE;
+
+ tg = tg_strtotg(cargv[0]);
+ if(!tg) {
+ controlreply(sender, "Couldn't look up trustgroup.");
+ return CMD_ERROR;
+ }
+
+ if(!trusts_str2cidr(cargv[1], &ip, &mask)) {
+ controlreply(sender, "Invalid IP/mask.");
+ return CMD_ERROR;
+ }
+
+ for(th=tg->hosts;th;th=th->next)
+ if((th->ip == ip) && (th->mask == mask))
+ break;
+
+ if(!th) {
+ controlreply(sender, "Couldn't find that host in that group.");
+ return CMD_ERROR;
+ }
+
+ triggerhook(HOOK_TRUSTS_DELHOST, th);
+ th_delete(th);
+ controlreply(sender, "Host deleted.");
+
+ /* TODO: controlwall */
+ return CMD_OK;
+}
+
+static int modifyname(trustgroup *tg, char *name) {
+ sstring *n = getsstring(name, TRUSTNAMELEN);
+ if(!n)
+ return 0;
+
+ freesstring(tg->name);
+ tg->name = n;
+
+ return 1;
+}
+
+static int modifycomment(trustgroup *tg, char *comment) {
+ sstring *n = getsstring(comment, COMMENTLEN);
+ if(!n)
+ return 0;
+
+ freesstring(tg->comment);
+ tg->comment = n;
+
+ return 1;
+}
+
+static int modifycontact(trustgroup *tg, char *contact) {
+ sstring *n = getsstring(contact, CONTACTLEN);
+ if(!n)
+ return 0;
+
+ freesstring(tg->contact);
+ tg->contact = n;
+
+ return 1;
+}
+
+static int modifytrustedfor(trustgroup *tg, char *num) {
+ unsigned int trustedfor = strtoul(num, NULL, 10);
+
+ if(trustedfor > MAXTRUSTEDFOR)
+ return 0;
+
+ tg->trustedfor = trustedfor;
+
+ return 1;
+}
+
+static int modifymaxperuser(trustgroup *tg, char *num) {
+ unsigned int maxperuser = strtoul(num, NULL, 10);
+
+ if(maxperuser > MAXPERIDENT)
+ return 0;
+
+ tg->maxperident = maxperuser;
+
+ return 1;
+}
+
+static int modifyenforceident(trustgroup *tg, char *num) {
+ if(num[0] == '1') {
+ tg->mode = 1;
+ } else if(num[0] == '0') {
+ tg->mode = 0;
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int modifyexpires(trustgroup *tg, char *expires) {
+ int howlong = durationtolong(expires);
+
+ if((howlong <= 0) || (howlong > MAXDURATION))
+ return 0;
+
+ tg->expires = time(NULL) + howlong;
+
+ return 1;
+}
+
+#define MS(x) (struct trustmodification){ .name = # x, .fn = modify ## x }
+
+static int trusts_cmdtrustgroupmodify(void *source, int cargc, char **cargv) {
+ trustgroup *tg;
+ nick *sender = source;
+ char *what, *to, validfields[512];
+ struct trustmodification *mods = (struct trustmodification []){ MS(expires), MS(enforceident), MS(maxperuser), MS(name), MS(contact), MS(comment), MS(trustedfor) };
+ int modcount = sizeof(mods) / sizeof(struct trustmodification);
+ int i;
+ StringBuf b;
+#undef MS
+
+ if(cargc < 3)
+ return CMD_USAGE;
+
+ tg = tg_strtotg(cargv[0]);
+ if(!tg) {
+ controlreply(sender, "Couldn't look up trustgroup.");
+ return CMD_ERROR;
+ }
+
+ what = cargv[1];
+ to = cargv[2];
+
+ sbinit(&b, validfields, sizeof(validfields));
+ for(i=0;i<modcount;i++) {
+ if(!strcmp(what, mods[i].name)) {
+ if(!(mods[i].fn)(tg, to)) {
+ controlreply(sender, "An error occured changing that property, check the syntax.");
+ return CMD_ERROR;
+ }
+ break;
+ }
+
+ if(i > 0)
+ sbaddstr(&b, ", ");
+ sbaddstr(&b, mods[i].name);
+ }
+
+ if(i == modcount) {
+ sbterminate(&b);
+ controlreply(sender, "No such field, valid fields are: %s", validfields);
+ return CMD_ERROR;
+ }
+
+ triggerhook(HOOK_TRUSTS_MODIFYGROUP, tg);
+ tg_update(tg);
+ controlreply(sender, "Group modified.");
+
+ /* TODO: controlwall */
+ return CMD_OK;
+}
+
static int commandsregistered;
static void registercommands(int hooknum, void *arg) {
registercontrolhelpcmd("trustgroupadd", NO_OPER, 6, trusts_cmdtrustgroupadd, "Usage: trustgroupadd <name> <howmany> <howlong> <maxperident> <enforceident> <contact> ?comment?");
registercontrolhelpcmd("trustadd", NO_OPER, 2, trusts_cmdtrustadd, "Usage: trustadd <#id|name|id> <host>");
+ registercontrolhelpcmd("trustgroupdel", NO_OPER, 1, trusts_cmdtrustgroupdel, "Usage: trustgroupdel <#id|name|id>");
+ registercontrolhelpcmd("trustdel", NO_OPER, 2, trusts_cmdtrustdel, "Usage: trustdel <#id|name|id> <ip/mask>");
+ registercontrolhelpcmd("trustgroupmodify", NO_OPER, 3, trusts_cmdtrustgroupmodify, "Usage: trustgroupmodify <#id|name|id> <field> <new value>");
}
static void deregistercommands(int hooknum, void *arg) {
deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd);
deregistercontrolcmd("trustadd", trusts_cmdtrustadd);
+ deregistercontrolcmd("trustgroupdel", trusts_cmdtrustgroupdel);
+ deregistercontrolcmd("trustdel", trusts_cmdtrustdel);
+ deregistercontrolcmd("trustgroupmodify", trusts_cmdtrustgroupmodify);
}
static int loaded;
xsb_broadcast("trdelhost", NULL, "%u", th->id);
}
+static void groupmodified(int hooknum, void *arg) {
+ trustgroup *tg = arg;
+
+ xsb_broadcast("trmodifygroup", NULL, "%s", dumptg(tg, 0));
+}
+
static int trusts_cmdtrustforceresync(void *source, int argc, char **argv) {
nick *np = source;
registerhook(HOOK_TRUSTS_DELGROUP, groupremoved);
registerhook(HOOK_TRUSTS_ADDHOST, hostadded);
registerhook(HOOK_TRUSTS_DELGROUP, hostremoved);
+ registerhook(HOOK_TRUSTS_MODIFYGROUP, groupmodified);
/* we've just reloaded */
/* if we're not online, no problem, other nodes will ask us individually */
registerhook(HOOK_TRUSTS_DELGROUP, groupremoved);
registerhook(HOOK_TRUSTS_ADDHOST, hostadded);
registerhook(HOOK_TRUSTS_DELGROUP, hostremoved);
+ registerhook(HOOK_TRUSTS_MODIFYGROUP, groupmodified);
deregistercontrolcmd("trustforceresync", trusts_cmdtrustforceresync);
}
syncing = 0;
- /* TODO: warn IRC */
+ controlwall(NO_DEVELOPER, NL_TRUSTS, "Warning: %s", buf2);
}
#define abandonreplication(x, ...) __abandonreplication(__FUNCTION__, __LINE__, x , # __VA_ARGS__)
return CMD_ERROR;
}
- th.group = tg_inttotg(tgid);
+ th.group = tg_getbyid(tgid);
if(!th.group) {
abandonreplication("unable to lookup trustgroup");
return CMD_ERROR;
}
static int xsb_trdelhost(void *source, int argc, char **argv) {
+ unsigned int id;
+ trusthost *th;
+
if(!synced)
return CMD_OK;
return CMD_ERROR;
}
+ id = strtoul(argv[0], NULL, 10);
+ if(!id) {
+ abandonreplication("unable to convert id to integer");
+ return CMD_ERROR;
+ }
+
+ th = th_getbyid(id);
+ if(!th) {
+ abandonreplication("unable to lookup id");
+ return CMD_ERROR;
+ }
+
+ th_delete(th);
+
return CMD_OK;
}
static int xsb_trdelgroup(void *source, int argc, char **argv) {
+ unsigned int id;
+ trustgroup *tg;
+
if(!synced)
return CMD_OK;
return CMD_ERROR;
}
+ id = strtoul(argv[0], NULL, 10);
+ if(!id) {
+ abandonreplication("unable to convert id to integer");
+ return CMD_ERROR;
+ }
+
+ tg = tg_getbyid(id);
+ if(!tg) {
+ abandonreplication("unable to lookup id");
+ return CMD_ERROR;
+ }
+
+ tg_delete(tg);
+
+ return CMD_OK;
+}
+
+static int xsb_trmodifygroup(void *source, int argc, char **argv) {
+ trustgroup tg, *otg;
+
+ if(!synced)
+ return CMD_OK;
+
+ if(!masterserver(source))
+ return CMD_ERROR;
+
+ if(argc < 1) {
+ abandonreplication("bad number of arguments");
+ return CMD_ERROR;
+ }
+
+ if(!parsetg(argv[0], &tg, 0)) {
+ abandonreplication("bad trustgroup line: %s", argv[0]);
+ return CMD_ERROR;
+ }
+
+ otg = tg_getbyid(tg.id);
+
+ if(otg && !tg_modify(otg, &tg)) {
+ abandonreplication("unable to modify database");
+ return CMD_ERROR;
+ }
+
+ freesstring(tg.name);
+ freesstring(tg.createdby);
+ freesstring(tg.contact);
+ freesstring(tg.comment);
+
+ if(!otg) {
+ abandonreplication("unable to lookup id");
+ return CMD_ERROR;
+ }
+
+ tg_update(otg);
+
return CMD_OK;
}
xsb_addcommand("traddgroup", 1, xsb_traddgroup);
xsb_addcommand("trdelhost", 1, xsb_trdelhost);
xsb_addcommand("trdelgroup", 1, xsb_trdelgroup);
+ xsb_addcommand("trmodifygroup", 1, xsb_trmodifygroup);
registerhook(HOOK_SERVER_LINKED, __serverlinked);
syncsched = schedulerecurring(time(NULL)+5, 0, 60, checksynced, NULL);
xsb_delcommand("traddgroup", xsb_traddgroup);
xsb_delcommand("trdelhost", xsb_trdelhost);
xsb_delcommand("trdelgroup", xsb_trdelgroup);
+ xsb_delcommand("trmodifygroup", xsb_trmodifygroup);
deregisterhook(HOOK_SERVER_LINKED, __serverlinked);