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