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