]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_db.c
Fix incorrect parameters for th_adjusthosts().
[irc/quakenet/newserv.git] / trusts / trusts_db.c
CommitLineData
01bd21d3
GB
1#include <stdio.h>
2#include <stdarg.h>
2b6e02e2
CP
3#include "../dbapi2/dbapi2.h"
4#include "../core/error.h"
be2823bc 5#include "../core/hooks.h"
4be1aaf2 6#include "../core/schedule.h"
01bd21d3 7#include "../control/control.h"
2b6e02e2
CP
8#include "trusts.h"
9
10DBAPIConn *trustsdb;
9bf9e8a1 11static int tgmaxid, thmaxid;
be2823bc 12static int loaderror;
4be1aaf2
CP
13static void *flushschedule;
14
be2823bc 15void createtrusttables(int migration);
b9c52ee0 16void trusts_flush(void (*)(trusthost *), void (*)(trustgroup *));
83bccee3 17void trusts_freeall(void);
b9c52ee0
CP
18static void th_dbupdatecounts(trusthost *th);
19static void tg_dbupdatecounts(trustgroup *tg);
2b6e02e2 20
35449aa5 21void createtrusttables(int mode) {
be2823bc
CP
22 char *groups, *hosts;
23
35449aa5 24 if(mode == TABLES_MIGRATION) {
be2823bc
CP
25 groups = "migration_groups";
26 hosts = "migration_hosts";
35449aa5
CP
27 } else if(mode == TABLES_REPLICATION) {
28 groups = "replication_groups";
29 hosts = "replication_hosts";
be2823bc
CP
30 } else {
31 groups = "groups";
32 hosts = "hosts";
33 }
34
35 trustsdb->createtable(trustsdb, NULL, NULL,
1f685425
CP
36 "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(?), trustedfor INT, mode INT, maxperident INT, maxusage INT, expires INT, lastseen INT, lastmaxusereset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
37 "Tdddd", groups, TRUSTNAMELEN, CREATEDBYLEN, CONTACTLEN, COMMENTLEN
be2823bc 38 );
9bf9e8a1
CP
39
40 /* I'd like multiple keys here but that's not gonna happen on a cross-database platform :( */
caf2d02a 41 trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, created INT, lastseen INT)", "Td", hosts, TRUSTHOSTLEN);
01bd21d3
GB
42
43 trustsdb->createtable(trustsdb, NULL, NULL,
1467e9a4
GB
44 "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, groupname VARCHAR(?), ts INT, username VARCHAR(?), message VARCHAR(?))",
45 "Tddd", "log", TRUSTNAMELEN, CREATEDBYLEN, TRUSTLOGLEN
01bd21d3 46 );
4be1aaf2
CP
47}
48
49static void flushdatabase(void *arg) {
b9c52ee0 50 trusts_flush(th_dbupdatecounts, tg_dbupdatecounts);
be2823bc
CP
51}
52
7938a2c3
CP
53static void triggerdbloaded(void *arg) {
54 triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
55}
56
4be1aaf2 57static void loadcomplete(void) {
bf5b66e5
CP
58 /* error has already been shown */
59 if(loaderror)
60 return;
2b6e02e2 61
34e3de85 62 th_linktree();
bf5b66e5 63 trustsdbloaded = 1;
4be1aaf2
CP
64 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
65
7938a2c3 66 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
be2823bc
CP
67}
68
be2823bc
CP
69static void loadhosts_data(const DBAPIResult *result, void *tag) {
70 if(!result) {
71 loaderror = 1;
72 return;
73 }
74
75 if(!result->success) {
76 Error("trusts", ERR_ERROR, "Error loading hosts table.");
77 loaderror = 1;
78
79 result->clear(result);
80 return;
81 }
82
caf2d02a 83 if(result->fields != 6) {
be2823bc
CP
84 Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
85 loaderror = 1;
86
87 result->clear(result);
88 return;
89 }
90
91 while(result->next(result)) {
82a316e7
CP
92 unsigned int groupid;
93 trusthost th;
5ada3782 94 char *host;
be2823bc 95
82a316e7
CP
96 th.id = strtoul(result->get(result, 0), NULL, 10);
97 if(th.id > thmaxid)
98 thmaxid = th.id;
9bf9e8a1
CP
99
100 groupid = strtoul(result->get(result, 1), NULL, 10);
be2823bc 101
82a316e7
CP
102 th.group = tg_getbyid(groupid);
103 if(!th.group) {
be2823bc
CP
104 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
105 continue;
106 }
107
9bf9e8a1 108 host = result->get(result, 2);
82a316e7
CP
109 if(!trusts_str2cidr(host, &th.ip, &th.mask)) {
110 Error("trusts", ERR_WARNING, "Error parsing cidr for host: %s", host);
111 continue;
112 }
113
114 th.maxusage = strtoul(result->get(result, 3), NULL, 10);
caf2d02a
GB
115 th.created = (time_t)strtoul(result->get(result, 4), NULL, 10);
116 th.lastseen = (time_t)strtoul(result->get(result, 5), NULL, 10);
be2823bc 117
82a316e7 118 if(!th_add(&th))
5ada3782 119 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
be2823bc
CP
120 }
121
122 result->clear(result);
123
bf5b66e5 124 loadcomplete();
be2823bc
CP
125}
126
127static void loadhosts_fini(const DBAPIResult *result, void *tag) {
9bf9e8a1 128 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
be2823bc
CP
129}
130
131static void loadgroups_data(const DBAPIResult *result, void *tag) {
132 if(!result) {
133 loaderror = 1;
134 return;
135 }
136
137 if(!result->success) {
138 Error("trusts", ERR_ERROR, "Error loading group table.");
139 loaderror = 1;
140
141 result->clear(result);
142 return;
143 }
144
145 if(result->fields != 12) {
146 Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
147 loaderror = 1;
148
149 result->clear(result);
150 return;
151 }
152
153 while(result->next(result)) {
82a316e7
CP
154 trustgroup tg;
155
156 tg.id = strtoul(result->get(result, 0), NULL, 10);
157 if(tg.id > tgmaxid)
158 tgmaxid = tg.id;
159
160 tg.name = getsstring(rtrim(result->get(result, 1)), TRUSTNAMELEN);
161 tg.trustedfor = strtoul(result->get(result, 2), NULL, 10);
162 tg.mode = atoi(result->get(result, 3));
163 tg.maxperident = strtoul(result->get(result, 4), NULL, 10);
164 tg.maxusage = strtoul(result->get(result, 5), NULL, 10);
165 tg.expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
166 tg.lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
1f685425
CP
167 tg.lastmaxusereset = (time_t)strtoul(result->get(result, 8), NULL, 10);
168 tg.createdby = getsstring(rtrim(result->get(result, 9)), CREATEDBYLEN);
82a316e7
CP
169 tg.contact = getsstring(rtrim(result->get(result, 10)), CONTACTLEN);
170 tg.comment = getsstring(rtrim(result->get(result, 11)), COMMENTLEN);
171
172 if(tg.name && tg.createdby && tg.contact && tg.comment) {
173 if(!tg_add(&tg))
174 Error("trusts", ERR_WARNING, "Error adding trustgroup %d: %s", tg.id, tg.name->content);
5ada3782 175 } else {
82a316e7 176 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", tg.id);
5ada3782 177 }
be2823bc 178
82a316e7
CP
179 freesstring(tg.name);
180 freesstring(tg.createdby);
181 freesstring(tg.contact);
182 freesstring(tg.comment);
be2823bc
CP
183 }
184
185 result->clear(result);
186}
187
188static void loadgroups_fini(const DBAPIResult *result, void *tag) {
189 Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
2b6e02e2
CP
190}
191
82a316e7 192static int trusts_connectdb(void) {
bf5b66e5 193 if(!trustsdb) {
83bccee3
CP
194 trustsdb = dbapi2open(NULL, "trusts");
195 if(!trustsdb) {
196 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
197 return 0;
198 }
bf5b66e5
CP
199 }
200
35449aa5 201 createtrusttables(TABLES_REGULAR);
2b6e02e2 202
82a316e7
CP
203 return 1;
204}
205
206int trusts_loaddb(void) {
207 if(!trusts_connectdb())
208 return 0;
209
be2823bc 210 loaderror = 0;
2b6e02e2 211
be2823bc
CP
212 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
213 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
bf5b66e5
CP
214
215 return 1;
2b6e02e2
CP
216}
217
83bccee3 218void trusts_closedb(int closeconnection) {
2b6e02e2
CP
219 if(!trustsdb)
220 return;
221
83bccee3
CP
222 if(flushschedule) {
223 deleteschedule(flushschedule, flushdatabase, NULL);
224 flushschedule = NULL;
225
226 flushdatabase(NULL);
227 }
4be1aaf2 228
bf5b66e5 229 trusts_freeall();
83bccee3 230
bf5b66e5 231 trustsdbloaded = 0;
9bf9e8a1 232 thmaxid = tgmaxid = 0;
bf5b66e5 233
83bccee3
CP
234 if(closeconnection) {
235 trustsdb->close(trustsdb);
236 trustsdb = NULL;
237 }
238
239 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
2b6e02e2 240}
4be1aaf2 241
b9c52ee0 242static void th_dbupdatecounts(trusthost *th) {
1b5bf791 243 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
4be1aaf2
CP
244}
245
b9c52ee0 246static void tg_dbupdatecounts(trustgroup *tg) {
1b5bf791 247 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
4be1aaf2 248}
d2c08930 249
82a316e7 250trusthost *th_copy(trusthost *ith) {
9097ab05 251 trusthost *th, *superset, *subset;
9097ab05 252
82a316e7
CP
253 th = th_add(ith);
254 if(!th)
9097ab05
CP
255 return NULL;
256
82a316e7 257 trustsdb_insertth("hosts", th, th->group->id);
9097ab05 258
82a316e7 259 th_getsuperandsubsets(ith->ip, ith->mask, &superset, &subset);
84dd9aa5 260 th_adjusthosts(th, superset, subset);
34e3de85 261 th_linktree();
82a316e7
CP
262
263 return th;
264}
265
266trusthost *th_new(trustgroup *tg, char *host) {
267 trusthost *th, nth;
268
269 if(!trusts_str2cidr(host, &nth.ip, &nth.mask))
270 return NULL;
271
272 nth.group = tg;
273 nth.id = thmaxid + 1;
caf2d02a 274 nth.created = time(NULL);
82a316e7
CP
275 nth.lastseen = 0;
276 nth.maxusage = 0;
277
278 th = th_copy(&nth);
d2c08930
CP
279 if(!th)
280 return NULL;
281
282 thmaxid++;
283
82a316e7
CP
284 return th;
285}
d2c08930 286
82a316e7
CP
287trustgroup *tg_copy(trustgroup *itg) {
288 trustgroup *tg = tg_add(itg);
289 if(!tg)
290 return NULL;
d2c08930 291
82a316e7
CP
292 trustsdb_inserttg("groups", tg);
293 return tg;
d2c08930
CP
294}
295
82a316e7
CP
296trustgroup *tg_new(trustgroup *itg) {
297 trustgroup *tg;
298
299 itg->id = tgmaxid + 1;
300 itg->maxusage = 0;
301 itg->lastseen = 0;
1f685425 302 itg->lastmaxusereset = 0;
82a316e7
CP
303
304 tg = tg_copy(itg);
d2c08930
CP
305 if(!tg)
306 return NULL;
307
308 tgmaxid++;
309
82a316e7
CP
310 return tg;
311}
312
313void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) {
d2c08930 314 trustsdb->squery(trustsdb,
644c6986 315 "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen) VALUES (?, ?, ?, ?, ?, ?)",
cbfc4d2f 316 "Tuusuut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->created, th->lastseen
d2c08930 317 );
82a316e7 318}
d2c08930 319
82a316e7
CP
320void trustsdb_inserttg(char *table, trustgroup *tg) {
321 trustsdb->squery(trustsdb,
1f685425
CP
322 "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxusereset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
323 "Tusuuuutttsss", table, tg->id, tg->name->content, tg->trustedfor, tg->mode, tg->maxperident, tg->maxusage, tg->expires, tg->lastseen, tg->lastmaxusereset, tg->createdby->content, tg->contact->content, tg->comment->content
82a316e7 324 );
d2c08930 325}
b9c52ee0 326
2ab0a1e7
CP
327void tg_update(trustgroup *tg) {
328 trustsdb->squery(trustsdb,
1f685425
CP
329 "UPDATE ? SET name = ?, trustedfor = ?, maxperident = ?, maxusage = ?, expires = ?, lastseen = ?, lastmaxusereset = ?, createdby = ?, contact = ?, comment = ? WHERE id = ?",
330 "Tsuuuutttsssu", "groups", tg->name->content, tg->trustedfor, tg->mode, tg->maxperident, tg->maxusage, tg->expires, tg->lastseen, tg->lastmaxusereset, tg->createdby->content, tg->contact->content, tg->comment->content, tg->id
2ab0a1e7
CP
331 );
332}
333
06deaa30
GB
334void trustsdb_deletetg(char *table, trustgroup *tg) {
335 trustsdb->squery(trustsdb,
336 "DELETE FROM ? WHERE id = ?",
337 "Tu", "groups", tg->id);
338}
339
2ab0a1e7 340void tg_delete(trustgroup *tg) {
06deaa30
GB
341 trustgroup **pnext;
342
343 for(pnext=&tglist;*pnext;pnext=&((*pnext)->next)) {
344 if(*pnext == tg) {
345 *pnext = tg->next;
346 break;
347 }
348 }
349
350 trustsdb_deletetg("groups", tg);
351 tg_free(tg, 1);
352}
353
354void trustsdb_deleteth(char *table, trusthost *th) {
355 trustsdb->squery(trustsdb,
356 "DELETE FROM ? WHERE id = ?",
357 "Tu", "hosts", th->id);
2ab0a1e7
CP
358}
359
360void th_delete(trusthost *th) {
06deaa30
GB
361 trusthost **pnext;
362 nick *np;
363
364 for(pnext=&(th->group->hosts);*pnext;pnext=&((*pnext)->next)) {
365 if(*pnext == th) {
366 *pnext = th->next;
367 break;
368 }
369 }
370
371 for(np=th->users;np;np=nextbytrust(np))
372 settrusthost(np, NULL);
373
374 th->group->count -= th->count;
375
376 trustsdb_deleteth("hosts", th);
377 th_free(th);
34e3de85
GB
378
379 th_linktree();
2ab0a1e7
CP
380}
381
1467e9a4 382void trustlog(trustgroup *tg, const char *user, const char *format, ...) {
01bd21d3
GB
383 char buf[TRUSTLOGLEN+1];
384 va_list va;
385 unsigned int now;
386
387 va_start(va, format);
388 vsnprintf(buf, sizeof(buf), format, va);
389 va_end(va);
390
391 now = time(NULL);
392
393 trustsdb->squery(trustsdb,
1467e9a4
GB
394 "INSERT INTO ? (ts, groupid, groupname, username, message) VALUES (?, ?, ?, ?, ?)",
395 "Tuusss", "log", now, tg->id, tg->name->content, user, buf);
01bd21d3
GB
396}
397
398static void trustlogquery_callback(const struct DBAPIResult *result, void *arg) {
399 nick *np = (nick *)arg;
400 int rows = 0;
401
402 if(!result || !result->success) {
403 controlreply(np, "Error querying the log.");
404
405 if(result)
406 result->clear(result);
407
408 return;
409 }
410
7db61652
GB
411 if(result->fields != 5) {
412 Error("trusts", ERR_ERROR, "Wrong number of fields in log table.");
413
414 result->clear(result);
415 return;
416 }
417
01bd21d3
GB
418 while(result->next(result)) {
419 unsigned int ts, groupid;
1467e9a4 420 char *groupname, *user, *message;
01bd21d3
GB
421
422 ts = strtoul(result->get(result, 0), NULL, 10);
423 groupid = strtoul(result->get(result, 1), NULL, 10);
1467e9a4
GB
424 groupname = result->get(result, 2);
425 user = result->get(result, 3);
426 message = result->get(result, 4);
01bd21d3 427
1467e9a4 428 controlreply(np, "[%s] #%d/%s (%s) %s", trusts_timetostr(ts), groupid, groupname, user, message);
01bd21d3
GB
429 rows++;
430 }
431
7db61652
GB
432 result->clear(result);
433
1467e9a4 434 controlreply(np, "--- Done. Found %d entries.", rows);
01bd21d3
GB
435}
436
1467e9a4 437void trustlogspewid(nick *np, unsigned int groupid, unsigned int limit) {
01bd21d3 438 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
1467e9a4 439 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupid = ? ORDER BY ts DESC LIMIT ?",
01bd21d3
GB
440 "Tuu", "log", groupid, limit);
441}
442
1467e9a4
GB
443void trustlogspewname(nick *np, const char *groupname, unsigned int limit) {
444 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
445 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupname = ? ORDER BY ts DESC LIMIT ?",
446 "Tsu", "log", groupname, limit);
447}
448
01bd21d3
GB
449void trustloggrep(nick *np, const char *pattern, unsigned int limit) {
450 char buf[512];
451 snprintf(buf, sizeof(buf), "%%%s%%", pattern);
452
453 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
7db61652 454 "SELECT ts, groupid, groupname, username, message FROM ? WHERE message LIKE ? ORDER BY ts DESC LIMIT ?",
01bd21d3
GB
455 "Tsu", "log", buf, limit);
456}
457
b9c52ee0 458void _init(void) {
82a316e7 459 trusts_connectdb();
b9c52ee0
CP
460}
461
462void _fini(void) {
463 trusts_closedb(1);
464}