48caa3bc9696a5978430b3c6f18c0d21374cb0e0
[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 "mpr_selector_set.h"
49 #include "tc_set.h"
50 #include "hna_set.h"
51 #include "mid_set.h"
52 #include "routing_table.h"
53 #include "log.h"
54 #include "misc.h"
55 #include "olsr_ip_prefix_list.h"
56 #include "parser.h"
57 #include "olsr_comport_txt.h"
58 #include "common/autobuf.h"
59
60 #include "olsrd_txtinfo.h"
61
62 #define PLUGIN_NAME    "OLSRD txtinfo plugin"
63 #define PLUGIN_VERSION "0.2"
64 #define PLUGIN_AUTHOR   "Henning Rogge"
65 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
66 #define PLUGIN_INTERFACE_VERSION 5
67
68 struct debuginfo_cmd {
69   const char *name;
70   olsr_txthandler handler;
71   struct olsr_txtcommand *normal, *csv;
72 };
73
74 static void txtinfo_new(void) __attribute__ ((constructor));
75 static void txtinfo_delete(void) __attribute__ ((destructor));
76
77 static enum olsr_txtcommand_result txtinfo_neigh(struct comport_connection *con, char *cmd, char *param);
78 static enum olsr_txtcommand_result txtinfo_link(struct comport_connection *con,  char *cmd, char *param);
79 static enum olsr_txtcommand_result txtinfo_routes(struct comport_connection *con,  char *cmd, char *param);
80 static enum olsr_txtcommand_result txtinfo_topology(struct comport_connection *con,  char *cmd, char *param);
81 static enum olsr_txtcommand_result txtinfo_hna(struct comport_connection *con,  char *cmd, char *param);
82 static enum olsr_txtcommand_result txtinfo_mid(struct comport_connection *con,  char *cmd, char *param);
83
84
85 /* plugin configuration */
86 static struct ip_acl allowed_nets;
87
88 /* plugin parameters */
89 static const struct olsrd_plugin_parameters plugin_parameters[] = {
90   {.name = IP_ACL_ACCEPT_PARAP,.set_plugin_parameter = &ip_acl_add_plugin_accept,.data = &allowed_nets},
91   {.name = IP_ACL_REJECT_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_reject,.data = &allowed_nets},
92   {.name = IP_ACL_CHECKFIRST_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_checkFirst,.data = &allowed_nets},
93   {.name = IP_ACL_DEFAULTPOLICY_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_defaultPolicy,.data = &allowed_nets}
94 };
95
96 /* command callbacks and names */
97 static struct debuginfo_cmd commands[] = {
98     {"neigh", &txtinfo_neigh, NULL, NULL},
99     {"link", &txtinfo_link, NULL, NULL},
100     {"routes", &txtinfo_routes, NULL, NULL},
101     {"topology", &txtinfo_topology, NULL, NULL},
102     {"hna", &txtinfo_hna, NULL, NULL},
103     {"mid", &txtinfo_mid, NULL, NULL},
104 };
105
106 int
107 olsrd_plugin_interface_version(void)
108 {
109   return PLUGIN_INTERFACE_VERSION;
110 }
111
112 void
113 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
114 {
115   *params = plugin_parameters;
116   *size = ARRAYSIZE(plugin_parameters);
117 }
118
119
120 /**
121  * Constructor of plugin, called before parameters are initialized
122  */
123 static void
124 txtinfo_new(void)
125 {
126   /* Print plugin info to stdout */
127   OLSR_INFO(LOG_PLUGINS, "%s\n", MOD_DESC);
128
129   ip_acl_init(&allowed_nets);
130
131   /* always allow localhost */
132   if (olsr_cnf->ip_version == AF_INET) {
133     union olsr_ip_addr ip;
134
135     ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
136     ip_acl_add(&allowed_nets, &ip, 32, false);
137   } else {
138     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
139     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
140   }
141 }
142
143 /**
144  * Destructor of plugin
145  */
146 static void
147 txtinfo_delete(void)
148 {
149   size_t i;
150
151   for (i=0; i<ARRAYSIZE(commands); i++) {
152     olsr_com_remove_normal_txtcommand(commands[i].normal);
153     olsr_com_remove_csv_txtcommand(commands[i].csv);
154   }
155   ip_acl_flush(&allowed_nets);
156 }
157
158 /*
159  * Initialization of plugin AFTER parameters have been read
160  */
161 int
162 olsrd_plugin_init(void)
163 {
164   size_t i;
165
166   for (i=0; i<ARRAYSIZE(commands); i++) {
167     commands[i].normal = olsr_com_add_normal_txtcommand(commands[i].name, commands[i].handler);
168     commands[i].csv = olsr_com_add_csv_txtcommand(commands[i].name, commands[i].handler);
169     commands[i].normal->acl = &allowed_nets;
170     commands[i].csv->acl = &allowed_nets;
171   }
172   return 1;
173 }
174
175 /**
176  * Callback for neigh command
177  */
178 static enum olsr_txtcommand_result
179 txtinfo_neigh(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
180 {
181   struct nbr_entry *neigh;
182   if (!con->is_csv && abuf_puts(&con->out, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
183     return ABUF_ERROR;
184   }
185
186   /* Neighbors */
187   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
188     struct ipaddr_str buf1;
189     if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%s\t%s\t%d\t%d\n" : "neigh,%s,%s,%s,%s,%d,%d\n",
190                        olsr_ip_to_string(&buf1, &neigh->nbr_addr),
191                        neigh->is_sym ? "YES" : "NO",
192                        neigh->is_mpr ? "YES" : "NO",
193                        olsr_lookup_mprs_set(&neigh->nbr_addr) ? "YES" : "NO", neigh->willingness, neigh->con_tree.count) < 0) {
194         return ABUF_ERROR;
195     }
196   } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
197
198   return CONTINUE;
199 }
200
201 /**
202  * Callback for link command
203  */
204 static enum olsr_txtcommand_result
205 txtinfo_link(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
206 {
207   struct link_entry *lnk;
208
209   OLSR_DEBUG(LOG_NETWORKING, "Starting 'link' command...\n");
210   if (!con->is_csv && abuf_puts(&con->out, "Table: Links\nLocal IP\tRemote IP\tLQ\tNLQ\tCost\n") < 0) {
211     return ABUF_ERROR;
212   }
213
214   /* Link set */
215   OLSR_FOR_ALL_LINK_ENTRIES(lnk) {
216     struct ipaddr_str buf1, buf2;
217     struct lqtextbuffer lqbuffer1, lqbuffer2;
218     if (abuf_appendf(&con->out,
219                      !con->is_csv ? "%s\t%s\t%s\t%s\t\n" : "link,%s,%s,%s,%s\n",
220                      olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
221                      olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
222                      get_link_entry_text(lnk, '\t', &lqbuffer1), get_linkcost_text(lnk->linkcost, false, &lqbuffer2)) < 0) {
223         return ABUF_ERROR;
224     }
225   } OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
226
227   return CONTINUE;
228 }
229
230 /**
231  * Callback for routes command
232  */
233 static enum olsr_txtcommand_result
234 txtinfo_routes(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
235 {
236   struct rt_entry *rt;
237
238   if (!con->is_csv && abuf_puts(&con->out, "Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n") < 0) {
239     return ABUF_ERROR;
240   }
241
242   /* Walk the route table */
243   OLSR_FOR_ALL_RT_ENTRIES(rt) {
244     struct ipaddr_str ipbuf;
245     struct ipprefix_str prefixstr;
246     struct lqtextbuffer lqbuffer;
247     if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%u\t%s\t%s\t\n" : "route,%s,%s,%u,%s,%s\n",
248                      olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
249                      olsr_ip_to_string(&ipbuf, &rt->rt_best->rtp_nexthop.gateway),
250                      rt->rt_best->rtp_metric.hops,
251                      get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer),
252                      rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]") < 0) {
253       return ABUF_ERROR;
254     }
255   } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
256   return CONTINUE;
257 }
258
259 /**
260  * Callback for topology command
261  */
262 static enum olsr_txtcommand_result
263 txtinfo_topology(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
264 {
265   struct tc_entry *tc;
266   if (!con->is_csv && abuf_puts(&con->out, "Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n") < 0) {
267     return ABUF_ERROR;
268   }
269
270   /* Topology */
271   OLSR_FOR_ALL_TC_ENTRIES(tc) {
272     struct tc_edge_entry *tc_edge;
273     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
274       if (tc_edge->edge_inv) {
275         struct ipaddr_str dstbuf, addrbuf;
276         struct lqtextbuffer lqbuffer1, lqbuffer2;
277         if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%s\t%s\n" : "topo,%s,%s,%s,%s\n",
278                          olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
279                          olsr_ip_to_string(&addrbuf, &tc->addr),
280                          get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
281                          get_linkcost_text(tc_edge->cost, false, &lqbuffer2)) < 0) {
282           return ABUF_ERROR;
283         }
284       }
285     } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
286   } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
287
288   return CONTINUE;
289 }
290
291 /**
292  * helper which prints an HNA entry
293  */
294 static INLINE bool
295 txtinfo_print_hna_entry(struct autobuf *buf, const char *format, const struct olsr_ip_prefix *hna_prefix, const union olsr_ip_addr *ipaddr)
296 {
297   struct ipaddr_str mainaddrbuf;
298   struct ipprefix_str addrbuf;
299   return abuf_appendf(buf, format, olsr_ip_prefix_to_string(&addrbuf, hna_prefix), olsr_ip_to_string(&mainaddrbuf, ipaddr)) < 0;
300 }
301
302 /**
303  * Callback for hna command
304  */
305 static enum olsr_txtcommand_result
306 txtinfo_hna(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
307 {
308   const struct ip_prefix_entry *hna;
309   struct tc_entry *tc;
310
311   const char *format = !con->is_csv ? "%s\t%s\n" : "hna,%s,%s\n";
312   if (!con->is_csv && abuf_puts(&con->out, "Table: HNA\nDestination\tGateway\n") < 0) {
313     return ABUF_ERROR;
314   }
315
316   /* Announced HNA entries */
317   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna) {
318     if (txtinfo_print_hna_entry(&con->out, format, &hna->net, &olsr_cnf->router_id)) {
319       return ABUF_ERROR;
320     }
321   }
322   OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
323
324     /* HNA entries */
325     OLSR_FOR_ALL_TC_ENTRIES(tc) {
326     struct hna_net *tmp_net;
327     /* Check all networks */
328     OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, tmp_net) {
329       if (txtinfo_print_hna_entry(&con->out, format, &tmp_net->hna_prefix, &tc->addr)) {
330         return ABUF_ERROR;
331       }
332     } OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, tmp_net);
333   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
334
335   return CONTINUE;
336 }
337
338 /**
339  * Callback for mid command
340  */
341 static enum olsr_txtcommand_result
342 txtinfo_mid(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
343 {
344   struct tc_entry *tc;
345   const char *prefix = !con->is_csv ? "" : "mid,";
346   const char sep = !con->is_csv ? '\t' : ',';
347
348   if (!con->is_csv && abuf_puts(&con->out, "Table: MID\nIP address\tAliases\n") < 0) {
349     return ABUF_ERROR;
350   }
351
352   /* MID root is the TC entry */
353   OLSR_FOR_ALL_TC_ENTRIES(tc) {
354     struct ipaddr_str ipbuf;
355     struct mid_entry *alias;
356
357     if (abuf_appendf(&con->out, "%s%s", prefix, olsr_ip_to_string(&ipbuf, &tc->addr)) < 0) {
358       return ABUF_ERROR;
359     }
360
361     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
362       if (abuf_appendf(&con->out, "%c%s", sep, olsr_ip_to_string(&ipbuf, &alias->mid_alias_addr)) < 0) {
363         return ABUF_ERROR;
364       }
365     }
366     OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
367     if (abuf_appendf(&con->out, "\n") < 0) {
368       return ABUF_ERROR;
369     }
370   } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
371   return CONTINUE;
372 }
373
374 /*
375  * Local Variables:
376  * mode: c
377  * style: linux
378  * c-basic-offset: 4
379  * indent-tabs-mode: nil
380  * End:
381  */