WIP: skeleton/planning
[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) + 9);
103               if (!self->string) abort();
104               strcpy (self->string, "# ");
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[2048];
140
141   // TODO better filenname validation / error handling
142   if (!filename ||
143       strchr (filename, '/') ||
144       strlen (filename) + strlen (base->rulesdir) > 2047)
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, 2048, 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
251 void
252 rxpd_socket_delete (struct rxpd_socket* self)
253 {
254   llist_unlink (&self->node);
255   event_del (&self->ev);
256   close (self->fd);
257 }
258
259 struct rxpd_socket*
260 rxpd_socket_activate (struct rxpd_socket* self)
261 {
262   if (self)
263     {
264       llist_insert_tail (&self->base->sockets_active, &self->node);
265       event_add (&self->ev, NULL);
266     }
267   return self;
268 }
269
270 struct rxpd_socket*
271 rxpd_socket_suspend (struct rxpd_socket* self)
272 {
273   if (self)
274     {
275       llist_insert_tail (&self->base->sockets_pending, &self->node);
276       event_del (&self->ev);
277     }
278   return self;
279 }
280
281 void
282 rxpd_socket_accept (int sock, short event, void* ptr)
283 {
284   printf ("incoming connection\n");
285
286   //struct rxpd_connection* conn;
287 }
288
289 ///
290
291 struct rxpd_connection*
292 rxpd_connection_new (struct rxpd_base* base)
293 {
294   return NULL;
295 }
296
297 void
298 rxpd_connection_delete (struct rxpd_connection* self)
299 {
300   free (self);
301 }
302
303 int
304 rxpd_connection_readline (struct rxpd_connection* self)
305 {
306 }
307
308 void
309 rxpd_connection_parse_cmd (int sock, short event, void* ptr)
310 {
311 }
312
313 void
314 rxpd_connection_cmd_CHECK (int sock, short event, void* ptr)
315 {
316 }
317
318 void
319 rxpd_connection_cmd_APPEND (int sock, short event, void* ptr)
320 {
321 }
322
323 void
324 rxpd_connection_cmd_PREPEND (int sock, short event, void* ptr)
325 {
326 }
327
328 void
329 rxpd_connection_cmd_REMOVE (int sock, short event, void* ptr)
330 {
331 }
332
333 void
334 rxpd_connection_cmd_REPLACE (int sock, short event, void* ptr)
335 {
336 }
337
338 void
339 rxpd_connection_cmd_LOAD (int sock, short event, void* ptr)
340 {
341 }
342
343 void
344 rxpd_connection_cmd_SAVE (int sock, short event, void* ptr)
345 {
346 }
347
348 void
349 rxpd_connection_cmd_DUMP (int sock, short event, void* ptr)
350 {
351 }
352
353 void
354 rxpd_connection_cmd_LIST (int sock, short event, void* ptr)
355 {
356 }
357
358 void
359 rxpd_connection_cmd_END (int sock, short event, void* ptr)
360 {
361 }
362
363