Namespace cleanup of scheduler, remove "polling" sockets
[olsrd.git] / lib / txtinfo / src / olsrd_txtinfo.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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 /*
43  * Dynamic linked library for the olsr.org olsr daemon
44  */
45 #include "olsr.h"
46 #include "ipcalc.h"
47 #include "neighbor_table.h"
48 #include "tc_set.h"
49 #include "hna_set.h"
50 #include "mid_set.h"
51 #include "routing_table.h"
52 #include "olsr_ip_prefix_list.h"
53 #include "parser.h"
54 #include "olsr_comport_txt.h"
55 #include "olsr_comport_http.h"
56 #include "common/string.h"
57 #include "common/autobuf.h"
58 #include "plugin_loader.h"
59 #include "plugin_util.h"
60
61 #define PLUGIN_DESCR    "OLSRD txtinfo plugin"
62 #define PLUGIN_AUTHOR   "Henning Rogge"
63
64
65 struct txtinfo_cmd {
66   const char *name;
67   olsr_txthandler handler;
68   struct olsr_txtcommand *cmd;
69 };
70
71 static int txtinfo_init(void);
72 static int txtinfo_enable(void);
73 static int txtinfo_disable(void);
74 static int txtinfo_exit(void);
75
76 static enum olsr_txtcommand_result txtinfo_neigh(struct comport_connection *con,
77     const char *cmd, const char *param);
78 static enum olsr_txtcommand_result txtinfo_link(struct comport_connection *con,
79     const char *cmd, const char *param);
80 static enum olsr_txtcommand_result txtinfo_routes(struct comport_connection *con,
81     const char *cmd, const char *param);
82 static enum olsr_txtcommand_result txtinfo_topology(struct comport_connection *con,
83     const char *cmd, const char *param);
84 static enum olsr_txtcommand_result txtinfo_hna(struct comport_connection *con,
85     const char *cmd, const char *param);
86 static enum olsr_txtcommand_result txtinfo_mid(struct comport_connection *con,
87     const char *cmd, const char *param);
88 static enum olsr_txtcommand_result txtinfo_interfaces(struct comport_connection *con,
89     const char *cmd, const char *param);
90
91 /* plugin configuration */
92 static struct ip_acl allowed_nets;
93
94 /* plugin parameters */
95 static const struct olsrd_plugin_parameters plugin_parameters[] = {
96   {.name = IP_ACL_ACCEPT_PARAP,.set_plugin_parameter = &ip_acl_add_plugin_accept,.data = &allowed_nets},
97   {.name = IP_ACL_REJECT_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_reject,.data = &allowed_nets},
98   {.name = IP_ACL_CHECKFIRST_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_checkFirst,.data = &allowed_nets},
99   {.name = IP_ACL_DEFAULTPOLICY_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_defaultPolicy,.data = &allowed_nets}
100 };
101
102 OLSR_PLUGIN6(plugin_parameters) {
103   .descr = PLUGIN_DESCR,
104   .author = PLUGIN_AUTHOR,
105   .init = txtinfo_init,
106   .enable = txtinfo_enable,
107   .disable = txtinfo_disable,
108   .exit = txtinfo_exit,
109   .deactivate = true
110 };
111
112 /* command callbacks and names */
113 static struct txtinfo_cmd commands[] = {
114     {"link", &txtinfo_link, NULL},
115     {"neigh", &txtinfo_neigh, NULL},
116     {"topology", &txtinfo_topology, NULL},
117     {"hna", &txtinfo_hna, NULL},
118     {"mid", &txtinfo_mid, NULL},
119     {"routes", &txtinfo_routes, NULL},
120     {"interfaces", &txtinfo_interfaces, NULL},
121 };
122
123 /* base path for http access (should end with a '/') */
124 static const char TXTINFO_HTTP_PATH[] = "/txtinfo/";
125
126 /* constants and static storage for template engine */
127 static const char KEY_LOCALIP[] = "localip";
128 static const char KEY_NEIGHIP[] = "neighip";
129 static const char KEY_ALIASIP[] = "aliasip";
130 static const char KEY_DESTPREFIX[] = "destprefix";
131 static const char KEY_SYM[] = "issym";
132 static const char KEY_MPR[] = "ismpr";
133 static const char KEY_MPRS[] = "ismprs";
134 static const char KEY_VIRTUAL[] = "isvirtual";
135 static const char KEY_WILLINGNESS[] = "will";
136 static const char KEY_2HOP[] = "2hop";
137 static const char KEY_LINKCOST[] = "linkcost";
138 static const char KEY_RAWLINKCOST[] = "rawlinkcost";
139 static const char KEY_HOPCOUNT[] = "hopcount";
140 static const char KEY_FAILCOUNT[] = "failcount";
141 static const char KEY_INTERFACE[] = "interface";
142 static const char KEY_VTIME[] = "vtime";
143 static const char KEY_STATE[] = "state";
144 static const char KEY_MTU[] = "mtu";
145 static const char KEY_SRCIP[] = "srcip";
146 static const char KEY_DSTIP[] = "dstip";
147
148 static struct ipaddr_str buf_localip, buf_neighip, buf_aliasip, buf_srcip, buf_dstip;
149 struct ipprefix_str buf_destprefix;
150 static char buf_sym[6], buf_mrp[4], buf_mprs[4], buf_virtual[4];
151 static char buf_willingness[7];
152 static char buf_2hop[6];
153 static char buf_rawlinkcost[11];
154 static char buf_linkcost[LQTEXT_MAXLENGTH];
155 static char buf_hopcount[4];
156 static char buf_failcount[8];
157 static char buf_state[5];
158 static char buf_mtu[5];
159 static char buf_interface[IF_NAMESIZE];
160 struct millitxt_buf buf_vtime;
161
162 static size_t tmpl_indices[32];
163
164 /* a link metric may contain up to 8 values */
165 static const char *keys_link[] = {
166   KEY_LOCALIP, KEY_NEIGHIP, KEY_SYM, KEY_MPR, KEY_VTIME,
167   KEY_RAWLINKCOST, KEY_LINKCOST,
168   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
169 };
170 static char *values_link[] = {
171   buf_localip.buf, buf_neighip.buf, buf_sym, buf_mrp, buf_vtime.buf,
172   buf_rawlinkcost, buf_linkcost,
173   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
174 };
175 static char tmpl_link[256], headline_link[256];
176 static size_t link_keys_static = 0, link_keys_count = 0, link_value_size = 0;
177
178 static const char *tmpl_neigh = "%neighip%\t%issym%\t%ismpr%\t%ismprs%\t%will%\t%2hop%\n";
179 static const char *keys_neigh[] = {
180   KEY_NEIGHIP, KEY_SYM, KEY_MPR, KEY_MPRS, KEY_WILLINGNESS, KEY_2HOP
181 };
182 static char *values_neigh[] = {
183   buf_neighip.buf, buf_sym, buf_mprs, buf_mprs, buf_willingness, buf_2hop
184 };
185
186 static const char *tmpl_routes = "%destprefix%\t%neighip%\t%hopcount%\t%linkcost%\t%interface%\t%failcount%\n";
187 static const char *keys_routes[] = {
188   KEY_DESTPREFIX, KEY_NEIGHIP, KEY_HOPCOUNT, KEY_VTIME,
189   KEY_INTERFACE, KEY_RAWLINKCOST, KEY_LINKCOST, KEY_FAILCOUNT
190 };
191 static char *values_routes[] = {
192   buf_destprefix.buf, buf_neighip.buf, buf_hopcount, buf_vtime.buf,
193   buf_interface, buf_rawlinkcost, buf_linkcost, buf_failcount
194 };
195
196 static const char *tmpl_topology = "%neighip%\t%localip%\t%isvirtual%\t%linkcost%\n";
197 static const char *keys_topology[] = {
198   KEY_LOCALIP, KEY_NEIGHIP, KEY_VIRTUAL, KEY_VTIME,
199   KEY_RAWLINKCOST, KEY_LINKCOST
200 };
201 static char *values_topology[] = {
202   buf_localip.buf, buf_neighip.buf, buf_virtual, buf_vtime.buf,
203   buf_rawlinkcost, buf_linkcost
204 };
205
206 static const char *tmpl_hna = "%destprefix%\t%localip%\t%vtime%\n";
207 static const char *keys_hna[] = {
208   KEY_LOCALIP, KEY_DESTPREFIX, KEY_VTIME
209 };
210 static char *values_hna[] = {
211   buf_localip.buf, buf_destprefix.buf, buf_vtime.buf
212 };
213
214 static const char *tmpl_mid = "%localip%\t%aliasip%\t%vtime%\n";
215 static const char *keys_mid[] = {
216   KEY_LOCALIP, KEY_ALIASIP, KEY_VTIME
217 };
218 static char *values_mid[] = {
219   buf_localip.buf, buf_aliasip.buf, buf_vtime.buf
220 };
221
222 static const char *tmpl_interface = "%interface%\t%state%\t%mtu%\t%srcip%\t%dstip%\n";
223 static const char *keys_interface[] = {
224   KEY_INTERFACE, KEY_STATE, KEY_MTU, 
225   KEY_SRCIP, KEY_DSTIP
226 };
227 static char *values_interface[] = {
228   buf_interface, buf_state, buf_mtu, 
229   buf_srcip.buf, buf_dstip.buf
230 };
231
232 /**
233  * Constructor of plugin, called before parameters are initialized
234  */
235 static int
236 txtinfo_init(void)
237 {
238   ip_acl_init(&allowed_nets);
239
240   /* always allow localhost */
241   if (olsr_cnf->ip_version == AF_INET) {
242     union olsr_ip_addr ip;
243
244     ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
245     ip_acl_add(&allowed_nets, &ip, 32, false);
246   } else {
247     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
248     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
249   }
250   return 0;
251 }
252
253 /**
254  * Destructor of plugin
255  */
256 static int
257 txtinfo_disable(void)
258 {
259   size_t i;
260
261   for (i=0; i<ARRAYSIZE(commands); i++) {
262     olsr_com_remove_normal_txtcommand(commands[i].cmd);
263   }
264   for (i=link_keys_static; i<link_keys_count; i++) {
265     free(values_link[i]);
266   }
267   return 0;
268 }
269
270 /*
271  * Initialization of plugin AFTER parameters have been read
272  */
273 static int
274 txtinfo_enable(void)
275 {
276   size_t i;
277
278   /* count static link keys */
279   while (keys_link[link_keys_static]) {
280     link_keys_static++;
281     link_keys_count++;
282   }
283
284   /* generate dynamic link keys */
285   for (i=1; i<olsr_get_linklabel_count(); i++) {
286     keys_link[link_keys_static + i - 1] = olsr_get_linklabel(i);
287     values_link[link_keys_static + i - 1] = olsr_malloc(LQTEXT_MAXLENGTH, "txtinfo linktemplate values");
288     link_keys_count++;
289   }
290   link_value_size = LQTEXT_MAXLENGTH;
291
292   /* generate link template */
293   strscpy(tmpl_link, "%localip%\t%neighip", sizeof(tmpl_link));
294   for (i=1; i<olsr_get_linklabel_count(); i++) {
295     strscat(tmpl_link, "%\t%", sizeof(tmpl_link));
296     strscat(tmpl_link, olsr_get_linklabel(i), sizeof(tmpl_link));
297   }
298   strscat(tmpl_link, "%\t%linkcost%\n", sizeof(tmpl_link));
299
300   /* generate link summary */
301   strscpy(headline_link, "Table: Links\nLocal IP\tRemote IP", sizeof(headline_link));
302   for (i=1; i<olsr_get_linklabel_count(); i++) {
303     strscat(headline_link, "\t", sizeof(headline_link));
304     strscat(headline_link, olsr_get_linklabel(i), sizeof(headline_link));
305   }
306   strscat(headline_link, "\t", sizeof(headline_link));
307   strscat(headline_link, olsr_get_linklabel(0), sizeof(headline_link));
308   strscat(headline_link, "\n", sizeof(headline_link));
309
310   for (i=0; i<ARRAYSIZE(commands); i++) {
311     commands[i].cmd = olsr_com_add_normal_txtcommand(commands[i].name, commands[i].handler);
312     commands[i].cmd->acl = &allowed_nets;
313   }
314   return 0;
315 }
316
317 static int
318 txtinfo_exit(void) {
319   ip_acl_flush(&allowed_nets);
320   return 0;
321 }
322
323 /**
324  * Parse user templates for \%, \n and \t
325  *
326  * @param template
327  */
328 static char *
329 parse_user_template(const char *template) {
330   // TODO: dynamic buffer ?
331   static char buffer[1024];
332   char *dst = buffer;
333
334   while (*template && (size_t)(dst - buffer) < sizeof(buffer)-1) {
335     if (*template == '\\') {
336       template++;
337       switch (*template) {
338         case 0:
339           *dst = 0;
340           break;
341         case 'n':
342           *dst = '\n';
343           break;
344         case 't':
345           *dst = '\t';
346           break;
347         case '\\':
348           *dst = '\\';
349           break;
350         default:
351           *dst++ = '\\';
352           *dst = *template;
353           break;
354       }
355     }
356     else {
357       *dst = *template;
358     }
359     template++;
360     dst++;
361   }
362   *dst = 0;
363   return buffer;
364 }
365
366 /**
367  * Callback for neigh command
368  */
369 static enum olsr_txtcommand_result
370 txtinfo_neigh(struct comport_connection *con,
371     const char *cmd __attribute__ ((unused)), const char *param)
372 {
373   struct nbr_entry *neigh, *iterator;
374   const char *template;
375   int indexLength;
376
377   template = param != NULL ? parse_user_template(param) : tmpl_neigh;
378   if (param == NULL &&
379       abuf_puts(&con->out, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
380     return ABUF_ERROR;
381   }
382
383   if ((indexLength = abuf_template_init(keys_neigh, ARRAYSIZE(keys_neigh), template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
384     return ABUF_ERROR;
385   }
386
387   /* Neighbors */
388   OLSR_FOR_ALL_NBR_ENTRIES(neigh, iterator) {
389     olsr_ip_to_string(&buf_neighip, &neigh->nbr_addr);
390     strscpy(buf_sym, neigh->is_sym ? OLSR_YES : OLSR_NO, sizeof(buf_sym));
391     strscpy(buf_mrp, neigh->is_mpr ? OLSR_YES : OLSR_NO, sizeof(buf_mrp));
392     strscpy(buf_mprs, neigh->mprs_count>0 ? OLSR_YES : OLSR_NO, sizeof(buf_mprs));
393
394     snprintf(buf_willingness, sizeof(buf_willingness), "%d", neigh->willingness);
395     snprintf(buf_2hop, sizeof(buf_2hop), "%d", neigh->con_tree.count);
396
397     if (abuf_templatef(&con->out, template, values_neigh, tmpl_indices, indexLength) < 0) {
398         return ABUF_ERROR;
399     }
400   }
401
402   return CONTINUE;
403 }
404
405 /**
406  * Callback for link command
407  */
408 static enum olsr_txtcommand_result
409 txtinfo_link(struct comport_connection *con,
410     const char *cmd __attribute__ ((unused)), const char *param)
411 {
412   struct link_entry *lnk, *iterator;
413   size_t i;
414   const char *template;
415   int indexLength;
416
417   template = param != NULL ? parse_user_template(param) : tmpl_link;
418   if (param == NULL) {
419     if (abuf_puts(&con->out, headline_link) < 0) {
420       return ABUF_ERROR;
421     }
422   }
423
424   if ((indexLength = abuf_template_init(keys_link, link_keys_count,
425       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
426     return ABUF_ERROR;
427   }
428
429   /* Link set */
430   OLSR_FOR_ALL_LINK_ENTRIES(lnk, iterator) {
431     olsr_ip_to_string(&buf_localip, &lnk->local_iface_addr);
432     olsr_ip_to_string(&buf_neighip, &lnk->neighbor_iface_addr);
433     strscpy(buf_sym, lnk->status == SYM_LINK ? OLSR_YES : OLSR_NO, sizeof(buf_sym));
434     strscpy(buf_mrp, lnk->is_mpr ? OLSR_YES : OLSR_NO, sizeof(buf_mrp));
435     olsr_milli_to_txt(&buf_vtime, lnk->link_sym_timer == NULL ? 0 : lnk->link_sym_timer->timer_clock - olsr_timer_getNow());
436     snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", lnk->linkcost);
437
438     olsr_get_linkcost_text(lnk->linkcost, false, buf_linkcost, sizeof(buf_linkcost));
439     for (i=1; i< olsr_get_linklabel_count(); i++) {
440       olsr_get_linkdata_text(lnk, i, values_link[link_keys_static + i - 1], link_value_size);
441     }
442
443     if (abuf_templatef(&con->out, template, values_link, tmpl_indices, indexLength) < 0) {
444         return ABUF_ERROR;
445     }
446   }
447
448   return CONTINUE;
449 }
450
451 /**
452  * Callback for routes command
453  */
454 static enum olsr_txtcommand_result
455 txtinfo_routes(struct comport_connection *con,
456     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
457 {
458   struct rt_entry *rt, *iterator;
459   const char *template;
460   int indexLength;
461
462   template = param != NULL ? parse_user_template(param) : tmpl_routes;
463   if (param == NULL) {
464     if (abuf_appendf(&con->out, "Table: Routes\nDestination\tGateway IP\tMetric\t%s\tInterface\n",
465         olsr_get_linklabel(0)) < 0) {
466       return ABUF_ERROR;
467     }
468   }
469
470   if ((indexLength = abuf_template_init(keys_routes, ARRAYSIZE(keys_routes),
471       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
472     return ABUF_ERROR;
473   }
474
475   /* Walk the route table */
476   OLSR_FOR_ALL_RT_ENTRIES(rt, iterator) {
477     if (!rt->rt_best) {
478       /* ignore entries without paths, they will be erased soon */
479       continue;
480     }
481     olsr_ip_prefix_to_string(&buf_destprefix, &rt->rt_dst);
482     olsr_ip_to_string(&buf_neighip, &rt->rt_best->rtp_nexthop.gateway);
483
484     if (rt->failure_count < 0)  snprintf(buf_failcount, sizeof(buf_failcount), "%d del", rt->failure_count*(-1));
485     else if (rt->failure_count == 0) snprintf(buf_failcount, sizeof(buf_failcount), "0");
486     else snprintf(buf_failcount, sizeof(buf_failcount), "%d add", rt->failure_count);
487
488     snprintf(buf_hopcount, sizeof(buf_hopcount), "%d", rt->rt_best->rtp_metric.hops);
489     snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", rt->rt_best->rtp_metric.cost);
490     olsr_get_linkcost_text(rt->rt_best->rtp_metric.cost, true, buf_linkcost, sizeof(buf_linkcost));
491     strscpy(buf_interface,
492         rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]",
493         sizeof(buf_interface));
494
495     if (abuf_templatef(&con->out, template, values_routes, tmpl_indices, indexLength) < 0) {
496         return ABUF_ERROR;
497     }
498   }
499   return CONTINUE;
500 }
501
502 /**
503  * Callback for topology command
504  */
505 static enum olsr_txtcommand_result
506 txtinfo_topology(struct comport_connection *con,
507     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
508 {
509   struct tc_entry *tc, *iterator;
510   const char *template;
511   int indexLength;
512
513   template = param != NULL ? parse_user_template(param) : tmpl_topology;
514   if (param == NULL) {
515     if (abuf_appendf(&con->out, "Table: Topology\nDest. IP\tLast hop IP\tVirtual\t%s\n",
516         olsr_get_linklabel(0)) < 0) {
517       return ABUF_ERROR;
518     }
519   }
520
521   if ((indexLength = abuf_template_init(keys_topology, ARRAYSIZE(keys_topology),
522       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
523     return ABUF_ERROR;
524   }
525
526   /* Topology */
527   OLSR_FOR_ALL_TC_ENTRIES(tc, iterator) {
528     struct tc_edge_entry *tc_edge, *edge_iterator;
529     olsr_ip_to_string(&buf_localip, &tc->addr);
530     if (tc->validity_timer) {
531       olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - olsr_timer_getNow());
532     }
533     else {
534       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
535     }
536
537     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge, edge_iterator) {
538       olsr_ip_to_string(&buf_neighip, &tc_edge->T_dest_addr);
539       strscpy(buf_virtual, tc_edge->virtual ? OLSR_YES : OLSR_NO, sizeof(buf_virtual));
540       if (tc_edge->virtual) {
541         buf_linkcost[0] = 0;
542         buf_rawlinkcost[0] = '0';
543         buf_rawlinkcost[1] = 0;
544       }
545       else {
546         snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", tc_edge->cost);
547         olsr_get_linkcost_text(tc_edge->cost, false, buf_linkcost, sizeof(buf_linkcost));
548       }
549
550       if (abuf_templatef(&con->out, template, values_topology, tmpl_indices, indexLength) < 0) {
551           return ABUF_ERROR;
552       }
553     }
554   }
555
556   return CONTINUE;
557 }
558
559 /**
560  * Callback for interfaces command
561  */
562 static enum olsr_txtcommand_result
563 txtinfo_interfaces(struct comport_connection *con,
564     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
565 {
566   const struct olsr_if_config *ifs;
567   const char *template;
568   int indexLength;
569
570   template = param != NULL ? parse_user_template(param) : tmpl_interface;
571   if (param == NULL) {
572     if (abuf_puts(&con->out, "Table: Interfaces\nName\tState\tMTU\tSrc-Adress\tDst-Adress\n") < 0) {
573       return ABUF_ERROR;
574     }
575   }
576
577   if ((indexLength = abuf_template_init(keys_interface, ARRAYSIZE(keys_interface),
578       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
579     return ABUF_ERROR;
580   }
581
582
583   for (ifs = olsr_cnf->if_configs; ifs != NULL; ifs = ifs->next) {
584     const struct interface *const rifs = ifs->interf;
585
586     //prepare values
587     strscpy(buf_interface, ifs->name, sizeof(buf_interface));
588
589     if (!rifs) {
590       snprintf(buf_state, sizeof(buf_state), "DOWN");
591       snprintf(buf_mtu, sizeof(buf_mtu), "-");
592       snprintf(buf_srcip.buf, sizeof(buf_srcip.buf), "-");
593       snprintf(buf_dstip.buf, sizeof(buf_srcip.buf), "-");
594     } else {
595       snprintf(buf_mtu, sizeof(buf_mtu), "%d", rifs->int_mtu);
596       snprintf(buf_state, sizeof(buf_state), "UP");
597
598       if (olsr_cnf->ip_version == AF_INET){
599         ip4_to_string(&buf_srcip, rifs->int_src.v4.sin_addr);
600         ip4_to_string(&buf_dstip, rifs->int_multicast.v4.sin_addr);
601       } else {
602         ip6_to_string(&buf_srcip, &rifs->int_src.v6.sin6_addr);
603         ip6_to_string(&buf_dstip, &rifs->int_multicast.v6.sin6_addr); 
604       }
605     }
606
607     if (abuf_templatef(&con->out, template, 
608         values_interface, tmpl_indices, indexLength) < 0) {
609         return ABUF_ERROR;
610     }
611   }
612
613   return CONTINUE;
614 }
615
616 /**
617  * Callback for hna command
618  */
619 static enum olsr_txtcommand_result
620 txtinfo_hna(struct comport_connection *con,
621     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
622 {
623   const struct ip_prefix_entry *hna, *prefix_iterator;
624   struct tc_entry *tc, *tc_iterator;
625   const char *template;
626   int indexLength;
627
628   template = param != NULL ? parse_user_template(param) : tmpl_hna;
629   if (param == NULL) {
630     if (abuf_puts(&con->out, "Table: HNA\nDestination\tGateway\tvtime\n") < 0) {
631       return ABUF_ERROR;
632     }
633   }
634
635   if ((indexLength = abuf_template_init(keys_hna, ARRAYSIZE(keys_hna),
636       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
637     return ABUF_ERROR;
638   }
639
640   /* Announced HNA entries */
641   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna, prefix_iterator) {
642     olsr_ip_to_string(&buf_localip, &olsr_cnf->router_id);
643     olsr_ip_prefix_to_string(&buf_destprefix, &hna->net);
644     strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
645
646     if (abuf_templatef(&con->out, template, values_hna, tmpl_indices, indexLength) < 0) {
647         return ABUF_ERROR;
648     }
649   }
650
651   /* HNA entries */
652   OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
653     struct hna_net *tmp_net, *hna_iterator;
654
655     olsr_ip_to_string(&buf_localip, &tc->addr);
656     if (tc->validity_timer) {
657       olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - olsr_timer_getNow());
658     }
659     else {
660       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
661     }
662
663     /* Check all networks */
664     OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, tmp_net, hna_iterator) {
665       olsr_ip_prefix_to_string(&buf_destprefix, &tmp_net->hna_prefix);
666
667       if (abuf_templatef(&con->out, template, values_hna, tmpl_indices, indexLength) < 0) {
668           return ABUF_ERROR;
669       }
670     }
671   }
672
673   return CONTINUE;
674 }
675
676 /**
677  * Callback for mid command
678  */
679 static enum olsr_txtcommand_result
680 txtinfo_mid(struct comport_connection *con,
681     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
682 {
683   struct tc_entry *tc, *tc_iterator;
684   struct interface *interface, *ifp_iterator;
685
686   const char *template;
687   int indexLength;
688
689   template = param != NULL ? parse_user_template(param) : tmpl_mid;
690   if (param == NULL) {
691     if (abuf_puts(&con->out, "Table: MID\nIP address\tAliases\tvtime\n") < 0) {
692       return ABUF_ERROR;
693     }
694   }
695
696   if ((indexLength = abuf_template_init(keys_mid, ARRAYSIZE(keys_mid),
697       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
698     return ABUF_ERROR;
699   }
700
701   OLSR_FOR_ALL_INTERFACES(interface, ifp_iterator) {
702     if (olsr_ipcmp(&olsr_cnf->router_id, &interface->ip_addr) != 0) {
703       olsr_ip_to_string(&buf_localip, &olsr_cnf->router_id);
704       olsr_ip_to_string(&buf_aliasip, &interface->ip_addr);
705       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
706
707       if (abuf_templatef(&con->out, template, values_mid, tmpl_indices, indexLength) < 0) {
708           return ABUF_ERROR;
709       }
710     }
711   }
712
713   /* MID root is the TC entry */
714   OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
715     struct mid_entry *alias, *alias_iterator;
716
717     olsr_ip_to_string(&buf_localip, &tc->addr);
718     if (tc->validity_timer) {
719       if (tc->validity_timer) {
720         olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - olsr_timer_getNow());
721       }
722       else {
723         strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
724       }
725
726       OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias, alias_iterator) {
727         olsr_ip_to_string(&buf_aliasip, &alias->mid_alias_addr);
728
729         if (abuf_templatef(&con->out, template, values_mid, tmpl_indices, indexLength) < 0) {
730           return ABUF_ERROR;
731         }
732       }
733     }
734   }
735   return CONTINUE;
736 }
737
738 /*
739  * Local Variables:
740  * mode: c
741  * style: linux
742  * c-basic-offset: 4
743  * indent-tabs-mode: nil
744  * End:
745  */