]> jfr.im git - solanum.git/blob - bandb/bandb.c
Merge branch 'master' into authd-framework-2
[solanum.git] / bandb / bandb.c
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 "common.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)
241 {
242 if(in_transaction)
243 rsdb_transaction(RSDB_TRANS_END);
244 exit(1);
245 }
246
247 #ifndef WINDOWS
248 static void
249 dummy_handler(int sig)
250 {
251 return;
252 }
253 #endif
254
255 static void
256 setup_signals(void)
257 {
258 #ifndef _WIN32
259 struct sigaction act;
260
261 act.sa_flags = 0;
262 act.sa_handler = SIG_IGN;
263 sigemptyset(&act.sa_mask);
264 sigaddset(&act.sa_mask, SIGPIPE);
265 sigaddset(&act.sa_mask, SIGALRM);
266 #ifdef SIGTRAP
267 sigaddset(&act.sa_mask, SIGTRAP);
268 #endif
269
270 #ifdef SIGWINCH
271 sigaddset(&act.sa_mask, SIGWINCH);
272 sigaction(SIGWINCH, &act, 0);
273 #endif
274 sigaction(SIGPIPE, &act, 0);
275 #ifdef SIGTRAP
276 sigaction(SIGTRAP, &act, 0);
277 #endif
278
279 act.sa_handler = dummy_handler;
280 sigaction(SIGALRM, &act, 0);
281 #endif
282 }
283
284
285 static void
286 db_error_cb(const char *errstr)
287 {
288 char buf[256];
289 snprintf(buf, sizeof(buf), "! :%s", errstr);
290 rb_helper_write(bandb_helper, "%s", buf);
291 rb_sleep(2 << 30, 0);
292 exit(1);
293 }
294
295 int
296 main(int argc, char *argv[])
297 {
298 setup_signals();
299 bandb_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256, 256, 256); /* XXX fix me */
300 if(bandb_helper == NULL)
301 {
302 fprintf(stderr,
303 "This is the charybdis bandb for internal ircd use.\n");
304 fprintf(stderr,
305 "You aren't supposed to run me directly (did you want bantool?). Exiting.\n");
306 exit(1);
307 }
308 rsdb_init(db_error_cb);
309 check_schema();
310 rb_helper_loop(bandb_helper, 0);
311
312 return 0;
313 }
314
315 static void
316 check_schema(void)
317 {
318 struct rsdb_table table;
319 int i;
320
321 for(i = 0; i < LAST_BANDB_TYPE; i++)
322 {
323 rsdb_exec_fetch(&table,
324 "SELECT name FROM sqlite_master WHERE type='table' AND name='%s'",
325 bandb_table[i]);
326
327 rsdb_exec_fetch_end(&table);
328
329 if(!table.row_count)
330 rsdb_exec(NULL,
331 "CREATE TABLE %s (mask1 TEXT, mask2 TEXT, oper TEXT, time INTEGER, perm INTEGER, reason TEXT)",
332 bandb_table[i]);
333 }
334 }