]> jfr.im git - irc/quakenet/newserv.git/blame_incremental - trusts/trusts_db.c
Add IP checking, now HOOK_TRUSTS_{NEW,LOST}NICK can fire with null trusthosts.
[irc/quakenet/newserv.git] / trusts / trusts_db.c
... / ...
CommitLineData
1#include "../dbapi2/dbapi2.h"
2#include "../core/error.h"
3#include "../core/hooks.h"
4#include "../core/schedule.h"
5#include "trusts.h"
6
7DBAPIConn *trustsdb;
8static int tgmaxid, thmaxid;
9static int loaderror;
10static void *flushschedule;
11
12void createtrusttables(int migration);
13void trusts_flush(void (*)(trusthost *), void (*)(trustgroup *));
14void trusts_freeall(void);
15static void th_dbupdatecounts(trusthost *th);
16static void tg_dbupdatecounts(trustgroup *tg);
17
18void createtrusttables(int migration) {
19 char *groups, *hosts;
20
21 if(migration) {
22 groups = "migration_groups";
23 hosts = "migration_hosts";
24 } else {
25 groups = "groups";
26 hosts = "hosts";
27 }
28
29 trustsdb->createtable(trustsdb, NULL, NULL,
30 "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(?), trustedfor INT, mode INT, maxperident INT, maxusage INT, expires INT, lastseen INT, lastmaxuserreset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
31 "Tdddd", groups, TRUSTNAMELEN, NICKLEN, CONTACTLEN, COMMENTLEN
32 );
33
34 /* I'd like multiple keys here but that's not gonna happen on a cross-database platform :( */
35 trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, lastseen INT)", "Td", hosts, TRUSTHOSTLEN);
36}
37
38static void flushdatabase(void *arg) {
39 trusts_flush(th_dbupdatecounts, tg_dbupdatecounts);
40}
41
42static void triggerdbloaded(void *arg) {
43 triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
44}
45
46static void loadcomplete(void) {
47 /* error has already been shown */
48 if(loaderror)
49 return;
50
51 th_linktree();
52 trustsdbloaded = 1;
53 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
54
55 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
56}
57
58static void loadhosts_data(const DBAPIResult *result, void *tag) {
59 if(!result) {
60 loaderror = 1;
61 return;
62 }
63
64 if(!result->success) {
65 Error("trusts", ERR_ERROR, "Error loading hosts table.");
66 loaderror = 1;
67
68 result->clear(result);
69 return;
70 }
71
72 if(result->fields != 5) {
73 Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
74 loaderror = 1;
75
76 result->clear(result);
77 return;
78 }
79
80 while(result->next(result)) {
81 unsigned int groupid, id;
82 char *host;
83 unsigned int maxusage, lastseen;
84 trustgroup *tg;
85
86 id = strtoul(result->get(result, 0), NULL, 10);
87 if(id > thmaxid)
88 thmaxid = id;
89
90 groupid = strtoul(result->get(result, 1), NULL, 10);
91
92 tg = tg_getbyid(groupid);
93 if(!tg) {
94 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
95 continue;
96 }
97
98 /* NOTE: 2 is at the bottom */
99 maxusage = strtoul(result->get(result, 3), NULL, 10);
100 lastseen = (time_t)strtoul(result->get(result, 4), NULL, 10);
101 host = result->get(result, 2);
102
103 if(!th_add(tg, id, host, maxusage, lastseen))
104 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
105 }
106
107 result->clear(result);
108
109 loadcomplete();
110}
111
112static void loadhosts_fini(const DBAPIResult *result, void *tag) {
113 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
114}
115
116static void loadgroups_data(const DBAPIResult *result, void *tag) {
117 if(!result) {
118 loaderror = 1;
119 return;
120 }
121
122 if(!result->success) {
123 Error("trusts", ERR_ERROR, "Error loading group table.");
124 loaderror = 1;
125
126 result->clear(result);
127 return;
128 }
129
130 if(result->fields != 12) {
131 Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
132 loaderror = 1;
133
134 result->clear(result);
135 return;
136 }
137
138 while(result->next(result)) {
139 unsigned int id;
140 sstring *name, *createdby, *contact, *comment;
141 unsigned int trustedfor, mode, maxperident, maxusage;
142 time_t expires, lastseen, lastmaxuserreset;
143
144 id = strtoul(result->get(result, 0), NULL, 10);
145 if(id > tgmaxid)
146 tgmaxid = id;
147
148 name = getsstring(result->get(result, 1), TRUSTNAMELEN);
149 trustedfor = strtoul(result->get(result, 2), NULL, 10);
150 mode = atoi(result->get(result, 3));
151 maxperident = strtoul(result->get(result, 4), NULL, 10);
152 maxusage = strtoul(result->get(result, 5), NULL, 10);
153 expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
154 lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
155 lastmaxuserreset = (time_t)strtoul(result->get(result, 8), NULL, 10);
156 createdby = getsstring(result->get(result, 9), NICKLEN);
157 contact = getsstring(result->get(result, 10), CONTACTLEN);
158 comment = getsstring(result->get(result, 11), COMMENTLEN);
159
160 if(name && createdby && contact && comment) {
161 if(!tg_add(id, name->content, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxuserreset, createdby->content, contact->content, comment->content))
162 Error("trusts", ERR_WARNING, "Error adding trustgroup %d: %s", id, name->content);
163 } else {
164 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", id);
165 }
166
167 freesstring(name);
168 freesstring(createdby);
169 freesstring(contact);
170 freesstring(comment);
171 }
172
173 result->clear(result);
174}
175
176static void loadgroups_fini(const DBAPIResult *result, void *tag) {
177 Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
178}
179
180int trusts_loaddb(void) {
181 if(!trustsdb) {
182 trustsdb = dbapi2open(NULL, "trusts");
183 if(!trustsdb) {
184 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
185 return 0;
186 }
187 }
188
189 createtrusttables(0);
190
191 loaderror = 0;
192
193 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
194 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
195
196 return 1;
197}
198
199void trusts_closedb(int closeconnection) {
200 if(!trustsdb)
201 return;
202
203 if(flushschedule) {
204 deleteschedule(flushschedule, flushdatabase, NULL);
205 flushschedule = NULL;
206
207 flushdatabase(NULL);
208 }
209
210 trusts_freeall();
211
212 trustsdbloaded = 0;
213 thmaxid = tgmaxid = 0;
214
215 if(closeconnection) {
216 trustsdb->close(trustsdb);
217 trustsdb = NULL;
218 }
219
220 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
221}
222
223static void th_dbupdatecounts(trusthost *th) {
224 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
225}
226
227static void tg_dbupdatecounts(trustgroup *tg) {
228 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
229}
230
231trusthost *th_new(trustgroup *tg, char *host) {
232 trusthost *th, *superset, *subset;
233 u_int32_t ip, mask;
234
235 /* ugh */
236 if(!trusts_str2cidr(host, &ip, &mask))
237 return NULL;
238
239 th_getsuperandsubsets(ip, mask, &superset, &subset);
240
241 th = th_add(tg, thmaxid + 1, host, 0, 0);
242 if(!th)
243 return NULL;
244
245 thmaxid++;
246
247 trustsdb->squery(trustsdb,
248 "INSERT INTO ? (id, groupid, host, maxusage, lastseen) VALUES (?, ?, ?, ?, ?)",
249 "Tuusut", "hosts", th->id, tg->id, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->lastseen
250 );
251
252 th_adjusthosts(th, subset, superset);
253
254 th_linktree();
255 return th;
256}
257
258trustgroup *tg_new(char *name, unsigned int trustedfor, int mode, unsigned int maxperident, time_t expires, char *createdby, char *contact, char *comment) {
259 trustgroup *tg = tg_add(tgmaxid + 1, name, trustedfor, mode, maxperident, 0, expires, 0, 0, createdby, contact, comment);
260 if(!tg)
261 return NULL;
262
263 tgmaxid++;
264
265 trustsdb->squery(trustsdb,
266 "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxuserreset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
267 "Tusuuuutttsss", "groups", tg->id, tg->name->content, tg->trustedfor, tg->mode, tg->maxperident, tg->maxusage, tg->expires, tg->lastseen, tg->lastmaxuserreset, tg->createdby->content, tg->contact->content, tg->comment->content
268 );
269
270 return tg;
271}
272
273void _init(void) {
274 trusts_loaddb();
275}
276
277void _fini(void) {
278 trusts_closedb(1);
279}