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