handle file part of a command
[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;
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 struct rxpd_file*
137 rxpd_file_new (struct rxpd_base* base, const char* filename)
138 {
139   char buf[4096];
140   struct rxpd_file* self = NULL;
141
142   // TODO better filenname validation / error handling
143   if (!filename ||
144       strchr (filename, '/') ||
145       strlen (filename) + strlen (base->rulesdir) > 4097)
146     return NULL;
147
148   strcpy (buf, base->rulesdir);
149   strcat (buf, filename);
150   filename = strdup (buf);
151   if (filename)
152     {
153       self = malloc (sizeof (struct rxpd_file));
154       if (self)
155         {
156           psplay_init (&self->node, filename);
157           llist_init (&self->rules);
158
159           psplay_insert (&base->files, &self->node);
160         }
161     }
162   return self;
163 }
164
165 void
166 rxpd_file_delete (PSplay f)
167 {
168   if (f)
169     {
170       struct rxpd_file* file = (struct rxpd_file*)f;
171       LLIST_WHILE_HEAD (&file->rules, n)
172         {
173           struct rxpd_rule* node = (struct rxpd_rule*)n;
174           rxpd_rule_delete (node);
175         }
176       free ((void*)file->node.key);
177       free (f);
178     }
179 }
180
181 int
182 rxpd_file_load (struct rxpd_file* self)
183 {
184   const char* filename = self->node.key;
185
186   FILE* f = fopen (filename, "r");
187   // TODO error handling
188   if (f)
189     {
190       // TODO test excess line length = error
191       char buf[4096];
192
193       while (fgets (buf, 4096, f))
194         {
195           size_t last = strlen(buf);
196           if (buf[last-1] == '\n')
197             buf[last-1] = '\0';
198
199           struct rxpd_rule* rule;
200           rule = rxpd_rule_new (buf);
201           if (!rule)
202             abort();
203
204           printf("%s\n", rule->string);
205
206           llist_insert_tail (&self->rules, &rule->node);
207         }
208
209       fclose (f);
210       return 1;
211     }
212   else
213     return 0;
214 }
215
216 int
217 rxpd_file_cmp (const void* A, const void* B)
218 {
219   return strcmp (A, B);
220 }
221
222
223 //
224
225 struct rxpd_socket*
226 rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short port)
227 {
228   struct rxpd_socket* self = malloc (sizeof (struct rxpd_socket));
229   if (!self)
230     abort();
231
232   self->base = base;
233
234   llist_init (&self->node);
235
236   self->fd = socket (PF_INET, SOCK_STREAM, 0);
237   if (self->fd == -1)
238     abort ();
239
240   struct sockaddr_in listen_addr;
241   memset (&listen_addr, 0, sizeof (listen_addr));
242
243   listen_addr.sin_family = AF_INET;
244   if (inet_aton (addr?addr:"0.0.0.0", &listen_addr.sin_addr) == 0)
245     abort();
246   listen_addr.sin_port = htons(port);
247
248   if (bind (self->fd, (struct sockaddr*)&listen_addr, sizeof (listen_addr)) == -1)
249     abort();
250
251   static int yes = 1;
252   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
253     abort ();
254
255   if (listen (self->fd, 20) == -1)
256     abort ();
257
258   event_set (&self->ev, self->fd, EV_READ, rxpd_socket_accept, self);
259   llist_insert_tail (&base->sockets_pending, &self->node);
260   return self;
261 }
262
263
264 void
265 rxpd_socket_delete (struct rxpd_socket* self)
266 {
267   if (self)
268     {
269       event_del (&self->ev);
270       llist_unlink (&self->node);
271       close (self->fd);
272     }
273   free (self);
274 }
275
276 struct rxpd_socket*
277 rxpd_socket_activate (struct rxpd_socket* self)
278 {
279   if (self)
280     {
281       llist_insert_head (&self->base->sockets_active, &self->node);
282       event_add (&self->ev, NULL);
283     }
284   return self;
285 }
286
287 struct rxpd_socket*
288 rxpd_socket_suspend (struct rxpd_socket* self)
289 {
290   if (self)
291     {
292       event_del (&self->ev);
293       llist_insert_tail (&self->base->sockets_pending, &self->node);
294     }
295   return self;
296 }
297
298 void
299 rxpd_socket_accept (int fd, short event, void* ptr)
300 {
301   printf ("incoming connection\n");
302
303   struct rxpd_socket* self = ptr;
304
305   struct rxpd_connection* conn =
306     rxpd_connection_new (self->base, fd);
307
308   rxpd_connection_activate (conn);
309   rxpd_socket_activate (self);
310 }
311
312 ///
313
314 struct rxpd_buffer*
315 rxpd_buffer_init (struct rxpd_buffer* self, struct rxpd_connection* conn)
316 {
317   self->conn = conn;
318   self->state = RXPD_OK;
319   self->eol = self->eob = self->buffer;
320   self->buffer [4095] = '\0';
321   return self;
322 }
323
324
325 char*
326 rxpd_buffer_readline (struct rxpd_buffer* self, int again)
327 {
328   int fd = self->conn->fd;
329
330   if (self->eol != self->buffer)
331     {
332       //there was a line pending, discard it now
333       memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
334       self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
335       self->eol = self->buffer;
336       // TODO handle \r's
337     }
338
339   if (!again && self->state == RXPD_OK)   // we only read when again is 0, first iteration
340     {
341       ssize_t r = 0;
342       do
343         {
344           r = read(fd, self->eob, 4096 - (self->eob - self->buffer));
345         }
346       while (r == -1 && errno == EINTR);
347
348       if (r == -1)
349         self->state = RXPD_ERROR;
350
351       if (r == 0)
352         {
353           shutdown (fd, SHUT_RD);
354           self->state = RXPD_EOF;
355         }
356
357       self->eob += r;
358     }
359
360   // find next newline, terminate string there
361   for (char* i = self->buffer; i < self->eob; ++i)
362     {
363       if (*i == '\n')
364         {
365           *i = '\0';
366           self->eol = i;
367           break;
368         }
369     }
370
371   // TODO handle buffer overfulls
372
373   return self->eol == self->buffer ? NULL : self->buffer;
374 }
375
376 /*
377 void
378 rxpd_buffer_write(int fd, short event, void* ptr)
379 {
380   struct rxpd_buffer* self = (struct rxpd_buffer*) ptr;
381
382   ssize_t n = write(int fd, const void *buf, size_t count);
383
384 }
385 */
386
387 int
388 rxpd_buffer_printf (struct rxpd_buffer* self, const char* fmt, ...)
389 {
390   // for now we do a blocking write, needs to be fixed some day
391   // add string to buffer
392   va_list ap;
393   va_start(ap, fmt);
394   //int sz = self->buffer+4096 - self->eob;
395   int n = vsnprintf (self->buffer, 4096, fmt, ap);
396   va_end(ap);
397
398   write (self->conn->fd, self->buffer, n);
399
400   if (n>4095)
401     return 0;
402
403   return 1;
404 }
405
406
407
408
409 ///
410
411 struct rxpd_connection*
412 rxpd_connection_new (struct rxpd_base* base, int fd)
413 {
414   struct rxpd_connection* self = malloc (sizeof (struct rxpd_connection));
415   if (!self)
416     abort();
417
418   llist_init (&self->node);
419
420   socklen_t addr_sz = sizeof (self->peer_addr); 
421   self->fd = accept (fd, (struct sockaddr*)&self->peer_addr, &addr_sz);
422   if (self->fd == -1)
423     abort ();
424
425   static int yes = 1;
426   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
427     abort ();
428
429   self->base = base;
430   self->file = NULL;
431
432   rxpd_buffer_init (&self->in, self);
433   rxpd_buffer_init (&self->out, self);
434   
435   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
436
437   llist_insert_tail (&base->connections_pending, &self->node);
438
439   return self;
440 }
441
442 void
443 rxpd_connection_delete (struct rxpd_connection* self)
444 {
445   if (self)
446     {
447       event_del (&self->ev);
448       llist_unlink (&self->node);
449       close (self->fd);
450     }
451   free (self);
452 }
453
454 struct rxpd_connection*
455 rxpd_connection_activate (struct rxpd_connection* self)
456 {
457   if (self)
458     {
459       llist_insert_tail (&self->base->connections_active, &self->node);
460       event_add (&self->ev, NULL);
461     }
462   return self;
463 }
464
465 struct rxpd_connection*
466 rxpd_connection_suspend (struct rxpd_connection* self)
467 {
468   if (self)
469     {
470       event_del (&self->ev);
471       llist_insert_tail (&self->base->connections_pending, &self->node);
472     }
473   return self;
474 }
475
476 void
477 rxpd_connection_parse_cmd (int fd, short event, void* ptr)
478 {
479   printf ("parse cmd\n");
480   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
481
482   char* line;
483   while (!(line = rxpd_buffer_readline (&self->in, 0)) && (rxpd_buffer_state (&self->in) == RXPD_OK));
484
485   if (!line)
486     {
487       rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
488       close (fd);
489       return;
490     }
491
492   static const struct cmd_table
493   {
494     enum rxpd_cmd_e nr;
495     const char* cmd;
496     size_t sz;
497   } cmds[] =
498     {
499 #define RXPD_CMD(cmd) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
500       RXPD_COMMANDS
501 #undef RXPD_CMD
502       {0, NULL, 0}
503     };
504
505   const struct cmd_table* i;
506   for (i = cmds; i->cmd; ++i)
507     if (strncmp (line, i->cmd, i->sz) == 0)
508       break;
509   if (!i->cmd)
510     {
511       rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
512       rxpd_connection_delete (self);
513       return;
514     }
515   // TODO policy check here
516
517   if (line[i->sz])
518     {
519       // rulename provided
520       self->file = (struct rxpd_file*) psplay_find (&self->base->files, &line[i->sz]);
521       if (!self->file)
522         {
523           self->file = rxpd_file_new (self->base, &line[i->sz]);
524           if (!self->file)
525             {
526               rxpd_buffer_printf (&self->out, "#ERROR: illegal rule\n");
527               rxpd_connection_delete (self);
528               return;
529             }
530         }
531     }
532
533   // dispatch
534   switch (i->nr)
535     {
536 #define RXPD_CMD(cmd)                                                           \
537 case RXPD_CMD_##cmd:                                                            \
538   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_cmd_##cmd, self);    \
539   break;
540       RXPD_COMMANDS
541 #undef RXPD_CMD
542     }
543   rxpd_connection_activate (self);
544 }
545
546 void
547 rxpd_connection_cmd_CHECK (int fd, short event, void* ptr)
548 {
549   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
550   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
551 }
552
553 void
554 rxpd_connection_cmd_APPEND (int fd, short event, void* ptr)
555 {
556   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
557   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
558 }
559
560 void
561 rxpd_connection_cmd_PREPEND (int fd, short event, void* ptr)
562 {
563   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
564   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
565 }
566
567 void
568 rxpd_connection_cmd_REMOVE (int fd, short event, void* ptr)
569 {
570   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
571   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
572 }
573
574 void
575 rxpd_connection_cmd_REPLACE (int fd, short event, void* ptr)
576 {
577   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
578   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
579 }
580
581 void
582 rxpd_connection_cmd_LOAD (int fd, short event, void* ptr)
583 {
584   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
585   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
586 }
587
588 void
589 rxpd_connection_cmd_SAVE (int fd, short event, void* ptr)
590 {
591   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
592   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
593 }
594
595 void
596 rxpd_connection_cmd_DUMP (int fd, short event, void* ptr)
597 {
598   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
599   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
600 }
601
602 void
603 rxpd_connection_cmd_LIST (int fd, short event, void* ptr)
604 {
605   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
606   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
607 }
608
609 void
610 rxpd_connection_cmd_SHUTDOWN (int fd, short event, void* ptr)
611 {
612   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
613   rxpd_buffer_printf (&self->out, "#ERROR: unimplemented command %s\n", &__func__[20]);
614 }
615