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