From Sven-Ola Tuecke <sven-ola@gmx.de>: add support for fixedpoint math
[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  */
41
42 #include <string.h>
43 #include <time.h> // clock_t required by olsrd includes
44
45 #include "link.h"
46 #include "plugin.h"
47 #include "lib.h"
48 #include "os_unix.h"
49 #include "http.h"
50 #include "glua.h"
51 #include "glua_ext.h"
52 #include "olsrd_plugin.h"
53 #include "net_olsr.h"
54
55 #include <defs.h>
56 #include <olsr.h>
57 #include <scheduler.h>
58 #include <parser.h>
59 #include <link_set.h>
60 #include <neighbor_table.h>
61 #include <two_hop_neighbor_table.h>
62 #include <mid_set.h>
63 #include <tc_set.h>
64 #include <hna_set.h>
65 #include <routing_table.h>
66 #include <olsr_protocol.h>
67 #include <lq_route.h>
68 #include <mpr_selector_set.h>
69 #include <duplicate_set.h>
70
71 #define PLUGIN_INTERFACE_VERSION 5
72
73 #define MESSAGE_TYPE 129
74
75 int olsrd_plugin_interface_version(void);
76 int olsrd_plugin_register_param(char *name, char *value);
77 int olsrd_plugin_init(void);
78
79 static int ipAddrLen;
80 static union olsr_ip_addr *mainAddr;
81
82 static struct interface *intTab = NULL;
83 static struct neighbor_entry *neighTab = NULL;
84 static struct mid_entry *midTab = NULL;
85 static struct hna_entry *hnaTab = NULL;
86 static struct olsrd_config *config = NULL;
87
88 static int iterIndex;
89 #if 0
90 /* not used */
91 static struct interface *iterIntTab = NULL;
92 static struct mid_entry *iterMidTab = NULL;
93 static struct hna_entry *iterHnaTab = NULL;
94 #endif
95
96 static struct link_entry *iterLinkTab = NULL;
97 static struct neighbor_entry *iterNeighTab = NULL;
98 static struct tc_entry *iterTcTab = NULL;
99 static struct rt_entry *iterRouteTab = NULL;
100
101 static void __attribute__((constructor)) banner(void)
102 {
103   printf("Tiny Application Server 0.1 by olsr.org\n");
104 }
105
106 int iterLinkTabNext(char *buff, int len)
107 {
108 #ifdef USE_FPM
109   fpm etx;
110 #else
111   double etx;
112 #endif
113
114   if (iterLinkTab == NULL)
115     return -1;
116
117   etx = olsr_calc_link_etx(iterLinkTab);
118
119   snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%s~lq~%s~nlq~%s~etx~%s~",
120            rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
121            rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
122            rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
123            olsr_etx_to_string(iterLinkTab->L_link_quality),
124            olsr_etx_to_string(iterLinkTab->loss_link_quality),
125            olsr_etx_to_string(iterLinkTab->neigh_link_quality),
126            olsr_etx_to_string(etx));
127
128   iterLinkTab = iterLinkTab->next;
129
130   return 0;
131 }
132
133 void iterLinkTabInit(void)
134 {
135   iterLinkTab = get_link_set();
136 }
137
138 int iterNeighTabNext(char *buff, int len)
139 {
140   int res;
141   int i;
142   struct neighbor_2_list_entry *neigh2;
143   
144   if (iterNeighTab == NULL)
145     return -1;
146
147   res = snprintf(buff, len,
148                  "main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~[~neighbors2~",
149                  rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen),
150                  iterNeighTab->status == SYM ? "true" : "false",
151                  iterNeighTab->is_mpr != 0 ? "true" : "false",
152                  olsr_lookup_mprs_set(&iterNeighTab->neighbor_main_addr) != NULL ?
153                  "true" : "false",
154                  iterNeighTab->willingness);
155
156   i = 0;
157
158   len -= res;
159   buff += res;
160
161   len -= 2;
162
163   for (neigh2 = iterNeighTab->neighbor_2_list.next;
164        neigh2 != &iterNeighTab->neighbor_2_list;
165        neigh2 = neigh2->next)
166   {
167     res = snprintf(buff, len, "%d~%s~", i,
168                    rawIpAddrToString(&neigh2->neighbor_2->neighbor_2_addr,
169                                      ipAddrLen));
170
171     if (res < len)
172       buff += res;
173
174     len -= res;
175
176     if (len <= 0)
177       break;
178
179     i++;
180   }
181
182   strcpy(buff, "]~");
183
184   iterNeighTab = iterNeighTab->next;
185
186   if (iterNeighTab == &neighTab[iterIndex])
187   {
188     iterNeighTab = NULL;
189     
190     while (++iterIndex < HASHSIZE)
191       if (neighTab[iterIndex].next != &neighTab[iterIndex])
192       {
193         iterNeighTab = neighTab[iterIndex].next;
194         break;
195       }
196   }
197
198   return 0;
199 }
200
201 void iterNeighTabInit(void)
202 {
203   iterNeighTab = NULL;
204
205   if (neighTab == NULL)
206     return;
207
208   for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
209     if (neighTab[iterIndex].next != &neighTab[iterIndex])
210     {
211       iterNeighTab = neighTab[iterIndex].next;
212       break;
213     }
214 }
215
216 int iterRouteTabNext(char *buff, int len)
217 {
218   struct avl_node *rt_tree_node;
219
220   if (iterRouteTab == NULL)
221     return -1;
222
223   snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
224            rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
225            rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
226            if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
227            iterRouteTab->rt_best->rtp_metric.hops);
228
229   rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
230   if (rt_tree_node) {
231       iterRouteTab = rt_tree_node->data;
232   } else {
233       iterRouteTab = NULL;
234   }
235
236   return 0;
237 }
238
239 void iterRouteTabInit(void)
240 {
241   struct avl_node *node;
242
243   avl_init(&routingtree, avl_comp_prefix_default);
244   routingtree_version = 0;
245
246   node = avl_walk_first(&routingtree);
247   iterRouteTab = node ? node->data : NULL;
248
249 }
250
251 /**
252  * Grab the next topology entry.
253  *
254  * @param adr the address to look for
255  * @return the entry found or NULL
256  */
257 static struct tc_entry *
258 tas_getnext_tc_entry(struct tc_entry *tc)
259 {
260   struct avl_node *node = avl_walk_next(&tc->vertex_node);
261
262   if (node) {
263     return node->data;
264   }
265
266   return NULL;
267 }
268
269 int iterTcTabNext(char *buff, int len)
270 {
271   int res;
272   int i;
273   struct tc_edge_entry *tc_edge;
274   
275   if (iterTcTab == NULL)
276     return -1;
277
278   res = snprintf(buff, len,
279                  "main~%s~[~destinations~",
280                  rawIpAddrToString(&iterTcTab->addr, ipAddrLen));
281
282   len -= res;
283   buff += res;
284
285   len -= 2;
286   i = 0;
287
288   OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
289
290     res = snprintf(buff, len, "[~%d~address~%s~etx~%s~]~", i,
291                    rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
292                    olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)));
293
294     if (res < len)
295       buff += res;
296
297     len -= res;
298
299     if (len <= 0)
300       break;
301
302     i++;
303   } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(iterTcTab, tc_edge);
304   
305   strcpy(buff, "]~");
306
307   iterTcTab = tas_getnext_tc_entry(iterTcTab);
308
309   return 0;
310 }
311
312 void iterTcTabInit(void)
313 {
314   struct avl_node *node;
315   
316   avl_init(&tc_tree, avl_comp_prefix_default);
317
318   node = avl_walk_first(&tc_tree);
319   iterTcTab = node ? node->data : NULL;
320 }
321
322 static void parserFunc(union olsr_message *msg, struct interface *inInt,
323                        union olsr_ip_addr *neighIntAddr)
324 {
325   char *mess = (char *)msg;
326   union olsr_ip_addr *orig = (union olsr_ip_addr *)(mess + 4);
327   unsigned short seqNo = (mess[ipAddrLen + 6] << 8) | mess[ipAddrLen + 7];
328   int len = (mess[2] << 8) | mess[3];
329   char *service, *string;
330   int i;
331
332   if (memcmp(orig, mainAddr, ipAddrLen) == 0)
333     return;
334
335   if (check_neighbor_link(neighIntAddr) != SYM_LINK)
336   {
337     error("TAS message not from symmetric neighbour\n");
338     return;
339   }
340
341   if (len < ipAddrLen + 8 + 2)
342   {
343     error("short TAS message received (%d bytes)\n", len);
344     return;
345   }
346
347   if (olsr_check_dup_table_proc(orig, seqNo) != 0)
348   {
349     len -= ipAddrLen + 8;
350     service = mess + ipAddrLen + 8;
351
352     for (i = 0; i < len && service[i] != 0; i++);
353
354     if (i++ == len)
355     {
356       error("TAS message has unterminated service string\n");
357       return;
358     }
359
360     if (i == len)
361     {
362       error("TAS message lacks payload string\n");
363       return;
364     }
365
366     string = service + i;
367     len -= i;
368
369     for (i = 0; i < len && string[i] != 0; i++);
370
371     if (i == len)
372     {
373       error("TAS message has unterminated payload string\n");
374       return;
375     }
376
377     httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
378   }
379
380   olsr_forward_message(msg, orig, seqNo, inInt, neighIntAddr);
381 }
382
383 void sendMessage(const char *service, const char *string)
384 {
385   unsigned char *mess, *walker;
386   int len, pad;
387   unsigned short seqNo;
388   struct interface *inter;
389
390   pad = len = ipAddrLen + 8 + strlen(service) + 1 + strlen(string) + 1;
391
392   len = 1 + ((len - 1) | 3);
393
394   pad = len - pad;
395
396   walker = mess = allocMem(len);
397
398   seqNo = get_msg_seqno();
399
400   *walker++ = MESSAGE_TYPE;
401   *walker++ = 0;
402   *walker++ = (unsigned char)(len >> 8);
403   *walker++ = (unsigned char)len;
404
405   memcpy(walker, mainAddr, ipAddrLen);
406   walker += ipAddrLen;
407
408   *walker++ = 255;
409   *walker++ = 0;
410   *walker++ = (unsigned char)(seqNo >> 8);
411   *walker++ = (unsigned char)seqNo;
412
413   while (*service != 0)
414     *walker++ = *service++;
415
416   *walker++ = 0;
417
418   while (*string != 0)
419     *walker++ = *string++;
420
421   *walker++ = 0;
422
423   while (pad-- > 0)
424     *walker++ = 0;
425
426   for (inter = intTab; inter != NULL; inter = inter->int_next)
427   {
428     if (net_outbuffer_push(inter, mess, len) != len)
429     {
430       net_output(inter);
431       net_outbuffer_push(inter, mess, len);
432     }
433   }
434 }
435
436 static void serviceFunc(void)
437 {
438   static int up = 0;
439
440   if (up == 0)
441   {
442     if (httpSetup() < 0)
443       return;
444
445     up = 1;
446   }
447
448   if (up != 0)
449     httpService((int)(1.0 / config->pollrate));
450 }
451
452 int olsrd_plugin_interface_version(void)
453 {
454   return PLUGIN_INTERFACE_VERSION;
455 }
456
457 int olsrd_plugin_init(void)
458 {
459   ipAddrLen = olsr_cnf->ipsize;
460   mainAddr = &olsr_cnf->main_addr;
461
462   intTab = ifnet;
463   neighTab = neighbortable;
464   midTab = mid_set;
465   hnaTab = hna_set;
466   config = olsr_cnf;
467
468   httpInit();
469   
470   olsr_register_timeout_function(serviceFunc, OLSR_FALSE);
471   olsr_parser_add_function(parserFunc, MESSAGE_TYPE, 1);
472
473   return 0;
474 }
475
476 static const struct olsrd_plugin_parameters plugin_parameters[] = {
477     { .name = "address",   .set_plugin_parameter = &httpSetAddress,   .data = NULL },
478     { .name = "port",      .set_plugin_parameter = &httpSetPort,      .data = NULL },
479     { .name = "rootdir",   .set_plugin_parameter = &httpSetRootDir,   .data = NULL },
480     { .name = "workdir",   .set_plugin_parameter = &httpSetWorkDir,   .data = NULL },
481     { .name = "indexfile", .set_plugin_parameter = &httpSetIndexFile, .data = NULL },
482     { .name = "user",      .set_plugin_parameter = &httpSetUser,      .data = NULL },
483     { .name = "password",  .set_plugin_parameter = &httpSetPassword,  .data = NULL },
484     { .name = "sesstime",  .set_plugin_parameter = &httpSetSessTime,  .data = NULL },
485     { .name = "pubdir",    .set_plugin_parameter = &httpSetPubDir,    .data = NULL },
486     { .name = "quantum",   .set_plugin_parameter = &httpSetQuantum,   .data = NULL },
487     { .name = "messtime",  .set_plugin_parameter = &httpSetMessTime,  .data = NULL },
488     { .name = "messlimit", .set_plugin_parameter = &httpSetMessLimit, .data = NULL },
489 };
490
491 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
492 {
493     *params = plugin_parameters;
494     *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
495 }
496
497 /*
498  * Local Variables:
499  * c-basic-offset: 2
500  * End:
501  */