]> jfr.im git - irc/quakenet/newserv.git/blob - trusts/trusts_db.c
HELPMOD2: Ignore friends in lamer control
[irc/quakenet/newserv.git] / trusts / trusts_db.c
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
7 DBAPIConn *trustsdb;
8 static int tgmaxid, thmaxid;
9 static int loaderror;
10 static void *flushschedule;
11
12 void createtrusttables(int migration);
13 void trusts_flush(void (*)(trusthost *), void (*)(trustgroup *));
14 void trusts_freeall(void);
15 static void th_dbupdatecounts(trusthost *th);
16 static void tg_dbupdatecounts(trustgroup *tg);
17
18 void createtrusttables(int mode) {
19 char *groups, *hosts;
20
21 if(mode == TABLES_MIGRATION) {
22 groups = "migration_groups";
23 hosts = "migration_hosts";
24 } else if(mode == TABLES_REPLICATION) {
25 groups = "replication_groups";
26 hosts = "replication_hosts";
27 } else {
28 groups = "groups";
29 hosts = "hosts";
30 }
31
32 trustsdb->createtable(trustsdb, NULL, NULL,
33 "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(?))",
34 "Tdddd", groups, TRUSTNAMELEN, CREATEDBYLEN, CONTACTLEN, COMMENTLEN
35 );
36
37 /* I'd like multiple keys here but that's not gonna happen on a cross-database platform :( */
38 trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (id INT PRIMARY KEY, groupid INT, host VARCHAR(?), maxusage INT, lastseen INT)", "Td", hosts, TRUSTHOSTLEN);
39 }
40
41 static void flushdatabase(void *arg) {
42 trusts_flush(th_dbupdatecounts, tg_dbupdatecounts);
43 }
44
45 static void triggerdbloaded(void *arg) {
46 triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
47 }
48
49 static void loadcomplete(void) {
50 /* error has already been shown */
51 if(loaderror)
52 return;
53
54 th_linktree();
55 trustsdbloaded = 1;
56 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
57
58 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
59 }
60
61 static void loadhosts_data(const DBAPIResult *result, void *tag) {
62 if(!result) {
63 loaderror = 1;
64 return;
65 }
66
67 if(!result->success) {
68 Error("trusts", ERR_ERROR, "Error loading hosts table.");
69 loaderror = 1;
70
71 result->clear(result);
72 return;
73 }
74
75 if(result->fields != 5) {
76 Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
77 loaderror = 1;
78
79 result->clear(result);
80 return;
81 }
82
83 while(result->next(result)) {
84 unsigned int groupid;
85 trusthost th;
86 char *host;
87
88 th.id = strtoul(result->get(result, 0), NULL, 10);
89 if(th.id > thmaxid)
90 thmaxid = th.id;
91
92 groupid = strtoul(result->get(result, 1), NULL, 10);
93
94 th.group = tg_getbyid(groupid);
95 if(!th.group) {
96 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
97 continue;
98 }
99
100 host = result->get(result, 2);
101 if(!trusts_str2cidr(host, &th.ip, &th.mask)) {
102 Error("trusts", ERR_WARNING, "Error parsing cidr for host: %s", host);
103 continue;
104 }
105
106 th.maxusage = strtoul(result->get(result, 3), NULL, 10);
107 th.lastseen = (time_t)strtoul(result->get(result, 4), NULL, 10);
108
109 if(!th_add(&th))
110 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
111 }
112
113 result->clear(result);
114
115 loadcomplete();
116 }
117
118 static void loadhosts_fini(const DBAPIResult *result, void *tag) {
119 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
120 }
121
122 static void loadgroups_data(const DBAPIResult *result, void *tag) {
123 if(!result) {
124 loaderror = 1;
125 return;
126 }
127
128 if(!result->success) {
129 Error("trusts", ERR_ERROR, "Error loading group table.");
130 loaderror = 1;
131
132 result->clear(result);
133 return;
134 }
135
136 if(result->fields != 12) {
137 Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
138 loaderror = 1;
139
140 result->clear(result);
141 return;
142 }
143
144 while(result->next(result)) {
145 trustgroup tg;
146
147 tg.id = strtoul(result->get(result, 0), NULL, 10);
148 if(tg.id > tgmaxid)
149 tgmaxid = tg.id;
150
151 tg.name = getsstring(rtrim(result->get(result, 1)), TRUSTNAMELEN);
152 tg.trustedfor = strtoul(result->get(result, 2), NULL, 10);
153 tg.mode = atoi(result->get(result, 3));
154 tg.maxperident = strtoul(result->get(result, 4), NULL, 10);
155 tg.maxusage = strtoul(result->get(result, 5), NULL, 10);
156 tg.expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
157 tg.lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
158 tg.lastmaxusereset = (time_t)strtoul(result->get(result, 8), NULL, 10);
159 tg.createdby = getsstring(rtrim(result->get(result, 9)), CREATEDBYLEN);
160 tg.contact = getsstring(rtrim(result->get(result, 10)), CONTACTLEN);
161 tg.comment = getsstring(rtrim(result->get(result, 11)), COMMENTLEN);
162
163 if(tg.name && tg.createdby && tg.contact && tg.comment) {
164 if(!tg_add(&tg))
165 Error("trusts", ERR_WARNING, "Error adding trustgroup %d: %s", tg.id, tg.name->content);
166 } else {
167 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", tg.id);
168 }
169
170 freesstring(tg.name);
171 freesstring(tg.createdby);
172 freesstring(tg.contact);
173 freesstring(tg.comment);
174 }
175
176 result->clear(result);
177 }
178
179 static void loadgroups_fini(const DBAPIResult *result, void *tag) {
180 Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
181 }
182
183 static int trusts_connectdb(void) {
184 if(!trustsdb) {
185 trustsdb = dbapi2open(NULL, "trusts");
186 if(!trustsdb) {
187 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
188 return 0;
189 }
190 }
191
192 createtrusttables(TABLES_REGULAR);
193
194 return 1;
195 }
196
197 int trusts_loaddb(void) {
198 if(!trusts_connectdb())
199 return 0;
200
201 loaderror = 0;
202
203 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
204 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
205
206 return 1;
207 }
208
209 void trusts_closedb(int closeconnection) {
210 if(!trustsdb)
211 return;
212
213 if(flushschedule) {
214 deleteschedule(flushschedule, flushdatabase, NULL);
215 flushschedule = NULL;
216
217 flushdatabase(NULL);
218 }
219
220 trusts_freeall();
221
222 trustsdbloaded = 0;
223 thmaxid = tgmaxid = 0;
224
225 if(closeconnection) {
226 trustsdb->close(trustsdb);
227 trustsdb = NULL;
228 }
229
230 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
231 }
232
233 static void th_dbupdatecounts(trusthost *th) {
234 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
235 }
236
237 static void tg_dbupdatecounts(trustgroup *tg) {
238 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
239 }
240
241 trusthost *th_copy(trusthost *ith) {
242 trusthost *th, *superset, *subset;
243
244 th = th_add(ith);
245 if(!th)
246 return NULL;
247
248 trustsdb_insertth("hosts", th, th->group->id);
249
250 th_getsuperandsubsets(ith->ip, ith->mask, &superset, &subset);
251 th_adjusthosts(th, subset, superset);
252 th_linktree();
253
254 return th;
255 }
256
257 trusthost *th_new(trustgroup *tg, char *host) {
258 trusthost *th, nth;
259
260 if(!trusts_str2cidr(host, &nth.ip, &nth.mask))
261 return NULL;
262
263 nth.group = tg;
264 nth.id = thmaxid + 1;
265 nth.lastseen = 0;
266 nth.maxusage = 0;
267
268 th = th_copy(&nth);
269 if(!th)
270 return NULL;
271
272 thmaxid++;
273
274 return th;
275 }
276
277 trustgroup *tg_copy(trustgroup *itg) {
278 trustgroup *tg = tg_add(itg);
279 if(!tg)
280 return NULL;
281
282 trustsdb_inserttg("groups", tg);
283 return tg;
284 }
285
286 trustgroup *tg_new(trustgroup *itg) {
287 trustgroup *tg;
288
289 itg->id = tgmaxid + 1;
290 itg->maxusage = 0;
291 itg->lastseen = 0;
292 itg->lastmaxusereset = 0;
293
294 tg = tg_copy(itg);
295 if(!tg)
296 return NULL;
297
298 tgmaxid++;
299
300 return tg;
301 }
302
303 void trustsdb_insertth(char *table, trusthost *th, unsigned int groupid) {
304 trustsdb->squery(trustsdb,
305 "INSERT INTO ? (id, groupid, host, maxusage, lastseen) VALUES (?, ?, ?, ?, ?)",
306 "Tuusut", table, th->id, groupid, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->lastseen
307 );
308 }
309
310 void trustsdb_inserttg(char *table, trustgroup *tg) {
311 trustsdb->squery(trustsdb,
312 "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxusereset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
313 "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
314 );
315 }
316
317 void tg_update(trustgroup *tg) {
318 trustsdb->squery(trustsdb,
319 "UPDATE ? SET name = ?, trustedfor = ?, maxperident = ?, maxusage = ?, expires = ?, lastseen = ?, lastmaxusereset = ?, createdby = ?, contact = ?, comment = ? WHERE id = ?",
320 "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
321 );
322 }
323
324 void tg_delete(trustgroup *tg) {
325 /* TODO */
326 }
327
328 void th_delete(trusthost *th) {
329 /* TODO */
330 }
331
332 void _init(void) {
333 trusts_connectdb();
334 }
335
336 void _fini(void) {
337 trusts_closedb(1);
338 }