first buffer, readline implementation
[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_tail (&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* sock = ptr;
290
291   struct rxpd_connection* conn =
292     rxpd_connection_new (sock->base, fd);
293
294   rxpd_connection_activate (conn);
295 }
296
297 ///
298
299 struct rxpd_buffer*
300 rxpd_buffer_init (struct rxpd_buffer* self, struct rxpd_connection* conn)
301 {
302   self->conn = conn;
303   self->state = RXPD_OK;
304   self->eol = self->eob = self->buffer;
305   self->buffer [4095] = '\0';
306   return self;
307 }
308
309
310 char*
311 rxpd_buffer_readline (struct rxpd_buffer* self, int again)
312 {
313   int fd = self->conn->fd;
314
315   if (self->eol != self->buffer)
316     {
317       //there was a line pending, discard it now
318       memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
319       self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
320       self->eol = self->buffer;
321       // TODO handle \r's
322     }
323
324   if (!again && self->state == RXPD_OK)   // we only read when again is 0, first iteration
325     {
326       ssize_t r = 0;
327       do
328         {
329           r = read(fd, self->eob, 4096 - (self->eob - self->buffer));
330         }
331       while (r == -1 && errno == EINTR);
332
333       if (r == -1)
334         self->state = RXPD_ERROR;
335
336       if (r == 0)
337         {
338           shutdown (fd, SHUT_RD);
339           self->state = RXPD_EOF;
340         }
341
342       self->eob += r;
343     }
344
345   // find next newline, terminate string there
346   for (char* i = self->buffer; i < self->eob; ++i)
347     {
348       if (*i == '\n')
349         {
350           *i = '\0';
351           self->eol = i;
352           break;
353         }
354     }
355
356   // TODO handle buffer overfulls
357  
358   return self->eol == self->buffer ? NULL : self->buffer;
359 }
360
361
362
363
364 ///
365
366 struct rxpd_connection*
367 rxpd_connection_new (struct rxpd_base* base, int fd)
368 {
369   struct rxpd_connection* self = malloc (sizeof (struct rxpd_connection));
370   if (!self)
371     abort();
372
373   llist_init (&self->node);
374
375   socklen_t addr_sz = sizeof (self->peer_addr); 
376   self->fd = accept (fd, (struct sockaddr*)&self->peer_addr, &addr_sz);
377   if (self->fd == -1)
378     abort ();
379
380   static int yes = 1;
381   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
382     abort ();
383
384
385   self->base = base;
386   self->file = NULL;
387
388   rxpd_buffer_init (&self->in, self);
389   rxpd_buffer_init (&self->out, self);
390   
391   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
392
393   llist_insert_tail (&base->connections_pending, &self->node);
394
395   return self;
396 }
397
398 void
399 rxpd_connection_delete (struct rxpd_connection* self)
400 {
401   if (self)
402     {
403       event_del (&self->ev);
404       llist_unlink (&self->node);
405       close (self->fd);
406     }
407   free (self);
408 }
409
410 struct rxpd_connection*
411 rxpd_connection_activate (struct rxpd_connection* self)
412 {
413   if (self)
414     {
415       llist_insert_tail (&self->base->connections_active, &self->node);
416       event_add (&self->ev, NULL);
417     }
418   return self;
419 }
420
421 struct rxpd_connection*
422 rxpd_connection_suspend (struct rxpd_connection* self)
423 {
424   if (self)
425     {
426       event_del (&self->ev);
427       llist_insert_tail (&self->base->connections_pending, &self->node);
428     }
429   return self;
430 }
431
432
433 void
434 rxpd_connection_parse_cmd (int sock, short event, void* ptr)
435 {
436   printf ("parse cmd\n");
437   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
438
439   char* line;
440   line = rxpd_buffer_readline (&self->in, 0);
441   printf ("got line '%s'\n", line);
442
443
444   // TODO policy check
445
446   //if (rxpd_buffer_state (&self->in) != RXPD_EOF)
447   //  event_add (&self->ev, NULL);
448 }
449
450 void
451 rxpd_connection_cmd_CHECK (int sock, short event, void* ptr)
452 {
453 }
454
455 void
456 rxpd_connection_cmd_APPEND (int sock, short event, void* ptr)
457 {
458 }
459
460 void
461 rxpd_connection_cmd_PREPEND (int sock, short event, void* ptr)
462 {
463 }
464
465 void
466 rxpd_connection_cmd_REMOVE (int sock, short event, void* ptr)
467 {
468 }
469
470 void
471 rxpd_connection_cmd_REPLACE (int sock, short event, void* ptr)
472 {
473 }
474
475 void
476 rxpd_connection_cmd_LOAD (int sock, short event, void* ptr)
477 {
478 }
479
480 void
481 rxpd_connection_cmd_SAVE (int sock, short event, void* ptr)
482 {
483 }
484
485 void
486 rxpd_connection_cmd_DUMP (int sock, short event, void* ptr)
487 {
488 }
489
490 void
491 rxpd_connection_cmd_LIST (int sock, short event, void* ptr)
492 {
493 }
494
495 void
496 rxpd_connection_cmd_END (int sock, short event, void* ptr)
497 {
498 }
499
500