]> jfr.im git - irc/quakenet/newserv.git/blame_incremental - trusts/trusts_db.c
Fix incorrect parameters for th_adjusthosts().
[irc/quakenet/newserv.git] / trusts / trusts_db.c
... / ...
CommitLineData
1#include <stdio.h>
2#include <stdarg.h>
3#include "../dbapi2/dbapi2.h"
4#include "../core/error.h"
5#include "../core/hooks.h"
6#include "../core/schedule.h"
7#include "../control/control.h"
8#include "trusts.h"
9
10DBAPIConn *trustsdb;
11static int tgmaxid, thmaxid;
12static int loaderror;
13static void *flushschedule;
14
15void createtrusttables(int migration);
16void trusts_flush(void (*)(trusthost *), void (*)(trustgroup *));
17void trusts_freeall(void);
18static void th_dbupdatecounts(trusthost *th);
19static void tg_dbupdatecounts(trustgroup *tg);
20
21void createtrusttables(int mode) {
22 char *groups, *hosts;
23
24 if(mode == TABLES_MIGRATION) {
25 groups = "migration_groups";
26 hosts = "migration_hosts";
27 } else if(mode == TABLES_REPLICATION) {
28 groups = "replication_groups";
29 hosts = "replication_hosts";
30 } else {
31 groups = "groups";
32 hosts = "hosts";
33 }
34
35 trustsdb->createtable(trustsdb, NULL, NULL,
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
38 );
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, created INT, lastseen INT)", "Td", hosts, TRUSTHOSTLEN);
42
43 trustsdb->createtable(trustsdb, NULL, NULL,
44 "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, groupname VARCHAR(?), ts INT, username VARCHAR(?), message VARCHAR(?))",
45 "Tddd", "log", TRUSTNAMELEN, CREATEDBYLEN, TRUSTLOGLEN
46 );
47}
48
49static void flushdatabase(void *arg) {
50 trusts_flush(th_dbupdatecounts, tg_dbupdatecounts);
51}
52
53static void triggerdbloaded(void *arg) {
54 triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
55}
56
57static void loadcomplete(void) {
58 /* error has already been shown */
59 if(loaderror)
60 return;
61
62 th_linktree();
63 trustsdbloaded = 1;
64 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
65
66 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
67}
68
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
83 if(result->fields != 6) {
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)) {
92 unsigned int groupid;
93 trusthost th;
94 char *host;
95
96 th.id = strtoul(result->get(result, 0), NULL, 10);
97 if(th.id > thmaxid)
98 thmaxid = th.id;
99
100 groupid = strtoul(result->get(result, 1), NULL, 10);
101
102 th.group = tg_getbyid(groupid);
103 if(!th.group) {
104 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
105 continue;
106 }
107
108 host = result->get(result, 2);
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.created = (time_t)strtoul(result->get(result, 4), NULL, 10);
116 th.lastseen = (time_t)strtoul(result->get(result, 5), NULL, 10);
117
118 if(!th_add(&th))
119 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
120 }
121
122 result->clear(result);
123
124 loadcomplete();
125}
126
127static void loadhosts_fini(const DBAPIResult *result, void *tag) {
128 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
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)) {
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);
167 tg.lastmaxusereset = (time_t)strtoul(result->get(result, 8), NULL, 10);
168 tg.createdby = getsstring(rtrim(result->get(result, 9)), CREATEDBYLEN);
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);
175 } else {
176 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", tg.id);
177 }
178
179 freesstring(tg.name);
180 freesstring(tg.createdby);
181 freesstring(tg.contact);
182 freesstring(tg.comment);
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);
190}
191
192static int trusts_connectdb(void) {
193 if(!trustsdb) {
194 trustsdb = dbapi2open(NULL, "trusts");
195 if(!trustsdb) {
196 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
197 return 0;
198 }
199 }
200
201 createtrusttables(TABLES_REGULAR);
202
203 return 1;
204}
205
206int trusts_loaddb(void) {
207 if(!trusts_connectdb())
208 return 0;
209
210 loaderror = 0;
211
212 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
213 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
214
215 return 1;
216}
217
218void trusts_closedb(int closeconnection) {
219 if(!trustsdb)
220 return;
221
222 if(flushschedule) {
223 deleteschedule(flushschedule, flushdatabase, NULL);
224 flushschedule = NULL;
225
226 flushdatabase(NULL);
227 }
228
229 trusts_freeall();
230
231 trustsdbloaded = 0;
232 thmaxid = tgmaxid = 0;
233
234 if(closeconnection) {
235 trustsdb->close(trustsdb);
236 trustsdb = NULL;
237 }
238
239 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
240}
241
242static void th_dbupdatecounts(trusthost *th) {
243 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
244}
245
246static void tg_dbupdatecounts(trustgroup *tg) {
247 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
248}
249
250trusthost *th_copy(trusthost *ith) {
251 trusthost *th, *superset, *subset;
252
253 th = th_add(ith);
254 if(!th)
255 return NULL;
256
257 trustsdb_insertth("hosts", th, th->group->id);
258
259 th_getsuperandsubsets(ith->ip, ith->mask, &superset, &subset);
260 th_adjusthosts(th, superset, subset);
261 th_linktree();
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;
274 nth.created = time(NULL);
275 nth.lastseen = 0;
276 nth.maxusage = 0;
277
278 th = th_copy(&nth);
279 if(!th)
280 return NULL;
281
282 thmaxid++;
283
284 return th;
285}
286
287trustgroup *tg_copy(trustgroup *itg) {
288 trustgroup *tg = tg_add(itg);
289 if(!tg)
290 return NULL;
291
292 trustsdb_inserttg("groups", tg);
293 return tg;
294}
295
296trustgroup *tg_new(trustgroup *itg) {
297 trustgroup *tg;
298
299 itg->id = tgmaxid + 1;
300 itg->maxusage = 0;
301 itg->lastseen = 0;
302 itg->lastmaxusereset = 0;
303
304 tg = tg_copy(itg);
305 if(!tg)
306 return NULL;
307
308 tgmaxid++;
309
310 return tg;
311}
312
313void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) {
314 trustsdb->squery(trustsdb,
315 "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen) VALUES (?, ?, ?, ?, ?, ?)",
316 "Tuusuut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->created, th->lastseen
317 );
318}
319
320void trustsdb_inserttg(char *table, trustgroup *tg) {
321 trustsdb->squery(trustsdb,
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
324 );
325}
326
327void tg_update(trustgroup *tg) {
328 trustsdb->squery(trustsdb,
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
331 );
332}
333
334void trustsdb_deletetg(char *table, trustgroup *tg) {
335 trustsdb->squery(trustsdb,
336 "DELETE FROM ? WHERE id = ?",
337 "Tu", "groups", tg->id);
338}
339
340void tg_delete(trustgroup *tg) {
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);
358}
359
360void th_delete(trusthost *th) {
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);
378
379 th_linktree();
380}
381
382void trustlog(trustgroup *tg, const char *user, const char *format, ...) {
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,
394 "INSERT INTO ? (ts, groupid, groupname, username, message) VALUES (?, ?, ?, ?, ?)",
395 "Tuusss", "log", now, tg->id, tg->name->content, user, buf);
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
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
418 while(result->next(result)) {
419 unsigned int ts, groupid;
420 char *groupname, *user, *message;
421
422 ts = strtoul(result->get(result, 0), NULL, 10);
423 groupid = strtoul(result->get(result, 1), NULL, 10);
424 groupname = result->get(result, 2);
425 user = result->get(result, 3);
426 message = result->get(result, 4);
427
428 controlreply(np, "[%s] #%d/%s (%s) %s", trusts_timetostr(ts), groupid, groupname, user, message);
429 rows++;
430 }
431
432 result->clear(result);
433
434 controlreply(np, "--- Done. Found %d entries.", rows);
435}
436
437void trustlogspewid(nick *np, unsigned int groupid, unsigned int limit) {
438 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
439 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupid = ? ORDER BY ts DESC LIMIT ?",
440 "Tuu", "log", groupid, limit);
441}
442
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
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,
454 "SELECT ts, groupid, groupname, username, message FROM ? WHERE message LIKE ? ORDER BY ts DESC LIMIT ?",
455 "Tsu", "log", buf, limit);
456}
457
458void _init(void) {
459 trusts_connectdb();
460}
461
462void _fini(void) {
463 trusts_closedb(1);
464}