]> jfr.im git - irc/quakenet/newserv.git/blob - trusts/db.c
Fix up trustlist for lastseen/expires in.
[irc/quakenet/newserv.git] / 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 int trustsdbloaded;
13
14 void createtrusttables(int migration);
15 void trusts_flush(void);
16 void trusts_freeall(void);
17
18 void 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
38 static void flushdatabase(void *arg) {
39 trusts_flush();
40 }
41
42 static void triggerdbloaded(void *arg) {
43 triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
44 }
45
46 static void loadcomplete(void) {
47 /* error has already been shown */
48 if(loaderror)
49 return;
50
51 trustsdbloaded = 1;
52 flushschedule = schedulerecurring(time(NULL) + 300, 0, 300, flushdatabase, NULL);
53
54 scheduleoneshot(time(NULL), triggerdbloaded, NULL);
55 }
56
57 static void loadhosts_data(const DBAPIResult *result, void *tag) {
58 if(!result) {
59 loaderror = 1;
60 return;
61 }
62
63 if(!result->success) {
64 Error("trusts", ERR_ERROR, "Error loading hosts table.");
65 loaderror = 1;
66
67 result->clear(result);
68 return;
69 }
70
71 if(result->fields != 5) {
72 Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
73 loaderror = 1;
74
75 result->clear(result);
76 return;
77 }
78
79 while(result->next(result)) {
80 unsigned int groupid, id;
81 char *host;
82 unsigned int maxusage, lastseen;
83 trustgroup *tg;
84
85 id = strtoul(result->get(result, 0), NULL, 10);
86 if(id > thmaxid)
87 thmaxid = id;
88
89 groupid = strtoul(result->get(result, 1), NULL, 10);
90
91 tg = tg_getbyid(groupid);
92 if(!tg) {
93 Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
94 continue;
95 }
96
97 /* NOTE: 2 is at the bottom */
98 maxusage = strtoul(result->get(result, 3), NULL, 10);
99 lastseen = (time_t)strtoul(result->get(result, 4), NULL, 10);
100 host = result->get(result, 2);
101
102 if(!th_add(tg, id, host, maxusage, lastseen))
103 Error("trusts", ERR_WARNING, "Error adding host to trust %d: %s", groupid, host);
104 }
105
106 result->clear(result);
107
108 loadcomplete();
109 }
110
111 static void loadhosts_fini(const DBAPIResult *result, void *tag) {
112 Error("trusts", ERR_INFO, "Finished loading hosts, maximum id: %d", thmaxid);
113 }
114
115 static void loadgroups_data(const DBAPIResult *result, void *tag) {
116 if(!result) {
117 loaderror = 1;
118 return;
119 }
120
121 if(!result->success) {
122 Error("trusts", ERR_ERROR, "Error loading group table.");
123 loaderror = 1;
124
125 result->clear(result);
126 return;
127 }
128
129 if(result->fields != 12) {
130 Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
131 loaderror = 1;
132
133 result->clear(result);
134 return;
135 }
136
137 while(result->next(result)) {
138 unsigned int id;
139 sstring *name, *createdby, *contact, *comment;
140 unsigned int trustedfor, mode, maxperident, maxusage;
141 time_t expires, lastseen, lastmaxuserreset;
142
143 id = strtoul(result->get(result, 0), NULL, 10);
144 if(id > tgmaxid)
145 tgmaxid = id;
146
147 name = getsstring(result->get(result, 1), TRUSTNAMELEN);
148 trustedfor = strtoul(result->get(result, 2), NULL, 10);
149 mode = atoi(result->get(result, 3));
150 maxperident = strtoul(result->get(result, 4), NULL, 10);
151 maxusage = strtoul(result->get(result, 5), NULL, 10);
152 expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
153 lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
154 lastmaxuserreset = (time_t)strtoul(result->get(result, 8), NULL, 10);
155 createdby = getsstring(result->get(result, 9), NICKLEN);
156 contact = getsstring(result->get(result, 10), CONTACTLEN);
157 comment = getsstring(result->get(result, 11), COMMENTLEN);
158
159 if(name && createdby && contact && comment) {
160 if(!tg_add(id, name->content, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxuserreset, createdby->content, contact->content, comment->content))
161 Error("trusts", ERR_WARNING, "Error adding trustgroup %d: %s", id, name->content);
162 } else {
163 Error("trusts", ERR_ERROR, "Error allocating sstring in group loader, id: %d", id);
164 }
165
166 freesstring(name);
167 freesstring(createdby);
168 freesstring(contact);
169 freesstring(comment);
170 }
171
172 result->clear(result);
173 }
174
175 static void loadgroups_fini(const DBAPIResult *result, void *tag) {
176 Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
177 }
178
179 int trusts_loaddb(void) {
180 if(!trustsdb) {
181 trustsdb = dbapi2open(NULL, "trusts");
182 if(!trustsdb) {
183 Error("trusts", ERR_WARNING, "Unable to connect to db -- not loaded.");
184 return 0;
185 }
186 }
187
188 createtrusttables(0);
189
190 loaderror = 0;
191
192 trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
193 trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
194
195 return 1;
196 }
197
198 void trusts_closedb(int closeconnection) {
199 if(!trustsdb)
200 return;
201
202 if(flushschedule) {
203 deleteschedule(flushschedule, flushdatabase, NULL);
204 flushschedule = NULL;
205
206 flushdatabase(NULL);
207 }
208
209 trusts_freeall();
210
211 trustsdbloaded = 0;
212 thmaxid = tgmaxid = 0;
213
214 if(closeconnection) {
215 trustsdb->close(trustsdb);
216 trustsdb = NULL;
217 }
218
219 triggerhook(HOOK_TRUSTS_DB_CLOSED, NULL);
220 }
221
222 void th_dbupdatecounts(trusthost *th) {
223 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "hosts", th->lastseen, th->maxusage, th->id);
224 }
225
226 void tg_dbupdatecounts(trustgroup *tg) {
227 trustsdb->squery(trustsdb, "UPDATE ? SET lastseen = ?, maxusage = ? WHERE id = ?", "Ttuu", "groups", tg->lastseen, tg->maxusage, tg->id);
228 }
229
230 trusthost *th_new(trustgroup *tg, char *host) {
231 trusthost *th = th_add(tg, thmaxid + 1, host, 0, 0);
232 if(!th)
233 return NULL;
234
235 thmaxid++;
236
237 trustsdb->squery(trustsdb,
238 "INSERT INTO ? (id, groupid, host, maxusage, lastseen) VALUES (?, ?, ?, ?, ?)",
239 "Tuusut", "hosts", th->id, tg->id, trusts_cidr2str(th->ip, th->mask), th->maxusage, th->lastseen
240 );
241
242 /* fix up stuff in memory */
243
244 return th;
245 }
246
247 trustgroup *tg_new(char *name, unsigned int trustedfor, int mode, unsigned int maxperident, time_t expires, char *createdby, char *contact, char *comment) {
248 trustgroup *tg = tg_add(tgmaxid + 1, name, trustedfor, mode, maxperident, 0, expires, 0, 0, createdby, contact, comment);
249 if(!tg)
250 return NULL;
251
252 tgmaxid++;
253
254 trustsdb->squery(trustsdb,
255 "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxusage, expires, lastseen, lastmaxuserreset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
256 "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
257 );
258
259 return tg;
260 }