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