]>
Commit | Line | Data |
---|---|---|
1 | /* bandb/bandb.c | |
2 | * | |
3 | * Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk> | |
4 | * Copyright (C) 2006-2008 ircd-ratbox development team | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are | |
8 | * met: | |
9 | * | |
10 | * 1.Redistributions of source code must retain the above copyright notice, | |
11 | * this list of conditions and the following disclaimer. | |
12 | * 2.Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3.The name of the author may not be used to endorse or promote products | |
16 | * derived from this software without specific prior written permission. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
22 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
28 | * POSSIBILITY OF SUCH DAMAGE. | |
29 | */ | |
30 | #include "setup.h" | |
31 | #include <rb_lib.h> | |
32 | #include <stdio.h> | |
33 | #include "rsdb.h" | |
34 | #include "ircd_defs.h" | |
35 | ||
36 | ||
37 | #define MAXPARA 10 | |
38 | ||
39 | #define COMMIT_INTERVAL 3 /* seconds */ | |
40 | ||
41 | typedef enum | |
42 | { | |
43 | BANDB_KLINE, | |
44 | BANDB_DLINE, | |
45 | BANDB_XLINE, | |
46 | BANDB_RESV, | |
47 | LAST_BANDB_TYPE | |
48 | } bandb_type; | |
49 | ||
50 | static char bandb_letter[LAST_BANDB_TYPE] = { | |
51 | 'K', 'D', 'X', 'R' | |
52 | }; | |
53 | ||
54 | static const char *bandb_table[LAST_BANDB_TYPE] = { | |
55 | "kline", "dline", "xline", "resv" | |
56 | }; | |
57 | ||
58 | ||
59 | static rb_helper *bandb_helper; | |
60 | static int in_transaction; | |
61 | ||
62 | static void check_schema(void); | |
63 | ||
64 | static void | |
65 | bandb_commit(void *unused) | |
66 | { | |
67 | rsdb_transaction(RSDB_TRANS_END); | |
68 | in_transaction = 0; | |
69 | } | |
70 | ||
71 | static void | |
72 | parse_ban(bandb_type type, char *parv[], int parc) | |
73 | { | |
74 | const char *mask1 = NULL; | |
75 | const char *mask2 = NULL; | |
76 | const char *oper = NULL; | |
77 | const char *curtime = NULL; | |
78 | const char *reason = NULL; | |
79 | const char *perm = NULL; | |
80 | int para = 1; | |
81 | ||
82 | if(type == BANDB_KLINE) | |
83 | { | |
84 | if(parc != 7) | |
85 | return; | |
86 | } | |
87 | else if(parc != 6) | |
88 | return; | |
89 | ||
90 | mask1 = parv[para++]; | |
91 | ||
92 | if(type == BANDB_KLINE) | |
93 | mask2 = parv[para++]; | |
94 | ||
95 | oper = parv[para++]; | |
96 | curtime = parv[para++]; | |
97 | perm = parv[para++]; | |
98 | reason = parv[para++]; | |
99 | ||
100 | if(!in_transaction) | |
101 | { | |
102 | rsdb_transaction(RSDB_TRANS_START); | |
103 | in_transaction = 1; | |
104 | rb_event_addonce("bandb_commit", bandb_commit, NULL, | |
105 | COMMIT_INTERVAL); | |
106 | } | |
107 | ||
108 | rsdb_exec(NULL, | |
109 | "INSERT INTO %s (mask1, mask2, oper, time, perm, reason) VALUES('%Q', '%Q', '%Q', %s, %s, '%Q')", | |
110 | bandb_table[type], mask1, mask2 ? mask2 : "", oper, curtime, perm, reason); | |
111 | } | |
112 | ||
113 | static void | |
114 | parse_unban(bandb_type type, char *parv[], int parc) | |
115 | { | |
116 | const char *mask1 = NULL; | |
117 | const char *mask2 = NULL; | |
118 | ||
119 | if(type == BANDB_KLINE) | |
120 | { | |
121 | if(parc != 3) | |
122 | return; | |
123 | } | |
124 | else if(parc != 2) | |
125 | return; | |
126 | ||
127 | mask1 = parv[1]; | |
128 | ||
129 | if(type == BANDB_KLINE) | |
130 | mask2 = parv[2]; | |
131 | ||
132 | if(!in_transaction) | |
133 | { | |
134 | rsdb_transaction(RSDB_TRANS_START); | |
135 | in_transaction = 1; | |
136 | rb_event_addonce("bandb_commit", bandb_commit, NULL, | |
137 | COMMIT_INTERVAL); | |
138 | } | |
139 | ||
140 | rsdb_exec(NULL, "DELETE FROM %s WHERE mask1='%Q' AND mask2='%Q'", | |
141 | bandb_table[type], mask1, mask2 ? mask2 : ""); | |
142 | } | |
143 | ||
144 | static void | |
145 | list_bans(void) | |
146 | { | |
147 | static char buf[512]; | |
148 | struct rsdb_table table; | |
149 | int i, j; | |
150 | ||
151 | /* schedule a clear of anything already pending */ | |
152 | rb_helper_write_queue(bandb_helper, "C"); | |
153 | ||
154 | for(i = 0; i < LAST_BANDB_TYPE; i++) | |
155 | { | |
156 | rsdb_exec_fetch(&table, "SELECT mask1,mask2,oper,reason FROM %s WHERE 1", | |
157 | bandb_table[i]); | |
158 | ||
159 | for(j = 0; j < table.row_count; j++) | |
160 | { | |
161 | if(i == BANDB_KLINE) | |
162 | snprintf(buf, sizeof(buf), "%c %s %s %s :%s", | |
163 | bandb_letter[i], table.row[j][0], | |
164 | table.row[j][1], table.row[j][2], table.row[j][3]); | |
165 | else | |
166 | snprintf(buf, sizeof(buf), "%c %s %s :%s", | |
167 | bandb_letter[i], table.row[j][0], | |
168 | table.row[j][2], table.row[j][3]); | |
169 | ||
170 | rb_helper_write_queue(bandb_helper, "%s", buf); | |
171 | } | |
172 | ||
173 | rsdb_exec_fetch_end(&table); | |
174 | } | |
175 | ||
176 | rb_helper_write(bandb_helper, "F"); | |
177 | } | |
178 | ||
179 | static void | |
180 | parse_request(rb_helper *helper) | |
181 | { | |
182 | static char *parv[MAXPARA + 1]; | |
183 | static char readbuf[READBUF_SIZE]; | |
184 | int parc; | |
185 | int len; | |
186 | ||
187 | ||
188 | while((len = rb_helper_read(helper, readbuf, sizeof(readbuf))) > 0) | |
189 | { | |
190 | parc = rb_string_to_array(readbuf, parv, MAXPARA); | |
191 | ||
192 | if(parc < 1) | |
193 | continue; | |
194 | ||
195 | switch (parv[0][0]) | |
196 | { | |
197 | case 'K': | |
198 | parse_ban(BANDB_KLINE, parv, parc); | |
199 | break; | |
200 | ||
201 | case 'D': | |
202 | parse_ban(BANDB_DLINE, parv, parc); | |
203 | break; | |
204 | ||
205 | case 'X': | |
206 | parse_ban(BANDB_XLINE, parv, parc); | |
207 | break; | |
208 | ||
209 | case 'R': | |
210 | parse_ban(BANDB_RESV, parv, parc); | |
211 | break; | |
212 | ||
213 | case 'k': | |
214 | parse_unban(BANDB_KLINE, parv, parc); | |
215 | break; | |
216 | ||
217 | case 'd': | |
218 | parse_unban(BANDB_DLINE, parv, parc); | |
219 | break; | |
220 | ||
221 | case 'x': | |
222 | parse_unban(BANDB_XLINE, parv, parc); | |
223 | break; | |
224 | ||
225 | case 'r': | |
226 | parse_unban(BANDB_RESV, parv, parc); | |
227 | break; | |
228 | ||
229 | case 'L': | |
230 | list_bans(); | |
231 | break; | |
232 | default: | |
233 | break; | |
234 | } | |
235 | } | |
236 | } | |
237 | ||
238 | ||
239 | static void | |
240 | error_cb(rb_helper *helper) __attribute__((noreturn)); | |
241 | ||
242 | static void | |
243 | error_cb(rb_helper *helper) | |
244 | { | |
245 | if(in_transaction) | |
246 | rsdb_transaction(RSDB_TRANS_END); | |
247 | exit(1); | |
248 | } | |
249 | ||
250 | #ifndef WINDOWS | |
251 | static void | |
252 | dummy_handler(int sig) | |
253 | { | |
254 | return; | |
255 | } | |
256 | #endif | |
257 | ||
258 | static void | |
259 | setup_signals(void) | |
260 | { | |
261 | #ifndef _WIN32 | |
262 | struct sigaction act; | |
263 | ||
264 | act.sa_flags = 0; | |
265 | act.sa_handler = SIG_IGN; | |
266 | sigemptyset(&act.sa_mask); | |
267 | sigaddset(&act.sa_mask, SIGPIPE); | |
268 | sigaddset(&act.sa_mask, SIGALRM); | |
269 | #ifdef SIGTRAP | |
270 | sigaddset(&act.sa_mask, SIGTRAP); | |
271 | #endif | |
272 | ||
273 | #ifdef SIGWINCH | |
274 | sigaddset(&act.sa_mask, SIGWINCH); | |
275 | sigaction(SIGWINCH, &act, 0); | |
276 | #endif | |
277 | sigaction(SIGPIPE, &act, 0); | |
278 | #ifdef SIGTRAP | |
279 | sigaction(SIGTRAP, &act, 0); | |
280 | #endif | |
281 | ||
282 | act.sa_handler = dummy_handler; | |
283 | sigaction(SIGALRM, &act, 0); | |
284 | #endif | |
285 | } | |
286 | ||
287 | ||
288 | static void | |
289 | db_error_cb(const char *errstr) __attribute__((noreturn)); | |
290 | ||
291 | static void | |
292 | db_error_cb(const char *errstr) | |
293 | { | |
294 | char buf[256]; | |
295 | snprintf(buf, sizeof(buf), "! :%s", errstr); | |
296 | rb_helper_write(bandb_helper, "%s", buf); | |
297 | rb_sleep(1 << 30, 0); | |
298 | exit(1); | |
299 | } | |
300 | ||
301 | int | |
302 | main(int argc, char *argv[]) | |
303 | { | |
304 | setup_signals(); | |
305 | bandb_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256, 256, 256); /* XXX fix me */ | |
306 | if(bandb_helper == NULL) | |
307 | { | |
308 | fprintf(stderr, | |
309 | "This is the charybdis bandb for internal ircd use.\n"); | |
310 | fprintf(stderr, | |
311 | "You aren't supposed to run me directly (did you want bantool?). Exiting.\n"); | |
312 | exit(1); | |
313 | } | |
314 | rsdb_init(db_error_cb); | |
315 | check_schema(); | |
316 | rb_helper_loop(bandb_helper, 0); | |
317 | ||
318 | return 0; | |
319 | } | |
320 | ||
321 | static void | |
322 | check_schema(void) | |
323 | { | |
324 | struct rsdb_table table; | |
325 | int i; | |
326 | ||
327 | for(i = 0; i < LAST_BANDB_TYPE; i++) | |
328 | { | |
329 | rsdb_exec_fetch(&table, | |
330 | "SELECT name FROM sqlite_master WHERE type='table' AND name='%s'", | |
331 | bandb_table[i]); | |
332 | ||
333 | rsdb_exec_fetch_end(&table); | |
334 | ||
335 | if(!table.row_count) | |
336 | rsdb_exec(NULL, | |
337 | "CREATE TABLE %s (mask1 TEXT, mask2 TEXT, oper TEXT, time INTEGER, perm INTEGER, reason TEXT)", | |
338 | bandb_table[i]); | |
339 | } | |
340 | } |