780066e4bd4e21c6636351a065d84671eff363db
[olsrd.git] / lib / tas / src / plugin.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon (olsrd)
4  *
5  * Copyright (c) 2004, Thomas Lopatic (thomas@olsr.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its
19  *   contributors may be used to endorse or promote products derived
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  */
42
43 #include <string.h>
44 #include <time.h>               // clock_t required by olsrd includes
45
46 #include "link.h"
47 #include "plugin.h"
48 #include "lib.h"
49 #include "os_unix.h"
50 #include "http.h"
51 #include "glua.h"
52 #include "glua_ext.h"
53 #include "olsrd_plugin.h"
54 #include "net_olsr.h"
55
56 #include <defs.h>
57 #include <olsr.h>
58 #include <scheduler.h>
59 #include <parser.h>
60 #include <link_set.h>
61 #include <neighbor_table.h>
62 #include <two_hop_neighbor_table.h>
63 #include <mid_set.h>
64 #include <tc_set.h>
65 #include <hna_set.h>
66 #include <routing_table.h>
67 #include <olsr_protocol.h>
68 #include <mpr_selector_set.h>
69 #include <duplicate_set.h>
70 #include <lq_plugin.h>
71
72 #define PLUGIN_INTERFACE_VERSION 5
73
74 #define MESSAGE_TYPE 129
75
76 int olsrd_plugin_interface_version(void);
77 int olsrd_plugin_register_param(char *name, char *value);
78 int olsrd_plugin_init(void);
79
80 static int ipAddrLen;
81 static union olsr_ip_addr *mainAddr;
82
83 static struct interface *intTab = NULL;
84 static struct neighbor_entry *neighTab = NULL;
85 static struct mid_entry *midTab = NULL;
86 static struct hna_entry *hnaTab = NULL;
87 static struct olsrd_config *config = NULL;
88
89 static int iterIndex;
90 #if 0
91
92 /* not used */
93 static struct interface *iterIntTab = NULL;
94 static struct mid_entry *iterMidTab = NULL;
95 static struct hna_entry *iterHnaTab = NULL;
96 #endif
97
98 static struct link_entry *iterLinkTab = NULL;
99 static struct neighbor_entry *iterNeighTab = NULL;
100 static struct tc_entry *iterTcTab = NULL;
101 static struct rt_entry *iterRouteTab = NULL;
102
103 static void __attribute__ ((constructor)) banner(void)
104 {
105   printf("Tiny Application Server 0.1 by olsr.org\n");
106 }
107
108 int
109 iterLinkTabNext(char *buff, int len)
110 {
111   struct list_node *link_node;
112   struct lqtextbuffer lqbuffer;
113
114   if (iterLinkTab == NULL)
115     return -1;
116
117   snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~cost~%s~",
118            rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen), rawIpAddrToString(&iterLinkTab->neighbor_iface_addr,
119                                                                                            ipAddrLen),
120            rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen), iterLinkTab->L_link_quality,
121            get_linkcost_text(iterLinkTab->linkcost, false, &lqbuffer));
122
123   link_node = iterLinkTab->link_list.next;
124   if (link_node != &link_entry_head) {
125     iterLinkTab = list2link(link_node);
126   } else {
127     iterLinkTab = NULL;
128   }
129
130   return 0;
131 }
132
133 void
134 iterLinkTabInit(void)
135 {
136   struct list_node *link_node;
137
138   link_node = link_entry_head.next;
139   if (link_node != &link_entry_head) {
140     iterLinkTab = list2link(link_node);
141   } else {
142     iterLinkTab = NULL;
143   }
144 }
145
146 int
147 iterNeighTabNext(char *buff, int len)
148 {
149   int res;
150   int i;
151   struct neighbor_2_list_entry *neigh2;
152
153   if (iterNeighTab == NULL)
154     return -1;
155
156   res =
157     snprintf(buff, len, "main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~[~neighbors2~",
158              rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen), iterNeighTab->status == SYM ? "true" : "false",
159              iterNeighTab->is_mpr != 0 ? "true" : "false",
160              olsr_lookup_mprs_set(&iterNeighTab->neighbor_main_addr) != NULL ? "true" : "false", 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; neigh2 != &iterNeighTab->neighbor_2_list; neigh2 = neigh2->next) {
170     res = snprintf(buff, len, "%d~%s~", i, rawIpAddrToString(&neigh2->neighbor_2->neighbor_2_addr, ipAddrLen));
171
172     if (res < len)
173       buff += res;
174
175     len -= res;
176
177     if (len <= 0)
178       break;
179
180     i++;
181   }
182
183   strcpy(buff, "]~");
184
185   iterNeighTab = iterNeighTab->next;
186
187   if (iterNeighTab == &neighTab[iterIndex]) {
188     iterNeighTab = NULL;
189
190     while (++iterIndex < HASHSIZE)
191       if (neighTab[iterIndex].next != &neighTab[iterIndex]) {
192         iterNeighTab = neighTab[iterIndex].next;
193         break;
194       }
195   }
196
197   return 0;
198 }
199
200 void
201 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       iterNeighTab = neighTab[iterIndex].next;
211       break;
212     }
213 }
214
215 int
216 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, ipAddrLen),
225            rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
226            if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index), iterRouteTab->rt_best->rtp_metric.hops);
227
228   rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
229   if (rt_tree_node) {
230     iterRouteTab = rt_tree2rt(rt_tree_node);
231   } else {
232     iterRouteTab = NULL;
233   }
234
235   return 0;
236 }
237
238 void
239 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
266 iterTcTabNext(char *buff, int len)
267 {
268   int res;
269   int i;
270   struct tc_edge_entry *tc_edge;
271   struct lqtextbuffer lqbuffer;
272
273   if (iterTcTab == NULL)
274     return -1;
275
276   res = snprintf(buff, len, "main~%s~[~destinations~", rawIpAddrToString(&iterTcTab->addr, ipAddrLen));
277
278   len -= res;
279   buff += res;
280
281   len -= 2;
282   i = 0;
283
284   OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
285
286     res =
287       snprintf(buff, len, "[~%d~address~%s~cost~%s~]~", i, rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
288                get_linkcost_text(tc_edge->cost, false, &lqbuffer));
289
290     if (res < len)
291       buff += res;
292
293     len -= res;
294
295     if (len <= 0)
296       break;
297
298     i++;
299   }
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
310 iterTcTabInit(void)
311 {
312   struct avl_node *node;
313
314   avl_init(&tc_tree, avl_comp_default);
315
316   node = avl_walk_first(&tc_tree);
317   iterTcTab = (node ? vertex_tree2tc(node) : NULL);
318 }
319
320 static bool
321 parserFunc(union olsr_message *msg, struct interface *inInt __attribute__ ((unused)), union olsr_ip_addr *neighIntAddr)
322 {
323   char *mess = (char *)msg;
324   union olsr_ip_addr *orig = (union olsr_ip_addr *)ARM_NOWARN_ALIGN(mess + 4);
325   int len = (mess[2] << 8) | mess[3];
326   char *service, *string;
327   int i;
328
329   if (memcmp(orig, mainAddr, ipAddrLen) == 0)
330     return false;
331
332   if (check_neighbor_link(neighIntAddr) != SYM_LINK) {
333     error("TAS message not from symmetric neighbour\n");
334     return false;
335   }
336
337   if (len < ipAddrLen + 8 + 2) {
338     error("short TAS message received (%d bytes)\n", len);
339     return false;
340   }
341
342   len -= ipAddrLen + 8;
343   service = mess + ipAddrLen + 8;
344
345   for (i = 0; i < len && service[i] != 0; i++);
346
347   if (i++ == len) {
348     error("TAS message has unterminated service string\n");
349     return false;
350   }
351
352   if (i == len) {
353     error("TAS message lacks payload string\n");
354     return false;
355   }
356
357   string = service + i;
358   len -= i;
359
360   for (i = 0; i < len && string[i] != 0; i++);
361
362   if (i == len) {
363     error("TAS message has unterminated payload string\n");
364     return false;
365   }
366
367   httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
368
369   /* Forward the message */
370   return true;
371 }
372
373 void
374 sendMessage(const char *service, const char *string)
375 {
376   unsigned char *mess, *walker;
377   int len, pad;
378   unsigned short seqNo;
379   struct interface *inter;
380
381   pad = len = ipAddrLen + 8 + strlen(service) + 1 + strlen(string) + 1;
382
383   len = 1 + ((len - 1) | 3);
384
385   pad = len - pad;
386
387   walker = mess = allocMem(len);
388
389   seqNo = get_msg_seqno();
390
391   *walker++ = MESSAGE_TYPE;
392   *walker++ = 0;
393   *walker++ = (unsigned char)(len >> 8);
394   *walker++ = (unsigned char)len;
395
396   memcpy(walker, mainAddr, ipAddrLen);
397   walker += ipAddrLen;
398
399   *walker++ = 255;
400   *walker++ = 0;
401   *walker++ = (unsigned char)(seqNo >> 8);
402   *walker++ = (unsigned char)seqNo;
403
404   while (*service != 0)
405     *walker++ = *service++;
406
407   *walker++ = 0;
408
409   while (*string != 0)
410     *walker++ = *string++;
411
412   *walker++ = 0;
413
414   while (pad-- > 0)
415     *walker++ = 0;
416
417   for (inter = intTab; inter != NULL; inter = inter->int_next) {
418     if (net_outbuffer_push(inter, mess, len) != len) {
419       net_output(inter);
420       net_outbuffer_push(inter, mess, len);
421     }
422   }
423 }
424
425 static void
426 serviceFunc(void *context __attribute__ ((unused)))
427 {
428   static int up = 0;
429
430   if (up == 0) {
431     if (httpSetup() < 0)
432       return;
433
434     up = 1;
435   }
436
437   if (up != 0)
438     httpService((int)(1.0 / config->pollrate));
439 }
440
441 int
442 olsrd_plugin_interface_version(void)
443 {
444   return PLUGIN_INTERFACE_VERSION;
445 }
446
447 int
448 olsrd_plugin_init(void)
449 {
450   ipAddrLen = olsr_cnf->ipsize;
451   mainAddr = &olsr_cnf->main_addr;
452
453   intTab = ifnet;
454   neighTab = neighbortable;
455   midTab = mid_set;
456   hnaTab = hna_set;
457   config = olsr_cnf;
458
459   httpInit();
460
461   olsr_start_timer(OLSR_TAS_SERVICE_INT, 0, OLSR_TIMER_PERIODIC, &serviceFunc, NULL, 0);
462
463   olsr_parser_add_function(parserFunc, MESSAGE_TYPE);
464
465   return 0;
466 }
467
468 static const struct olsrd_plugin_parameters plugin_parameters[] = {
469   {.name = "address",.set_plugin_parameter = &httpSetAddress,.data = NULL},
470   {.name = "port",.set_plugin_parameter = &httpSetPort,.data = NULL},
471   {.name = "rootdir",.set_plugin_parameter = &httpSetRootDir,.data = NULL},
472   {.name = "workdir",.set_plugin_parameter = &httpSetWorkDir,.data = NULL},
473   {.name = "indexfile",.set_plugin_parameter = &httpSetIndexFile,.data = NULL},
474   {.name = "user",.set_plugin_parameter = &httpSetUser,.data = NULL},
475   {.name = "password",.set_plugin_parameter = &httpSetPassword,.data = NULL},
476   {.name = "sesstime",.set_plugin_parameter = &httpSetSessTime,.data = NULL},
477   {.name = "pubdir",.set_plugin_parameter = &httpSetPubDir,.data = NULL},
478   {.name = "quantum",.set_plugin_parameter = &httpSetQuantum,.data = NULL},
479   {.name = "messtime",.set_plugin_parameter = &httpSetMessTime,.data = NULL},
480   {.name = "messlimit",.set_plugin_parameter = &httpSetMessLimit,.data = NULL},
481 };
482
483 void
484 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
485 {
486   *params = plugin_parameters;
487   *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);
488 }
489
490 /*
491  * Local Variables:
492  * c-basic-offset: 2
493  * indent-tabs-mode: nil
494  * End:
495  */