]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_db.c
Treat 6to4 clients as if they're connecting via IPv4.
[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
bf5b66e5 62 trustsdbloaded = 1;
4be1aaf2
CP
63 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
64
7938a2c3 65 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
be2823bc
CP
66}
67
be2823bc
CP
68static void loadhosts_data(const DBAPIResult *result, void *tag) {
69 if(!result) {
70 loaderror = 1;
71 return;
72 }
73
74 if(!result->success) {
75 Error("trusts", ERR_ERROR, "Error loading hosts table.");
76 loaderror = 1;
77
78 result->clear(result);
79 return;
80 }
81
caf2d02a 82 if(result->fields != 6) {
be2823bc
CP
83 Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
84 loaderror = 1;
85
86 result->clear(result);
87 return;
88 }
89
90 while(result->next(result)) {
82a316e7
CP
91 unsigned int groupid;
92 trusthost th;
5ada3782 93 char *host;
be2823bc 94
82a316e7
CP
95 th.id = strtoul(result->get(result, 0), NULL, 10);
96 if(th.id > thmaxid)
97 thmaxid = th.id;
9bf9e8a1
CP
98
99 groupid = strtoul(result->get(result, 1), NULL, 10);
be2823bc 100
82a316e7
CP
101 th.group = tg_getbyid(groupid);
102 if(!th.group) {
be2823bc
CP
103 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
104 continue;
105 }
106
9bf9e8a1 107 host = result->get(result, 2);
82a316e7
CP
108 if(!trusts_str2cidr(host, &th.ip, &th.mask)) {
109 Error("trusts", ERR_WARNING, "Error parsing cidr for host: %s", host);
110 continue;
111 }
112
113 th.maxusage = strtoul(result->get(result, 3), NULL, 10);
caf2d02a
GB
114 th.created = (time_t)strtoul(result->get(result, 4), NULL, 10);
115 th.lastseen = (time_t)strtoul(result->get(result, 5), 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);
82a316e7
CP
260
261 return th;
262}
263
264trusthost *th_new(trustgroup *tg, char *host) {
265 trusthost *th, nth;
266
267 if(!trusts_str2cidr(host, &nth.ip, &nth.mask))
268 return NULL;
269
270 nth.group = tg;
271 nth.id = thmaxid + 1;
caf2d02a 272 nth.created = time(NULL);
82a316e7
CP
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,
644c6986 313 "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen) VALUES (?, ?, ?, ?, ?, ?)",
cbfc4d2f 314 "Tuusuut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->created, 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);
2ab0a1e7
CP
376}
377
1467e9a4 378void trustlog(trustgroup *tg, const char *user, const char *format, ...) {
01bd21d3
GB
379 char buf[TRUSTLOGLEN+1];
380 va_list va;
381 unsigned int now;
382
383 va_start(va, format);
384 vsnprintf(buf, sizeof(buf), format, va);
385 va_end(va);
386
387 now = time(NULL);
388
389 trustsdb->squery(trustsdb,
1467e9a4
GB
390 "INSERT INTO ? (ts, groupid, groupname, username, message) VALUES (?, ?, ?, ?, ?)",
391 "Tuusss", "log", now, tg->id, tg->name->content, user, buf);
01bd21d3
GB
392}
393
394static void trustlogquery_callback(const struct DBAPIResult *result, void *arg) {
395 nick *np = (nick *)arg;
396 int rows = 0;
397
398 if(!result || !result->success) {
399 controlreply(np, "Error querying the log.");
400
401 if(result)
402 result->clear(result);
403
404 return;
405 }
406
7db61652
GB
407 if(result->fields != 5) {
408 Error("trusts", ERR_ERROR, "Wrong number of fields in log table.");
409
410 result->clear(result);
411 return;
412 }
413
01bd21d3
GB
414 while(result->next(result)) {
415 unsigned int ts, groupid;
1467e9a4 416 char *groupname, *user, *message;
01bd21d3
GB
417
418 ts = strtoul(result->get(result, 0), NULL, 10);
419 groupid = strtoul(result->get(result, 1), NULL, 10);
1467e9a4
GB
420 groupname = result->get(result, 2);
421 user = result->get(result, 3);
422 message = result->get(result, 4);
01bd21d3 423
1467e9a4 424 controlreply(np, "[%s] #%d/%s (%s) %s", trusts_timetostr(ts), groupid, groupname, user, message);
01bd21d3
GB
425 rows++;
426 }
427
7db61652
GB
428 result->clear(result);
429
1467e9a4 430 controlreply(np, "--- Done. Found %d entries.", rows);
01bd21d3
GB
431}
432
1467e9a4 433void trustlogspewid(nick *np, unsigned int groupid, unsigned int limit) {
01bd21d3 434 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
1467e9a4 435 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupid = ? ORDER BY ts DESC LIMIT ?",
01bd21d3
GB
436 "Tuu", "log", groupid, limit);
437}
438
1467e9a4
GB
439void trustlogspewname(nick *np, const char *groupname, unsigned int limit) {
440 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
441 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupname = ? ORDER BY ts DESC LIMIT ?",
442 "Tsu", "log", groupname, limit);
443}
444
01bd21d3
GB
445void trustloggrep(nick *np, const char *pattern, unsigned int limit) {
446 char buf[512];
447 snprintf(buf, sizeof(buf), "%%%s%%", pattern);
448
449 trustsdb->query(trustsdb, trustlogquery_callback, (void *)np,
7db61652 450 "SELECT ts, groupid, groupname, username, message FROM ? WHERE message LIKE ? ORDER BY ts DESC LIMIT ?",
01bd21d3
GB
451 "Tsu", "log", buf, limit);
452}
453
b9c52ee0 454void _init(void) {
82a316e7 455 trusts_connectdb();
b9c52ee0
CP
456}
457
458void _fini(void) {
459 trusts_closedb(1);
460}