#include "../core/config.h"
#include "../core/error.h"
#include "../control/control.h"
-#include "../xsb/xsb.h"
#include "../lib/sha1.h"
#include "../lib/hmac.h"
#include "../lib/irc_string.h"
#include "../core/schedule.h"
#include "../server/server.h"
+#include "../xsb/xsb.h"
#include "trusts.h"
static int syncing, synced;
-static sstring *masterserver;
+static sstring *smasterserver;
static unsigned int curlineno, totallines;
static SHA1_CTX s;
void trusts_replication_swap(void);
void trusts_replication_complete(int);
+static int masterserver(void *source);
+
static void __abandonreplication(const char *fn, int line, char *error, ...) {
va_list ap;
char buf[512], buf2[600];
va_start(ap, error);
- vsnprintf(buf, sizeof(buf), "%s", ap);
+ vsnprintf(buf, sizeof(buf), error, ap);
va_end(ap);
snprintf(buf2, sizeof(buf2), "Error replicating (function: %s, line: %d): %s", fn, line, buf);
Error("trusts_slave", ERR_ERROR, "%s", buf2);
- syncing = 0;
+ syncing = synced = 0;
- /* TODO: warn IRC */
+ controlwall(NO_DEVELOPER, NL_TRUSTS, "Warning: %s", buf2);
}
#define abandonreplication(x, ...) __abandonreplication(__FUNCTION__, __LINE__, x , # __VA_ARGS__)
return NULL;
if(lineno != curlineno) {
- abandonreplication("unexpected line number");
- Error("trusts_slave", ERR_ERROR, "Didn't get expected line number (%u vs. %u).", lineno, curlineno);
+ abandonreplication("unexpected line number (%u vs. %u)", lineno, curlineno);
return NULL;
}
if(lineno > totallines) {
abandonreplication("too many lines");
- Error("trusts_slave", ERR_ERROR, "Too many lines received!");
return NULL;
}
char *buf;
unsigned int forced;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of args");
return CMD_ERROR;
return CMD_ERROR;
}
- if(!forced || synced)
+ if(!forced && synced)
return CMD_OK;
if(!extractline(argv[0], 1, 1, 0))
if(!syncing)
return CMD_OK;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of args");
return CMD_ERROR;
if(buf[0] == 'G') {
trustgroup tg;
if(!parsetg(&buf[2], &tg, 0)) {
- abandonreplication("bad trustgroup line");
- Error("trusts_slave", ERR_ERROR, "Bad trustgroup line: %s", buf);
+ abandonreplication("bad trustgroup line: %s", buf);
return CMD_ERROR;
}
trustsdb_inserttg("replication_groups", &tg);
trusthost th;
if(!parseth(&buf[2], &th, &tgid, 0)) {
- abandonreplication("bad trusthost line");
- Error("trusts_slave", ERR_ERROR, "Bad trusthost line: %s", buf);
+ abandonreplication("bad trusthost line: %s", buf);
return CMD_ERROR;
}
trustsdb_insertth("replication_hosts", &th, tgid);
} else {
- abandonreplication("bad trust type");
+ abandonreplication("bad trust type: %c", buf[0]);
- Error("trusts_slave", ERR_ERROR, "Bad trust type: %c", buf[0]);
return CMD_ERROR;
}
} else {
- abandonreplication("malformed line");
-
- Error("trusts_slave", ERR_ERROR, "Malformed data line: %s", buf);
+ abandonreplication("malformed line: %s", buf);
}
return CMD_OK;
if(!syncing)
return CMD_OK;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of args");
return CMD_ERROR;
return CMD_ERROR;
if((totallines + 1) != curlineno) {
- abandonreplication("wrong number of lines received");
- Error("trusts_slave", ERR_ERROR, "Wrong number of lines received (%u vs. %u).", totallines, curlineno - 1);
+ abandonreplication("wrong number of lines received: %u vs. %u", totallines, curlineno - 1);
return CMD_ERROR;
}
SHA1Final(digest, &s);
if(strcasecmp(hmac_printhex(digest, digestbuf, SHA1_DIGESTSIZE), buf)) {
abandonreplication("digest mismatch");
- Error("trusts_slave", ERR_ERROR, "Digest mismatch.");
return CMD_ERROR;
}
trusts_replication_swap();
synced = 1;
+ syncing = 0;
return CMD_OK;
}
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");
- Error("trusts_slave", ERR_ERROR, "Bad trustgroup line: %s", argv[0]);
+ abandonreplication("bad trustgroup line: %s", argv[0]);
return CMD_ERROR;
}
if(!synced)
return CMD_OK;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of arguments");
return CMD_ERROR;
}
if(!parseth(argv[0], &th, &tgid, 0)) {
- abandonreplication("bad trusthost line");
- Error("trusts_slave", ERR_ERROR, "Bad trusthost line: %s", argv[0]);
+ abandonreplication("bad trusthost line: %s", argv[0]);
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;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of arguments");
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;
+ if(!masterserver(source))
+ return CMD_ERROR;
+
if(argc < 1) {
abandonreplication("bad number of arguments");
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 trusts_cmdtrustresync(void *source, int argc, char **argv) {
- nick *np = source;
+static int xsb_trmodifygroup(void *source, int argc, char **argv) {
+ trustgroup tg, *otg;
- if(syncing) {
- controlreply(np, "Synchronisation is already in progress.");
+ if(!synced)
+ return CMD_OK;
+
+ if(!masterserver(source))
+ return CMD_ERROR;
+
+ if(argc < 1) {
+ abandonreplication("bad number of arguments");
return CMD_ERROR;
}
- synced = 0;
- xsb_broadcast("trrequestsync", NULL, "%s", "");
- controlreply(np, "Synchronisation request sent.");
+ 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;
}
-static int loaded;
+static int loaded, masternumeric = -1;
static void *syncsched;
+static int masterserver(void *source) {
+ nick *np = source;
+ int home = homeserver(np->numeric);
+
+ if(home < 0)
+ return 0;
+
+ if(home != masternumeric) {
+ Error("trusts_slave", ERR_WARNING, "Command from server that isn't a master: %s", serverlist[home].name->content);
+ return 0;
+ }
+
+ return 1;
+}
+
static void checksynced(void *arg) {
- if(!synced || !syncing)
- xsb_broadcast("trrequestsync", NULL, "%s", "");
+ if(!synced && !syncing)
+ xsb_broadcast("trrequeststart", NULL, "%s", "");
+}
+
+static int trusts_cmdtrustresync(void *source, int argc, char **argv) {
+ nick *np = source;
+
+ syncing = synced = 0;
+
+ checksynced(NULL);
+ controlreply(np, "Synchronisation request sent.");
+
+ return CMD_OK;
}
static void __serverlinked(int hooknum, void *arg) {
- int servernum = (int)arg;
+ int servernum = (int)(long)arg;
- if(!ircd_strcmp(serverlist[servernum].name->content, masterserver->content)) {
+ if(!ircd_strcmp(serverlist[servernum].name->content, smasterserver->content)) {
+ masternumeric = servernum;
syncing = synced = 0;
- xsb_broadcast("trrequestsync", NULL, "%s", "");
+ checksynced(NULL);
}
}
return;
}
- masterserver = getcopyconfigitem("trusts", "masterserver", "", 255);
- if(!masterserver || !masterserver->content || !masterserver->content[0]) {
+ smasterserver = getcopyconfigitem("trusts", "masterserver", "", 255);
+ if(!smasterserver || !smasterserver->content || !smasterserver->content[0]) {
Error("trusts_slave", ERR_ERROR, "No master server defined.");
- freesstring(masterserver);
+ freesstring(smasterserver);
return;
}
+ masternumeric = findserver(smasterserver->content);
+
loaded = 1;
registercontrolhelpcmd("trustresync", NO_DEVELOPER, 0, trusts_cmdtrustresync, "Usage: trustresync");
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);
if(trusts_fullyonline())
- xsb_broadcast("trrequestsync", NULL, "%s", "");
+ checksynced(NULL);
}
void _fini(void) {
if(!loaded)
return;
- freesstring(masterserver);
+ freesstring(smasterserver);
deregistercontrolcmd("trustresync", trusts_cmdtrustresync);
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);