#define HOOK_AUTH_FLAGSUPDATED 801 /* Argument is void*[2] (authname*, u_int64_t*) */
#define HOOK_AUTH_LOSTAUTHNAME 802 /* Argument is authname* */
+#define HOOK_TRUSTS_DB_LOADED 901 /* No arg */
+
#define PRIORITY_DEFAULT 0
#define PRIORITY_MAX LONG_MIN
@include@ @includel@../build.mk@includel@
.PHONY: all
-all: trusts.so
+all: trusts.so trusts_commands.so
trusts.so: trusts.o migration.o db.o db-migration.o
+
+trusts_commands.so: trusts_commands.o
trustmigration *migration_start(TrustMigrationGroup, TrustMigrationHost, TrustMigrationFini, void *);
void migration_stop(trustmigration *);
+void createtrusttables(int migration);
struct callbackdata {
void *tag;
struct callbackdata *cbd;
if(migration)
- return 0;
+ return 1;
if(callback) {
cbd = malloc(sizeof(struct callbackdata));
if(!cbd)
- return 0;
+ return 2;
cbd->callback = callback;
cbd->tag = tag;
cbd = NULL;
}
- trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "groups");
- trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "hosts");
+ createtrusttables(1);
+ trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "migration_groups");
+ trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "migration_hosts");
migration = migration_start(tm_group, tm_host, tm_final, cbd);
if(!migration) {
free(cbd);
- return 0;
+ return 3;
}
- return 1;
+ return 0;
}
void trusts_migration_stop(void) {
trustsdb->squery(trustsdb,
"INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- "Tusuuuutttsss", "groups", id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment
+ "Tusuuuutttsss", "migration_groups", id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment
);
}
static void tm_host(void *tag, unsigned int id, char *host, unsigned int max, time_t lastseen) {
trustsdb->squery(trustsdb,
"INSERT INTO ? (groupid, host, max, lastseen) VALUES (?, ?, ?, ?)",
- "Tusut", "hosts", id, host, max, lastseen
+ "Tusut", "migration_hosts", id, host, max, lastseen
);
}
-static void tm_final(void *tag, int errcode) {
+static void tm_complete(const DBAPIResult *r, void *tag) {
struct callbackdata *cbd = tag;
- migration = NULL;
+ int errcode = 0;
- if(errcode) {
- Error("trusts", ERR_ERROR, "Migration error: %d", errcode);
+ if(!r) {
+ errcode = MIGRATION_STOPPED;
} else {
- Error("trusts", ERR_INFO, "Migration completed.");
+ if(!r->success) {
+ Error("trusts", ERR_ERROR, "A error occured executing the rename table query.");
+ errcode = 100;
+ } else {
+ Error("trusts", ERR_INFO, "Migration table copying complete.");
+ }
+ r->clear(r);
}
if(cbd) {
- cbd->callback(errcode, tag);
+ cbd->callback(errcode, cbd->tag);
free(cbd);
}
}
+
+static void tm_final(void *tag, int errcode) {
+ struct callbackdata *cbd = tag;
+ migration = NULL;
+
+ if(errcode) {
+ Error("trusts", ERR_ERROR, "Migration error: %d", errcode);
+ if(cbd) {
+ cbd->callback(errcode, cbd->tag);
+ free(cbd);
+ }
+ } else {
+ Error("trusts", ERR_INFO, "Migration completed, copying tables...");
+/*
+ trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+ "BEGIN TRANSACTION; DROP TABLE ?; ALTER TABLE ? RENAME TO ?; DROP TABLE ?; ALTER TABLE ? RENAME TO ?; COMMIT;",
+ "TTsTTs", "groups", "migration_groups", "groups", "hosts", "migration_hosts", "hosts");
+*/
+/*
+ trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+ "BEGIN TRANSACTION; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; COMMIT;",
+ "TTTTTT", "groups", "groups", "migration_groups", "hosts", "hosts", "migration_hosts");
+*/
+/*
+ trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+ "DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?;",
+ "TTTTTT", "groups", "groups", "migration_groups", "hosts", "hosts", "migration_hosts");
+*/
+ trustsdb->squery(trustsdb, "BEGIN TRANSACTION", "");
+ trustsdb->squery(trustsdb, "DROP TABLE ?", "T", "groups");
+ trustsdb->squery(trustsdb, "ALTER TABLE ? RENAME TO ?", "Ts", "migration_groups", "groups");
+ trustsdb->squery(trustsdb, "DROP TABLE ?", "T", "hosts");
+ trustsdb->squery(trustsdb, "ALTER TABLE ? RENAME TO ?", "Ts", "migration_hosts", "hosts");
+ trustsdb->query(trustsdb, tm_complete, cbd, "COMMIT", "");
+ }
+}
#include "../dbapi2/dbapi2.h"
#include "../core/error.h"
#include "../nick/nick.h"
+#include "../core/hooks.h"
#include "trusts.h"
DBAPIConn *trustsdb;
-extern trustgroup *tglist;
+static int tgmaxid;
+static int loaderror;
+int trustsdbloaded;
void trusts_reloaddb(void);
+void createtrusttables(int migration);
int trusts_loaddb(void) {
trustsdb = dbapi2open(NULL, "trusts");
return 0;
}
- trustsdb->createtable(trustsdb, NULL, NULL,
- "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(100), trustedfor INT, mode INT, maxperident INT, maxseen INT, expires INT, lastseen INT, lastmaxuserreset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
- "Tddd", "groups", NICKLEN, CONTACTLEN, COMMENTLEN
- );
- trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (groupid INT, host VARCHAR(100), max INT, lastseen INT, PRIMARY KEY (groupid, host))", "T", "hosts");
+ createtrusttables(0);
trusts_reloaddb();
return 1;
}
+void createtrusttables(int migration) {
+ char *groups, *hosts;
+
+ if(migration) {
+ groups = "migration_groups";
+ hosts = "migration_hosts";
+ } else {
+ groups = "groups";
+ hosts = "hosts";
+ }
+
+ trustsdb->createtable(trustsdb, NULL, NULL,
+ "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(?), trustedfor INT, mode INT, maxperident INT, maxseen INT, expires INT, lastseen INT, lastmaxuserreset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
+ "Tdddd", groups, TRUSTNAMELEN, NICKLEN, CONTACTLEN, COMMENTLEN
+ );
+ trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (groupid INT, host VARCHAR(?), max INT, lastseen INT, PRIMARY KEY (groupid, host))", "Td", hosts, TRUSTHOSTLEN);
+}
+
static void trusts_freedb(void) {
-/* do stuff */
+ trustgroup *tg, *ntg;
+ trusthost *th, *nth;
+
+ for(tg=tglist;tg;tg=ntg) {
+ ntg = tg->next;
+ for(th=tg->hosts;th;th=nth) {
+ nth = th->next;
+
+ freesstring(th->host);
+ free(th);
+ }
+
+ freesstring(tg->name);
+ freesstring(tg->createdby);
+ freesstring(tg->contact);
+ freesstring(tg->comment);
+ free(tg);
+ }
+ trustsdbloaded = 0;
tglist = NULL;
+ tgmaxid = 0;
+}
+
+trustgroup *tg_getbyid(unsigned int id) {
+ trustgroup *tg;
+
+ for(tg=tglist;tg;tg=tg->next)
+ if(tg->id == id)
+ return tg;
+
+ return NULL;
+}
+
+static void loadhosts_data(const DBAPIResult *result, void *tag) {
+ if(!result) {
+ loaderror = 1;
+ return;
+ }
+
+ if(!result->success) {
+ Error("trusts", ERR_ERROR, "Error loading hosts table.");
+ loaderror = 1;
+
+ result->clear(result);
+ return;
+ }
+
+ if(result->fields != 4) {
+ Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
+ loaderror = 1;
+
+ result->clear(result);
+ return;
+ }
+
+ while(result->next(result)) {
+ unsigned int groupid;
+ trusthost *th;
+ trustgroup *tg;
+
+ groupid = strtoul(result->get(result, 0), NULL, 10);
+
+ tg = tg_getbyid(groupid);
+ if(!tg) {
+ Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
+ continue;
+ }
+
+ th = malloc(sizeof(trusthost));
+ if(!th)
+ continue;
+
+ th->host = getsstring(result->get(result, 1), TRUSTHOSTLEN);
+ th->maxseen = strtoul(result->get(result, 2), NULL, 10);
+ th->lastseen = (time_t)strtoul(result->get(result, 3), NULL, 10);
+
+ th->next = tg->hosts;
+ tg->hosts = th;
+ }
+
+ result->clear(result);
+
+ if(!loaderror) {
+ trustsdbloaded = 1;
+ triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
+ }
+}
+
+static void loadhosts_fini(const DBAPIResult *result, void *tag) {
+ Error("trusts", ERR_INFO, "Finished loading hosts.");
+}
+
+static void loadgroups_data(const DBAPIResult *result, void *tag) {
+ if(!result) {
+ loaderror = 1;
+ return;
+ }
+
+ if(!result->success) {
+ Error("trusts", ERR_ERROR, "Error loading group table.");
+ loaderror = 1;
+
+ result->clear(result);
+ return;
+ }
+
+ if(result->fields != 12) {
+ Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
+ loaderror = 1;
+
+ result->clear(result);
+ return;
+ }
+
+ while(result->next(result)) {
+ unsigned int id;
+ trustgroup *tg;
+
+ id = strtoul(result->get(result, 0), NULL, 10);
+ if(id > tgmaxid)
+ tgmaxid = id;
+
+ tg = malloc(sizeof(trustgroup));
+ if(!tg)
+ continue;
+
+ tg->id = id;
+ tg->name = getsstring(result->get(result, 1), TRUSTNAMELEN);
+ tg->trustedfor = strtoul(result->get(result, 2), NULL, 10);
+ tg->mode = atoi(result->get(result, 3));
+ tg->maxperident = strtoul(result->get(result, 4), NULL, 10);
+ tg->maxseen = strtoul(result->get(result, 5), NULL, 10);
+ tg->expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
+ tg->lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
+ tg->lastmaxuserreset = (time_t)strtoul(result->get(result, 8), NULL, 10);
+ tg->createdby = getsstring(result->get(result, 9), NICKLEN);
+ tg->contact = getsstring(result->get(result, 10), CONTACTLEN);
+ tg->comment = getsstring(result->get(result, 11), COMMENTLEN);
+
+ tg->hosts = NULL;
+
+ tg->next = tglist;
+ tglist = tg;
+ }
+
+ result->clear(result);
+}
+
+static void loadgroups_fini(const DBAPIResult *result, void *tag) {
+ Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
}
void trusts_reloaddb(void) {
trusts_freedb();
+ loaderror = 0;
+ trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
+ trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
}
void trusts_closedb(void) {
#include "../nterfacer/nterfacer.h"
-#include "../nick/nick.h"
#include "../lib/strlfunc.h"
#include "trusts.h"
#include <stdio.h>
-#include "../core/error.h"
#include "trusts.h"
trustgroup *tglist;
int trusts_loaddb(void);
void trusts_closedb(void);
-void trusts_reloaddb(void);
-int trusts_migration_start(TrustDBMigrationCallback, void *);
-void trusts_migration_stop(void);
void _init(void) {
if(!trusts_loaddb())
return;
-
- trusts_migration_start(NULL, NULL);
}
void _fini(void) {
- trusts_migration_stop();
trusts_closedb();
}
#define CONTACTLEN 100
#define COMMENTLEN 300
+#define TRUSTNAMELEN 100
+#define TRUSTHOSTLEN 100
struct trustmigration;
typedef void (*TrustDBMigrationCallback)(int, void *);
+typedef struct trusthost {
+ sstring *host;
+ unsigned int maxseen;
+ time_t lastseen;
+
+ struct trusthost *next;
+} trusthost;
+
typedef struct trustgroup {
unsigned int id;
unsigned int trustedfor;
int mode;
unsigned int maxperident;
+ unsigned int maxseen;
time_t expires;
- time_t latseeen;
+ time_t lastseen;
time_t lastmaxuserreset;
-
sstring *createdby, *contact, *comment;
+ trusthost *hosts;
+
struct trustgroup *next;
} trustgroup;
-typedef struct trusthost {
- unsigned int id;
+void trusts_reloaddb(void);
- sstring *mask;
- unsigned int max;
- time_t lastseen;
-
- struct trusthost *next;
-} trusthost;
+extern int trustsdbloaded;
+extern trustgroup *tglist;
#endif
--- /dev/null
+#include "../control/control.h"
+#include "../nick/nick.h"
+#include "trusts.h"
+
+int trusts_migration_start(TrustDBMigrationCallback, void *);
+void trusts_migration_stop(void);
+static void registercommands(void);
+static void deregistercommands(void);
+
+static int commandsregistered;
+
+static void migrate_status(int errcode, void *tag) {
+ long sender = (long)tag;
+ nick *np = getnickbynumeric(sender);
+
+ if(!np)
+ return;
+
+ if(!errcode) {
+ controlreply(np, "Migration complete.");
+ trusts_reloaddb();
+ } else {
+ controlreply(np, "Error %d occured during migration.", errcode);
+ registercommands();
+ }
+}
+
+static int trusts_cmdmigrate(void *source, int cargc, char **cargv) {
+ nick *sender = source;
+ int ret;
+
+ /* iffy but temporary */
+ ret = trusts_migration_start(migrate_status, (void *)(sender->numeric));
+ if(!ret) {
+ controlreply(sender, "Migration started.");
+ deregistercommands();
+ } else {
+ controlreply(sender, "Error %d starting migration.", ret);
+ }
+
+ return CMD_OK;
+}
+
+static void dbloaded(int hooknum, void *arg) {
+ registercommands();
+}
+
+void _init(void) {
+ registerhook(HOOK_TRUSTS_DB_LOADED, dbloaded);
+
+ if(trustsdbloaded)
+ registercommands();
+}
+
+void _fini(void) {
+ deregisterhook(HOOK_TRUSTS_DB_LOADED, dbloaded);
+ deregistercommands();
+
+ trusts_migration_stop();
+}
+
+static void registercommands(void) {
+ if(!trustsdbloaded || commandsregistered)
+ return;
+
+ commandsregistered = 1;
+ registercontrolhelpcmd("trustmigrate", NO_OPER, 0, trusts_cmdmigrate, "Usage: trustmigrate\nCopies trust data from O and reloads the database.");
+}
+
+static void deregistercommands(void) {
+ if(!commandsregistered)
+ return;
+
+ deregistercontrolcmd("trustmigrate", trusts_cmdmigrate);
+ commandsregistered = 0;
+}