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