]>
jfr.im git - irc/quakenet/newserv.git/blob - trusts/trusts_db.c
3 #include "../lib/version.h"
4 #include "../dbapi2/dbapi2.h"
5 #include "../core/error.h"
6 #include "../core/hooks.h"
7 #include "../core/schedule.h"
8 #include "../control/control.h"
9 #include "../irc/irc.h"
15 static int tgmaxid
, thmaxid
;
17 static void *flushschedule
;
19 void createtrusttables(int migration
);
20 void trusts_flush(void (*)(trusthost
*), void (*)(trustgroup
*));
21 void trusts_freeall(void);
22 static void th_dbupdatecounts(trusthost
*th
);
23 static void tg_dbupdatecounts(trustgroup
*tg
);
25 void createtrusttables(int mode
) {
28 if(mode
== TABLES_MIGRATION
) {
29 groups
= "migration_groups";
30 hosts
= "migration_hosts";
31 } else if(mode
== TABLES_REPLICATION
) {
32 groups
= "replication_groups";
33 hosts
= "replication_hosts";
39 trustsdb
->createtable(trustsdb
, NULL
, NULL
,
40 "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(?), trustedfor INT, flags INT, maxperident INT, maxusage INT, expires INT, lastseen INT, lastmaxusereset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
41 "Tdddd", groups
, TRUSTNAMELEN
, CREATEDBYLEN
, CONTACTLEN
, COMMENTLEN
44 /* I'd like multiple keys here but that's not gonna happen on a cross-database platform :( */
45 trustsdb
->createtable(trustsdb
, NULL
, NULL
, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, created INT, lastseen INT, maxpernode INT, nodebits INT)", "Td", hosts
, TRUSTHOSTLEN
);
47 trustsdb
->createtable(trustsdb
, NULL
, NULL
,
48 "CREATE TABLE ? (groupid INT, groupname VARCHAR(?), ts INT, username VARCHAR(?), message VARCHAR(?))",
49 "Tddd", "log", TRUSTNAMELEN
, CREATEDBYLEN
, TRUSTLOGLEN
53 static void flushdatabase(void *arg
) {
54 trusts_flush(th_dbupdatecounts
, tg_dbupdatecounts
);
57 static void triggerdbloaded(void *arg
) {
58 triggerhook(HOOK_TRUSTS_DB_LOADED
, NULL
);
61 static void loadcomplete(void) {
62 /* error has already been shown */
68 flushschedule
= schedulerecurring(time(NULL
) + 300, 0, 300, flushdatabase
, NULL
);
70 scheduleoneshot(time(NULL
), triggerdbloaded
, NULL
);
73 static void loadhosts_data(const DBAPIResult
*result
, void *tag
) {
79 if(!result
->success
) {
80 Error("trusts", ERR_ERROR
, "Error loading hosts table.");
83 result
->clear(result
);
87 if(result
->fields
!= 8) {
88 Error("trusts", ERR_ERROR
, "Wrong number of fields in hosts table.");
91 result
->clear(result
);
95 while(result
->next(result
)) {
100 th
.id
= strtoul(result
->get(result
, 0), NULL
, 10);
104 groupid
= strtoul(result
->get(result
, 1), NULL
, 10);
106 th
.group
= tg_getbyid(groupid
);
108 Error("trusts", ERR_WARNING
, "Orphaned trust group host: %d", groupid
);
112 host
= result
->get(result
, 2);
113 if(!ipmask_parse(host
, &th
.ip
, &th
.bits
)) {
114 Error("trusts", ERR_WARNING
, "Error parsing cidr for host: %s", host
);
118 th
.maxusage
= strtoul(result
->get(result
, 3), NULL
, 10);
119 th
.created
= (time_t)strtoul(result
->get(result
, 4), NULL
, 10);
120 th
.lastseen
= (time_t)strtoul(result
->get(result
, 5), NULL
, 10);
121 th
.maxpernode
= strtol(result
->get(result
, 6), NULL
, 10);
122 th
.nodebits
= strtol(result
->get(result
, 7), NULL
, 10);
125 Error("trusts", ERR_WARNING
, "Error adding host to trust %d: %s", groupid
, host
);
128 result
->clear(result
);
133 static void loadhosts_fini(const DBAPIResult
*result
, void *tag
) {
134 Error("trusts", ERR_INFO
, "Finished loading hosts, maximum id: %d", thmaxid
);
137 static void loadgroups_data(const DBAPIResult
*result
, void *tag
) {
143 if(!result
->success
) {
144 Error("trusts", ERR_ERROR
, "Error loading group table.");
147 result
->clear(result
);
151 if(result
->fields
!= 12) {
152 Error("trusts", ERR_ERROR
, "Wrong number of fields in groups table.");
155 result
->clear(result
);
159 while(result
->next(result
)) {
162 tg
.id
= strtoul(result
->get(result
, 0), NULL
, 10);
166 tg
.name
= getsstring(rtrim(result
->get(result
, 1)), TRUSTNAMELEN
);
167 tg
.trustedfor
= strtoul(result
->get(result
, 2), NULL
, 10);
168 tg
.flags
= atoi(result
->get(result
, 3));
169 tg
.maxperident
= strtoul(result
->get(result
, 4), NULL
, 10);
170 tg
.maxusage
= strtoul(result
->get(result
, 5), NULL
, 10);
171 tg
.expires
= (time_t)strtoul(result
->get(result
, 6), NULL
, 10);
172 tg
.lastseen
= (time_t)strtoul(result
->get(result
, 7), NULL
, 10);
173 tg
.lastmaxusereset
= (time_t)strtoul(result
->get(result
, 8), NULL
, 10);
174 tg
.createdby
= getsstring(rtrim(result
->get(result
, 9)), CREATEDBYLEN
);
175 tg
.contact
= getsstring(rtrim(result
->get(result
, 10)), CONTACTLEN
);
176 tg
.comment
= getsstring(rtrim(result
->get(result
, 11)), COMMENTLEN
);
178 if(tg
.name
&& tg
.createdby
&& tg
.contact
&& tg
.comment
) {
180 Error("trusts", ERR_WARNING
, "Error adding trustgroup %d: %s", tg
.id
, tg
.name
->content
);
182 Error("trusts", ERR_ERROR
, "Error allocating sstring in group loader, id: %d", tg
.id
);
185 freesstring(tg
.name
);
186 freesstring(tg
.createdby
);
187 freesstring(tg
.contact
);
188 freesstring(tg
.comment
);
191 result
->clear(result
);
194 static void loadgroups_fini(const DBAPIResult
*result
, void *tag
) {
195 Error("trusts", ERR_INFO
, "Finished loading groups, maximum id: %d.", tgmaxid
);
198 static int trusts_connectdb(void) {
200 trustsdb
= dbapi2open(NULL
, "trusts");
202 Error("trusts", ERR_WARNING
, "Unable to connect to db -- not loaded.");
207 createtrusttables(TABLES_REGULAR
);
212 int trusts_loaddb(void) {
213 if(!trusts_connectdb())
218 trustsdb
->loadtable(trustsdb
, NULL
, loadgroups_data
, loadgroups_fini
, NULL
, "groups");
219 trustsdb
->loadtable(trustsdb
, NULL
, loadhosts_data
, loadhosts_fini
, NULL
, "hosts");
224 void trusts_closedb(int closeconnection
) {
229 deleteschedule(flushschedule
, flushdatabase
, NULL
);
230 flushschedule
= NULL
;
238 thmaxid
= tgmaxid
= 0;
240 if(closeconnection
) {
241 trustsdb
->close(trustsdb
);
245 triggerhook(HOOK_TRUSTS_DB_CLOSED
, NULL
);
248 static void th_dbupdatecounts(trusthost
*th
) {
249 trustsdb
->squery(trustsdb
, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th
->lastseen
, th
->maxusage
, th
->id
);
252 static void tg_dbupdatecounts(trustgroup
*tg
) {
253 trustsdb
->squery(trustsdb
, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg
->lastseen
, tg
->maxusage
, tg
->id
);
256 trusthost
*th_copy(trusthost
*ith
) {
257 trusthost
*th
, *superset
, *subset
;
263 trustsdb_insertth("hosts", th
, th
->group
->id
);
265 th_getsuperandsubsets(&ith
->ip
, ith
->bits
, &superset
, &subset
);
266 th_adjusthosts(th
, superset
, subset
);
272 trusthost
*th_new(trustgroup
*tg
, char *host
) {
275 if(!ipmask_parse(host
, &nth
.ip
, &nth
.bits
))
279 nth
.id
= thmaxid
+ 1;
280 nth
.created
= getnettime();
285 nth
.nodebits
= (irc_in_addr_is_ipv4(&nth
.ip
))?128:64;
287 if (nth
.bits
< nth
.nodebits
)
288 nth
.nodebits
= nth
.bits
;
299 trustgroup
*tg_copy(trustgroup
*itg
) {
300 trustgroup
*tg
= tg_add(itg
);
304 trustsdb_inserttg("groups", tg
);
308 trustgroup
*tg_new(trustgroup
*itg
) {
311 itg
->id
= tgmaxid
+ 1;
314 itg
->lastmaxusereset
= 0;
325 void trustsdb_insertth(char *table
, trusthost
*th
, unsigned int groupid
) {
326 trustsdb
->squery(trustsdb
,
327 "INSERT INTO ? (id, groupid, host, maxusage, created, lastseen, maxpernode, nodebits) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
328 "Tuusuutuu", table
, th
->id
, groupid
, CIDRtostr(th
->ip
, th
->bits
), th
->maxusage
, th
->created
, th
->lastseen
, th
->maxpernode
, th
->nodebits
332 void trustsdb_inserttg(char *table
, trustgroup
*tg
) {
333 trustsdb
->squery(trustsdb
,
334 "INSERT INTO ? (id, name, trustedfor, flags, maxperident, maxusage, expires, lastseen, lastmaxusereset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
335 "Tusuuuutttsss", table
, tg
->id
, tg
->name
->content
, tg
->trustedfor
, tg
->flags
, tg
->maxperident
, tg
->maxusage
, tg
->expires
, tg
->lastseen
, tg
->lastmaxusereset
, tg
->createdby
->content
, tg
->contact
->content
, tg
->comment
->content
339 void tg_update(trustgroup
*tg
) {
340 trustsdb
->squery(trustsdb
,
341 "UPDATE ? SET name = ?, trustedfor = ?, flags = ?, maxperident = ?, maxusage = ?, expires = ?, lastseen = ?, lastmaxusereset = ?, createdby = ?, contact = ?, comment = ? WHERE id = ?",
342 "Tsuuuutttsssu", "groups", tg
->name
->content
, tg
->trustedfor
, tg
->flags
, tg
->maxperident
, tg
->maxusage
, tg
->expires
, tg
->lastseen
, tg
->lastmaxusereset
, tg
->createdby
->content
, tg
->contact
->content
, tg
->comment
->content
, tg
->id
346 void trustsdb_deletetg(char *table
, trustgroup
*tg
) {
347 trustsdb
->squery(trustsdb
,
348 "DELETE FROM ? WHERE id = ?",
349 "Tu", "groups", tg
->id
);
352 void tg_delete(trustgroup
*tg
) {
355 for(pnext
=&tglist
;*pnext
;pnext
=&((*pnext
)->next
)) {
362 trustsdb_deletetg("groups", tg
);
366 void th_update(trusthost
*th
) {
367 trustsdb
->squery(trustsdb
,
368 "UPDATE ? SET maxpernode = ?, nodebits = ? WHERE id = ?",
369 "Tuuu", "hosts", th
->maxpernode
, th
->nodebits
, th
->id
373 void trustsdb_deleteth(char *table
, trusthost
*th
) {
374 trustsdb
->squery(trustsdb
,
375 "DELETE FROM ? WHERE id = ?",
376 "Tu", "hosts", th
->id
);
379 void th_delete(trusthost
*th
) {
383 for(pnext
=&(th
->group
->hosts
);*pnext
;pnext
=&((*pnext
)->next
)) {
391 for(pnext
=&(th
->parent
->children
);*pnext
;pnext
=&((*pnext
)->nextbychild
)) {
393 *pnext
= th
->nextbychild
;
399 for(np
=th
->users
;np
;np
=nextbytrust(np
))
400 settrusthost(np
, NULL
);
402 th
->group
->count
-= th
->count
;
405 th
->parent
->count
+= th
->count
;
407 if(th
->lastseen
> th
->parent
->lastseen
)
408 th
->parent
->lastseen
= th
->lastseen
;
411 trustsdb_deleteth("hosts", th
);
417 void trustlog(trustgroup
*tg
, const char *user
, const char *format
, ...) {
418 char buf
[TRUSTLOGLEN
+1];
422 va_start(va
, format
);
423 vsnprintf(buf
, sizeof(buf
), format
, va
);
428 trustsdb
->squery(trustsdb
,
429 "INSERT INTO ? (ts, groupid, groupname, username, message) VALUES (?, ?, ?, ?, ?)",
430 "Tuusss", "log", now
, tg
->id
, tg
->name
->content
, user
, buf
);
433 static void trustlogquery_callback(const struct DBAPIResult
*result
, void *arg
) {
434 nick
*np
= (nick
*)arg
;
437 if(!result
|| !result
->success
) {
438 controlreply(np
, "Error querying the log.");
441 result
->clear(result
);
446 if(result
->fields
!= 5) {
447 Error("trusts", ERR_ERROR
, "Wrong number of fields in log table.");
449 result
->clear(result
);
453 while(result
->next(result
)) {
454 unsigned int ts
, groupid
;
455 char *groupname
, *user
, *message
;
457 ts
= strtoul(result
->get(result
, 0), NULL
, 10);
458 groupid
= strtoul(result
->get(result
, 1), NULL
, 10);
459 groupname
= result
->get(result
, 2);
460 user
= result
->get(result
, 3);
461 message
= result
->get(result
, 4);
463 controlreply(np
, "[%s] #%d/%s (%s) %s", trusts_timetostr(ts
), groupid
, groupname
, user
, message
);
467 result
->clear(result
);
469 controlreply(np
, "--- Done. Found %d entries.", rows
);
472 void trustlogspewid(nick
*np
, unsigned int groupid
, unsigned int limit
) {
473 trustsdb
->query(trustsdb
, trustlogquery_callback
, (void *)np
,
474 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupid = ? ORDER BY ts DESC LIMIT ?",
475 "Tuu", "log", groupid
, limit
);
478 void trustlogspewname(nick
*np
, const char *groupname
, unsigned int limit
) {
479 trustsdb
->query(trustsdb
, trustlogquery_callback
, (void *)np
,
480 "SELECT ts, groupid, groupname, username, message FROM ? WHERE groupname = ? ORDER BY ts DESC LIMIT ?",
481 "Tsu", "log", groupname
, limit
);
484 void trustloggrep(nick
*np
, const char *pattern
, unsigned int limit
) {
486 snprintf(buf
, sizeof(buf
), "%%%s%%", pattern
);
488 trustsdb
->query(trustsdb
, trustlogquery_callback
, (void *)np
,
489 "SELECT ts, groupid, groupname, username, message FROM ? WHERE message LIKE ? ORDER BY ts DESC LIMIT ?",
490 "Tsu", "log", buf
, limit
);