bd77371e8589f6e9fc38a968e5e27014706b03a7
[olsrd.git] / lib / tas / src / plugin.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * Copyright (c) 2004, Thomas Lopatic (thomas@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright 
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright 
14  *   notice, this list of conditions and the following disclaimer in 
15  *   the documentation and/or other materials provided with the 
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its 
18  *   contributors may be used to endorse or promote products derived 
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  * $Id: plugin.c,v 1.1 2005/04/12 17:17:26 tlopatic Exp $
41  */
42
43 #include <string.h>
44 #include <time.h> // clock_t required by olsrd includes
45
46 #include "link.h"
47 #include "plugin.h"
48 #include "lib.h"
49 #include "os_unix.h"
50 #include "http.h"
51 #include "glua.h"
52 #include "glua_ext.h"
53
54 #include <olsr_plugin_io.h>
55 #include <plugin_loader.h>
56 #include <link_set.h>
57 #include <neighbor_table.h>
58 #include <two_hop_neighbor_table.h>
59 #include <mid_set.h>
60 #include <tc_set.h>
61 #include <hna_set.h>
62 #include <routing_table.h>
63 #include <olsr_protocol.h>
64 #include <lq_route.h>
65
66 #define MESSAGE_TYPE 129
67
68 int get_plugin_interface_version(void);
69 int plugin_io(int cmd, void *data, int len);
70 int register_olsr_data(struct olsr_plugin_data *data);
71 int register_olsr_param(char *name, char *value);
72
73 static int ipAddrLen;
74 static union olsr_ip_addr *mainAddr;
75
76 static struct interface *intTab = NULL;
77 static struct neighbor_entry *neighTab = NULL;
78 static struct neighbor_2_entry *neigh2Tab = NULL;
79 static struct mid_entry *midTab = NULL;
80 static struct tc_entry *tcTab = NULL;
81 static struct hna_entry *hnaTab = NULL;
82 static struct rt_entry *routeTab = NULL;
83 static struct olsrd_config *config = NULL;
84
85 static int (*pluginIo)(int which, void *data, int len);
86
87 static int (*regTimeout)(void (*timeoutFunc)(void));
88 static int (*regParser)(void (*parserFunc)(unsigned char *mess,
89                                            struct interface *inInt,
90                                            union olsr_ip_addr *neighIntAddr),
91                         int type, int forward);
92 static int (*checkLink)(union olsr_ip_addr *neighIntAddr);
93 static int (*checkDup)(union olsr_ip_addr *origAddr, unsigned short seqNo);
94 static int (*forward)(unsigned char *mess, union olsr_ip_addr *origAddr,
95                       unsigned short seqNo, struct interface *inInt,
96                       union olsr_ip_addr *neighIntAddr);
97
98 static unsigned short (*getSeqNo)(void);
99 static int (*netPush)(struct interface *outInt, void *mess,
100                       unsigned short size);
101 static int (*netOutput)(struct interface *outInt);
102
103 static void *(*lookupMprs)(union olsr_ip_addr *neighAddr);
104
105 static int iterIndex;
106 static struct interface *iterIntTab = NULL;
107 static struct link_entry *iterLinkTab = NULL;
108 static struct neighbor_entry *iterNeighTab = NULL;
109 static struct neighbor_2_entry *iterNeigh2Tab = NULL;
110 static struct mid_entry *iterMidTab = NULL;
111 static struct tc_entry *iterTcTab = NULL;
112 static struct hna_entry *iterHnaTab = NULL;
113 static struct rt_entry *iterRouteTab = NULL;
114
115 static void __attribute__((constructor)) banner(void)
116 {
117   printf("Tiny Application Server 0.1 by olsr.org\n");
118 }
119
120 int iterLinkTabNext(char *buff, int len)
121 {
122   double etx;
123
124   if (iterLinkTab == NULL)
125     return -1;
126
127   if (iterLinkTab->loss_link_quality < MIN_LINK_QUALITY ||
128       iterLinkTab->neigh_link_quality < MIN_LINK_QUALITY)
129     etx = 0.0;
130
131   else
132     etx = 1.0 / (iterLinkTab->loss_link_quality *
133                  iterLinkTab->neigh_link_quality);
134
135   snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~lq~%f~nlq~%f~etx~%f~",
136            rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
137            rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
138            rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
139            iterLinkTab->L_link_quality, iterLinkTab->loss_link_quality,
140            iterLinkTab->neigh_link_quality, etx);
141
142   iterLinkTab = iterLinkTab->next;
143
144   return 0;
145 }
146
147 void iterLinkTabInit(void)
148 {
149   if (pluginIo == NULL)
150   {
151     iterLinkTab = NULL;
152     return;
153   }
154
155   pluginIo(GETD__LINK_SET, &iterLinkTab, sizeof (iterLinkTab));
156 }
157
158 int iterNeighTabNext(char *buff, int len)
159 {
160   if (iterNeighTab == NULL)
161     return -1;
162
163   snprintf(buff, len, "main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~",
164            rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen),
165            iterNeighTab->status == SYM ? "true" : "false",
166            iterNeighTab->is_mpr != 0 ? "true" : "false",
167            lookupMprs(&iterNeighTab->neighbor_main_addr) != NULL ?
168            "true" : "false",
169            iterNeighTab->willingness);
170
171   iterNeighTab = iterNeighTab->next;
172
173   if (iterNeighTab == &neighTab[iterIndex])
174   {
175     iterNeighTab = NULL;
176     
177     while (++iterIndex < HASHSIZE)
178       if (neighTab[iterIndex].next != &neighTab[iterIndex])
179       {
180         iterNeighTab = neighTab[iterIndex].next;
181         break;
182       }
183   }
184
185   return 0;
186 }
187
188 void iterNeighTabInit(void)
189 {
190   iterNeighTab = NULL;
191
192   if (neighTab == NULL)
193     return;
194
195   for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
196     if (neighTab[iterIndex].next != &neighTab[iterIndex])
197     {
198       iterNeighTab = neighTab[iterIndex].next;
199       break;
200     }
201 }
202
203 int iterRouteTabNext(char *buff, int len)
204 {
205   if (iterRouteTab == NULL)
206     return -1;
207
208   snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
209            rawIpAddrToString(&iterRouteTab->rt_dst, ipAddrLen),
210            rawIpAddrToString(&iterRouteTab->rt_router, ipAddrLen),
211            iterRouteTab->rt_if->int_name, iterRouteTab->rt_metric);
212
213   iterRouteTab = iterRouteTab->next;
214
215   if (iterRouteTab == &routeTab[iterIndex])
216   {
217     iterRouteTab = NULL;
218     
219     while (++iterIndex < HASHSIZE)
220       if (routeTab[iterIndex].next != &routeTab[iterIndex])
221       {
222         iterRouteTab = routeTab[iterIndex].next;
223         break;
224       }
225   }
226
227   return 0;
228 }
229
230 void iterRouteTabInit(void)
231 {
232   iterRouteTab = NULL;
233
234   if (routeTab == NULL)
235     return;
236
237   for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
238     if (routeTab[iterIndex].next != &routeTab[iterIndex])
239     {
240       iterRouteTab = routeTab[iterIndex].next;
241       break;
242     }
243 }
244
245 static void parserFunc(unsigned char *mess, struct interface *inInt,
246                        union olsr_ip_addr *neighIntAddr)
247 {
248   union olsr_ip_addr *orig = (union olsr_ip_addr *)(mess + 4);
249   unsigned short seqNo = (mess[ipAddrLen + 6] << 8) | mess[ipAddrLen + 7];
250   int len = (mess[2] << 8) | mess[3];
251   char *service, *string;
252   int i;
253
254   if (memcmp(orig, mainAddr, ipAddrLen) == 0)
255     return;
256
257   if (checkLink(neighIntAddr) != SYM_LINK)
258   {
259     error("TAS message not from symmetric neighbour\n");
260     return;
261   }
262
263   if (len < ipAddrLen + 8 + 2)
264   {
265     error("short TAS message received (%d bytes)\n", len);
266     return;
267   }
268
269   if (checkDup(orig, seqNo) != 0)
270   {
271     len -= ipAddrLen + 8;
272     service = mess + ipAddrLen + 8;
273
274     for (i = 0; i < len && service[i] != 0; i++);
275
276     if (i++ == len)
277     {
278       error("TAS message has unterminated service string\n");
279       return;
280     }
281
282     if (i == len)
283     {
284       error("TAS message lacks payload string\n");
285       return;
286     }
287
288     string = service + i;
289     len -= i;
290
291     for (i = 0; i < len && string[i] != 0; i++);
292
293     if (i == len)
294     {
295       error("TAS message has unterminated payload string\n");
296       return;
297     }
298
299     httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
300   }
301
302   forward(mess, orig, seqNo, inInt, neighIntAddr);
303 }
304
305 void sendMessage(const char *service, const char *string)
306 {
307   unsigned char *mess, *walker;
308   int len, pad;
309   unsigned short seqNo;
310   struct interface *inter;
311
312   pad = len = ipAddrLen + 8 + strlen(service) + 1 + strlen(string) + 1;
313
314   len = 1 + ((len - 1) | 3);
315
316   pad = len - pad;
317
318   walker = mess = allocMem(len);
319
320   seqNo = getSeqNo();
321
322   *walker++ = MESSAGE_TYPE;
323   *walker++ = 0;
324   *walker++ = (unsigned char)(len >> 8);
325   *walker++ = (unsigned char)len;
326
327   memcpy(walker, mainAddr, ipAddrLen);
328   walker += ipAddrLen;
329
330   *walker++ = 255;
331   *walker++ = 0;
332   *walker++ = (unsigned char)(seqNo >> 8);
333   *walker++ = (unsigned char)seqNo;
334
335   while (*service != 0)
336     *walker++ = *service++;
337
338   *walker++ = 0;
339
340   while (*string != 0)
341     *walker++ = *string++;
342
343   *walker++ = 0;
344
345   while (pad-- > 0)
346     *walker++ = 0;
347
348   for (inter = intTab; inter != NULL; inter = inter->int_next)
349   {
350     if (netPush(inter, mess, len) != len)
351     {
352       netOutput(inter);
353       netPush(inter, mess, len);
354     }
355   }
356 }
357
358 static void serviceFunc(void)
359 {
360   static int up = 0;
361
362   if (up == 0)
363   {
364     if (httpSetup() < 0)
365       return;
366
367     up = 1;
368   }
369
370   if (up != 0)
371     httpService((int)(1.0 / config->pollrate));
372 }
373
374 int get_plugin_interface_version(void)
375 {
376   httpInit();
377
378   return 3;
379 }
380
381 int plugin_io(int cmd, void *data, int len)
382 {
383   return 0;
384 }
385
386 int register_olsr_data(struct olsr_plugin_data *data)
387 {
388   ipAddrLen = addrLen(data->ipversion);
389   mainAddr = data->main_addr;
390
391   pluginIo = (int (*)(int, void *, int))data->olsr_plugin_io;
392
393   pluginIo(GETD__IFNET, &intTab, sizeof (intTab));
394   pluginIo(GETD__NEIGHBORTABLE, &neighTab, sizeof (neighTab));
395   pluginIo(GETD__TWO_HOP_NEIGHBORTABLE, &neigh2Tab, sizeof (neigh2Tab));
396   pluginIo(GETD__MID_SET, &midTab, sizeof (midTab));
397   pluginIo(GETD__TC_TABLE, &tcTab, sizeof (tcTab));
398   pluginIo(GETD__HNA_SET, &hnaTab, sizeof (hnaTab));
399   pluginIo(GETD__ROUTINGTABLE, &routeTab, sizeof (routeTab));
400   pluginIo(GETD__OLSR_CNF, &config, sizeof (config));
401
402   pluginIo(GETF__OLSR_REGISTER_TIMEOUT_FUNCTION, &regTimeout,
403            sizeof (regTimeout));
404   pluginIo(GETF__OLSR_PARSER_ADD_FUNCTION, &regParser, sizeof (regParser));
405   pluginIo(GETF__CHECK_NEIGHBOR_LINK, &checkLink, sizeof (checkLink));
406   pluginIo(GETF__OLSR_CHECK_DUP_TABLE_PROC, &checkDup, sizeof (checkDup));
407   pluginIo(GETF__OLSR_FORWARD_MESSAGE, &forward, sizeof (forward));
408
409   pluginIo(GETF__GET_MSG_SEQNO, &getSeqNo, sizeof (getSeqNo));
410   pluginIo(GETF__NET_OUTBUFFER_PUSH, &netPush, sizeof (netPush));
411   pluginIo(GETF__NET_OUTPUT, &netOutput, sizeof (netOutput));
412
413   pluginIo(GETF__OLSR_LOOKUP_MPRS_SET, &lookupMprs, sizeof (lookupMprs));
414
415   regTimeout(serviceFunc);
416   regParser(parserFunc, MESSAGE_TYPE, 1);
417
418   return 0;
419 }
420
421 int register_olsr_param(char *name, char *value)
422 {
423   if (strcmp(name, "address") == 0)
424   {
425     if (httpSetAddress(value) < 0)
426       return 0;
427
428     return 1;
429   }
430
431   if (strcmp(name, "port") == 0)
432   {
433     if (httpSetPort(value) < 0)
434       return 0;
435
436     return 1;
437   }
438
439   if (strcmp(name, "rootdir") == 0)
440   {
441     if (httpSetRootDir(value) < 0)
442       return 0;
443
444     return 1;
445   }
446
447   if (strcmp(name, "workdir") == 0)
448   {
449     if (httpSetWorkDir(value) < 0)
450       return 0;
451
452     return 1;
453   }
454
455   if (strcmp(name, "indexfile") == 0)
456   {
457     httpSetIndexFile(value);
458     return 1;
459   }
460
461   if (strcmp(name, "user") == 0)
462   {
463     httpSetUser(value);
464     return 1;
465   }
466
467   if (strcmp(name, "password") == 0)
468   {
469     httpSetPassword(value);
470     return 1;
471   }
472
473   if (strcmp(name, "sesstime") == 0)
474   {
475     if (httpSetSessTime(value) < 0)
476       return 0;
477
478     return 1;
479   }
480
481   if (strcmp(name, "pubdir") == 0)
482   {
483     httpSetPubDir(value);
484     return 1;
485   }
486
487   if (strcmp(name, "quantum") == 0)
488   {
489     if (httpSetQuantum(value) < 0)
490       return 0;
491
492     return 1;
493   }
494
495   if (strcmp(name, "messtime") == 0)
496   {
497     if (httpSetMessTime(value) < 0)
498       return 0;
499
500     return 1;
501   }
502
503   if (strcmp(name, "messlimit") == 0)
504   {
505     if (httpSetMessLimit(value) < 0)
506       return 0;
507
508     return 1;
509   }
510
511   return 0;
512 }