4195f402086b2e66aa924494f4c1d7522c67dcb9
[olsrd.git] / lib / jsoninfo / src / olsrd_jsoninfo.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004
4  *
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 #include "olsrd_jsoninfo.h"
43
44 #include <unistd.h>
45 #include <ctype.h>
46 #include <libgen.h>
47
48 #include "ipcalc.h"
49 #include "builddata.h"
50 #include "neighbor_table.h"
51 #include "mpr_selector_set.h"
52 #include "routing_table.h"
53 #include "mid_set.h"
54 #include "gateway.h"
55 #include "egressTypes.h"
56 #include "olsrd_jsoninfo_helpers.h"
57 #include "olsrd_plugin.h"
58 #include "../../info/info_types.h"
59
60 struct timeval start_time;
61
62 #ifdef __linux__
63 static bool isGwSelectable(struct gateway_entry * gw, bool ipv6) {
64   if (!ipv6) {
65     return gw->ipv4 //
66         && ((olsr_cnf->ip_version == AF_INET) //
67             || olsr_cnf->use_niit) //
68         && (olsr_cnf->smart_gw_allow_nat //
69             || !gw->ipv4nat);
70   }
71
72   return gw->ipv6 //
73       && (olsr_cnf->ip_version == AF_INET6);
74 }
75 #endif /* __linux__ */
76
77 void plugin_init(const char *plugin_name) {
78   /* Get start time */
79   gettimeofday(&start_time, NULL);
80
81   if (!strlen(uuidfile))
82     strscpy(uuidfile, "uuid.txt", sizeof(uuidfile));
83   read_uuid_from_file(plugin_name, uuidfile);
84 }
85
86 bool isCommand(const char *str, unsigned int siw) {
87   const char * cmd;
88   switch (siw) {
89     case SIW_OLSRD_CONF:
90       cmd = "/olsrd.conf";
91       break;
92
93     case SIW_ALL:
94       cmd = "/all";
95       break;
96
97     case SIW_RUNTIME_ALL:
98       cmd = "/runtime";
99       break;
100
101     case SIW_STARTUP_ALL:
102       cmd = "/startup";
103       break;
104
105     case SIW_NEIGHBORS:
106       cmd = "/neighbors";
107       break;
108
109     case SIW_LINKS:
110       cmd = "/links";
111       break;
112
113     case SIW_ROUTES:
114       cmd = "/routes";
115       break;
116
117     case SIW_HNA:
118       cmd = "/hna";
119       break;
120
121     case SIW_MID:
122       cmd = "/mid";
123       break;
124
125     case SIW_TOPOLOGY:
126       cmd = "/topology";
127       break;
128
129     case SIW_GATEWAYS:
130       cmd = "/gateways";
131       break;
132
133     case SIW_INTERFACES:
134       cmd = "/interfaces";
135       break;
136
137     case SIW_2HOP:
138       cmd = "/2hop";
139       break;
140
141     case SIW_SGW:
142       cmd = "/sgw";
143       break;
144
145     case SIW_VERSION:
146       cmd = "/version";
147       break;
148
149     case SIW_CONFIG:
150       cmd = "/config";
151       break;
152
153     case SIW_PLUGINS:
154       cmd = "/plugins";
155       break;
156
157     case SIW_NEIGHBORS_FREIFUNK:
158       cmd = "/neighbours";
159       break;
160
161     default:
162       return false;
163   }
164
165   return !strcmp(str, cmd);
166 }
167
168 const char * determine_mime_type(unsigned int send_what) {
169   return (send_what & SIW_ALL) ? "application/json; charset=utf-8" : "text/plain; charset=utf-8";
170 }
171
172 void output_start(struct autobuf *abuf) {
173   /* global variables for tracking when to put a comma in for JSON */
174   abuf_json_reset_entry_number_and_depth();
175   abuf_json_mark_output(true, abuf);
176
177   abuf_json_int(abuf, "systemTime", time(NULL));
178   abuf_json_int(abuf, "timeSinceStartup", now_times);
179   if (*uuid)
180     abuf_json_string(abuf, "uuid", uuid);
181 }
182
183 void output_end(struct autobuf *abuf) {
184   abuf_json_mark_output(false, abuf);
185   abuf_puts(abuf, "\n");
186 }
187
188 static void ipc_print_neighbors_internal(struct autobuf *abuf, bool list_2hop) {
189   struct ipaddr_str buf1, buf2;
190   struct neighbor_entry *neigh;
191   struct neighbor_2_list_entry *list_2;
192
193   if (!list_2hop)
194     abuf_json_mark_object(true, true, abuf, "neighbors");
195   else
196     abuf_json_mark_object(true, true, abuf, "2hop");
197
198   /* Neighbors */
199   OLSR_FOR_ALL_NBR_ENTRIES(neigh)
200       {
201         abuf_json_mark_array_entry(true, abuf);
202
203         abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf1, &neigh->neighbor_main_addr));
204         abuf_json_boolean(abuf, "symmetric", (neigh->status == SYM));
205         abuf_json_int(abuf, "willingness", neigh->willingness);
206         abuf_json_boolean(abuf, "isMultiPointRelay", neigh->is_mpr);
207         abuf_json_boolean(abuf, "wasMultiPointRelay", neigh->was_mpr);
208         abuf_json_boolean(abuf, "multiPointRelaySelector", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) != NULL);
209         abuf_json_boolean(abuf, "skip", neigh->skip);
210         abuf_json_int(abuf, "neighbor2nocov", neigh->neighbor_2_nocov);
211         abuf_json_int(abuf, "linkcount", neigh->linkcount);
212
213         if (!list_2hop) {
214           int thop_cnt = 0;
215           for (list_2 = neigh->neighbor_2_list.next; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next) {
216             thop_cnt++;
217           }
218           abuf_json_int(abuf, "twoHopNeighborCount", thop_cnt);
219         } else {
220           abuf_json_mark_object(true, true, abuf, "twoHopNeighbors");
221           for (list_2 = neigh->neighbor_2_list.next; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next) {
222             abuf_json_mark_array_entry(true, abuf);
223             abuf_json_string(abuf, "ipAddress", list_2->neighbor_2 ? olsr_ip_to_string(&buf2, &list_2->neighbor_2->neighbor_2_addr) : "");
224             abuf_json_mark_array_entry(false, abuf);
225           }
226           abuf_json_mark_object(false, true, abuf, false);
227         }
228
229         abuf_json_mark_array_entry(false, abuf);
230       }OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
231   abuf_json_mark_object(false, true, abuf, NULL);
232 }
233
234 void ipc_print_neighbors(struct autobuf *abuf) {
235   ipc_print_neighbors_internal(abuf, false);
236 }
237
238 void ipc_print_links(struct autobuf *abuf) {
239   struct link_entry *my_link;
240
241   abuf_json_mark_object(true, true, abuf, "links");
242
243   OLSR_FOR_ALL_LINK_ENTRIES(my_link)
244       {
245         struct ipaddr_str localAddr;
246         struct ipaddr_str remoteAddr;
247         struct lqtextbuffer lqBuffer;
248         const char* lqString = get_link_entry_text(my_link, '\t', &lqBuffer);
249         char * nlqString = strrchr(lqString, '\t');
250
251         if (nlqString) {
252           *nlqString = '\0';
253           nlqString++;
254         }
255
256         abuf_json_mark_array_entry(true, abuf);
257
258         abuf_json_string(abuf, "localIP", olsr_ip_to_string(&localAddr, &my_link->local_iface_addr));
259         abuf_json_string(abuf, "remoteIP", olsr_ip_to_string(&remoteAddr, &my_link->neighbor_iface_addr));
260         abuf_json_string(abuf, "olsrInterface", (my_link->inter && my_link->inter->int_name) ? my_link->inter->int_name : "");
261         abuf_json_string(abuf, "ifName", my_link->if_name ? my_link->if_name : "");
262         abuf_json_int(abuf, "validityTime", my_link->link_timer ? (long) (my_link->link_timer->timer_clock - now_times) : 0);
263         abuf_json_int(abuf, "symmetryTime", my_link->link_sym_timer ? (long) (my_link->link_sym_timer->timer_clock - now_times) : 0);
264         abuf_json_int(abuf, "asymmetryTime", my_link->ASYM_time);
265         abuf_json_int(abuf, "vtime", (long) my_link->vtime);
266         // neighbor (no need to print, can be looked up via neighbours)
267         abuf_json_string(abuf, "currentLinkStatus", linkTypeToString(lookup_link_status(my_link)));
268         abuf_json_string(abuf, "previousLinkStatus", linkTypeToString(my_link->prev_status));
269
270         abuf_json_float(abuf, "linkQuality", atof(lqString));
271         abuf_json_float(abuf, "neighborLinkQuality", nlqString ? atof(nlqString) : 0.0);
272         abuf_json_boolean(abuf, "pending", my_link->L_link_pending != 0);
273         abuf_json_int(abuf, "lostLinkTime", (long) my_link->L_LOST_LINK_time);
274         abuf_json_int(abuf, "helloTime", my_link->link_hello_timer ? (long) (my_link->link_hello_timer->timer_clock - now_times) : 0);
275         abuf_json_int(abuf, "lastHelloTime", (long) my_link->last_htime);
276         abuf_json_boolean(abuf, "seqnoValid", my_link->olsr_seqno_valid);
277         abuf_json_int(abuf, "seqno", my_link->olsr_seqno);
278
279         abuf_json_int(abuf, "lossHelloInterval", (long) my_link->loss_helloint);
280         abuf_json_int(abuf, "lossTime", my_link->link_loss_timer ? (long) (my_link->link_loss_timer->timer_clock - now_times) : 0);
281
282         abuf_json_int(abuf, "lossMultiplier", (long) my_link->loss_link_multiplier);
283
284         abuf_json_int(abuf, "linkCost", MIN(my_link->linkcost, LINK_COST_BROKEN));
285
286         abuf_json_mark_array_entry(false, abuf);
287       }OLSR_FOR_ALL_LINK_ENTRIES_END(my_link);
288   abuf_json_mark_object(false, true, abuf, NULL);
289 }
290
291 void ipc_print_routes(struct autobuf *abuf) {
292   struct ipaddr_str buf1, buf2;
293   struct rt_entry *rt;
294
295   abuf_json_mark_object(true, true, abuf, "routes");
296
297   /* Walk the route table */
298   OLSR_FOR_ALL_RT_ENTRIES(rt)
299       {
300         abuf_json_mark_array_entry(true, abuf);
301         abuf_json_string(abuf, "destination", olsr_ip_to_string(&buf1, &rt->rt_dst.prefix));
302         abuf_json_int(abuf, "genmask", rt->rt_dst.prefix_len);
303         abuf_json_string(abuf, "gateway", olsr_ip_to_string(&buf2, &rt->rt_best->rtp_nexthop.gateway));
304         abuf_json_int(abuf, "metric", rt->rt_best->rtp_metric.hops);
305         if (rt->rt_best->rtp_metric.cost >= ROUTE_COST_BROKEN)
306           abuf_json_int(abuf, "rtpMetricCost", ROUTE_COST_BROKEN);
307         else
308           abuf_json_int(abuf, "rtpMetricCost", rt->rt_best->rtp_metric.cost);
309         abuf_json_string(abuf, "networkInterface", if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
310         abuf_json_mark_array_entry(false, abuf);
311       }OLSR_FOR_ALL_RT_ENTRIES_END(rt);
312
313   abuf_json_mark_object(false, true, abuf, NULL);
314 }
315
316 void ipc_print_topology(struct autobuf *abuf) {
317   struct tc_entry *tc;
318
319   abuf_json_mark_object(true, true, abuf, "topology");
320
321   /* Topology */
322   OLSR_FOR_ALL_TC_ENTRIES(tc)
323       {
324         struct tc_edge_entry *tc_edge;
325         OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge)
326             {
327               if (tc_edge->edge_inv) {
328                 struct ipaddr_str dstbuf, addrbuf;
329                 struct lqtextbuffer lqbuffer1;
330                 uint32_t vt = tc->validity_timer != NULL ? (tc->validity_timer->timer_clock - now_times) : 0;
331                 int diff = (int) (vt);
332                 const char* lqs;
333                 abuf_json_mark_array_entry(true, abuf);
334                 abuf_json_string(abuf, "destinationIP", olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr));
335                 abuf_json_string(abuf, "lastHopIP", olsr_ip_to_string(&addrbuf, &tc->addr));
336                 lqs = get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1);
337                 abuf_json_float(abuf, "linkQuality", atof(lqs));
338                 abuf_json_float(abuf, "neighborLinkQuality", atof(strrchr(lqs, '\t')));
339                 if (tc_edge->cost >= LINK_COST_BROKEN)
340                   abuf_json_int(abuf, "tcEdgeCost", LINK_COST_BROKEN);
341                 else
342                   abuf_json_int(abuf, "tcEdgeCost", tc_edge->cost);
343                 abuf_json_int(abuf, "validityTime", diff);
344                 abuf_json_mark_array_entry(false, abuf);
345               }
346             }OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
347       }OLSR_FOR_ALL_TC_ENTRIES_END(tc);
348
349   abuf_json_mark_object(false, true, abuf, NULL);
350 }
351
352 void ipc_print_hna(struct autobuf *abuf) {
353   struct ip_prefix_list *hna;
354   struct hna_entry *tmp_hna;
355
356   abuf_json_mark_object(true, true, abuf, "hna");
357
358   /* Announced HNA entries */
359   {
360     struct ipaddr_str mainaddrbuf;
361     struct ipaddr_str prefixbuf;
362
363     olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr);
364
365     for (hna = olsr_cnf->hna_entries; hna != NULL ; hna = hna->next) {
366       abuf_json_mark_array_entry(true, abuf);
367       abuf_json_string(abuf, "gateway", mainaddrbuf.buf);
368       abuf_json_string(abuf, "destination", olsr_ip_to_string(&prefixbuf, &hna->net.prefix));
369       abuf_json_int(abuf, "genmask", hna->net.prefix_len);
370       abuf_json_int(abuf, "validityTime", 0);
371       abuf_json_mark_array_entry(false, abuf);
372     }
373   }
374
375   OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna)
376         {
377           struct hna_net *tmp_net;
378
379           /* Check all networks */
380           for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
381             struct ipaddr_str mainaddrbuf;
382             struct ipaddr_str prefixbuf;
383             uint32_t vt = tmp_net->hna_net_timer ? (tmp_net->hna_net_timer->timer_clock - now_times) : 0;
384
385             abuf_json_mark_array_entry(true, abuf);
386             abuf_json_string(abuf, "gateway", olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
387             abuf_json_string(abuf, "destination", olsr_ip_to_string(&prefixbuf, &tmp_net->hna_prefix.prefix));
388             abuf_json_int(abuf, "genmask", tmp_net->hna_prefix.prefix_len);
389             abuf_json_int(abuf, "validityTime", (long) vt);
390             abuf_json_mark_array_entry(false, abuf);
391           }
392         }OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
393
394   abuf_json_mark_object(false, true, abuf, NULL);
395 }
396
397 void ipc_print_mid(struct autobuf *abuf) {
398   int idx;
399   struct mid_entry *entry;
400   struct mid_address *alias;
401
402   abuf_json_mark_object(true, true, abuf, "mid");
403
404   /* MID */
405   for (idx = 0; idx < HASHSIZE; idx++) {
406     entry = mid_set[idx].next;
407
408     while (entry != &mid_set[idx]) {
409       struct ipaddr_str buf, buf2;
410       abuf_json_mark_array_entry(true, abuf);
411       abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf, &entry->main_addr));
412
413       abuf_json_mark_object(true, true, abuf, "aliases");
414       alias = entry->aliases;
415       while (alias) {
416         uint32_t vt = alias->vtime - now_times;
417         int diff = (int) (vt);
418
419         abuf_json_mark_array_entry(true, abuf);
420         abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf2, &alias->alias));
421         abuf_json_int(abuf, "validityTime", diff);
422         abuf_json_mark_array_entry(false, abuf);
423
424         alias = alias->next_alias;
425       }
426       abuf_json_mark_object(false, true, abuf, NULL); // aliases
427       abuf_json_mark_array_entry(false, abuf);
428       entry = entry->next;
429     }
430   }
431   abuf_json_mark_object(false, true, abuf, NULL); // mid
432 }
433
434 #ifdef __linux__
435
436 static void ipc_print_gateway_entry(struct autobuf *abuf, bool ipv6, struct gateway_entry * current_gw, struct gateway_entry * gw) {
437   struct tc_entry* tc = olsr_lookup_tc_entry(&gw->originator);
438
439   abuf_json_boolean(abuf, "selected", current_gw && (current_gw == gw));
440   abuf_json_boolean(abuf, "selectable", isGwSelectable(gw, ipv6));
441   abuf_json_ip_address(abuf, "originator", &gw->originator);
442   abuf_json_ip_address(abuf, "prefix", &gw->external_prefix.prefix);
443   abuf_json_int(abuf, "prefixLen", gw->external_prefix.prefix_len);
444   abuf_json_int(abuf, "uplink", gw->uplink);
445   abuf_json_int(abuf, "downlink", gw->downlink);
446   abuf_json_int(abuf, "pathcost", !tc ? ROUTE_COST_BROKEN : tc->path_cost);
447   abuf_json_boolean(abuf, "IPv4", gw->ipv4);
448   abuf_json_boolean(abuf, "IPv4-NAT", gw->ipv4nat);
449   abuf_json_boolean(abuf, "IPv6", gw->ipv6);
450   abuf_json_int(abuf, "cost", gw->path_cost);
451   abuf_json_int(abuf, "hops", !tc ? 0 : tc->hops);
452 }
453
454 static void ipc_print_gateways_ipvx(struct autobuf *abuf, bool ipv6) {
455   abuf_json_mark_object(true, true, abuf, ipv6 ? "ipv6" : "ipv4");
456
457   if (olsr_cnf->smart_gw_active) {
458     struct gateway_entry * current_gw = olsr_get_inet_gateway(ipv6);
459     struct gateway_entry * gw;
460     OLSR_FOR_ALL_GATEWAY_ENTRIES(gw)
461         {
462           if (!(!ipv6 && gw->ipv4) && !(ipv6 && gw->ipv6)) {
463             continue;
464           }
465
466           abuf_json_mark_array_entry(true, abuf);
467           ipc_print_gateway_entry(abuf, ipv6, current_gw, gw);
468           abuf_json_mark_array_entry(false, abuf);
469         }OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
470   }
471
472   abuf_json_mark_object(false, true, abuf, NULL);
473 }
474 #endif /* __linux__ */
475
476 void ipc_print_gateways(struct autobuf *abuf) {
477 #ifndef __linux__
478   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
479 #else /* __linux__ */
480   abuf_json_mark_object(true, false, abuf, "gateways");
481
482   ipc_print_gateways_ipvx(abuf, false);
483   ipc_print_gateways_ipvx(abuf, true);
484
485   abuf_json_mark_object(false, false, abuf, NULL);
486 #endif /* __linux__ */
487 }
488
489 #ifdef __linux__
490
491 /** interface names for smart gateway tunnel interfaces, IPv4 */
492 extern struct interfaceName * sgwTunnel4InterfaceNames;
493
494 /** interface names for smart gateway tunnel interfaces, IPv6 */
495 extern struct interfaceName * sgwTunnel6InterfaceNames;
496
497 /**
498  * Construct the sgw table for a given ip version
499  *
500  * @param abuf the string buffer
501  * @param ipv6 true for IPv6, false for IPv4
502  * @param fmtv the format for printing
503  */
504 static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
505   struct interfaceName * sgwTunnelInterfaceNames = !ipv6 ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
506
507   abuf_json_mark_object(true, true, abuf, ipv6 ? "ipv6" : "ipv4");
508
509   if (olsr_cnf->smart_gw_active && sgwTunnelInterfaceNames) {
510     struct gateway_entry * current_gw = olsr_get_inet_gateway(ipv6);
511     int i;
512     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
513       struct interfaceName * node = &sgwTunnelInterfaceNames[i];
514       struct gateway_entry * gw = node->gw;
515
516       if (!gw) {
517         continue;
518       }
519
520       abuf_json_mark_array_entry(true, abuf);
521       ipc_print_gateway_entry(abuf, ipv6, current_gw, gw);
522       abuf_json_ip_address(abuf, "destination", &gw->originator);
523       abuf_json_string(abuf, "tunnel", node->name);
524       abuf_json_int(abuf, "tableNr", node->tableNr);
525       abuf_json_int(abuf, "ruleNr", node->ruleNr);
526       abuf_json_int(abuf, "bypassRuleNr", node->bypassRuleNr);
527       abuf_json_mark_array_entry(false, abuf);
528     }
529   }
530
531   abuf_json_mark_object(false, true, abuf, NULL);
532 }
533 #endif /* __linux__ */
534
535 void ipc_print_sgw(struct autobuf *abuf) {
536 #ifndef __linux__
537   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
538 #else
539   abuf_json_mark_object(true, false, abuf, "sgw");
540
541   sgw_ipvx(abuf, false);
542   sgw_ipvx(abuf, true);
543
544   abuf_json_mark_object(false, false, abuf, NULL);
545 #endif /* __linux__ */
546 }
547
548 void ipc_print_version(struct autobuf *abuf) {
549   abuf_json_mark_object(true, false, abuf, "version");
550
551   abuf_json_string(abuf, "version", olsrd_version);
552   abuf_json_string(abuf, "date", build_date);
553   abuf_json_string(abuf, "host", build_host);
554
555   abuf_json_mark_object(false, false, abuf, NULL);
556 }
557
558 void ipc_print_olsrd_conf(struct autobuf *abuf) {
559   olsrd_write_cnf_autobuf(abuf, olsr_cnf);
560 }
561
562 void ipc_print_interfaces(struct autobuf *abuf) {
563 #ifdef __linux__
564   int linklen;
565   char path[PATH_MAX], linkpath[PATH_MAX];
566 #endif /* __linux__ */
567   char ipv6_buf[INET6_ADDRSTRLEN]; /* buffer for IPv6 inet_htop */
568   struct olsr_lq_mult *mult;
569   const struct olsr_if *ifs;
570   abuf_json_mark_object(true, true, abuf, "interfaces");
571   for (ifs = olsr_cnf->interfaces; ifs != NULL ; ifs = ifs->next) {
572     const struct interface_olsr * const rifs = ifs->interf;
573     abuf_json_mark_array_entry(true, abuf);
574     abuf_json_string(abuf, "name", ifs->name);
575
576     abuf_json_mark_object(true, true, abuf, "linkQualityMultipliers");
577     for (mult = ifs->cnf->lq_mult; mult != NULL ; mult = mult->next) {
578       abuf_json_mark_array_entry(true, abuf);
579       abuf_json_string(abuf, "route", inet_ntop(olsr_cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)));
580       abuf_json_float(abuf, "multiplier", mult->value / 65535.0);
581       abuf_json_mark_array_entry(false, abuf);
582     }
583     abuf_json_mark_object(false, true, abuf, NULL);
584
585     if (!rifs) {
586       abuf_json_string(abuf, "state", "down");
587     } else {
588       abuf_json_string(abuf, "state", "up");
589       abuf_json_string(abuf, "nameFromKernel", rifs->int_name);
590       abuf_json_int(abuf, "interfaceMode", rifs->mode);
591       abuf_json_boolean(abuf, "emulatedHostClientInterface", rifs->is_hcif);
592       abuf_json_boolean(abuf, "sendTcImmediately", rifs->immediate_send_tc);
593       abuf_json_int(abuf, "fishEyeTtlIndex", rifs->ttl_index);
594       abuf_json_int(abuf, "olsrForwardingTimeout", rifs->fwdtimer);
595       abuf_json_int(abuf, "olsrMessageSequenceNumber", rifs->olsr_seqnum);
596       abuf_json_int(abuf, "olsrInterfaceMetric", rifs->int_metric);
597       abuf_json_int(abuf, "olsrMTU", rifs->int_mtu);
598       abuf_json_int(abuf, "helloEmissionInterval", rifs->hello_etime);
599       abuf_json_int(abuf, "helloValidityTime", me_to_reltime(rifs->valtimes.hello));
600       abuf_json_int(abuf, "tcValidityTime", me_to_reltime(rifs->valtimes.tc));
601       abuf_json_int(abuf, "midValidityTime", me_to_reltime(rifs->valtimes.mid));
602       abuf_json_int(abuf, "hnaValidityTime", me_to_reltime(rifs->valtimes.hna));
603       abuf_json_boolean(abuf, "wireless", rifs->is_wireless);
604
605 #ifdef __linux__
606       abuf_json_boolean(abuf, "icmpRedirect", rifs->nic_state.redirect);
607       abuf_json_boolean(abuf, "spoofFilter", rifs->nic_state.spoof);
608 #endif /* __linux__ */
609
610       if (olsr_cnf->ip_version == AF_INET) {
611         struct ipaddr_str addrbuf, maskbuf, bcastbuf;
612         abuf_json_string(abuf, "ipv4Address", ip4_to_string(&addrbuf, rifs->int_addr.sin_addr));
613         abuf_json_string(abuf, "netmask", ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr));
614         abuf_json_string(abuf, "broadcast", ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
615       } else {
616         struct ipaddr_str addrbuf, maskbuf;
617         abuf_json_string(abuf, "ipv6Address", ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr));
618         abuf_json_string(abuf, "multicast", ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
619       }
620     }
621 #ifdef __linux__
622     snprintf(path, PATH_MAX, "/sys/class/net/%s/device/driver/module", ifs->name);
623     linklen = readlink(path, linkpath, PATH_MAX - 1);
624     if (linklen > 1) {
625       linkpath[linklen] = '\0';
626       abuf_json_string(abuf, "kernelModule", basename(linkpath));
627     }
628
629     abuf_json_sys_class_net(abuf, "addressLength", ifs->name, "addr_len");
630     abuf_json_sys_class_net(abuf, "carrier", ifs->name, "carrier");
631     abuf_json_sys_class_net(abuf, "dormant", ifs->name, "dormant");
632     abuf_json_sys_class_net(abuf, "features", ifs->name, "features");
633     abuf_json_sys_class_net(abuf, "flags", ifs->name, "flags");
634     abuf_json_sys_class_net(abuf, "linkMode", ifs->name, "link_mode");
635     abuf_json_sys_class_net(abuf, "macAddress", ifs->name, "address");
636     abuf_json_sys_class_net(abuf, "ethernetMTU", ifs->name, "mtu");
637     abuf_json_sys_class_net(abuf, "operationalState", ifs->name, "operstate");
638     abuf_json_sys_class_net(abuf, "txQueueLength", ifs->name, "tx_queue_len");
639     abuf_json_sys_class_net(abuf, "collisions", ifs->name, "statistics/collisions");
640     abuf_json_sys_class_net(abuf, "multicastPackets", ifs->name, "statistics/multicast");
641     abuf_json_sys_class_net(abuf, "rxBytes", ifs->name, "statistics/rx_bytes");
642     abuf_json_sys_class_net(abuf, "rxCompressed", ifs->name, "statistics/rx_compressed");
643     abuf_json_sys_class_net(abuf, "rxCrcErrors", ifs->name, "statistics/rx_crc_errors");
644     abuf_json_sys_class_net(abuf, "rxDropped", ifs->name, "statistics/rx_dropped");
645     abuf_json_sys_class_net(abuf, "rxErrors", ifs->name, "statistics/rx_errors");
646     abuf_json_sys_class_net(abuf, "rxFifoErrors", ifs->name, "statistics/rx_fifo_errors");
647     abuf_json_sys_class_net(abuf, "rxFrameErrors", ifs->name, "statistics/rx_frame_errors");
648     abuf_json_sys_class_net(abuf, "rxLengthErrors", ifs->name, "statistics/rx_length_errors");
649     abuf_json_sys_class_net(abuf, "rxMissedErrors", ifs->name, "statistics/rx_missed_errors");
650     abuf_json_sys_class_net(abuf, "rxOverErrors", ifs->name, "statistics/rx_over_errors");
651     abuf_json_sys_class_net(abuf, "rxPackets", ifs->name, "statistics/rx_packets");
652     abuf_json_sys_class_net(abuf, "txAbortedErrors", ifs->name, "statistics/tx_aborted_errors");
653     abuf_json_sys_class_net(abuf, "txBytes", ifs->name, "statistics/tx_bytes");
654     abuf_json_sys_class_net(abuf, "txCarrierErrors", ifs->name, "statistics/tx_carrier_errors");
655     abuf_json_sys_class_net(abuf, "txCompressed", ifs->name, "statistics/tx_compressed");
656     abuf_json_sys_class_net(abuf, "txDropped", ifs->name, "statistics/tx_dropped");
657     abuf_json_sys_class_net(abuf, "txErrors", ifs->name, "statistics/tx_errors");
658     abuf_json_sys_class_net(abuf, "txFifoErrors", ifs->name, "statistics/tx_fifo_errors");
659     abuf_json_sys_class_net(abuf, "txHeartbeatErrors", ifs->name, "statistics/tx_heartbeat_errors");
660     abuf_json_sys_class_net(abuf, "txPackets", ifs->name, "statistics/tx_packets");
661     abuf_json_sys_class_net(abuf, "txWindowErrors", ifs->name, "statistics/tx_window_errors");
662     abuf_json_sys_class_net(abuf, "beaconing", ifs->name, "wireless/beacon");
663     abuf_json_sys_class_net(abuf, "encryptionKey", ifs->name, "wireless/crypt");
664     abuf_json_sys_class_net(abuf, "fragmentationThreshold", ifs->name, "wireless/fragment");
665     abuf_json_sys_class_net(abuf, "signalLevel", ifs->name, "wireless/level");
666     abuf_json_sys_class_net(abuf, "linkQuality", ifs->name, "wireless/link");
667     abuf_json_sys_class_net(abuf, "misc", ifs->name, "wireless/misc");
668     abuf_json_sys_class_net(abuf, "noiseLevel", ifs->name, "wireless/noise");
669     abuf_json_sys_class_net(abuf, "nwid", ifs->name, "wireless/nwid");
670     abuf_json_sys_class_net(abuf, "wirelessRetries", ifs->name, "wireless/retries");
671     abuf_json_sys_class_net(abuf, "wirelessStatus", ifs->name, "wireless/status");
672 #endif /* __linux__ */
673     abuf_json_mark_array_entry(false, abuf);
674   }
675   abuf_json_mark_object(false, true, abuf, NULL);
676 }
677
678 void ipc_print_twohop(struct autobuf *abuf) {
679   ipc_print_neighbors_internal(abuf, true);
680 }
681
682 void ipc_print_config(struct autobuf *abuf) {
683   struct ip_prefix_list *hna;
684   struct ipaddr_str buf, mainaddrbuf;
685   struct ip_prefix_list *ipcn;
686   struct olsr_lq_mult *mult;
687   char ipv6_buf[INET6_ADDRSTRLEN]; /* buffer for IPv6 inet_htop */
688
689   abuf_json_mark_object(true, false, abuf, "config");
690
691   abuf_json_int(abuf, "olsrPort", olsr_cnf->olsrport);
692   abuf_json_int(abuf, "debugLevel", olsr_cnf->debug_level);
693   abuf_json_boolean(abuf, "noFork", olsr_cnf->no_fork);
694   abuf_json_boolean(abuf, "hostEmulation", olsr_cnf->host_emul);
695   abuf_json_int(abuf, "ipVersion", olsr_cnf->ip_version);
696   abuf_json_boolean(abuf, "allowNoInterfaces", olsr_cnf->allow_no_interfaces);
697   abuf_json_int(abuf, "typeOfService", olsr_cnf->tos);
698   abuf_json_int(abuf, "rtProto", olsr_cnf->rt_proto);
699   abuf_json_int(abuf, "rtTable", olsr_cnf->rt_table);
700   abuf_json_int(abuf, "rtTableDefault", olsr_cnf->rt_table_default);
701   abuf_json_int(abuf, "rtTableTunnel", olsr_cnf->rt_table_tunnel);
702   abuf_json_int(abuf, "rtTablePriority", olsr_cnf->rt_table_pri);
703   abuf_json_int(abuf, "rtTableTunnelPriority", olsr_cnf->rt_table_tunnel_pri);
704   abuf_json_int(abuf, "rtTableDefauiltOlsrPriority", olsr_cnf->rt_table_defaultolsr_pri);
705   abuf_json_int(abuf, "rtTableDefaultPriority", olsr_cnf->rt_table_default_pri);
706   abuf_json_int(abuf, "willingness", olsr_cnf->willingness);
707   abuf_json_boolean(abuf, "willingnessAuto", olsr_cnf->willingness_auto);
708
709   abuf_json_int(abuf, "brokenLinkCost", LINK_COST_BROKEN);
710   abuf_json_int(abuf, "brokenRouteCost", ROUTE_COST_BROKEN);
711
712   abuf_json_string(abuf, "fibMetrics", FIB_METRIC_TXT[olsr_cnf->fib_metric]);
713
714   abuf_json_string(abuf, "defaultIpv6Multicast", inet_ntop(AF_INET6, &olsr_cnf->interface_defaults->ipv6_multicast.v6, ipv6_buf, sizeof(ipv6_buf)));
715   if (olsr_cnf->interface_defaults->ipv4_multicast.v4.s_addr)
716     abuf_json_string(abuf, "defaultIpv4Broadcast", inet_ntoa(olsr_cnf->interface_defaults->ipv4_multicast.v4));
717   else
718     abuf_json_string(abuf, "defaultIpv4Broadcast", "auto");
719
720   if (olsr_cnf->interface_defaults->mode == IF_MODE_ETHER)
721     abuf_json_string(abuf, "defaultInterfaceMode", "ether");
722   else
723     abuf_json_string(abuf, "defaultInterfaceMode", "mesh");
724
725   abuf_json_float(abuf, "defaultHelloEmissionInterval", olsr_cnf->interface_defaults->hello_params.emission_interval);
726   abuf_json_float(abuf, "defaultHelloValidityTime", olsr_cnf->interface_defaults->hello_params.validity_time);
727   abuf_json_float(abuf, "defaultTcEmissionInterval", olsr_cnf->interface_defaults->tc_params.emission_interval);
728   abuf_json_float(abuf, "defaultTcValidityTime", olsr_cnf->interface_defaults->tc_params.validity_time);
729   abuf_json_float(abuf, "defaultMidEmissionInterval", olsr_cnf->interface_defaults->mid_params.emission_interval);
730   abuf_json_float(abuf, "defaultMidValidityTime", olsr_cnf->interface_defaults->mid_params.validity_time);
731   abuf_json_float(abuf, "defaultHnaEmissionInterval", olsr_cnf->interface_defaults->hna_params.emission_interval);
732   abuf_json_float(abuf, "defaultHnaValidityTime", olsr_cnf->interface_defaults->hna_params.validity_time);
733   abuf_json_boolean(abuf, "defaultAutoDetectChanges", olsr_cnf->interface_defaults->autodetect_chg);
734
735   abuf_json_mark_object(true, true, abuf, "defaultLinkQualityMultipliers");
736   for (mult = olsr_cnf->interface_defaults->lq_mult; mult != NULL ; mult = mult->next) {
737     abuf_json_mark_array_entry(true, abuf);
738     abuf_json_string(abuf, "route", inet_ntop(olsr_cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)));
739     abuf_json_float(abuf, "multiplier", mult->value / 65535.0);
740     abuf_json_mark_array_entry(false, abuf);
741   }
742   abuf_json_mark_object(false, true, abuf, NULL);
743
744   abuf_json_mark_object(true, true, abuf, "hna");
745   for (hna = olsr_cnf->hna_entries; hna != NULL ; hna = hna->next) {
746     abuf_json_mark_array_entry(true, abuf);
747     abuf_json_string(abuf, "destination", olsr_ip_to_string(&buf, &hna->net.prefix));
748     abuf_json_int(abuf, "genmask", hna->net.prefix_len);
749     abuf_json_string(abuf, "gateway", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
750     abuf_json_mark_array_entry(false, abuf);
751   }
752   abuf_json_mark_object(false, true, abuf, NULL);
753
754   abuf_json_int(abuf, "totalIpcConnectionsAllowed", olsr_cnf->ipc_connections);
755   abuf_json_mark_object(true, true, abuf, "ipcAllowedAddresses");
756   if (olsr_cnf->ipc_connections) {
757     for (ipcn = olsr_cnf->ipc_nets; ipcn != NULL ; ipcn = ipcn->next) {
758       abuf_json_mark_array_entry(true, abuf);
759       abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&mainaddrbuf, &ipcn->net.prefix));
760       abuf_json_int(abuf, "netmask", ipcn->net.prefix_len);
761       abuf_json_mark_array_entry(false, abuf);
762     }
763   }
764   abuf_json_mark_object(false, true, abuf, NULL);
765
766   // keep all time in ms, so convert these two, which are in seconds
767   abuf_json_int(abuf, "pollRate", olsr_cnf->pollrate * 1000);
768   abuf_json_int(abuf, "nicChangePollInterval", olsr_cnf->nic_chgs_pollrate * 1000);
769   abuf_json_boolean(abuf, "clearScreen", olsr_cnf->clear_screen);
770   abuf_json_int(abuf, "tcRedundancy", olsr_cnf->tc_redundancy);
771   abuf_json_int(abuf, "mprCoverage", olsr_cnf->mpr_coverage);
772
773   if (!olsr_cnf->lq_level) {
774     abuf_json_boolean(abuf, "useHysteresis", olsr_cnf->use_hysteresis);
775     if (olsr_cnf->use_hysteresis) {
776       abuf_json_float(abuf, "hysteresisScaling", olsr_cnf->hysteresis_param.scaling);
777       abuf_json_float(abuf, "hysteresisLowThreshold", olsr_cnf->hysteresis_param.thr_low);
778       abuf_json_float(abuf, "hysteresisHighThreshold", olsr_cnf->hysteresis_param.thr_high);
779     }
780   }
781   abuf_json_int(abuf, "linkQualityLevel", olsr_cnf->lq_level);
782   abuf_json_float(abuf, "linkQualityAging", olsr_cnf->lq_aging);
783   abuf_json_boolean(abuf, "linkQualityFisheye", olsr_cnf->lq_fish);
784   abuf_json_string(abuf, "linkQualityAlgorithm", olsr_cnf->lq_algorithm);
785   // keep all time in ms, so convert this from seconds
786   abuf_json_int(abuf, "minTcValidTime", olsr_cnf->min_tc_vtime * 1000);
787   abuf_json_boolean(abuf, "setIpForward", olsr_cnf->set_ip_forward);
788   abuf_json_string(abuf, "lockFile", olsr_cnf->lock_file);
789   abuf_json_boolean(abuf, "useNiit", olsr_cnf->use_niit);
790
791 #ifdef __linux__
792   abuf_json_boolean(abuf, "smartGateway", olsr_cnf->smart_gw_active);
793   if (olsr_cnf->smart_gw_active) {
794     abuf_json_boolean(abuf, "smartGatewayAlwaysRemoveServerTunnel", olsr_cnf->smart_gw_always_remove_server_tunnel);
795     abuf_json_int(abuf, "smartGatewayUseCount", olsr_cnf->smart_gw_use_count);
796     abuf_json_string(abuf, "smartGatewayInstanceId", olsr_cnf->smart_gw_instance_id);
797     abuf_json_string(abuf, "smartGatewayPolicyRoutingScript", olsr_cnf->smart_gw_policyrouting_script);
798     {
799       struct autobuf egressbuf;
800       struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
801
802       abuf_init(&egressbuf, (olsr_cnf->smart_gw_egress_interfaces_count * IFNAMSIZ) /* interface names */
803       + (olsr_cnf->smart_gw_egress_interfaces_count - 1) /* commas */);
804       while (egressif) {
805         if (egressbuf.len) {
806           abuf_puts(&egressbuf, ",");
807         }
808         abuf_appendf(&egressbuf, "%s", egressif->name);
809         egressif = egressif->next;
810       }
811       abuf_json_string(abuf, "smartGatewayEgressInterfaces", egressbuf.buf);
812       abuf_free(&egressbuf);
813     }
814     abuf_json_int(abuf, "smartGatewayTablesOffset", olsr_cnf->smart_gw_offset_tables);
815     abuf_json_int(abuf, "smartGatewayRulesOffset", olsr_cnf->smart_gw_offset_rules);
816     abuf_json_boolean(abuf, "smartGatewayAllowNat", olsr_cnf->smart_gw_allow_nat);
817     abuf_json_boolean(abuf, "smartGatewayUplinkNat", olsr_cnf->smart_gw_uplink_nat);
818     abuf_json_int(abuf, "smartGatewayPeriod", olsr_cnf->smart_gw_period);
819     abuf_json_int(abuf, "smartGatewayStableCount", olsr_cnf->smart_gw_stablecount);
820     abuf_json_int(abuf, "smartGatewayThreshold", olsr_cnf->smart_gw_thresh);
821     abuf_json_int(abuf, "smartGatewayUplink", olsr_cnf->smart_gw_uplink);
822     abuf_json_int(abuf, "smartGatewayDownlink", olsr_cnf->smart_gw_downlink);
823     abuf_json_int(abuf, "smartGatewayType", olsr_cnf->smart_gw_type);
824     abuf_json_string(abuf, "smartGatewayPrefix", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->smart_gw_prefix.prefix));
825     abuf_json_int(abuf, "smartGatewayPrefixLength", olsr_cnf->smart_gw_prefix.prefix_len);
826   }
827 #endif /* __linux__ */
828
829   abuf_json_string(abuf, "mainIpAddress", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
830   abuf_json_string(abuf, "unicastSourceIpAddress", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->unicast_src_ip));
831
832   abuf_json_boolean(abuf, "useSourceIpRoutes", olsr_cnf->use_src_ip_routes);
833
834   abuf_json_int(abuf, "maxPrefixLength", olsr_cnf->maxplen);
835   abuf_json_int(abuf, "ipSize", olsr_cnf->ipsize);
836   abuf_json_boolean(abuf, "deleteInternetGatewaysAtStartup", olsr_cnf->del_gws);
837   // keep all time in ms, so convert this from seconds
838   abuf_json_int(abuf, "willingnessUpdateInterval", olsr_cnf->will_int * 1000);
839   abuf_json_float(abuf, "maxSendMessageJitter", olsr_cnf->max_jitter);
840   abuf_json_int(abuf, "exitValue", olsr_cnf->exit_value);
841   // keep all time in ms, so convert this from seconds
842   abuf_json_int(abuf, "maxTcValidTime", olsr_cnf->max_tc_vtime * 1000);
843
844   abuf_json_int(abuf, "niit4to6InterfaceIndex", olsr_cnf->niit4to6_if_index);
845   abuf_json_int(abuf, "niit6to4InterfaceIndex", olsr_cnf->niit6to4_if_index);
846
847   abuf_json_boolean(abuf, "hasIpv4Gateway", olsr_cnf->has_ipv4_gateway);
848   abuf_json_boolean(abuf, "hasIpv6Gateway", olsr_cnf->has_ipv6_gateway);
849
850   abuf_json_int(abuf, "ioctlSocket", olsr_cnf->ioctl_s);
851 #ifdef __linux__
852   abuf_json_int(abuf, "routeNetlinkSocket", olsr_cnf->rtnl_s);
853   abuf_json_int(abuf, "routeMonitorSocket", olsr_cnf->rt_monitor_socket);
854 #endif /* __linux__ */
855
856 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
857   abuf_json_int(abuf, "routeChangeSocket", olsr_cnf->rts);
858 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
859   abuf_json_float(abuf, "linkQualityNatThreshold", olsr_cnf->lq_nat_thresh);
860
861   abuf_json_string(abuf, "olsrdVersion", olsrd_version);
862   abuf_json_string(abuf, "olsrdBuildDate", build_date);
863   abuf_json_string(abuf, "olsrdBuildHost", build_host);
864
865 #if defined _WIN32 || defined _WIN64
866   abuf_json_string(abuf, "os", "Windows");
867 #elif defined __gnu_linux__
868   abuf_json_string(abuf, "os", "GNU/Linux");
869 #elif defined __ANDROID__
870   abuf_json_string(abuf, "os", "Android");
871 #elif defined __APPLE__
872   abuf_json_string(abuf, "os", "Mac OS X");
873 #elif defined __NetBSD__
874   abuf_json_string(abuf, "os", "NetBSD");
875 #elif defined __OpenBSD__
876   abuf_json_string(abuf, "os", "OpenBSD");
877 #elif defined __FreeBSD__ || defined __FreeBSD_kernel__
878   abuf_json_string(abuf, "os", "FreeBSD");
879 #else /* OS detection */
880   abuf_json_string(abuf, "os", "Undefined");
881 #endif /* OS detection */
882
883   abuf_json_int(abuf, "startTime", start_time.tv_sec);
884
885   abuf_json_mark_object(false, false, abuf, NULL);
886 }
887
888 void ipc_print_plugins(struct autobuf *abuf) {
889   struct plugin_entry *pentry;
890   struct plugin_param *pparam;
891   abuf_json_mark_object(true, true, abuf, "plugins");
892   if (olsr_cnf->plugins)
893     for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
894       abuf_json_mark_array_entry(true, abuf);
895       abuf_json_string(abuf, "plugin", pentry->name);
896       for (pparam = pentry->params; pparam; pparam = pparam->next) {
897         int i, keylen = strlen(pparam->key);
898         char key[keylen + 1];
899         long value;
900         char valueTest[256];
901         strcpy(key, pparam->key);
902         for (i = 0; i < keylen; i++)
903           key[i] = tolower(key[i]);
904
905         // test if a int/long and set as such in JSON
906         value = atol(pparam->value);
907         snprintf(valueTest, 255, "%li", value);
908         if (!strcmp(valueTest, pparam->value))
909           abuf_json_int(abuf, key, value);
910         else
911           abuf_json_string(abuf, key, pparam->value);
912       }
913       abuf_json_mark_array_entry(false, abuf);
914     }
915   abuf_json_mark_object(false, true, abuf, NULL);
916 }