]>
jfr.im git - irc/quakenet/newserv.git/blob - trusts/trusts_slave.c
6 #include "../core/hooks.h"
7 #include "../core/config.h"
8 #include "../core/error.h"
9 #include "../control/control.h"
10 #include "../lib/sha1.h"
11 #include "../lib/hmac.h"
12 #include "../lib/irc_string.h"
13 #include "../core/schedule.h"
14 #include "../server/server.h"
15 #include "../xsb/xsb.h"
18 static int syncing
, synced
;
19 static sstring
*smasterserver
;
21 static unsigned int curlineno
, totallines
;
24 void trusts_replication_createtables(void);
25 void trusts_replication_swap(void);
26 void trusts_replication_complete(int);
28 static int masterserver(void *source
);
30 static void __abandonreplication(const char *fn
, int line
, char *error
, ...) {
32 char buf
[512], buf2
[600];
35 vsnprintf(buf
, sizeof(buf
), error
, ap
);
38 snprintf(buf2
, sizeof(buf2
), "Error replicating (function: %s, line: %d): %s", fn
, line
, buf
);
40 Error("trusts_slave", ERR_ERROR
, "%s", buf2
);
44 controlwall(NO_DEVELOPER
, NL_TRUSTS
, "Warning: %s", buf2
);
47 #define abandonreplication(x, ...) __abandonreplication(__FUNCTION__, __LINE__, x , # __VA_ARGS__)
49 void trusts_replication_complete(int error
) {
51 abandonreplication("final replication stage: error %d", error
);
54 Error("trusts_slave", ERR_INFO
, "Replication complete!");
56 if(!trusts_loaddb()) {
57 abandonreplication("couldn't load database");
64 static char *extractline(char *buf
, int reset
, int update
, int final
) {
65 unsigned char n
= '\n';
67 unsigned int lineno
, id
;
68 static unsigned int curid
;
70 if(sscanf(buf
, "%u %u %n", &id
, &lineno
, &chars
) != 2) {
71 abandonreplication("bad number for sscanf result");
76 abandonreplication("bad number of characters");
80 if(reset
&& (lineno
!= 1)) {
81 abandonreplication("bad initial line number");
91 /* will happen if two are sent at once, but that's ok */
95 if(lineno
!= curlineno
) {
96 abandonreplication("unexpected line number (%u vs. %u)", lineno
, curlineno
);
99 if(lineno
> totallines
) {
100 abandonreplication("too many lines");
109 SHA1Update(&s
, (unsigned char *)buf
, strlen(buf
));
110 SHA1Update(&s
, &n
, 1);
117 /* trinit id lineno force totallines */
118 static int xsb_trinit(void *source
, int argc
, char **argv
) {
122 if(!masterserver(source
))
126 abandonreplication("bad number of args");
130 buf
= extractline(argv
[0], 1, 0, 1);
134 if((sscanf(buf
, "%u %u", &forced
, &totallines
) != 2)) {
135 abandonreplication("bad number for sscanf result");
140 abandonreplication("bad number of lines");
144 if(!forced
&& synced
)
147 if(!extractline(argv
[0], 1, 1, 0))
150 trusts_replication_createtables();
154 Error("trusts_slave", ERR_INFO
, "Replication in progress. . .");
158 /* trdata id lines type data */
159 static int xsb_trdata(void *source
, int argc
, char **argv
) {
165 if(!masterserver(source
))
169 abandonreplication("bad number of args");
173 buf
= extractline(argv
[0], 0, 1, 0);
177 if(buf
[0] && (buf
[1] == ' ')) {
180 if(!parsetg(&buf
[2], &tg
, 0)) {
181 abandonreplication("bad trustgroup line: %s", buf
);
184 trustsdb_inserttg("replication_groups", &tg
);
186 freesstring(tg
.name
);
187 freesstring(tg
.createdby
);
188 freesstring(tg
.contact
);
189 freesstring(tg
.comment
);
191 } else if(buf
[0] == 'H') {
195 if(!parseth(&buf
[2], &th
, &tgid
, 0)) {
196 abandonreplication("bad trusthost line: %s", buf
);
199 trustsdb_insertth("replication_hosts", &th
, tgid
);
201 abandonreplication("bad trust type: %c", buf
[0]);
206 abandonreplication("malformed line: %s", buf
);
212 /* trfini id lines sha */
213 static int xsb_trfini(void *source
, int argc
, char **argv
) {
214 char *buf
, digestbuf
[SHA1_DIGESTSIZE
* 2 + 1];
215 unsigned char digest
[SHA1_DIGESTSIZE
];
220 if(!masterserver(source
))
224 abandonreplication("bad number of args");
228 buf
= extractline(argv
[0], 0, 1, 1);
232 if((totallines
+ 1) != curlineno
) {
233 abandonreplication("wrong number of lines received: %u vs. %u", totallines
, curlineno
- 1);
237 SHA1Final(digest
, &s
);
238 if(hmac_strcmp(hmac_printhex(digest
, digestbuf
, SHA1_DIGESTSIZE
), buf
)) {
239 abandonreplication("digest mismatch");
243 Error("trusts_slave", ERR_INFO
, "Data verification successful.");
245 trusts_replication_swap();
253 static int xsb_traddgroup(void *source
, int argc
, char **argv
) {
259 if(!masterserver(source
))
263 abandonreplication("bad number of arguments");
267 if(!parsetg(argv
[0], &tg
, 0)) {
268 abandonreplication("bad trustgroup line: %s", argv
[0]);
274 freesstring(tg
.name
);
275 freesstring(tg
.createdby
);
276 freesstring(tg
.contact
);
277 freesstring(tg
.comment
);
280 abandonreplication("unable to add trustgroup");
287 static int xsb_traddhost(void *source
, int argc
, char **argv
) {
294 if(!masterserver(source
))
298 abandonreplication("bad number of arguments");
302 if(!parseth(argv
[0], &th
, &tgid
, 0)) {
303 abandonreplication("bad trusthost line: %s", argv
[0]);
307 th
.group
= tg_getbyid(tgid
);
309 abandonreplication("unable to lookup trustgroup");
314 abandonreplication("unable to add trusthost");
321 static int xsb_trdelhost(void *source
, int argc
, char **argv
) {
328 if(!masterserver(source
))
332 abandonreplication("bad number of arguments");
336 id
= strtoul(argv
[0], NULL
, 10);
338 abandonreplication("unable to convert id to integer");
344 abandonreplication("unable to lookup id");
353 static int xsb_trdelgroup(void *source
, int argc
, char **argv
) {
360 if(!masterserver(source
))
364 abandonreplication("bad number of arguments");
368 id
= strtoul(argv
[0], NULL
, 10);
370 abandonreplication("unable to convert id to integer");
376 abandonreplication("unable to lookup id");
385 static int xsb_trmodifygroup(void *source
, int argc
, char **argv
) {
391 if(!masterserver(source
))
395 abandonreplication("bad number of arguments");
399 if(!parsetg(argv
[0], &tg
, 0)) {
400 abandonreplication("bad trustgroup line: %s", argv
[0]);
404 otg
= tg_getbyid(tg
.id
);
406 if(otg
&& !tg_modify(otg
, &tg
)) {
407 abandonreplication("unable to modify database");
411 freesstring(tg
.name
);
412 freesstring(tg
.createdby
);
413 freesstring(tg
.contact
);
414 freesstring(tg
.comment
);
417 abandonreplication("unable to lookup id");
426 static int xsb_trmodifyhost(void *source
, int argc
, char **argv
) {
429 unsigned int groupid
;
434 if(!masterserver(source
))
438 abandonreplication("bad number of arguments");
442 if(!parseth(argv
[0], &th
, &groupid
, 0)) {
443 abandonreplication("bad trusthost line: %s", argv
[0]);
447 tg
= tg_getbyid(groupid
);
449 for(oth
=tg
->hosts
;oth
;oth
=oth
->next
) {
450 if(ipmask_check(&oth
->ip
, &th
.ip
, th
.bits
) && th
.bits
== oth
->bits
)
454 if(oth
&& !th_modify(oth
, &th
)) {
455 abandonreplication("unable to modify database");
460 abandonreplication("unable to lookup host");
469 static int loaded
, masternumeric
= -1;
470 static void *syncsched
;
472 static int masterserver(void *source
) {
474 int home
= homeserver(np
->numeric
);
479 if(home
!= masternumeric
) {
480 Error("trusts_slave", ERR_WARNING
, "Command from server that isn't a master: %s", serverlist
[home
].name
->content
);
487 static void checksynced(void *arg
) {
488 if(!synced
&& !syncing
)
489 xsb_broadcast("trrequeststart", NULL
, "%s", "");
492 static int trusts_cmdtrustresync(void *source
, int argc
, char **argv
) {
495 syncing
= synced
= 0;
498 controlreply(np
, "Synchronisation request sent.");
503 static void __serverlinked(int hooknum
, void *arg
) {
504 int servernum
= (int)(long)arg
;
506 if(!ircd_strcmp(serverlist
[servernum
].name
->content
, smasterserver
->content
)) {
507 masternumeric
= servernum
;
508 syncing
= synced
= 0;
516 m
= getconfigitem("trusts", "master");
517 if(m
&& (atoi(m
->content
) != 0)) {
518 Error("trusts_slave", ERR_ERROR
, "Not a slave server, not loaded.");
522 smasterserver
= getcopyconfigitem("trusts", "masterserver", "", 255);
523 if(!smasterserver
|| !smasterserver
->content
|| !smasterserver
->content
[0]) {
524 Error("trusts_slave", ERR_ERROR
, "No master server defined.");
525 freesstring(smasterserver
);
529 masternumeric
= findserver(smasterserver
->content
);
533 registercontrolhelpcmd("trustresync", NO_DEVELOPER
, 0, trusts_cmdtrustresync
, "Usage: trustresync");
535 xsb_addcommand("trinit", 1, xsb_trinit
);
536 xsb_addcommand("trdata", 1, xsb_trdata
);
537 xsb_addcommand("trfini", 1, xsb_trfini
);
538 xsb_addcommand("traddhost", 1, xsb_traddhost
);
539 xsb_addcommand("traddgroup", 1, xsb_traddgroup
);
540 xsb_addcommand("trdelhost", 1, xsb_trdelhost
);
541 xsb_addcommand("trdelgroup", 1, xsb_trdelgroup
);
542 xsb_addcommand("trmodifygroup", 1, xsb_trmodifygroup
);
543 xsb_addcommand("trmodifyhost", 1, xsb_trmodifyhost
);
545 registerhook(HOOK_SERVER_LINKED
, __serverlinked
);
546 syncsched
= schedulerecurring(time(NULL
)+5, 0, 60, checksynced
, NULL
);
548 if(trusts_fullyonline())
556 freesstring(smasterserver
);
558 deregistercontrolcmd("trustresync", trusts_cmdtrustresync
);
560 xsb_delcommand("trinit", xsb_trinit
);
561 xsb_delcommand("trdata", xsb_trdata
);
562 xsb_delcommand("trfini", xsb_trfini
);
563 xsb_delcommand("traddhost", xsb_traddhost
);
564 xsb_delcommand("traddgroup", xsb_traddgroup
);
565 xsb_delcommand("trdelhost", xsb_trdelhost
);
566 xsb_delcommand("trdelgroup", xsb_trdelgroup
);
567 xsb_delcommand("trmodifygroup", xsb_trmodifygroup
);
568 xsb_delcommand("trmodifyhost", xsb_trmodifyhost
);
570 deregisterhook(HOOK_SERVER_LINKED
, __serverlinked
);
572 deleteschedule(syncsched
, checksynced
, NULL
);