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