]>
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/version.h"
11 #include "../lib/sha1.h"
12 #include "../lib/hmac.h"
13 #include "../lib/irc_string.h"
14 #include "../core/schedule.h"
15 #include "../server/server.h"
16 #include "../xsb/xsb.h"
21 static int syncing
, synced
;
22 static sstring
*smasterserver
;
24 static unsigned int curlineno
, totallines
;
27 void trusts_replication_createtables(void);
28 void trusts_replication_swap(void);
29 void trusts_replication_complete(int);
31 static int masterserver(void *source
);
33 static void __abandonreplication(const char *fn
, int line
, char *error
, ...) {
35 char buf
[512], buf2
[600];
38 vsnprintf(buf
, sizeof(buf
), error
, ap
);
41 snprintf(buf2
, sizeof(buf2
), "Error replicating (function: %s, line: %d): %s", fn
, line
, buf
);
43 Error("trusts_slave", ERR_ERROR
, "%s", buf2
);
47 controlwall(NO_DEVELOPER
, NL_TRUSTS
, "Warning: %s", buf2
);
50 #define abandonreplication(x, ...) __abandonreplication(__FUNCTION__, __LINE__, x , # __VA_ARGS__)
52 void trusts_replication_complete(int error
) {
54 abandonreplication("final replication stage: error %d", error
);
57 Error("trusts_slave", ERR_INFO
, "Replication complete!");
59 if(!trusts_loaddb()) {
60 abandonreplication("couldn't load database");
67 static char *extractline(char *buf
, int reset
, int update
, int final
) {
68 unsigned char n
= '\n';
70 unsigned int lineno
, id
;
71 static unsigned int curid
;
73 if(sscanf(buf
, "%u %u %n", &id
, &lineno
, &chars
) != 2) {
74 abandonreplication("bad number for sscanf result");
79 abandonreplication("bad number of characters");
83 if(reset
&& (lineno
!= 1)) {
84 abandonreplication("bad initial line number");
94 /* will happen if two are sent at once, but that's ok */
98 if(lineno
!= curlineno
) {
99 abandonreplication("unexpected line number (%u vs. %u)", lineno
, curlineno
);
102 if(lineno
> totallines
) {
103 abandonreplication("too many lines");
112 SHA1Update(&s
, (unsigned char *)buf
, strlen(buf
));
113 SHA1Update(&s
, &n
, 1);
120 /* trinit id lineno force totallines */
121 static int xsb_trinit(void *source
, int argc
, char **argv
) {
125 if(!masterserver(source
))
129 abandonreplication("bad number of args");
133 buf
= extractline(argv
[0], 1, 0, 1);
137 if((sscanf(buf
, "%u %u", &forced
, &totallines
) != 2)) {
138 abandonreplication("bad number for sscanf result");
143 abandonreplication("bad number of lines");
147 if(!forced
&& synced
)
150 if(!extractline(argv
[0], 1, 1, 0))
153 trusts_replication_createtables();
157 Error("trusts_slave", ERR_INFO
, "Replication in progress. . .");
161 /* trdata id lines type data */
162 static int xsb_trdata(void *source
, int argc
, char **argv
) {
168 if(!masterserver(source
))
172 abandonreplication("bad number of args");
176 buf
= extractline(argv
[0], 0, 1, 0);
180 if(buf
[0] && (buf
[1] == ' ')) {
183 if(!parsetg(&buf
[2], &tg
, 0)) {
184 abandonreplication("bad trustgroup line: %s", buf
);
187 trustsdb_inserttg("replication_groups", &tg
);
189 freesstring(tg
.name
);
190 freesstring(tg
.createdby
);
191 freesstring(tg
.contact
);
192 freesstring(tg
.comment
);
194 } else if(buf
[0] == 'H') {
198 if(!parseth(&buf
[2], &th
, &tgid
, 0)) {
199 abandonreplication("bad trusthost line: %s", buf
);
202 trustsdb_insertth("replication_hosts", &th
, tgid
);
204 abandonreplication("bad trust type: %c", buf
[0]);
209 abandonreplication("malformed line: %s", buf
);
215 /* trfini id lines sha */
216 static int xsb_trfini(void *source
, int argc
, char **argv
) {
217 char *buf
, digestbuf
[SHA1_DIGESTSIZE
* 2 + 1];
218 unsigned char digest
[SHA1_DIGESTSIZE
];
223 if(!masterserver(source
))
227 abandonreplication("bad number of args");
231 buf
= extractline(argv
[0], 0, 1, 1);
235 if((totallines
+ 1) != curlineno
) {
236 abandonreplication("wrong number of lines received: %u vs. %u", totallines
, curlineno
- 1);
240 SHA1Final(digest
, &s
);
241 if(hmac_strcmp(hmac_printhex(digest
, digestbuf
, SHA1_DIGESTSIZE
), buf
)) {
242 abandonreplication("digest mismatch");
246 Error("trusts_slave", ERR_INFO
, "Data verification successful.");
248 trusts_replication_swap();
256 static int xsb_traddgroup(void *source
, int argc
, char **argv
) {
262 if(!masterserver(source
))
266 abandonreplication("bad number of arguments");
270 if(!parsetg(argv
[0], &tg
, 0)) {
271 abandonreplication("bad trustgroup line: %s", argv
[0]);
277 freesstring(tg
.name
);
278 freesstring(tg
.createdby
);
279 freesstring(tg
.contact
);
280 freesstring(tg
.comment
);
283 abandonreplication("unable to add trustgroup");
290 static int xsb_traddhost(void *source
, int argc
, char **argv
) {
297 if(!masterserver(source
))
301 abandonreplication("bad number of arguments");
305 if(!parseth(argv
[0], &th
, &tgid
, 0)) {
306 abandonreplication("bad trusthost line: %s", argv
[0]);
310 th
.group
= tg_getbyid(tgid
);
312 abandonreplication("unable to lookup trustgroup");
317 abandonreplication("unable to add trusthost");
324 static int xsb_trdelhost(void *source
, int argc
, char **argv
) {
331 if(!masterserver(source
))
335 abandonreplication("bad number of arguments");
339 id
= strtoul(argv
[0], NULL
, 10);
341 abandonreplication("unable to convert id to integer");
347 abandonreplication("unable to lookup id");
356 static int xsb_trdelgroup(void *source
, int argc
, char **argv
) {
363 if(!masterserver(source
))
367 abandonreplication("bad number of arguments");
371 id
= strtoul(argv
[0], NULL
, 10);
373 abandonreplication("unable to convert id to integer");
379 abandonreplication("unable to lookup id");
388 static int xsb_trmodifygroup(void *source
, int argc
, char **argv
) {
394 if(!masterserver(source
))
398 abandonreplication("bad number of arguments");
402 if(!parsetg(argv
[0], &tg
, 0)) {
403 abandonreplication("bad trustgroup line: %s", argv
[0]);
407 otg
= tg_getbyid(tg
.id
);
409 if(otg
&& !tg_modify(otg
, &tg
)) {
410 abandonreplication("unable to modify database");
414 freesstring(tg
.name
);
415 freesstring(tg
.createdby
);
416 freesstring(tg
.contact
);
417 freesstring(tg
.comment
);
420 abandonreplication("unable to lookup id");
429 static int xsb_trmodifyhost(void *source
, int argc
, char **argv
) {
432 unsigned int groupid
;
437 if(!masterserver(source
))
441 abandonreplication("bad number of arguments");
445 if(!parseth(argv
[0], &th
, &groupid
, 0)) {
446 abandonreplication("bad trusthost line: %s", argv
[0]);
450 tg
= tg_getbyid(groupid
);
452 for(oth
=tg
->hosts
;oth
;oth
=oth
->next
) {
453 if(ipmask_check(&oth
->ip
, &th
.ip
, th
.bits
) && th
.bits
== oth
->bits
)
457 if(oth
&& !th_modify(oth
, &th
)) {
458 abandonreplication("unable to modify database");
463 abandonreplication("unable to lookup host");
472 static int loaded
, masternumeric
= -1;
473 static void *syncsched
;
475 static int masterserver(void *source
) {
477 int home
= homeserver(np
->numeric
);
482 if(home
!= masternumeric
) {
483 Error("trusts_slave", ERR_WARNING
, "Command from server that isn't a master: %s", serverlist
[home
].name
->content
);
490 static void checksynced(void *arg
) {
491 if(!synced
&& !syncing
)
492 xsb_broadcast("trrequeststart", NULL
, "%s", "");
495 static int trusts_cmdtrustresync(void *source
, int argc
, char **argv
) {
498 syncing
= synced
= 0;
501 controlreply(np
, "Synchronisation request sent.");
506 static void __serverlinked(int hooknum
, void *arg
) {
507 int servernum
= (int)(long)arg
;
509 if(!ircd_strcmp(serverlist
[servernum
].name
->content
, smasterserver
->content
)) {
510 masternumeric
= servernum
;
511 syncing
= synced
= 0;
519 m
= getconfigitem("trusts", "master");
520 if(m
&& (atoi(m
->content
) != 0)) {
521 Error("trusts_slave", ERR_ERROR
, "Not a slave server, not loaded.");
525 smasterserver
= getcopyconfigitem("trusts", "masterserver", "", 255);
526 if(!smasterserver
|| !smasterserver
->content
|| !smasterserver
->content
[0]) {
527 Error("trusts_slave", ERR_ERROR
, "No master server defined.");
528 freesstring(smasterserver
);
532 masternumeric
= findserver(smasterserver
->content
);
536 registercontrolhelpcmd("trustresync", NO_DEVELOPER
, 0, trusts_cmdtrustresync
, "Usage: trustresync");
538 xsb_addcommand("trinit", 1, xsb_trinit
);
539 xsb_addcommand("trdata", 1, xsb_trdata
);
540 xsb_addcommand("trfini", 1, xsb_trfini
);
541 xsb_addcommand("traddhost", 1, xsb_traddhost
);
542 xsb_addcommand("traddgroup", 1, xsb_traddgroup
);
543 xsb_addcommand("trdelhost", 1, xsb_trdelhost
);
544 xsb_addcommand("trdelgroup", 1, xsb_trdelgroup
);
545 xsb_addcommand("trmodifygroup", 1, xsb_trmodifygroup
);
546 xsb_addcommand("trmodifyhost", 1, xsb_trmodifyhost
);
548 registerhook(HOOK_SERVER_LINKED
, __serverlinked
);
549 syncsched
= schedulerecurring(time(NULL
)+5, 0, 60, checksynced
, NULL
);
551 if(trusts_fullyonline())
559 freesstring(smasterserver
);
561 deregistercontrolcmd("trustresync", trusts_cmdtrustresync
);
563 xsb_delcommand("trinit", xsb_trinit
);
564 xsb_delcommand("trdata", xsb_trdata
);
565 xsb_delcommand("trfini", xsb_trfini
);
566 xsb_delcommand("traddhost", xsb_traddhost
);
567 xsb_delcommand("traddgroup", xsb_traddgroup
);
568 xsb_delcommand("trdelhost", xsb_trdelhost
);
569 xsb_delcommand("trdelgroup", xsb_trdelgroup
);
570 xsb_delcommand("trmodifygroup", xsb_trmodifygroup
);
571 xsb_delcommand("trmodifyhost", xsb_trmodifyhost
);
573 deregisterhook(HOOK_SERVER_LINKED
, __serverlinked
);
575 deleteschedule(syncsched
, checksynced
, NULL
);