185ea76036c3ea6ce2f2d06e0b0185dfe11daa8b
[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 bool txtinfo_init(void);
72 static bool txtinfo_enable(void);
73 static bool txtinfo_disable(void);
74 static bool 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 bool
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 false;
251 }
252
253 /**
254  * Destructor of plugin
255  */
256 static bool
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 false;
268 }
269
270 /*
271  * Initialization of plugin AFTER parameters have been read
272  */
273 static bool
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 false;
315 }
316
317 static bool
318 txtinfo_exit(void) {
319   ip_acl_flush(&allowed_nets);
320   return false;
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;
374   struct list_iterator iterator;
375   const char *template;
376   int indexLength;
377
378   template = param != NULL ? parse_user_template(param) : tmpl_neigh;
379   if (param == NULL &&
380       abuf_puts(&con->out, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
381     return ABUF_ERROR;
382   }
383
384   if ((indexLength = abuf_template_init(keys_neigh, ARRAYSIZE(keys_neigh), template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
385     return ABUF_ERROR;
386   }
387
388   /* Neighbors */
389   OLSR_FOR_ALL_NBR_ENTRIES(neigh, iterator) {
390     olsr_ip_to_string(&buf_neighip, &neigh->nbr_addr);
391     strscpy(buf_sym, neigh->is_sym ? OLSR_YES : OLSR_NO, sizeof(buf_sym));
392     strscpy(buf_mrp, neigh->is_mpr ? OLSR_YES : OLSR_NO, sizeof(buf_mrp));
393     strscpy(buf_mprs, neigh->mprs_count>0 ? OLSR_YES : OLSR_NO, sizeof(buf_mprs));
394
395     snprintf(buf_willingness, sizeof(buf_willingness), "%d", neigh->willingness);
396     snprintf(buf_2hop, sizeof(buf_2hop), "%d", neigh->con_tree.count);
397
398     if (abuf_templatef(&con->out, template, values_neigh, tmpl_indices, indexLength) < 0) {
399         return ABUF_ERROR;
400     }
401   }
402
403   return CONTINUE;
404 }
405
406 /**
407  * Callback for link command
408  */
409 static enum olsr_txtcommand_result
410 txtinfo_link(struct comport_connection *con,
411     const char *cmd __attribute__ ((unused)), const char *param)
412 {
413   struct link_entry *lnk;
414   struct list_iterator iterator;
415   size_t i;
416   const char *template;
417   int indexLength;
418
419   template = param != NULL ? parse_user_template(param) : tmpl_link;
420   if (param == NULL) {
421     if (abuf_puts(&con->out, headline_link) < 0) {
422       return ABUF_ERROR;
423     }
424   }
425
426   if ((indexLength = abuf_template_init(keys_link, link_keys_count,
427       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
428     return ABUF_ERROR;
429   }
430
431   /* Link set */
432   OLSR_FOR_ALL_LINK_ENTRIES(lnk, iterator) {
433     olsr_ip_to_string(&buf_localip, &lnk->local_iface_addr);
434     olsr_ip_to_string(&buf_neighip, &lnk->neighbor_iface_addr);
435     strscpy(buf_sym, lnk->status == SYM_LINK ? OLSR_YES : OLSR_NO, sizeof(buf_sym));
436     strscpy(buf_mrp, lnk->is_mpr ? OLSR_YES : OLSR_NO, sizeof(buf_mrp));
437     olsr_milli_to_txt(&buf_vtime, lnk->link_sym_timer == NULL ? 0 : lnk->link_sym_timer->timer_clock - now_times);
438     snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", lnk->linkcost);
439
440     olsr_get_linkcost_text(lnk->linkcost, false, buf_linkcost, sizeof(buf_linkcost));
441     for (i=1; i< olsr_get_linklabel_count(); i++) {
442       olsr_get_linkdata_text(lnk, i, values_link[link_keys_static + i - 1], link_value_size);
443     }
444
445     if (abuf_templatef(&con->out, template, values_link, tmpl_indices, indexLength) < 0) {
446         return ABUF_ERROR;
447     }
448   }
449
450   return CONTINUE;
451 }
452
453 /**
454  * Callback for routes command
455  */
456 static enum olsr_txtcommand_result
457 txtinfo_routes(struct comport_connection *con,
458     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
459 {
460   struct rt_entry *rt;
461   struct list_iterator iterator;
462   const char *template;
463   int indexLength;
464
465   template = param != NULL ? parse_user_template(param) : tmpl_routes;
466   if (param == NULL) {
467     if (abuf_appendf(&con->out, "Table: Routes\nDestination\tGateway IP\tMetric\t%s\tInterface\n",
468         olsr_get_linklabel(0)) < 0) {
469       return ABUF_ERROR;
470     }
471   }
472
473   if ((indexLength = abuf_template_init(keys_routes, ARRAYSIZE(keys_routes),
474       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
475     return ABUF_ERROR;
476   }
477
478   /* Walk the route table */
479   OLSR_FOR_ALL_RT_ENTRIES(rt, iterator) {
480     if (!rt->rt_best) {
481       /* ignore entries without paths, they will be erased soon */
482       continue;
483     }
484     olsr_ip_prefix_to_string(&buf_destprefix, &rt->rt_dst);
485     olsr_ip_to_string(&buf_neighip, &rt->rt_best->rtp_nexthop.gateway);
486
487     if (rt->failure_count < 0)  snprintf(buf_failcount, sizeof(buf_failcount), "%d del", rt->failure_count*(-1));
488     else if (rt->failure_count == 0) snprintf(buf_failcount, sizeof(buf_failcount), "0");
489     else snprintf(buf_failcount, sizeof(buf_failcount), "%d add", rt->failure_count);
490
491     snprintf(buf_hopcount, sizeof(buf_hopcount), "%d", rt->rt_best->rtp_metric.hops);
492     snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", rt->rt_best->rtp_metric.cost);
493     olsr_get_linkcost_text(rt->rt_best->rtp_metric.cost, true, buf_linkcost, sizeof(buf_linkcost));
494     strscpy(buf_interface,
495         rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]",
496         sizeof(buf_interface));
497
498     if (abuf_templatef(&con->out, template, values_routes, tmpl_indices, indexLength) < 0) {
499         return ABUF_ERROR;
500     }
501   }
502   return CONTINUE;
503 }
504
505 /**
506  * Callback for topology command
507  */
508 static enum olsr_txtcommand_result
509 txtinfo_topology(struct comport_connection *con,
510     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
511 {
512   struct tc_entry *tc;
513   struct list_iterator iterator, iterator2;
514   const char *template;
515   int indexLength;
516
517   template = param != NULL ? parse_user_template(param) : tmpl_topology;
518   if (param == NULL) {
519     if (abuf_appendf(&con->out, "Table: Topology\nDest. IP\tLast hop IP\tVirtual\t%s\n",
520         olsr_get_linklabel(0)) < 0) {
521       return ABUF_ERROR;
522     }
523   }
524
525   if ((indexLength = abuf_template_init(keys_topology, ARRAYSIZE(keys_topology),
526       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
527     return ABUF_ERROR;
528   }
529
530   /* Topology */
531   OLSR_FOR_ALL_TC_ENTRIES(tc, iterator) {
532     struct tc_edge_entry *tc_edge;
533     olsr_ip_to_string(&buf_localip, &tc->addr);
534     if (tc->validity_timer) {
535       olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - now_times);
536     }
537     else {
538       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
539     }
540
541     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge, iterator2) {
542       olsr_ip_to_string(&buf_neighip, &tc_edge->T_dest_addr);
543       strscpy(buf_virtual, tc_edge->virtual ? OLSR_YES : OLSR_NO, sizeof(buf_virtual));
544       if (tc_edge->virtual) {
545         buf_linkcost[0] = 0;
546         buf_rawlinkcost[0] = '0';
547         buf_rawlinkcost[1] = 0;
548       }
549       else {
550         snprintf(buf_rawlinkcost, sizeof(buf_rawlinkcost), "%ud", tc_edge->cost);
551         olsr_get_linkcost_text(tc_edge->cost, false, buf_linkcost, sizeof(buf_linkcost));
552       }
553
554       if (abuf_templatef(&con->out, template, values_topology, tmpl_indices, indexLength) < 0) {
555           return ABUF_ERROR;
556       }
557     }
558   }
559
560   return CONTINUE;
561 }
562
563 /**
564  * Callback for interfaces command
565  */
566 static enum olsr_txtcommand_result
567 txtinfo_interfaces(struct comport_connection *con,
568     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
569 {
570   const struct olsr_if_config *ifs;
571   const char *template;
572   int indexLength;
573
574   template = param != NULL ? parse_user_template(param) : tmpl_interface;
575   if (param == NULL) {
576     if (abuf_puts(&con->out, "Table: Interfaces\nName\tState\tMTU\tSrc-Adress\tDst-Adress\n") < 0) {
577       return ABUF_ERROR;
578     }
579   }
580
581   if ((indexLength = abuf_template_init(keys_interface, ARRAYSIZE(keys_interface),
582       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
583     return ABUF_ERROR;
584   }
585
586
587   for (ifs = olsr_cnf->if_configs; ifs != NULL; ifs = ifs->next) {
588     const struct interface *const rifs = ifs->interf;
589
590     //prepare values
591     strscpy(buf_interface, ifs->name, sizeof(buf_interface));
592
593     if (!rifs) {
594       snprintf(buf_state, sizeof(buf_state), "DOWN");
595       snprintf(buf_mtu, sizeof(buf_mtu), "-");
596       snprintf(buf_srcip.buf, sizeof(buf_srcip.buf), "-");
597       snprintf(buf_dstip.buf, sizeof(buf_srcip.buf), "-");
598     } else {
599       snprintf(buf_mtu, sizeof(buf_mtu), "%d", rifs->int_mtu);
600       snprintf(buf_state, sizeof(buf_state), "UP");
601
602       if (olsr_cnf->ip_version == AF_INET){
603         ip4_to_string(&buf_srcip, rifs->int_src.v4.sin_addr);
604         ip4_to_string(&buf_dstip, rifs->int_multicast.v4.sin_addr);
605       } else {
606         ip6_to_string(&buf_srcip, &rifs->int_src.v6.sin6_addr);
607         ip6_to_string(&buf_dstip, &rifs->int_multicast.v6.sin6_addr); 
608       }
609     }
610
611     if (abuf_templatef(&con->out, template, 
612         values_interface, tmpl_indices, indexLength) < 0) {
613         return ABUF_ERROR;
614     }
615   }
616
617   return CONTINUE;
618 }
619
620 /**
621  * Callback for hna command
622  */
623 static enum olsr_txtcommand_result
624 txtinfo_hna(struct comport_connection *con,
625     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
626 {
627   const struct ip_prefix_entry *hna;
628   struct list_iterator iterator, iterator2;
629   struct tc_entry *tc;
630   const char *template;
631   int indexLength;
632
633   template = param != NULL ? parse_user_template(param) : tmpl_hna;
634   if (param == NULL) {
635     if (abuf_puts(&con->out, "Table: HNA\nDestination\tGateway\tvtime\n") < 0) {
636       return ABUF_ERROR;
637     }
638   }
639
640   if ((indexLength = abuf_template_init(keys_hna, ARRAYSIZE(keys_hna),
641       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
642     return ABUF_ERROR;
643   }
644
645   /* Announced HNA entries */
646   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna, iterator) {
647     olsr_ip_to_string(&buf_localip, &olsr_cnf->router_id);
648     olsr_ip_prefix_to_string(&buf_destprefix, &hna->net);
649     strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
650
651     if (abuf_templatef(&con->out, template, values_hna, tmpl_indices, indexLength) < 0) {
652         return ABUF_ERROR;
653     }
654   }
655
656   /* HNA entries */
657   OLSR_FOR_ALL_TC_ENTRIES(tc, iterator) {
658     struct hna_net *tmp_net;
659
660     olsr_ip_to_string(&buf_localip, &tc->addr);
661     if (tc->validity_timer) {
662       olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - now_times);
663     }
664     else {
665       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
666     }
667
668     /* Check all networks */
669     OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, tmp_net, iterator2) {
670       olsr_ip_prefix_to_string(&buf_destprefix, &tmp_net->hna_prefix);
671
672       if (abuf_templatef(&con->out, template, values_hna, tmpl_indices, indexLength) < 0) {
673           return ABUF_ERROR;
674       }
675     }
676   }
677
678   return CONTINUE;
679 }
680
681 /**
682  * Callback for mid command
683  */
684 static enum olsr_txtcommand_result
685 txtinfo_mid(struct comport_connection *con,
686     const char *cmd __attribute__ ((unused)), const char *param __attribute__ ((unused)))
687 {
688   struct tc_entry *tc;
689   struct interface *interface;
690   struct list_iterator iterator, iterator2;
691
692   const char *template;
693   int indexLength;
694
695   template = param != NULL ? parse_user_template(param) : tmpl_mid;
696   if (param == NULL) {
697     if (abuf_puts(&con->out, "Table: MID\nIP address\tAliases\tvtime\n") < 0) {
698       return ABUF_ERROR;
699     }
700   }
701
702   if ((indexLength = abuf_template_init(keys_mid, ARRAYSIZE(keys_mid),
703       template, tmpl_indices, ARRAYSIZE(tmpl_indices))) < 0) {
704     return ABUF_ERROR;
705   }
706
707   OLSR_FOR_ALL_INTERFACES(interface, iterator) {
708     if (olsr_ipcmp(&olsr_cnf->router_id, &interface->ip_addr) != 0) {
709       olsr_ip_to_string(&buf_localip, &olsr_cnf->router_id);
710       olsr_ip_to_string(&buf_aliasip, &interface->ip_addr);
711       strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
712
713       if (abuf_templatef(&con->out, template, values_mid, tmpl_indices, indexLength) < 0) {
714           return ABUF_ERROR;
715       }
716     }
717   }
718
719   /* MID root is the TC entry */
720   OLSR_FOR_ALL_TC_ENTRIES(tc, iterator) {
721     struct mid_entry *alias;
722
723     olsr_ip_to_string(&buf_localip, &tc->addr);
724     if (tc->validity_timer) {
725       if (tc->validity_timer) {
726         olsr_milli_to_txt(&buf_vtime, tc->validity_timer->timer_clock - now_times);
727       }
728       else {
729         strscpy(buf_vtime.buf, "0.0", sizeof(buf_vtime));
730       }
731
732       OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias, iterator2) {
733         olsr_ip_to_string(&buf_aliasip, &alias->mid_alias_addr);
734
735         if (abuf_templatef(&con->out, template, values_mid, tmpl_indices, indexLength) < 0) {
736           return ABUF_ERROR;
737         }
738       }
739     }
740   }
741   return CONTINUE;
742 }
743
744 /*
745  * Local Variables:
746  * mode: c
747  * style: linux
748  * c-basic-offset: 4
749  * indent-tabs-mode: nil
750  * End:
751  */