]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_db.c
Add TG name in the trust log.
[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 :( */
41 trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage 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
b76fd8e6 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
9bf9e8a1 83 if(result->fields != 5) {
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);
115 th.lastseen = (time_t)strtoul(result->get(result, 4), NULL, 10);
be2823bc 116
82a316e7 117 if(!th_add(&th))
5ada3782 118 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
be2823bc
CP
119 }
120
121 result->clear(result);
122
bf5b66e5 123 loadcomplete();
be2823bc
CP
124}
125
126static void loadhosts_fini(const DBAPIResult *result, void *tag) {
9bf9e8a1 127 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
be2823bc
CP
128}
129
130static void loadgroups_data(const DBAPIResult *result, void *tag) {
131 if(!result) {
132 loaderror = 1;
133 return;
134 }
135
136 if(!result->success) {
137 Error("trusts", ERR_ERROR, "Error loading group table.");
138 loaderror = 1;
139
140 result->clear(result);
141 return;
142 }
143
144 if(result->fields != 12) {
145 Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
146 loaderror = 1;
147
148 result->clear(result);
149 return;
150 }
151
152 while(result->next(result)) {
82a316e7
CP
153 trustgroup tg;
154
155 tg.id = strtoul(result->get(result, 0), NULL, 10);
156 if(tg.id > tgmaxid)
157 tgmaxid = tg.id;
158
159 tg.name = getsstring(rtrim(result->get(result, 1)), TRUSTNAMELEN);
160 tg.trustedfor = strtoul(result->get(result, 2), NULL, 10);
161 tg.mode = atoi(result->get(result, 3));
162 tg.maxperident = strtoul(result->get(result, 4), NULL, 10);
163 tg.maxusage = strtoul(result->get(result, 5), NULL, 10);
164 tg.expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
165 tg.lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
1f685425
CP
166 tg.lastmaxusereset = (time_t)strtoul(result->get(result, 8), NULL, 10);
167 tg.createdby = getsstring(rtrim(result->get(result, 9)), CREATEDBYLEN);
82a316e7
CP
168 tg.contact = getsstring(rtrim(result->get(result, 10)), CONTACTLEN);
169 tg.comment = getsstring(rtrim(result->get(result, 11)), COMMENTLEN);
170
171 if(tg.name && tg.createdby && tg.contact && tg.comment) {
172 if(!tg_add(&tg))
173 Error("trusts", ERR_WARNING, "Error adding trustgroup %d: %s", tg.id, tg.name->content);
5ada3782 174 } else {
82a316e7 175 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", tg.id);
5ada3782 176 }
be2823bc 177
82a316e7
CP
178 freesstring(tg.name);
179 freesstring(tg.createdby);
180 freesstring(tg.contact);
181 freesstring(tg.comment);
be2823bc
CP
182 }
183
184 result->clear(result);
185}
186
187static void loadgroups_fini(const DBAPIResult *result, void *tag) {
188 Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
2b6e02e2
CP
189}
190
82a316e7 191static int trusts_connectdb(void) {
bf5b66e5 192 if(!trustsdb) {
83bccee3
CP
193 trustsdb = dbapi2open(NULL, "trusts");
194 if(!trustsdb) {
195 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
196 return 0;
197 }
bf5b66e5
CP
198 }
199
35449aa5 200 createtrusttables(TABLES_REGULAR);
2b6e02e2 201
82a316e7
CP
202 return 1;
203}
204
205int trusts_loaddb(void) {
206 if(!trusts_connectdb())
207 return 0;
208
be2823bc 209 loaderror = 0;
2b6e02e2 210
be2823bc
CP
211 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
212 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
bf5b66e5
CP
213
214 return 1;
2b6e02e2
CP
215}
216
83bccee3 217void trusts_closedb(int closeconnection) {
2b6e02e2
CP
218 if(!trustsdb)
219 return;
220
83bccee3
CP
221 if(flushschedule) {
222 deleteschedule(flushschedule, flushdatabase, NULL);
223 flushschedule = NULL;
224
225 flushdatabase(NULL);
226 }
4be1aaf2 227
bf5b66e5 228 trusts_freeall();
83bccee3 229
bf5b66e5 230 trustsdbloaded = 0;
9bf9e8a1 231 thmaxid = tgmaxid = 0;
bf5b66e5 232
83bccee3
CP
233 if(closeconnection) {
234 trustsdb->close(trustsdb);
235 trustsdb = NULL;
236 }
237
238 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
2b6e02e2 239}
4be1aaf2 240
b9c52ee0 241static void th_dbupdatecounts(trusthost *th) {
1b5bf791 242 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
4be1aaf2
CP
243}
244
b9c52ee0 245static void tg_dbupdatecounts(trustgroup *tg) {
1b5bf791 246 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
4be1aaf2 247}
d2c08930 248
82a316e7 249trusthost *th_copy(trusthost *ith) {
9097ab05 250 trusthost *th, *superset, *subset;
9097ab05 251
82a316e7
CP
252 th = th_add(ith);
253 if(!th)
9097ab05
CP
254 return NULL;
255
82a316e7 256 trustsdb_insertth("hosts", th, th->group->id);
9097ab05 257
82a316e7
CP
258 th_getsuperandsubsets(ith->ip, ith->mask, &superset, &subset);
259 th_adjusthosts(th, subset, superset);
260 th_linktree();
261
262 return th;
263}
264
265trusthost *th_new(trustgroup *tg, char *host) {
266 trusthost *th, nth;
267
268 if(!trusts_str2cidr(host, &nth.ip, &nth.mask))
269 return NULL;
270
271 nth.group = tg;
272 nth.id = thmaxid + 1;
273 nth.lastseen = 0;
274 nth.maxusage = 0;
275
276 th = th_copy(&nth);
d2c08930
CP
277 if(!th)
278 return NULL;
279
280 thmaxid++;
281
82a316e7
CP
282 return th;
283}
d2c08930 284
82a316e7
CP
285trustgroup *tg_copy(trustgroup *itg) {
286 trustgroup *tg = tg_add(itg);
287 if(!tg)
288 return NULL;
d2c08930 289
82a316e7
CP
290 trustsdb_inserttg("groups", tg);
291 return tg;
d2c08930
CP
292}
293
82a316e7
CP
294trustgroup *tg_new(trustgroup *itg) {
295 trustgroup *tg;
296
297 itg->id = tgmaxid + 1;
298 itg->maxusage = 0;
299 itg->lastseen = 0;
1f685425 300 itg->lastmaxusereset = 0;
82a316e7
CP
301
302 tg = tg_copy(itg);
d2c08930
CP
303 if(!tg)
304 return NULL;
305
306 tgmaxid++;
307
82a316e7
CP
308 return tg;
309}
310
311void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) {
d2c08930 312 trustsdb->squery(trustsdb,
82a316e7
CP
313 "INSERT INTO ? (id, groupid, host, maxusage, lastseen) VALUES (?, ?, ?, ?, ?)",
314 "Tuusut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->lastseen
d2c08930 315 );
82a316e7 316}
d2c08930 317
82a316e7
CP
318void trustsdb_inserttg(char *table, trustgroup *tg) {
319 trustsdb->squery(trustsdb,
1f685425
CP
320 "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxusereset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
321 "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 322 );
d2c08930 323}
b9c52ee0 324
2ab0a1e7
CP
325void tg_update(trustgroup *tg) {
326 trustsdb->squery(trustsdb,
1f685425
CP
327 "UPDATE ? SET name = ?, trustedfor = ?, maxperident = ?, maxusage = ?, expires = ?, lastseen = ?, lastmaxusereset = ?, createdby = ?, contact = ?, comment = ? WHERE id = ?",
328 "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
329 );
330}
331
06deaa30
GB
332void trustsdb_deletetg(char *table, trustgroup *tg) {
333 trustsdb->squery(trustsdb,
334 "DELETE FROM ? WHERE id = ?",
335 "Tu", "groups", tg->id);
336}
337
2ab0a1e7 338void tg_delete(trustgroup *tg) {
06deaa30
GB
339 trustgroup **pnext;
340
341 for(pnext=&tglist;*pnext;pnext=&((*pnext)->next)) {
342 if(*pnext == tg) {
343 *pnext = tg->next;
344 break;
345 }
346 }
347
348 trustsdb_deletetg("groups", tg);
349 tg_free(tg, 1);
350}
351
352void trustsdb_deleteth(char *table, trusthost *th) {
353 trustsdb->squery(trustsdb,
354 "DELETE FROM ? WHERE id = ?",
355 "Tu", "hosts", th->id);
2ab0a1e7
CP
356}
357
358void th_delete(trusthost *th) {
06deaa30
GB
359 trusthost **pnext;
360 nick *np;
361
362 for(pnext=&(th->group->hosts);*pnext;pnext=&((*pnext)->next)) {
363 if(*pnext == th) {
364 *pnext = th->next;
365 break;
366 }
367 }
368
369 for(np=th->users;np;np=nextbytrust(np))
370 settrusthost(np, NULL);
371
372 th->group->count -= th->count;
373
374 trustsdb_deleteth("hosts", th);
375 th_free(th);
376
377 th_linktree();
2ab0a1e7
CP
378}
379
1467e9a4 380void trustlog(trustgroup *tg, const char *user, const char *format, ...) {
01bd21d3
GB
381 char buf[TRUSTLOGLEN+1];
382 va_list va;
383 unsigned int now;
384
385 va_start(va, format);
386 vsnprintf(buf, sizeof(buf), format, va);
387 va_end(va);
388
389 now = time(NULL);
390
391 trustsdb->squery(trustsdb,
1467e9a4
GB
392 "INSERT INTO ? (ts, groupid, groupname, username, message) VALUES (?, ?, ?, ?, ?)",
393 "Tuusss", "log", now, tg->id, tg->name->content, user, buf);
01bd21d3
GB
394}
395
396static void trustlogquery_callback(const struct DBAPIResult *result, void *arg) {
397 nick *np = (nick *)arg;
398 int rows = 0;
399
400 if(!result || !result->success) {
401 controlreply(np, "Error querying the log.");
402
403 if(result)
404 result->clear(result);
405
406 return;
407 }
408
409 while(result->next(result)) {
410 unsigned int ts, groupid;
1467e9a4 411 char *groupname, *user, *message;
01bd21d3
GB
412
413 ts = strtoul(result->get(result, 0), NULL, 10);
414 groupid = strtoul(result->get(result, 1), NULL, 10);
1467e9a4
GB
415 groupname = result->get(result, 2);
416 user = result->get(result, 3);
417 message = result->get(result, 4);
01bd21d3 418
1467e9a4 419 controlreply(np, "[%s] #%d/%s (%s) %s", trusts_timetostr(ts), groupid, groupname, user, message);
01bd21d3
GB
420 rows++;
421 }
422
1467e9a4 423 controlreply(np, "--- Done. Found %d entries.", rows);
01bd21d3
GB
424}
425
1467e9a4 426void trustlogspewid(nick *np, unsigned int groupid, unsigned int limit) {
01bd21d3 427 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
1467e9a4 428 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupid = ? ORDER BY ts DESC LIMIT ?",
01bd21d3
GB
429 "Tuu", "log", groupid, limit);
430}
431
1467e9a4
GB
432void trustlogspewname(nick *np, const char *groupname, unsigned int limit) {
433 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
434 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupname = ? ORDER BY ts DESC LIMIT ?",
435 "Tsu", "log", groupname, limit);
436}
437
01bd21d3
GB
438void trustloggrep(nick *np, const char *pattern, unsigned int limit) {
439 char buf[512];
440 snprintf(buf, sizeof(buf), "%%%s%%", pattern);
441
442 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
443 "SELECT ts, groupid, username, message FROM ? WHERE message LIKE ? ORDER BY ts DESC LIMIT ?",
444 "Tsu", "log", buf, limit);
445}
446
b9c52ee0 447void _init(void) {
82a316e7 448 trusts_connectdb();
b9c52ee0
CP
449}
450
451void _fini(void) {
452 trusts_closedb(1);
453}