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