command dispatcher
[rxpd] / rxpd.c
1 /*
2     rxpd.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "rxpd.h"
23
24 static struct rxpd_base global_base = {NULL};
25
26 struct rxpd_base*
27 rxpd_init (char* rulesdir)
28 {
29   if (global_base.rulesdir)
30     return NULL;
31
32   global_base.rulesdir = strdup (rulesdir);
33   if (!global_base.rulesdir) abort();
34
35   psplay_init_root (&global_base.files, rxpd_file_cmp, rxpd_file_delete);
36
37   llist_init (&global_base.sockets_pending);
38   llist_init (&global_base.sockets_active);
39   llist_init (&global_base.connections_pending);
40   llist_init (&global_base.connections_active);
41
42   return &global_base;
43 }
44
45 void
46 rxpd_destroy (void)
47 {
48   if (global_base.rulesdir)
49     {
50       free (global_base.rulesdir);
51       psplay_destroy_root (&global_base.files);
52       LLIST_WHILE_HEAD (&global_base.sockets_pending, n)
53         {
54           struct rxpd_socket* socket = (struct rxpd_socket*)n;
55           rxpd_socket_delete (socket);
56         }
57       LLIST_WHILE_HEAD (&global_base.sockets_active, n)
58         {
59           struct rxpd_socket* socket = (struct rxpd_socket*)n;
60           rxpd_socket_delete (socket);
61         }
62       LLIST_WHILE_HEAD (&global_base.connections_pending, n)
63         {
64           struct rxpd_connection* connection = (struct rxpd_connection*)n;
65           rxpd_connection_delete (connection);
66         }
67       LLIST_WHILE_HEAD (&global_base.connections_active, n)
68         {
69           struct rxpd_connection* connection = (struct rxpd_connection*)n;
70           rxpd_connection_delete (connection);
71         }
72     }
73 }
74
75
76 //
77 struct rxpd_rule*
78 rxpd_rule_new (const char* buf)
79 {
80   struct rxpd_rule* self = malloc (sizeof (struct rxpd_rule));
81   if (self)
82     {
83       llist_init (&self->node);
84
85       if (*buf != '#')
86         {
87           int err;
88           char* rxstart = strchr (buf, ':') + 1;
89
90           err = regcomp (&self->rx, rxstart, REG_EXTENDED|REG_ICASE|REG_NOSUB);
91
92           if (!err)
93             {
94               self->string = strdup (buf);
95               if (!self->string) abort();
96             }
97           else
98             {
99               regfree (&self->rx);
100               char ebuf[256];
101               size_t len = regerror (err, NULL, ebuf, 256);
102               self->string = malloc(len + strlen(buf) + 14);
103               if (!self->string) abort();
104               strcpy (self->string, "#ERROR ");
105               strcat (self->string, ebuf);
106               strcat (self->string, " in '");
107               strcat (self->string, buf);
108               strcat (self->string, "'");
109             }
110         }
111       else
112         {
113           self->string = strdup (buf);
114           if (!self->string) abort();
115         }
116     }
117   return self;
118 }
119
120 void
121 rxpd_rule_delete (struct rxpd_rule* rule)
122 {
123   if (rule)
124     {
125       llist_unlink (&rule->node);
126       if (rule->string[0] != '#')
127         regfree (&rule->rx);
128       free (rule->string);
129       free(rule);
130     }
131 }
132
133 //
134
135
136 int
137 rxpd_file_load (struct rxpd_base* base, const char* filename)
138 {
139   char buf[4096];
140
141   // TODO better filenname validation / error handling
142   if (!filename ||
143       strchr (filename, '/') ||
144       strlen (filename) + strlen (base->rulesdir) > 4097)
145     abort();
146
147   strcpy (buf, base->rulesdir);
148   strcat (buf, filename);
149   filename = strdup (buf);
150
151   struct rxpd_file* file = malloc (sizeof (struct rxpd_file));
152   if (!file || !filename) abort();
153
154   psplay_init (&file->node, filename);
155   llist_init (&file->rules);
156   
157   FILE* f = fopen (filename, "r");
158   // TODO error handling
159   if (!f) abort();
160
161   // TODO test excess line length = error
162   while (fgets (buf, 4096, f))
163     {
164       size_t last = strlen(buf);
165       if (buf[last-1] == '\n')
166         buf[last-1] = '\0';
167
168       struct rxpd_rule* rule;
169       rule = rxpd_rule_new (buf);
170       if (!rule)
171         abort();
172
173
174       printf("%s\n", rule->string);
175
176       llist_insert_tail (&file->rules, &rule->node);
177     }
178
179   fclose (f);
180
181   psplay_insert (&base->files, &file->node);
182
183   return 0;
184 }
185
186 void
187 rxpd_file_delete (PSplay f)
188 {
189   if (f)
190     {
191       struct rxpd_file* file = (struct rxpd_file*)f;
192       LLIST_WHILE_HEAD (&file->rules, n)
193         {
194           struct rxpd_rule* node = (struct rxpd_rule*)n;
195           rxpd_rule_delete (node);
196         }
197       free ((void*)file->node.key);
198       free (f);
199     }
200 }
201
202 int
203 rxpd_file_cmp (const void* A, const void* B)
204 {
205   return strcmp (A, B);
206 }
207
208
209 //
210
211 struct rxpd_socket*
212 rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short port)
213 {
214   struct rxpd_socket* self = malloc (sizeof (struct rxpd_socket));
215   if (!self)
216     abort();
217
218   self->base = base;
219
220   llist_init (&self->node);
221
222   self->fd = socket (PF_INET, SOCK_STREAM, 0);
223   if (self->fd == -1)
224     abort ();
225
226   struct sockaddr_in listen_addr;
227   memset (&listen_addr, 0, sizeof (listen_addr));
228
229   listen_addr.sin_family = AF_INET;
230   if (inet_aton (addr?addr:"0.0.0.0", &listen_addr.sin_addr) == 0)
231     abort();
232   listen_addr.sin_port = htons(port);
233
234   if (bind (self->fd, (struct sockaddr*)&listen_addr, sizeof (listen_addr)) == -1)
235     abort();
236
237   static int yes = 1;
238   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
239     abort ();
240
241   if (listen (self->fd, 20) == -1)
242     abort ();
243
244   event_set (&self->ev, self->fd, EV_READ, rxpd_socket_accept, self);
245   llist_insert_tail (&base->sockets_pending, &self->node);
246   return self;
247 }
248
249
250 void
251 rxpd_socket_delete (struct rxpd_socket* self)
252 {
253   if (self)
254     {
255       event_del (&self->ev);
256       llist_unlink (&self->node);
257       close (self->fd);
258     }
259   free (self);
260 }
261
262 struct rxpd_socket*
263 rxpd_socket_activate (struct rxpd_socket* self)
264 {
265   if (self)
266     {
267       llist_insert_head (&self->base->sockets_active, &self->node);
268       event_add (&self->ev, NULL);
269     }
270   return self;
271 }
272
273 struct rxpd_socket*
274 rxpd_socket_suspend (struct rxpd_socket* self)
275 {
276   if (self)
277     {
278       event_del (&self->ev);
279       llist_insert_tail (&self->base->sockets_pending, &self->node);
280     }
281   return self;
282 }
283
284 void
285 rxpd_socket_accept (int fd, short event, void* ptr)
286 {
287   printf ("incoming connection\n");
288
289   struct rxpd_socket* self = ptr;
290
291   struct rxpd_connection* conn =
292     rxpd_connection_new (self->base, fd);
293
294   rxpd_connection_activate (conn);
295   rxpd_socket_activate (self);
296 }
297
298 ///
299
300 struct rxpd_buffer*
301 rxpd_buffer_init (struct rxpd_buffer* self, struct rxpd_connection* conn)
302 {
303   self->conn = conn;
304   self->state = RXPD_OK;
305   self->eol = self->eob = self->buffer;
306   self->buffer [4095] = '\0';
307   return self;
308 }
309
310
311 char*
312 rxpd_buffer_readline (struct rxpd_buffer* self, int again)
313 {
314   int fd = self->conn->fd;
315
316   if (self->eol != self->buffer)
317     {
318       //there was a line pending, discard it now
319       memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
320       self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
321       self->eol = self->buffer;
322       // TODO handle \r's
323     }
324
325   if (!again && self->state == RXPD_OK)   // we only read when again is 0, first iteration
326     {
327       ssize_t r = 0;
328       do
329         {
330           r = read(fd, self->eob, 4096 - (self->eob - self->buffer));
331         }
332       while (r == -1 && errno == EINTR);
333
334       if (r == -1)
335         self->state = RXPD_ERROR;
336
337       if (r == 0)
338         {
339           shutdown (fd, SHUT_RD);
340           self->state = RXPD_EOF;
341         }
342
343       self->eob += r;
344     }
345
346   // find next newline, terminate string there
347   for (char* i = self->buffer; i < self->eob; ++i)
348     {
349       if (*i == '\n')
350         {
351           *i = '\0';
352           self->eol = i;
353           break;
354         }
355     }
356
357   // TODO handle buffer overfulls
358
359   return self->eol == self->buffer ? NULL : self->buffer;
360 }
361
362 /*
363 void
364 rxpd_buffer_write(int fd, short event, void* ptr)
365 {
366   struct rxpd_buffer* self = (struct rxpd_buffer*) ptr;
367
368   ssize_t n = write(int fd, const void *buf, size_t count);
369
370 }
371 */
372
373 int
374 rxpd_buffer_printf (struct rxpd_buffer* self, const char* fmt, ...)
375 {
376   // for now we do a blocking write, needs to be fixed some day
377   // add string to buffer
378   va_list ap;
379   va_start(ap, fmt);
380   //int sz = self->buffer+4096 - self->eob;
381   int n = vsnprintf (self->buffer, 4096, fmt, ap);
382   va_end(ap);
383
384   write (self->conn->fd, self->buffer, n);
385
386   if (n>4095)
387     return 0;
388
389   return 1;
390 }
391
392
393
394
395 ///
396
397 struct rxpd_connection*
398 rxpd_connection_new (struct rxpd_base* base, int fd)
399 {
400   struct rxpd_connection* self = malloc (sizeof (struct rxpd_connection));
401   if (!self)
402     abort();
403
404   llist_init (&self->node);
405
406   socklen_t addr_sz = sizeof (self->peer_addr); 
407   self->fd = accept (fd, (struct sockaddr*)&self->peer_addr, &addr_sz);
408   if (self->fd == -1)
409     abort ();
410
411   static int yes = 1;
412   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
413     abort ();
414
415   self->base = base;
416   self->file = NULL;
417
418   rxpd_buffer_init (&self->in, self);
419   rxpd_buffer_init (&self->out, self);
420   
421   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
422
423   llist_insert_tail (&base->connections_pending, &self->node);
424
425   return self;
426 }
427
428 void
429 rxpd_connection_delete (struct rxpd_connection* self)
430 {
431   if (self)
432     {
433       event_del (&self->ev);
434       llist_unlink (&self->node);
435       close (self->fd);
436     }
437   free (self);
438 }
439
440 struct rxpd_connection*
441 rxpd_connection_activate (struct rxpd_connection* self)
442 {
443   if (self)
444     {
445       llist_insert_tail (&self->base->connections_active, &self->node);
446       event_add (&self->ev, NULL);
447     }
448   return self;
449 }
450
451 struct rxpd_connection*
452 rxpd_connection_suspend (struct rxpd_connection* self)
453 {
454   if (self)
455     {
456       event_del (&self->ev);
457       llist_insert_tail (&self->base->connections_pending, &self->node);
458     }
459   return self;
460 }
461
462
463 void
464 rxpd_connection_parse_cmd (int fd, short event, void* ptr)
465 {
466   printf ("parse cmd\n");
467   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
468
469   char* line;
470   while (!(line = rxpd_buffer_readline (&self->in, 0)) && (rxpd_buffer_state (&self->in) == RXPD_OK));
471
472   if (!line)
473     {
474       printf ("got no data\n");
475       close (fd);
476       return;
477     }
478
479
480
481   static const struct cmd_table
482   {
483     enum rxpd_cmd_e nr;
484     const char* cmd;
485     size_t sz;
486   } cmds[] =
487     {
488 #define RXPD_CMD(cmd) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
489       RXPD_COMMANDS
490 #undef RXPD_CMD
491       {0, NULL, 0}
492     };
493
494   const struct cmd_table* i;
495   for (i = cmds; i->cmd; ++i)
496     if (strncmp (line, i->cmd, i->sz) == 0)
497       break;
498   if (!i->cmd)
499     {
500       printf ("no command\n");
501       rxpd_connection_delete (self);
502       return;
503     }
504   // TODO policy check
505
506   // dispatch
507   switch (i->nr)
508     {
509 #define RXPD_CMD(cmd)                                                           \
510 case RXPD_CMD_##cmd:                                                            \
511   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_cmd_##cmd, self);    \
512   break;
513       RXPD_COMMANDS
514 #undef RXPD_CMD
515     }
516   rxpd_connection_activate (self);
517 }
518
519 void
520 rxpd_connection_cmd_CHECK (int fd, short event, void* ptr)
521 {
522   printf ("%s\n", __func__);
523 }
524
525 void
526 rxpd_connection_cmd_APPEND (int fd, short event, void* ptr)
527 {
528   printf ("%s\n", __func__);
529 }
530
531 void
532 rxpd_connection_cmd_PREPEND (int fd, short event, void* ptr)
533 {
534   printf ("%s\n", __func__);
535 }
536
537 void
538 rxpd_connection_cmd_REMOVE (int fd, short event, void* ptr)
539 {
540   printf ("%s\n", __func__);
541 }
542
543 void
544 rxpd_connection_cmd_REPLACE (int fd, short event, void* ptr)
545 {
546   printf ("%s\n", __func__);
547 }
548
549 void
550 rxpd_connection_cmd_LOAD (int fd, short event, void* ptr)
551 {
552   printf ("%s\n", __func__);
553 }
554
555 void
556 rxpd_connection_cmd_SAVE (int fd, short event, void* ptr)
557 {
558   printf ("%s\n", __func__);
559 }
560
561 void
562 rxpd_connection_cmd_DUMP (int fd, short event, void* ptr)
563 {
564   printf ("%s\n", __func__);
565 }
566
567 void
568 rxpd_connection_cmd_LIST (int fd, short event, void* ptr)
569 {
570   printf ("%s\n", __func__);
571 }
572