44ffccaf1d407a2ef8460ae8ef1b7556ac30f64a
[oonf.git] / src / generic / layer2info / layer2info.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, 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  * @file
44  */
45
46 #include <stdio.h>
47
48 #include <oonf/libcommon/autobuf.h>
49 #include <oonf/oonf.h>
50 #include <oonf/libcommon/netaddr.h>
51 #include <oonf/libcommon/netaddr_acl.h>
52 #include <oonf/libcommon/string.h>
53 #include <oonf/libcommon/template.h>
54
55 #include <oonf/libcore/oonf_logging.h>
56 #include <oonf/libcore/oonf_subsystem.h>
57 #include <oonf/subsystems/oonf_clock.h>
58 #include <oonf/subsystems/oonf_layer2.h>
59 #include <oonf/subsystems/oonf_telnet.h>
60 #include <oonf/subsystems/oonf_viewer.h>
61
62 #include <oonf/generic/layer2info/layer2info.h>
63
64 /* definitions */
65 #define LOG_LAYER2INFO _oonf_layer2info_subsystem.logging
66
67 /* prototypes */
68 static int _init(void);
69 static void _cleanup(void);
70
71 static enum oonf_telnet_result _cb_layer2info(struct oonf_telnet_data *con);
72 static enum oonf_telnet_result _cb_layer2info_help(struct oonf_telnet_data *con);
73
74 static void _initialize_if_data_values(struct oonf_viewer_template *template, struct oonf_layer2_data *data);
75 static void _initialize_if_origin_values(struct oonf_layer2_data *data);
76 static void _initialize_if_values(struct oonf_layer2_net *net);
77 static void _initialize_if_ip_values(struct oonf_layer2_peer_address *peer_ip);
78
79 static void _initialize_neigh_data_values(struct oonf_viewer_template *template, struct oonf_layer2_data *data);
80 static void _initialize_neigh_origin_values(struct oonf_layer2_data *data);
81 static void _initialize_neigh_values(struct oonf_layer2_neigh *neigh);
82 static void _initialize_neigh_ip_values(struct oonf_layer2_neighbor_address *neigh_addr);
83
84 static int _cb_create_text_interface(struct oonf_viewer_template *);
85 static int _cb_create_text_interface_ip(struct oonf_viewer_template *);
86 static int _cb_create_text_neighbor(struct oonf_viewer_template *);
87 static int _cb_create_text_neighbor_ip(struct oonf_viewer_template *);
88 static int _cb_create_text_default(struct oonf_viewer_template *);
89 static int _cb_create_text_dst(struct oonf_viewer_template *);
90
91 /*
92  * list of template keys and corresponding buffers for values.
93  *
94  * The keys are API, so they should not be changed after published
95  */
96
97 /*! template key for interface name */
98 #define KEY_IF "if"
99
100 /*! template key for interface index */
101 #define KEY_IF_INDEX "if_index"
102
103 /*! template key for interface type */
104 #define KEY_IF_TYPE "if_type"
105
106 /*! template key for DLEP interface */
107 #define KEY_IF_DLEP "if_dlep"
108
109 /*! template key for interface identifier */
110 #define KEY_IF_IDENT "if_ident"
111
112 /*! template key for interface address identifier */
113 #define KEY_IF_IDENT_ADDR "if_ident_addr"
114
115 /*! template key for local interface address */
116 #define KEY_IF_LOCAL_ADDR "if_local_addr"
117
118 /*! template key for last time interface was active */
119 #define KEY_IF_LASTSEEN "if_lastseen"
120
121 /*! template key for IP/prefixes of the local radio/model */
122 #define KEY_IF_PEER_IP "if_peer_ip"
123
124 /*! template key for IP/prefixes origin of the local radio/model */
125 #define KEY_IF_PEER_IP_ORIGIN "if_peer_ip_origin"
126
127 /*! template key for neighbor address */
128 #define KEY_NEIGH_ADDR "neigh_addr"
129
130 /*! template key for neighbor link-id */
131 #define KEY_NEIGH_LID "neigh_lid"
132
133 /*! template key for neighbor link-id length */
134 #define KEY_NEIGH_LID_LEN "neigh_lid_length"
135
136 /*! template key for last time neighbor was active */
137 #define KEY_NEIGH_LASTSEEN "neigh_lastseen"
138
139 /*! template key for IP/prefixes of the neighbors remote router */
140 #define KEY_NEIGH_REMOTE_IP "neigh_remote_ip"
141
142 /*! template key for IP/prefixes origin of the neighbors remote router */
143 #define KEY_NEIGH_REMOTE_IP_ORIGIN "neigh_remote_ip_origin"
144
145 /*! template key for destination address */
146 #define KEY_DST_ADDR "dst_addr"
147
148 /*! template key for destination origin */
149 #define KEY_DST_ORIGIN "dst_origin"
150
151 /*! string prefix for all interface keys */
152 #define KEY_IF_PREFIX "if_"
153
154 /*! string prefix for all neighbor keys */
155 #define KEY_NEIGH_PREFIX "neigh_"
156
157 /*! string suffix for all data originators */
158 #define KEY_ORIGIN_SUFFIX "_origin"
159
160 /*
161  * buffer space for values that will be assembled
162  * into the output of the plugin
163  */
164 static char _value_if[IF_NAMESIZE];
165 static char _value_if_index[12];
166 static char _value_if_type[16];
167 static char _value_if_dlep[TEMPLATE_JSON_BOOL_LENGTH];
168 static char _value_if_ident[33];
169 static struct netaddr_str _value_if_ident_addr;
170 static struct netaddr_str _value_if_local_addr;
171 static struct isonumber_str _value_if_lastseen;
172 static struct netaddr_str _value_if_peer_ip;
173 static char _value_if_peer_ip_origin[IF_NAMESIZE];
174 static char _value_if_data[OONF_LAYER2_NET_COUNT][64];
175 static char _value_if_origin[OONF_LAYER2_NET_COUNT][IF_NAMESIZE];
176 static struct netaddr_str _value_neigh_addr;
177 static union oonf_layer2_neigh_key_str _value_neigh_key;
178 static char _value_neigh_key_length[6];
179 static struct isonumber_str _value_neigh_lastseen;
180 static struct netaddr_str _value_neigh_remote_ip;
181 static char _value_neigh_remote_ip_origin[IF_NAMESIZE];
182 static char _value_neigh_data[OONF_LAYER2_NEIGH_COUNT][64];
183 static char _value_neigh_origin[OONF_LAYER2_NEIGH_COUNT][IF_NAMESIZE];
184
185 static struct netaddr_str _value_dst_addr;
186 static char _value_dst_origin[IF_NAMESIZE];
187
188 /* definition of the template data entries for JSON and table output */
189 static struct abuf_template_data_entry _tde_if_key[] = {
190   { KEY_IF, _value_if, true },
191   { KEY_IF_INDEX, _value_if_index, false },
192   { KEY_IF_LOCAL_ADDR, _value_if_local_addr.buf, true },
193 };
194
195 static struct abuf_template_data_entry _tde_if[] = {
196   { KEY_IF_TYPE, _value_if_type, true },
197   { KEY_IF_DLEP, _value_if_dlep, true },
198   { KEY_IF_IDENT, _value_if_ident, true },
199   { KEY_IF_IDENT_ADDR, _value_if_ident_addr.buf, true },
200   { KEY_IF_LASTSEEN, _value_if_lastseen.buf, false },
201 };
202
203 static struct abuf_template_data_entry _tde_if_peer_ip[] = {
204   { KEY_IF_PEER_IP, _value_if_peer_ip.buf, true },
205   { KEY_IF_PEER_IP_ORIGIN, _value_if_peer_ip_origin, true },
206 };
207
208 static struct abuf_template_data_entry _tde_if_data[OONF_LAYER2_NET_COUNT];
209 static struct abuf_template_data_entry _tde_if_origin[OONF_LAYER2_NET_COUNT];
210
211 static struct abuf_template_data_entry _tde_neigh_key[] = {
212   { KEY_NEIGH_ADDR, _value_neigh_addr.buf, true },
213   { KEY_NEIGH_LID, _value_neigh_key.buf, true },
214   { KEY_NEIGH_LID_LEN, _value_neigh_key_length, false },
215 };
216
217 static struct abuf_template_data_entry _tde_neigh[] = {
218   { KEY_NEIGH_LASTSEEN, _value_neigh_lastseen.buf, false },
219 };
220
221 static struct abuf_template_data_entry _tde_neigh_remote_ip[] = {
222   { KEY_NEIGH_REMOTE_IP, _value_neigh_remote_ip.buf, true },
223   { KEY_NEIGH_REMOTE_IP_ORIGIN, _value_neigh_remote_ip_origin, true },
224 };
225
226 static struct abuf_template_data_entry _tde_neigh_data[OONF_LAYER2_NEIGH_COUNT];
227 static struct abuf_template_data_entry _tde_neigh_origin[OONF_LAYER2_NEIGH_COUNT];
228
229 static struct abuf_template_data_entry _tde_dst_key[] = {
230   { KEY_DST_ADDR, _value_dst_addr.buf, true },
231 };
232 static struct abuf_template_data_entry _tde_dst[] = {
233   { KEY_DST_ORIGIN, _value_dst_origin, true },
234 };
235
236 static struct abuf_template_storage _template_storage;
237 static struct autobuf _key_storage;
238
239 /* Template Data objects (contain one or more Template Data Entries) */
240 static struct abuf_template_data _td_if[] = {
241   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
242   { _tde_if, ARRAYSIZE(_tde_if) },
243   { _tde_if_data, ARRAYSIZE(_tde_if_data) },
244   { _tde_if_origin, ARRAYSIZE(_tde_if_origin) },
245 };
246 static struct abuf_template_data _td_if_ips[] = {
247   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
248   { _tde_if_peer_ip, ARRAYSIZE(_tde_if_peer_ip) },
249 };
250 static struct abuf_template_data _td_neigh[] = {
251   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
252   { _tde_neigh_key, ARRAYSIZE(_tde_neigh_key) },
253   { _tde_neigh, ARRAYSIZE(_tde_neigh) },
254   { _tde_neigh_data, ARRAYSIZE(_tde_neigh_data) },
255   { _tde_neigh_origin, ARRAYSIZE(_tde_neigh_origin) },
256 };
257 static struct abuf_template_data _td_neigh_ips[] = {
258   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
259   { _tde_neigh_key, ARRAYSIZE(_tde_neigh_key) },
260   { _tde_neigh_remote_ip, ARRAYSIZE(_tde_neigh_remote_ip) },
261 };
262 static struct abuf_template_data _td_default[] = {
263   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
264   { _tde_neigh_data, ARRAYSIZE(_tde_neigh_data) },
265   { _tde_neigh_origin, ARRAYSIZE(_tde_neigh_origin) },
266 };
267 static struct abuf_template_data _td_dst[] = {
268   { _tde_if_key, ARRAYSIZE(_tde_if_key) },
269   { _tde_neigh_key, ARRAYSIZE(_tde_neigh_key) },
270   { _tde_dst_key, ARRAYSIZE(_tde_dst_key) },
271   { _tde_dst, ARRAYSIZE(_tde_dst) },
272 };
273
274 /* OONF viewer templates (based on Template Data arrays) */
275 static struct oonf_viewer_template _templates[] = {
276   {
277     .data = _td_if,
278     .data_size = ARRAYSIZE(_td_if),
279     .json_name = "interface",
280     .cb_function = _cb_create_text_interface,
281   },
282   {
283     .data = _td_if_ips,
284     .data_size = ARRAYSIZE(_td_if_ips),
285     .json_name = "interface_ip",
286     .cb_function = _cb_create_text_interface_ip,
287   },
288   {
289     .data = _td_neigh,
290     .data_size = ARRAYSIZE(_td_neigh),
291     .json_name = "neighbor",
292     .cb_function = _cb_create_text_neighbor,
293   },
294   {
295     .data = _td_neigh_ips,
296     .data_size = ARRAYSIZE(_td_neigh_ips),
297     .json_name = "neighbor_ip",
298     .cb_function = _cb_create_text_neighbor_ip,
299   },
300   {
301     .data = _td_default,
302     .data_size = ARRAYSIZE(_td_default),
303     .json_name = "default",
304     .cb_function = _cb_create_text_default,
305   },
306   {
307     .data = _td_dst,
308     .data_size = ARRAYSIZE(_td_dst),
309     .json_name = "destination",
310     .cb_function = _cb_create_text_dst,
311   },
312 };
313
314 /* telnet command of this plugin */
315 static struct oonf_telnet_command _telnet_commands[] = {
316   TELNET_CMD(OONF_LAYER2INFO_SUBSYSTEM, _cb_layer2info, "", .help_handler = _cb_layer2info_help),
317 };
318
319 /* plugin declaration */
320 static const char *_dependencies[] = {
321   OONF_CLOCK_SUBSYSTEM,
322   OONF_LAYER2_SUBSYSTEM,
323   OONF_TELNET_SUBSYSTEM,
324   OONF_VIEWER_SUBSYSTEM,
325 };
326
327 static struct oonf_subsystem _olsrv2_layer2info_subsystem = {
328   .name = OONF_LAYER2INFO_SUBSYSTEM,
329   .dependencies = _dependencies,
330   .dependencies_count = ARRAYSIZE(_dependencies),
331   .descr = "OLSRv2 layer2 info plugin",
332   .author = "Henning Rogge",
333   .init = _init,
334   .cleanup = _cleanup,
335 };
336 DECLARE_OONF_PLUGIN(_olsrv2_layer2info_subsystem);
337
338 /**
339  * Initialize plugin
340  * @return -1 if an error happened, 0 otherwise
341  */
342 static int
343 _init(void) {
344   size_t i;
345
346   abuf_init(&_key_storage);
347
348   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
349     _tde_if_data[i].key = abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
350     _tde_if_data[i].value = _value_if_data[i];
351     _tde_if_data[i].string = true;
352
353     abuf_puts(&_key_storage, KEY_IF_PREFIX);
354     abuf_puts(&_key_storage, oonf_layer2_net_metadata_get(i)->key);
355     abuf_memcpy(&_key_storage, "\0", 1);
356
357     _tde_if_origin[i].key = abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
358     _tde_if_origin[i].value = _value_if_origin[i];
359     _tde_if_origin[i].string = true;
360
361     abuf_puts(&_key_storage, KEY_IF_PREFIX);
362     abuf_puts(&_key_storage, oonf_layer2_net_metadata_get(i)->key);
363     abuf_puts(&_key_storage, KEY_ORIGIN_SUFFIX);
364     abuf_memcpy(&_key_storage, "\0", 1);
365   }
366
367   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
368     _tde_neigh_data[i].key = abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
369     _tde_neigh_data[i].value = _value_neigh_data[i];
370     _tde_neigh_data[i].string = true;
371
372     abuf_puts(&_key_storage, KEY_NEIGH_PREFIX);
373     abuf_puts(&_key_storage, oonf_layer2_neigh_metadata_get(i)->key);
374     abuf_memcpy(&_key_storage, "\0", 1);
375
376     _tde_neigh_origin[i].key = abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
377     _tde_neigh_origin[i].value = _value_neigh_origin[i];
378     _tde_neigh_origin[i].string = true;
379
380     abuf_puts(&_key_storage, KEY_NEIGH_PREFIX);
381     abuf_puts(&_key_storage, oonf_layer2_neigh_metadata_get(i)->key);
382     abuf_puts(&_key_storage, KEY_ORIGIN_SUFFIX);
383     abuf_memcpy(&_key_storage, "\0", 1);
384   }
385
386   oonf_telnet_add(&_telnet_commands[0]);
387
388   return abuf_has_failed(&_key_storage) ? -1 : 0;
389 }
390
391 /**
392  * Cleanup plugin
393  */
394 static void
395 _cleanup(void) {
396   oonf_telnet_remove(&_telnet_commands[0]);
397   abuf_free(&_key_storage);
398 }
399
400 /**
401  * Callback for the telnet command of this plugin
402  * @param con pointer to telnet session data
403  * @return telnet result value
404  */
405 static enum oonf_telnet_result
406 _cb_layer2info(struct oonf_telnet_data *con) {
407   return oonf_viewer_telnet_handler(
408     con->out, &_template_storage, OONF_LAYER2INFO_SUBSYSTEM, con->parameter, _templates, ARRAYSIZE(_templates));
409 }
410
411 /**
412  * Callback for the help output of this plugin
413  * @param con pointer to telnet session data
414  * @return telnet result value
415  */
416 static enum oonf_telnet_result
417 _cb_layer2info_help(struct oonf_telnet_data *con) {
418   return oonf_viewer_telnet_help(
419     con->out, OONF_LAYER2INFO_SUBSYSTEM, con->parameter, _templates, ARRAYSIZE(_templates));
420 }
421
422 /**
423  * Initialize the value buffers for a layer2 interface
424  * @param net pointer to layer2 interface
425  */
426 static void
427 _initialize_if_values(struct oonf_layer2_net *net) {
428   struct os_interface *os_if;
429
430   os_if = net->if_listener.data;
431
432   strscpy(_value_if, net->name, sizeof(_value_if));
433   snprintf(_value_if_index, sizeof(_value_if_index), "%u", os_if->index);
434   strscpy(_value_if_ident, net->if_ident, sizeof(_value_if_ident));
435   netaddr_to_string(&_value_if_local_addr, &os_if->mac);
436   strscpy(_value_if_type, oonf_layer2_net_get_type_name(net->if_type), IF_NAMESIZE);
437   strscpy(_value_if_dlep, json_getbool(net->if_dlep), TEMPLATE_JSON_BOOL_LENGTH);
438
439   if (net->last_seen) {
440     oonf_clock_toIntervalString(&_value_if_lastseen, -oonf_clock_get_relative(net->last_seen));
441   }
442   else {
443     _value_if_lastseen.buf[0] = 0;
444   }
445 }
446
447 /**
448  * Initialize the value buffers for a l2 peer address object
449  * @param peer_ip peer address object
450  */
451 static void
452 _initialize_if_ip_values(struct oonf_layer2_peer_address *peer_ip) {
453   netaddr_to_string(&_value_if_peer_ip, &peer_ip->ip);
454   strscpy(_value_if_peer_ip_origin, peer_ip->origin->name, sizeof(_value_if_peer_ip_origin));
455 }
456
457 /**
458  * Initialize the value buffers for an array of layer2 data objects
459  * @param template viewer template
460  * @param data array of data objects
461  */
462 static void
463 _initialize_if_data_values(struct oonf_viewer_template *template, struct oonf_layer2_data *data) {
464   size_t i;
465
466   memset(_value_if_data, 0, sizeof(_value_if_data));
467
468   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
469     oonf_layer2_net_data_to_string(_value_if_data[i], sizeof(_value_if_data[i]), &data[i], i, template->create_raw);
470   }
471 }
472
473 /**
474  * Initialize the network origin buffers for an array of layer2 data objects
475  * @param data array of data objects
476  */
477 static void
478 _initialize_if_origin_values(struct oonf_layer2_data *data) {
479   size_t i;
480
481   memset(_value_if_origin, 0, sizeof(_value_if_origin));
482
483   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
484     if (oonf_layer2_data_has_value(&data[i])) {
485       strscpy(_value_if_origin[i], oonf_layer2_data_get_origin(&data[i])->name, IF_NAMESIZE);
486     }
487   }
488 }
489
490 /**
491  * Initialize the value buffers for a layer2 neighbor
492  * @param neigh layer2 neighbor
493  */
494 static void
495 _initialize_neigh_values(struct oonf_layer2_neigh *neigh) {
496   netaddr_to_string(&_value_neigh_addr, &neigh->key.addr);
497   oonf_layer2_neigh_key_to_string(&_value_neigh_key, &neigh->key, false);
498   snprintf(_value_neigh_key_length, sizeof(_value_neigh_key_length), "%u", neigh->key.link_id_length);
499
500   if (neigh->last_seen) {
501     oonf_clock_toIntervalString(&_value_neigh_lastseen, -oonf_clock_get_relative(neigh->last_seen));
502   }
503   else {
504     _value_neigh_lastseen.buf[0] = 0;
505   }
506 }
507
508 /**
509  * Initialize the value buffers for a l2 neighbor remote address object
510  * @param neigh_addr neighbor remote address
511  */
512 static void
513 _initialize_neigh_ip_values(struct oonf_layer2_neighbor_address *neigh_addr) {
514   netaddr_to_string(&_value_neigh_remote_ip, &neigh_addr->ip);
515   strscpy(_value_neigh_remote_ip_origin, neigh_addr->origin->name, sizeof(_value_neigh_remote_ip_origin));
516 }
517
518 /**
519  * Initialize the value buffers for an array of layer2 data objects
520  * @param template viewer template
521  * @param data array of data objects
522  */
523 static void
524 _initialize_neigh_data_values(struct oonf_viewer_template *template, struct oonf_layer2_data *data) {
525   size_t i;
526
527   memset(_value_neigh_data, 0, sizeof(_value_neigh_data));
528
529   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
530     oonf_layer2_neigh_data_to_string(
531       _value_neigh_data[i], sizeof(_value_neigh_data[i]), &data[i], i, template->create_raw);
532   }
533 }
534
535 /**
536  * Initialize the network origin buffers for an array of layer2 data objects
537  * @param data array of data objects
538  */
539 static void
540 _initialize_neigh_origin_values(struct oonf_layer2_data *data) {
541   size_t i;
542
543   memset(_value_neigh_origin, 0, sizeof(_value_neigh_origin));
544
545   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
546     if (oonf_layer2_data_has_value(&data[i])) {
547       strscpy(_value_neigh_origin[i], oonf_layer2_data_get_origin(&data[i])->name, IF_NAMESIZE);
548     }
549   }
550 }
551
552 /**
553  * Initialize the value buffers for a layer2 destination
554  * @param l2dst layer2 destination
555  */
556 static void
557 _initialize_destination_values(struct oonf_layer2_destination *l2dst) {
558   netaddr_to_string(&_value_dst_addr, &l2dst->destination);
559   strscpy(_value_dst_origin, l2dst->origin->name, IF_NAMESIZE);
560 }
561
562 /**
563  * Callback to generate text/json description of all layer2 interfaces
564  * @param template viewer template
565  * @return -1 if an error happened, 0 otherwise
566  */
567 static int
568 _cb_create_text_interface(struct oonf_viewer_template *template) {
569   struct oonf_layer2_net *net;
570
571   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
572     _initialize_if_values(net);
573     _initialize_if_data_values(template, net->data);
574     _initialize_if_origin_values(net->data);
575
576     /* generate template output */
577     oonf_viewer_output_print_line(template);
578   }
579   return 0;
580 }
581
582 /**
583  * Callback to generate text/json description of all layer2 interface ips
584  * @param template viewer template
585  * @return -1 if an error happened, 0 otherwise
586  */
587 static int
588 _cb_create_text_interface_ip(struct oonf_viewer_template *template) {
589   struct oonf_layer2_net *net;
590   struct oonf_layer2_peer_address *peer_ip;
591
592   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
593     _initialize_if_values(net);
594
595     avl_for_each_element(&net->local_peer_ips, peer_ip, _net_node) {
596       _initialize_if_ip_values(peer_ip);
597
598       /* generate template output */
599       oonf_viewer_output_print_line(template);
600     }
601   }
602   return 0;
603 }
604
605 /**
606  * Callback to generate text/json description of all layer2 neighbors
607  * @param template viewer template
608  * @return -1 if an error happened, 0 otherwise
609  */
610 static int
611 _cb_create_text_neighbor(struct oonf_viewer_template *template) {
612   struct oonf_layer2_neigh *neigh;
613   struct oonf_layer2_net *net;
614
615   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
616     _initialize_if_values(net);
617
618     avl_for_each_element(&net->neighbors, neigh, _node) {
619       _initialize_neigh_values(neigh);
620       _initialize_neigh_data_values(template, neigh->data);
621       _initialize_neigh_origin_values(neigh->data);
622
623       /* generate template output */
624       oonf_viewer_output_print_line(template);
625     }
626   }
627   return 0;
628 }
629
630 /**
631  * Callback to generate text/json description of all layer2 neighbor ips
632  * @param template viewer template
633  * @return -1 if an error happened, 0 otherwise
634  */
635 static int
636 _cb_create_text_neighbor_ip(struct oonf_viewer_template *template) {
637   struct oonf_layer2_neighbor_address *remote_ip;
638   struct oonf_layer2_neigh *neigh;
639   struct oonf_layer2_net *net;
640
641   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
642     _initialize_if_values(net);
643
644     avl_for_each_element(&net->neighbors, neigh, _node) {
645       _initialize_neigh_values(neigh);
646
647       avl_for_each_element(&neigh->remote_neighbor_ips, remote_ip, _neigh_node) {
648         _initialize_neigh_ip_values(remote_ip);
649
650         /* generate template output */
651         oonf_viewer_output_print_line(template);
652       }
653     }
654   }
655   return 0;
656 }
657
658 /**
659  * Callback to generate text/json description of the defaults stored
660  * in the layer2 interfaces for their neighbors
661  * @param template viewer template
662  * @return -1 if an error happened, 0 otherwise
663  */
664 static int
665 _cb_create_text_default(struct oonf_viewer_template *template) {
666   struct oonf_layer2_net *net;
667
668   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
669     _initialize_if_values(net);
670     _initialize_neigh_data_values(template, net->neighdata);
671     _initialize_neigh_origin_values(net->neighdata);
672
673     /* generate template output */
674     oonf_viewer_output_print_line(template);
675   }
676   return 0;
677 }
678
679 /**
680  * Callback to generate text/json description of all layer2 destinations
681  * @param template viewer template
682  * @return -1 if an error happened, 0 otherwise
683  */
684 static int
685 _cb_create_text_dst(struct oonf_viewer_template *template) {
686   struct oonf_layer2_destination *l2dst;
687   struct oonf_layer2_neigh *neigh;
688   struct oonf_layer2_net *net;
689
690   avl_for_each_element(oonf_layer2_get_net_tree(), net, _node) {
691     _initialize_if_values(net);
692
693     avl_for_each_element(&net->neighbors, neigh, _node) {
694       _initialize_neigh_values(neigh);
695
696       avl_for_each_element(&neigh->destinations, l2dst, _node) {
697         _initialize_destination_values(l2dst);
698
699         /* generate template output */
700         oonf_viewer_output_print_line(template);
701       }
702     }
703   }
704   return 0;
705 }