rename lq_route into olsr_spf
[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 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   struct list_node *link_node;
109   struct lqtextbuffer lqbuffer;
110   
111   if (iterLinkTab == NULL)
112     return -1;
113
114   snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~cost~%s~",
115            rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
116            rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
117            rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
118            iterLinkTab->L_link_quality,
119            get_linkcost_text(iterLinkTab->linkcost, OLSR_FALSE, &lqbuffer));
120
121
122   link_node = iterLinkTab->link_list.next;
123   if (link_node != &link_entry_head) {
124     iterLinkTab = list2link(link_node);
125   } else {
126     iterLinkTab = NULL;
127   }
128
129   return 0;
130 }
131
132 void iterLinkTabInit(void)
133 {
134   struct list_node *link_node;
135
136   link_node = link_entry_head.next;
137   if (link_node != &link_entry_head) {
138     iterLinkTab = list2link(link_node);
139   } else {
140     iterLinkTab = NULL;
141   }
142 }
143
144 int iterNeighTabNext(char *buff, int len)
145 {
146   int res;
147   int i;
148   struct neighbor_2_list_entry *neigh2;
149   
150   if (iterNeighTab == NULL)
151     return -1;
152
153   res = snprintf(buff, len,
154                  "main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~[~neighbors2~",
155                  rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen),
156                  iterNeighTab->status == SYM ? "true" : "false",
157                  iterNeighTab->is_mpr != 0 ? "true" : "false",
158                  olsr_lookup_mprs_set(&iterNeighTab->neighbor_main_addr) != NULL ?
159                  "true" : "false",
160                  iterNeighTab->willingness);
161
162   i = 0;
163
164   len -= res;
165   buff += res;
166
167   len -= 2;
168
169   for (neigh2 = iterNeighTab->neighbor_2_list.next;
170        neigh2 != &iterNeighTab->neighbor_2_list;
171        neigh2 = neigh2->next)
172   {
173     res = snprintf(buff, len, "%d~%s~", i,
174                    rawIpAddrToString(&neigh2->neighbor_2->neighbor_2_addr,
175                                      ipAddrLen));
176
177     if (res < len)
178       buff += res;
179
180     len -= res;
181
182     if (len <= 0)
183       break;
184
185     i++;
186   }
187
188   strcpy(buff, "]~");
189
190   iterNeighTab = iterNeighTab->next;
191
192   if (iterNeighTab == &neighTab[iterIndex])
193   {
194     iterNeighTab = NULL;
195     
196     while (++iterIndex < HASHSIZE)
197       if (neighTab[iterIndex].next != &neighTab[iterIndex])
198       {
199         iterNeighTab = neighTab[iterIndex].next;
200         break;
201       }
202   }
203
204   return 0;
205 }
206
207 void iterNeighTabInit(void)
208 {
209   iterNeighTab = NULL;
210
211   if (neighTab == NULL)
212     return;
213
214   for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
215     if (neighTab[iterIndex].next != &neighTab[iterIndex])
216     {
217       iterNeighTab = neighTab[iterIndex].next;
218       break;
219     }
220 }
221
222 int iterRouteTabNext(char *buff, int len)
223 {
224   struct avl_node *rt_tree_node;
225
226   if (iterRouteTab == NULL)
227     return -1;
228
229   snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
230            rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
231            rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
232            if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
233            iterRouteTab->rt_best->rtp_metric.hops);
234
235   rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
236   if (rt_tree_node) {
237       iterRouteTab = rt_tree2rt(rt_tree_node);
238   } else {
239       iterRouteTab = NULL;
240   }
241
242   return 0;
243 }
244
245 void iterRouteTabInit(void)
246 {
247   struct avl_node *node;
248
249   avl_init(&routingtree, avl_comp_prefix_default);
250   routingtree_version = 0;
251
252   node = avl_walk_first(&routingtree);
253   iterRouteTab = node ? rt_tree2rt(node) : NULL;
254
255 }
256
257 /**
258  * Grab the next topology entry.
259  *
260  * @param adr the address to look for
261  * @return the entry found or NULL
262  */
263 static struct tc_entry *
264 tas_getnext_tc_entry(struct tc_entry *tc)
265 {
266   struct avl_node *node = avl_walk_next(&tc->vertex_node);
267
268   return (node ? vertex_tree2tc(node) : NULL);
269 }
270
271 int iterTcTabNext(char *buff, int len)
272 {
273   int res;
274   int i;
275   struct tc_edge_entry *tc_edge;
276   struct lqtextbuffer lqbuffer;
277   
278   if (iterTcTab == NULL)
279     return -1;
280
281   res = snprintf(buff, len,
282                  "main~%s~[~destinations~",
283                  rawIpAddrToString(&iterTcTab->addr, ipAddrLen));
284
285   len -= res;
286   buff += res;
287
288   len -= 2;
289   i = 0;
290
291   OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
292
293     res = snprintf(buff, len, "[~%d~address~%s~cost~%s~]~", i,
294                    rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
295                    get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer));
296
297     if (res < len)
298       buff += res;
299
300     len -= res;
301
302     if (len <= 0)
303       break;
304
305     i++;
306   } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(iterTcTab, tc_edge);
307   
308   strcpy(buff, "]~");
309
310   iterTcTab = tas_getnext_tc_entry(iterTcTab);
311
312   return 0;
313 }
314
315 void iterTcTabInit(void)
316 {
317   struct avl_node *node;
318   
319   avl_init(&tc_tree, avl_comp_default);
320
321   node = avl_walk_first(&tc_tree);
322   iterTcTab = (node ? vertex_tree2tc(node) : NULL);
323 }
324
325 static void parserFunc(union olsr_message *msg,
326                        struct interface *inInt __attribute__((unused)),
327                        union olsr_ip_addr *neighIntAddr)
328 {
329   char *mess = (char *)msg;
330   union olsr_ip_addr *orig = (union olsr_ip_addr *)(mess + 4);
331   int len = (mess[2] << 8) | mess[3];
332   char *service, *string;
333   int i;
334
335   if (memcmp(orig, mainAddr, ipAddrLen) == 0)
336     return;
337
338   if (check_neighbor_link(neighIntAddr) != SYM_LINK)
339   {
340     error("TAS message not from symmetric neighbour\n");
341     return;
342   }
343
344   if (len < ipAddrLen + 8 + 2)
345   {
346     error("short TAS message received (%d bytes)\n", len);
347     return;
348   }
349
350     len -= ipAddrLen + 8;
351     service = mess + ipAddrLen + 8;
352
353     for (i = 0; i < len && service[i] != 0; i++);
354
355     if (i++ == len)
356     {
357       error("TAS message has unterminated service string\n");
358       return;
359     }
360
361     if (i == len)
362     {
363       error("TAS message lacks payload string\n");
364       return;
365     }
366
367     string = service + i;
368     len -= i;
369
370     for (i = 0; i < len && string[i] != 0; i++);
371
372     if (i == len)
373     {
374       error("TAS message has unterminated payload string\n");
375       return;
376     }
377
378     httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
379
380   olsr_forward_message(msg, 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 *context __attribute__((unused)))
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_start_timer(OLSR_TAS_SERVICE_INT, 0, OLSR_TIMER_PERIODIC,
471                    &serviceFunc, NULL, 0);
472
473   olsr_parser_add_function(parserFunc, MESSAGE_TYPE, 1);
474
475   return 0;
476 }
477
478 static const struct olsrd_plugin_parameters plugin_parameters[] = {
479     { .name = "address",   .set_plugin_parameter = &httpSetAddress,   .data = NULL },
480     { .name = "port",      .set_plugin_parameter = &httpSetPort,      .data = NULL },
481     { .name = "rootdir",   .set_plugin_parameter = &httpSetRootDir,   .data = NULL },
482     { .name = "workdir",   .set_plugin_parameter = &httpSetWorkDir,   .data = NULL },
483     { .name = "indexfile", .set_plugin_parameter = &httpSetIndexFile, .data = NULL },
484     { .name = "user",      .set_plugin_parameter = &httpSetUser,      .data = NULL },
485     { .name = "password",  .set_plugin_parameter = &httpSetPassword,  .data = NULL },
486     { .name = "sesstime",  .set_plugin_parameter = &httpSetSessTime,  .data = NULL },
487     { .name = "pubdir",    .set_plugin_parameter = &httpSetPubDir,    .data = NULL },
488     { .name = "quantum",   .set_plugin_parameter = &httpSetQuantum,   .data = NULL },
489     { .name = "messtime",  .set_plugin_parameter = &httpSetMessTime,  .data = NULL },
490     { .name = "messlimit", .set_plugin_parameter = &httpSetMessLimit, .data = NULL },
491 };
492
493 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
494 {
495     *params = plugin_parameters;
496     *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
497 }
498
499 /*
500  * Local Variables:
501  * c-basic-offset: 2
502  * End:
503  */