info: move json helpers here from jsoninfo
[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 "mid_set.h"
53 #include "routing_table.h"
54 #include "lq_plugin.h"
55 #include "gateway.h"
56 #include "olsrd_plugin.h"
57 #include "../../info/info_types.h"
58 #include "../../info/http_headers.h"
59 #include "../../info/info_json_helpers.h"
60 #include "gateway_default_handler.h"
61 #include "egressTypes.h"
62
63 #define UUIDLEN 256
64 char uuid[UUIDLEN];
65
66 struct timeval start_time;
67
68 static int read_uuid_from_file(const char * name, const char *file) {
69   FILE *f;
70   char* end;
71   int r = 0;
72   size_t chars;
73
74   assert(name);
75   assert(file);
76
77   memset(uuid, 0, sizeof(uuid));
78
79   f = fopen(file, "r");
80   olsr_printf(1, "(%s) Reading UUID from '%s'\n", name, file);
81   if (!f) {
82     olsr_printf(1, "(%s) Could not open '%s': %s\n", name, file, strerror(errno));
83     return -1;
84   }
85   chars = fread(uuid, 1, sizeof(uuid) - 1, f);
86   if (chars > 0) {
87     uuid[chars] = '\0'; /* null-terminate the string */
88
89     /* we only use the first line of the file */
90     end = strchr(uuid, '\n');
91     if (end)
92       *end = 0;
93     r = 0;
94   } else {
95     olsr_printf(1, "(%s) Could not read UUID from '%s': %s\n", name, file, strerror(errno));
96     r = -1;
97   }
98
99   fclose(f);
100   return r;
101 }
102
103 void plugin_init(const char *plugin_name) {
104   /* Get start time */
105   gettimeofday(&start_time, NULL);
106
107   if (!strlen(uuidfile)) {
108     strscpy(uuidfile, "uuid.txt", sizeof(uuidfile));
109   }
110   read_uuid_from_file(plugin_name, uuidfile);
111 }
112
113 bool isCommand(const char *str, unsigned long long siw) {
114   const char * cmd;
115   switch (siw) {
116     case SIW_OLSRD_CONF:
117       cmd = "/olsrd.conf";
118       break;
119
120     case SIW_ALL:
121       cmd = "/all";
122       break;
123
124     case SIW_RUNTIME_ALL:
125       cmd = "/runtime";
126       break;
127
128     case SIW_STARTUP_ALL:
129       cmd = "/startup";
130       break;
131
132     case SIW_NEIGHBORS:
133       cmd = "/neighbors";
134       break;
135
136     case SIW_LINKS:
137       cmd = "/links";
138       break;
139
140     case SIW_ROUTES:
141       cmd = "/routes";
142       break;
143
144     case SIW_HNA:
145       cmd = "/hna";
146       break;
147
148     case SIW_MID:
149       cmd = "/mid";
150       break;
151
152     case SIW_TOPOLOGY:
153       cmd = "/topology";
154       break;
155
156     case SIW_GATEWAYS:
157       cmd = "/gateways";
158       break;
159
160     case SIW_INTERFACES:
161       cmd = "/interfaces";
162       break;
163
164     case SIW_2HOP:
165       cmd = "/2hop";
166       break;
167
168     case SIW_SGW:
169       cmd = "/sgw";
170       break;
171
172     case SIW_VERSION:
173       cmd = "/version";
174       break;
175
176     case SIW_CONFIG:
177       cmd = "/config";
178       break;
179
180     case SIW_PLUGINS:
181       cmd = "/plugins";
182       break;
183
184     case SIW_NEIGHBORS_FREIFUNK:
185       cmd = "/neighbours";
186       break;
187
188     default:
189       return false;
190   }
191
192   return !strcmp(str, cmd);
193 }
194
195 const char * determine_mime_type(unsigned int send_what) {
196   return (send_what & SIW_OLSRD_CONF) ? "text/plain; charset=utf-8" : "application/json; charset=utf-8";
197 }
198
199 void output_start(struct autobuf *abuf) {
200   /* global variables for tracking when to put a comma in for JSON */
201   abuf_json_reset_entry_number_and_depth();
202   abuf_json_mark_output(true, abuf);
203
204   abuf_json_int(abuf, "systemTime", time(NULL));
205   abuf_json_int(abuf, "timeSinceStartup", now_times);
206   if (*uuid) {
207     abuf_json_string(abuf, "uuid", uuid);
208   }
209 }
210
211 void output_end(struct autobuf *abuf) {
212   abuf_json_mark_output(false, abuf);
213   abuf_puts(abuf, "\n");
214 }
215
216 void output_error(struct autobuf *abuf, unsigned int status, const char * req, bool http_headers) {
217   struct autobuf abufInternal;
218
219   if (http_headers || (status == INFO_HTTP_OK)) {
220     return;
221   }
222
223   abuf_init(&abufInternal, 1024);
224
225   output_start(abuf);
226
227   switch (status) {
228     case INFO_HTTP_NOTFOUND:
229       abuf_appendf(&abufInternal, "Invalid request '%s'", req);
230       abuf_json_string(abuf, "error", abufInternal.buf);
231       break;
232
233     case INFO_HTTP_NOCONTENT:
234       abuf_json_string(abuf, "error", "no content");
235       break;
236
237     default:
238       abuf_appendf(&abufInternal, "Unknown status %d for request '%s'", status, req);
239       abuf_json_string(abuf, "error", abufInternal.buf);
240       break;
241   }
242
243   output_end(abuf);
244 }
245
246 static void print_msg_params(struct autobuf *abuf, struct olsr_msg_params *params, const char * name) {
247   assert(abuf);
248   assert(params);
249   assert(name);
250
251   abuf_json_mark_object(true, false, abuf, name);
252   abuf_json_float(abuf, "emissionInterval", params->emission_interval);
253   abuf_json_float(abuf, "validityTime", params->validity_time);
254   abuf_json_mark_object(false, false, abuf, NULL);
255 }
256
257 static void print_hna_array_entry(struct autobuf *abuf, union olsr_ip_addr *gw, union olsr_ip_addr *ip, uint8_t prefix_len, long long validityTime) {
258   assert(abuf);
259
260   abuf_json_mark_array_entry(true, abuf);
261   abuf_json_ip_address(abuf, "gateway", gw);
262   abuf_json_ip_address(abuf, "destination", ip);
263   abuf_json_int(abuf, "genmask", prefix_len);
264   abuf_json_int(abuf, "validityTime", validityTime);
265   abuf_json_mark_array_entry(false, abuf);
266 }
267
268 static void print_link_quality_multipliers_array_entry(struct autobuf *abuf, struct olsr_lq_mult *mult) {
269   assert(abuf);
270   assert(mult);
271
272   abuf_json_mark_array_entry(true, abuf);
273   abuf_json_ip_address(abuf, "route", &mult->addr);
274   abuf_json_float(abuf, "multiplier", mult->value / 65535.0);
275   abuf_json_mark_array_entry(false, abuf);
276 }
277
278 static void print_ipc_net_array_entry(struct autobuf *abuf, struct ip_prefix_list *ipc_nets) {
279   assert(abuf);
280   assert(ipc_nets);
281
282   abuf_json_mark_array_entry(true, abuf);
283   abuf_json_boolean(abuf, "host", (ipc_nets->net.prefix_len == olsr_cnf->maxplen));
284   abuf_json_ip_address(abuf, "ipAddress", &ipc_nets->net.prefix);
285   abuf_json_int(abuf, "genmask", ipc_nets->net.prefix_len);
286   abuf_json_mark_array_entry(false, abuf);
287 }
288
289 static void print_interface_config(struct autobuf *abuf, const char * name, struct if_config_options* id) {
290   assert(abuf);
291   assert(name);
292
293   abuf_json_mark_object(true, false, abuf, name);
294   if (id) {
295     struct olsr_lq_mult *mult;
296
297     abuf_json_ip_address(abuf, "ipv4Broadcast", &id->ipv4_multicast);
298     abuf_json_ip_address(abuf, "ipv6Multicast", &id->ipv6_multicast);
299
300     abuf_json_ip_address(abuf, "ipv4Source", &id->ipv4_src);
301     abuf_json_ip_address(abuf, "ipv6Source", &id->ipv6_src.prefix);
302     abuf_json_int(abuf, "ipv6SourcePrefixLength", id->ipv6_src.prefix_len);
303
304     abuf_json_string(abuf, "mode", ((id->mode < IF_MODE_MESH) || (id->mode >= IF_MODE_CNT)) ? "" : OLSR_IF_MODE[id->mode]);
305
306     abuf_json_int(abuf, "weightValue", id->weight.value);
307     abuf_json_boolean(abuf, "weightFixed", id->weight.fixed);
308     print_msg_params(abuf, &id->hello_params, "hello");
309     print_msg_params(abuf, &id->tc_params, "tc");
310     print_msg_params(abuf, &id->mid_params, "mid");
311     print_msg_params(abuf, &id->hna_params, "hna");
312     abuf_json_mark_object(true, true, abuf, "linkQualityMultipliers");
313     for (mult = olsr_cnf->interface_defaults->lq_mult; mult != NULL ; mult = mult->next) {
314       print_link_quality_multipliers_array_entry(abuf, mult);
315     }
316     abuf_json_mark_object(false, true, abuf, NULL);
317     abuf_json_int(abuf, "linkQualityMultipliersCount", id->orig_lq_mult_cnt);
318     abuf_json_boolean(abuf, "autoDetectChanges", id->autodetect_chg);
319   }
320   abuf_json_mark_object(false, false, abuf, NULL);
321 }
322
323 static void print_interface_olsr(struct autobuf *abuf, const char * name, struct interface_olsr * rifs) {
324   assert(abuf);
325   assert(name);
326
327   abuf_json_mark_object(true, false, abuf, name);
328   abuf_json_boolean(abuf, "up", rifs != NULL);
329   if (!rifs) {
330     abuf_json_mark_object(false, false, abuf, NULL);
331     return;
332   }
333
334   abuf_json_ip_address46(abuf, "ipv4Address", &rifs->int_addr.sin_addr, AF_INET);
335   abuf_json_ip_address46(abuf, "ipv4Netmask", &rifs->int_netmask.sin_addr, AF_INET);
336   abuf_json_ip_address46(abuf, "ipv4Broadcast", &rifs->int_broadaddr.sin_addr, AF_INET);
337   abuf_json_string(abuf, "mode", ((rifs->mode < IF_MODE_MESH) || (rifs->mode >= IF_MODE_CNT)) ? "" : OLSR_IF_MODE[rifs->mode]);
338
339   abuf_json_ip_address46(abuf, "ipv6Address", &rifs->int6_addr.sin6_addr, AF_INET6);
340   abuf_json_ip_address46(abuf, "ipv6Multicast", &rifs->int6_multaddr.sin6_addr, AF_INET6);
341
342   abuf_json_ip_address(abuf, "ipAddress", &rifs->ip_addr);
343   abuf_json_boolean(abuf, "emulatedInterface", rifs->is_hcif);
344
345   abuf_json_int(abuf, "olsrSocket", rifs->olsr_socket);
346   abuf_json_int(abuf, "sendSocket", rifs->send_socket);
347
348   abuf_json_int(abuf, "metric", rifs->int_metric);
349   abuf_json_int(abuf, "mtu", rifs->int_mtu);
350   abuf_json_int(abuf, "flags", rifs->int_flags);
351   abuf_json_int(abuf, "index", rifs->if_index);
352   abuf_json_boolean(abuf, "wireless", rifs->is_wireless);
353   abuf_json_string(abuf, "name", rifs->int_name);
354   abuf_json_int(abuf, "seqNum", rifs->olsr_seqnum);
355
356
357   abuf_json_mark_object(true, false, abuf, "messageTimes");
358   abuf_json_int(abuf, "hello", rifs->hello_gen_timer ? (long) (rifs->hello_gen_timer->timer_clock - now_times) : 0);
359   abuf_json_int(abuf, "tc", rifs->tc_gen_timer ? (long) (rifs->tc_gen_timer->timer_clock - now_times) : 0);
360   abuf_json_int(abuf, "mid", rifs->mid_gen_timer ? (long) (rifs->mid_gen_timer->timer_clock - now_times) : 0);
361   abuf_json_int(abuf, "hna", rifs->hna_gen_timer ? (long) (rifs->hna_gen_timer->timer_clock - now_times) : 0);
362   abuf_json_mark_object(false, false, abuf, NULL);
363
364 #ifdef __linux__
365
366
367
368
369   abuf_json_boolean(abuf, "icmpRedirectBackup", rifs->nic_state.redirect);
370
371
372   abuf_json_boolean(abuf, "spoofFilterBackup", rifs->nic_state.spoof);
373
374 #endif /* __linux__ */
375
376   abuf_json_int(abuf, "helloEmissionInterval", rifs->hello_etime);
377   abuf_json_mark_object(true, false, abuf, "validityTimes");
378   abuf_json_int(abuf, "hello", me_to_reltime(rifs->valtimes.hello));
379   abuf_json_int(abuf, "tc", me_to_reltime(rifs->valtimes.tc));
380   abuf_json_int(abuf, "mid", me_to_reltime(rifs->valtimes.mid));
381   abuf_json_int(abuf, "hna", me_to_reltime(rifs->valtimes.hna));
382   abuf_json_mark_object(false, false, abuf, NULL);
383
384   abuf_json_int(abuf, "forwardingTimeout", rifs->fwdtimer);
385
386
387   abuf_json_int(abuf, "sgwZeroBwTimeout", rifs->sgw_sgw_zero_bw_timeout);
388
389
390   // netbuf
391
392
393   // gen_properties
394
395
396   abuf_json_int(abuf, "ttlIndex", rifs->ttl_index);
397
398
399   abuf_json_boolean(abuf, "immediateSendTc", rifs->immediate_send_tc);
400
401   abuf_json_mark_object(false, false, abuf, NULL);
402 }
403
404 #ifdef __linux__
405 static void ipc_print_gateway_entry(struct autobuf *abuf, bool ipv6, struct gateway_entry * current_gw, struct gateway_entry * gw) {
406   struct tc_entry* tc;
407
408   assert(abuf);
409   assert(gw);
410
411   tc = olsr_lookup_tc_entry(&gw->originator);
412
413   abuf_json_boolean(abuf, "selected", current_gw && (current_gw == gw));
414   abuf_json_boolean(abuf, "selectable", isGwSelectable(gw, ipv6));
415   abuf_json_ip_address(abuf, "originator", &gw->originator);
416   abuf_json_ip_address(abuf, "prefix", &gw->external_prefix.prefix);
417   abuf_json_int(abuf, "prefixLen", gw->external_prefix.prefix_len);
418   abuf_json_int(abuf, "uplink", gw->uplink);
419   abuf_json_int(abuf, "downlink", gw->downlink);
420   abuf_json_int(abuf, "cost", gw->path_cost);
421   abuf_json_boolean(abuf, "IPv4", gw->ipv4);
422   abuf_json_boolean(abuf, "IPv4-NAT", gw->ipv4nat);
423   abuf_json_boolean(abuf, "IPv6", gw->ipv6);
424   abuf_json_int(abuf, "expireTime", gw->expire_timer ? (gw->expire_timer->timer_clock - now_times) : 0);
425   abuf_json_int(abuf, "cleanupTime", gw->cleanup_timer ? (gw->cleanup_timer->timer_clock - now_times) : 0);
426
427   abuf_json_int(abuf, "pathcost", !tc ? ROUTE_COST_BROKEN : tc->path_cost);
428   abuf_json_int(abuf, "hops", !tc ? 0 : tc->hops);
429 }
430 #endif /* __linux__ */
431
432 static void ipc_print_neighbors_internal(struct autobuf *abuf, bool list_2hop) {
433   struct neighbor_entry *neigh;
434
435   assert(abuf);
436
437   if (!list_2hop) {
438     abuf_json_mark_object(true, true, abuf, "neighbors");
439   } else {
440     abuf_json_mark_object(true, true, abuf, "2hop");
441   }
442
443   /* Neighbors */
444   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
445     struct neighbor_2_list_entry *list_2;
446     int thop_cnt = 0;
447
448     abuf_json_mark_array_entry(true, abuf);
449
450     abuf_json_ip_address(abuf, "ipAddress", &neigh->neighbor_main_addr);
451     abuf_json_boolean(abuf, "symmetric", (neigh->status == SYM));
452     abuf_json_int(abuf, "willingness", neigh->willingness);
453     abuf_json_boolean(abuf, "isMultiPointRelay", neigh->is_mpr);
454     abuf_json_boolean(abuf, "wasMultiPointRelay", neigh->was_mpr);
455     abuf_json_boolean(abuf, "multiPointRelaySelector", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) != NULL);
456     abuf_json_boolean(abuf, "skip", neigh->skip);
457     abuf_json_int(abuf, "neighbor2nocov", neigh->neighbor_2_nocov);
458     abuf_json_int(abuf, "linkcount", neigh->linkcount);
459
460     if (list_2hop) {
461       abuf_json_mark_object(true, true, abuf, "twoHopNeighbors");
462     }
463
464     thop_cnt = 0;
465     for (list_2 = neigh->neighbor_2_list.next; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next) {
466       if (list_2hop && list_2->neighbor_2) {
467         abuf_json_ip_address(abuf, NULL, &list_2->neighbor_2->neighbor_2_addr);
468       }
469       thop_cnt++;
470     }
471
472     if (list_2hop) {
473       abuf_json_mark_object(false, true, abuf, NULL);
474     }
475     abuf_json_int(abuf, "twoHopNeighborCount", thop_cnt);
476
477     abuf_json_mark_array_entry(false, abuf);
478   } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
479   abuf_json_mark_object(false, true, abuf, NULL);
480 }
481
482 void ipc_print_neighbors(struct autobuf *abuf) {
483   ipc_print_neighbors_internal(abuf, false);
484 }
485
486 void ipc_print_links(struct autobuf *abuf) {
487   struct link_entry *my_link;
488
489   abuf_json_mark_object(true, true, abuf, "links");
490
491   OLSR_FOR_ALL_LINK_ENTRIES(my_link) {
492     struct lqtextbuffer lqBuffer;
493     const char* lqString = get_link_entry_text(my_link, '\t', &lqBuffer);
494     char * nlqString = strrchr(lqString, '\t');
495
496     if (nlqString) {
497       *nlqString = '\0';
498       nlqString++;
499     }
500
501     abuf_json_mark_array_entry(true, abuf);
502
503     abuf_json_ip_address(abuf, "localIP", &my_link->local_iface_addr);
504     abuf_json_ip_address(abuf, "remoteIP", &my_link->neighbor_iface_addr);
505     abuf_json_string(abuf, "olsrInterface", (my_link->inter && my_link->inter->int_name) ? my_link->inter->int_name : "");
506     abuf_json_string(abuf, "ifName", my_link->if_name ? my_link->if_name : "");
507     abuf_json_int(abuf, "validityTime", my_link->link_timer ? (long) (my_link->link_timer->timer_clock - now_times) : 0);
508     abuf_json_int(abuf, "symmetryTime", my_link->link_sym_timer ? (long) (my_link->link_sym_timer->timer_clock - now_times) : 0);
509     abuf_json_int(abuf, "asymmetryTime", my_link->ASYM_time);
510     abuf_json_int(abuf, "vtime", (long) my_link->vtime);
511     // neighbor (no need to print, can be looked up via neighbours)
512     abuf_json_string(abuf, "currentLinkStatus", linkTypeToString(lookup_link_status(my_link)));
513     abuf_json_string(abuf, "previousLinkStatus", linkTypeToString(my_link->prev_status));
514
515     abuf_json_float(abuf, "hysteresis", my_link->L_link_quality);
516     abuf_json_boolean(abuf, "pending", my_link->L_link_pending != 0);
517     abuf_json_int(abuf, "lostLinkTime", (long) my_link->L_LOST_LINK_time);
518     abuf_json_int(abuf, "helloTime", my_link->link_hello_timer ? (long) (my_link->link_hello_timer->timer_clock - now_times) : 0);
519     abuf_json_int(abuf, "lastHelloTime", (long) my_link->last_htime);
520     abuf_json_boolean(abuf, "seqnoValid", my_link->olsr_seqno_valid);
521     abuf_json_int(abuf, "seqno", my_link->olsr_seqno);
522
523     abuf_json_int(abuf, "lossHelloInterval", (long) my_link->loss_helloint);
524     abuf_json_int(abuf, "lossTime", my_link->link_loss_timer ? (long) (my_link->link_loss_timer->timer_clock - now_times) : 0);
525
526     abuf_json_int(abuf, "lossMultiplier", (long) my_link->loss_link_multiplier);
527
528     abuf_json_int(abuf, "linkCost", MIN(my_link->linkcost, LINK_COST_BROKEN));
529
530     abuf_json_float(abuf, "linkQuality", atof(lqString));
531     abuf_json_float(abuf, "neighborLinkQuality", nlqString ? atof(nlqString) : 0.0);
532
533     abuf_json_mark_array_entry(false, abuf);
534   } OLSR_FOR_ALL_LINK_ENTRIES_END(my_link);
535   abuf_json_mark_object(false, true, abuf, NULL);
536 }
537
538 void ipc_print_routes(struct autobuf *abuf) {
539   struct rt_entry *rt;
540
541   abuf_json_mark_object(true, true, abuf, "routes");
542
543   /* Walk the route table */
544   OLSR_FOR_ALL_RT_ENTRIES(rt) {
545     struct lqtextbuffer costbuffer;
546
547     if (rt->rt_best) {
548       abuf_json_mark_array_entry(true, abuf);
549       abuf_json_ip_address(abuf, "destination", &rt->rt_dst.prefix);
550       abuf_json_int(abuf, "genmask", rt->rt_dst.prefix_len);
551       abuf_json_ip_address(abuf, "gateway", &rt->rt_best->rtp_nexthop.gateway);
552       abuf_json_int(abuf, "metric", rt->rt_best->rtp_metric.hops);
553       abuf_json_float(abuf, "etx", atof(get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &costbuffer)));
554       abuf_json_int(abuf, "rtpMetricCost", MIN(ROUTE_COST_BROKEN, rt->rt_best->rtp_metric.cost));
555       abuf_json_string(abuf, "networkInterface", if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
556       abuf_json_mark_array_entry(false, abuf);
557     }
558   } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
559
560   abuf_json_mark_object(false, true, abuf, NULL);
561 }
562
563 void ipc_print_topology(struct autobuf *abuf) {
564   struct tc_entry *tc;
565
566   abuf_json_mark_object(true, true, abuf, "topology");
567
568   /* Topology */
569   OLSR_FOR_ALL_TC_ENTRIES(tc) {
570     struct tc_edge_entry *tc_edge;
571     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
572       if (tc_edge->edge_inv) {
573         struct lqtextbuffer lqbuffer;
574         const char* lqString = get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer);
575         char * nlqString = strrchr(lqString, '\t');
576
577         if (nlqString) {
578           *nlqString = '\0';
579           nlqString++;
580         }
581
582         abuf_json_mark_array_entry(true, abuf);
583
584         // vertex_node
585         abuf_json_ip_address(abuf, "lastHopIP", &tc->addr);
586         // cand_tree_node
587         abuf_json_int(abuf, "pathCost", MIN(tc->path_cost, ROUTE_COST_BROKEN));
588         // path_list_node
589         // edge_tree
590         // prefix_tree
591         // next_hop
592         // edge_gc_timer
593         abuf_json_int(abuf, "validityTime", tc->validity_timer ? (tc->validity_timer->timer_clock - now_times) : 0);
594         abuf_json_int(abuf, "refCount", tc->refcount);
595         abuf_json_int(abuf, "msgSeq", tc->msg_seq);
596         abuf_json_int(abuf, "msgHops", tc->msg_hops);
597         abuf_json_int(abuf, "hops", tc->hops);
598         abuf_json_int(abuf, "ansn", tc->ansn);
599         abuf_json_int(abuf, "tcIgnored", tc->ignored);
600
601         abuf_json_int(abuf, "errSeq", tc->err_seq);
602         abuf_json_boolean(abuf, "errSeqValid", tc->err_seq_valid);
603
604         // edge_node
605         abuf_json_ip_address(abuf, "destinationIP", &tc_edge->T_dest_addr);
606         // tc
607         abuf_json_int(abuf, "tcEdgeCost", MIN(LINK_COST_BROKEN, tc_edge->cost));
608         abuf_json_int(abuf, "ansnEdge", tc_edge->ansn);
609         abuf_json_float(abuf, "linkQuality", atof(lqString));
610         abuf_json_float(abuf, "neighborLinkQuality", nlqString ? atof(nlqString) : 0.0);
611
612         abuf_json_mark_array_entry(false, abuf);
613       }
614     } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
615   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
616
617   abuf_json_mark_object(false, true, abuf, NULL);
618 }
619
620 void ipc_print_hna(struct autobuf *abuf) {
621   struct ip_prefix_list *hna;
622   struct hna_entry *tmp_hna;
623
624   abuf_json_mark_object(true, true, abuf, "hna");
625
626   /* Announced HNA entries */
627   for (hna = olsr_cnf->hna_entries; hna != NULL ; hna = hna->next) {
628     print_hna_array_entry( //
629         abuf, //
630         &olsr_cnf->main_addr, //
631         &hna->net.prefix, //
632         hna->net.prefix_len, //
633         0);
634   }
635
636   OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna) {
637     struct hna_net *tmp_net;
638
639     /* Check all networks */
640     for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
641       print_hna_array_entry( //
642           abuf, //
643           &tmp_hna->A_gateway_addr, //
644           &tmp_net->hna_prefix.prefix, //
645           tmp_net->hna_prefix.prefix_len, //
646           tmp_net->hna_net_timer ? (tmp_net->hna_net_timer->timer_clock - now_times) : 0);
647     }
648   } OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
649
650   abuf_json_mark_object(false, true, abuf, NULL);
651 }
652
653 void ipc_print_mid(struct autobuf *abuf) {
654   int idx;
655
656   abuf_json_mark_object(true, true, abuf, "mid");
657
658   /* MID */
659   for (idx = 0; idx < HASHSIZE; idx++) {
660     struct mid_entry * entry = mid_set[idx].next;
661
662     while (entry != &mid_set[idx]) {
663       abuf_json_mark_array_entry(true, abuf);
664
665       abuf_json_mark_object(true, false, abuf, "main");
666       abuf_json_ip_address(abuf, "ipAddress", &entry->main_addr);
667       abuf_json_int(abuf, "validityTime", entry->mid_timer ? (entry->mid_timer->timer_clock - now_times) : 0);
668       abuf_json_mark_object(false, false, abuf, NULL); // main
669
670       {
671         struct mid_address * alias = entry->aliases;
672
673         abuf_json_mark_object(true, true, abuf, "aliases");
674         while (alias) {
675           abuf_json_mark_array_entry(true, abuf);
676           abuf_json_ip_address(abuf, "ipAddress", &alias->alias);
677           abuf_json_int(abuf, "validityTime", alias->vtime - now_times);
678           abuf_json_mark_array_entry(false, abuf);
679
680           alias = alias->next_alias;
681         }
682         abuf_json_mark_object(false, true, abuf, NULL); // aliases
683       }
684       abuf_json_mark_array_entry(false, abuf); // entry
685
686       entry = entry->next;
687     }
688   }
689   abuf_json_mark_object(false, true, abuf, NULL); // mid
690 }
691
692 #ifdef __linux__
693
694 static void ipc_print_gateways_ipvx(struct autobuf *abuf, bool ipv6) {
695   assert(abuf);
696
697   abuf_json_mark_object(true, true, abuf, ipv6 ? "ipv6" : "ipv4");
698
699   if (olsr_cnf->smart_gw_active) {
700     struct gateway_entry * current_gw = olsr_get_inet_gateway(ipv6);
701     struct gateway_entry * gw;
702     OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
703       if ((!ipv6 && !gw->ipv4) || (ipv6 && !gw->ipv6)) {
704         /* gw does not advertise the requested IP version */
705         continue;
706       }
707
708       abuf_json_mark_array_entry(true, abuf);
709       ipc_print_gateway_entry(abuf, ipv6, current_gw, gw);
710       abuf_json_mark_array_entry(false, abuf);
711     } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
712   }
713
714   abuf_json_mark_object(false, true, abuf, NULL);
715 }
716 #endif /* __linux__ */
717
718 void ipc_print_gateways(struct autobuf *abuf) {
719 #ifndef __linux__
720   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
721 #else /* __linux__ */
722   abuf_json_mark_object(true, false, abuf, "gateways");
723
724   ipc_print_gateways_ipvx(abuf, false);
725   ipc_print_gateways_ipvx(abuf, true);
726
727   abuf_json_mark_object(false, false, abuf, NULL);
728 #endif /* __linux__ */
729 }
730
731 #ifdef __linux__
732
733 /** interface names for smart gateway tunnel interfaces, IPv4 */
734 extern struct interfaceName * sgwTunnel4InterfaceNames;
735
736 /** interface names for smart gateway tunnel interfaces, IPv6 */
737 extern struct interfaceName * sgwTunnel6InterfaceNames;
738
739 /**
740  * Construct the sgw table for a given ip version
741  *
742  * @param abuf the string buffer
743  * @param ipv6 true for IPv6, false for IPv4
744  * @param fmtv the format for printing
745  */
746 static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
747   struct interfaceName * sgwTunnelInterfaceNames;
748
749   assert(abuf);
750
751   sgwTunnelInterfaceNames = !ipv6 ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
752
753   abuf_json_mark_object(true, true, abuf, ipv6 ? "ipv6" : "ipv4");
754
755   if (olsr_cnf->smart_gw_active && sgwTunnelInterfaceNames) {
756     struct gateway_entry * current_gw = olsr_get_inet_gateway(ipv6);
757     int i;
758     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
759       struct interfaceName * node = &sgwTunnelInterfaceNames[i];
760       struct gateway_entry * gw = node->gw;
761
762       if (!gw) {
763         continue;
764       }
765
766       abuf_json_mark_array_entry(true, abuf);
767       ipc_print_gateway_entry(abuf, ipv6, current_gw, gw);
768       abuf_json_ip_address(abuf, "destination", &gw->originator);
769       abuf_json_string(abuf, "tunnel", node->name);
770       abuf_json_int(abuf, "tableNr", node->tableNr);
771       abuf_json_int(abuf, "ruleNr", node->ruleNr);
772       abuf_json_int(abuf, "bypassRuleNr", node->bypassRuleNr);
773       abuf_json_mark_array_entry(false, abuf);
774     }
775   }
776
777   abuf_json_mark_object(false, true, abuf, NULL);
778 }
779 #endif /* __linux__ */
780
781 void ipc_print_sgw(struct autobuf *abuf) {
782 #ifndef __linux__
783   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
784 #else
785   abuf_json_mark_object(true, false, abuf, "sgw");
786
787   sgw_ipvx(abuf, false);
788   sgw_ipvx(abuf, true);
789
790   abuf_json_mark_object(false, false, abuf, NULL);
791 #endif /* __linux__ */
792 }
793
794 void ipc_print_version(struct autobuf *abuf) {
795   abuf_json_mark_object(true, false, abuf, "version");
796
797   abuf_json_string(abuf, "version", olsrd_version);
798
799   abuf_json_string(abuf, "date", build_date);
800   abuf_json_string(abuf, "host", build_host);
801   abuf_json_string(abuf, "gitDescriptor", git_descriptor);
802   abuf_json_string(abuf, "gitSha", git_sha);
803   abuf_json_string(abuf, "releaseVersion", release_version);
804   abuf_json_string(abuf, "sourceHash", source_hash);
805
806   abuf_json_mark_object(false, false, abuf, NULL);
807 }
808
809 void ipc_print_olsrd_conf(struct autobuf *abuf) {
810   olsrd_write_cnf_autobuf(abuf, olsr_cnf);
811 }
812
813 void ipc_print_interfaces(struct autobuf *abuf) {
814   struct olsr_if *ifs;
815
816   abuf_json_mark_object(true, true, abuf, "interfaces");
817   for (ifs = olsr_cnf->interfaces; ifs != NULL ; ifs = ifs->next) {
818     abuf_json_mark_array_entry(true, abuf);
819     abuf_json_string(abuf, "name", ifs->name);
820     abuf_json_boolean(abuf, "configured", ifs->configured);
821     abuf_json_boolean(abuf, "hostEmulation", ifs->host_emul);
822     abuf_json_ip_address(abuf, "hostEmulationAddress", &ifs->hemu_ip);
823     print_interface_olsr(abuf, "olsrInterface", ifs->interf);
824     print_interface_config(abuf, "InterfaceConfiguration", ifs->cnf);
825     print_interface_config(abuf, "InterfaceConfigurationDefaults", ifs->cnfi);
826     abuf_json_mark_array_entry(false, abuf);
827   }
828   abuf_json_mark_object(false, true, abuf, NULL); // interfaces
829 }
830
831 void ipc_print_twohop(struct autobuf *abuf) {
832   ipc_print_neighbors_internal(abuf, true);
833 }
834
835 void ipc_print_config(struct autobuf *abuf) {
836   abuf_json_mark_object(true, false, abuf, "config");
837
838   abuf_json_string(abuf, "configurationFile", olsr_cnf->configuration_file);
839   abuf_json_int(abuf, "olsrPort", olsr_cnf->olsrport);
840   abuf_json_int(abuf, "debugLevel", olsr_cnf->debug_level);
841   abuf_json_boolean(abuf, "noFork", olsr_cnf->no_fork);
842   abuf_json_string(abuf, "pidFile", olsr_cnf->pidfile);
843   abuf_json_boolean(abuf, "hostEmulation", olsr_cnf->host_emul);
844   abuf_json_int(abuf, "ipVersion", (olsr_cnf->ip_version == AF_INET) ? 4 : 6);
845   abuf_json_boolean(abuf, "allowNoInt", olsr_cnf->allow_no_interfaces);
846   abuf_json_int(abuf, "tosValue", olsr_cnf->tos);
847
848   abuf_json_int(abuf, "rtProto", olsr_cnf->rt_proto);
849   abuf_json_mark_object(true, false, abuf, "rtTable");
850   abuf_json_int(abuf, "main", olsr_cnf->rt_table);
851   abuf_json_int(abuf, "default", olsr_cnf->rt_table_default);
852   abuf_json_int(abuf, "tunnel", olsr_cnf->rt_table_tunnel);
853   abuf_json_int(abuf, "priority", olsr_cnf->rt_table_pri);
854   abuf_json_int(abuf, "tunnelPriority", olsr_cnf->rt_table_tunnel_pri);
855   abuf_json_int(abuf, "defaultOlsrPriority", olsr_cnf->rt_table_defaultolsr_pri);
856   abuf_json_int(abuf, "defaultPriority", olsr_cnf->rt_table_default_pri);
857   abuf_json_mark_object(false, false, abuf, NULL);
858
859   abuf_json_mark_object(true, false, abuf, "willingness");
860   abuf_json_int(abuf, "willingness", olsr_cnf->willingness);
861   abuf_json_boolean(abuf, "auto", olsr_cnf->willingness_auto);
862   abuf_json_float(abuf, "updateInterval", olsr_cnf->will_int);
863   abuf_json_mark_object(false, false, abuf, NULL);
864
865
866   // ipc_connections: later
867
868   abuf_json_mark_object(true, false, abuf, "fib");
869   abuf_json_string(abuf, "metric", ((olsr_cnf->fib_metric < FIBM_FLAT) || (olsr_cnf->fib_metric >= FIBM_CNT)) ? "" : FIB_METRIC_TXT[olsr_cnf->fib_metric]);
870   abuf_json_string(abuf, "metricDefault", FIB_METRIC_TXT[olsr_cnf->fib_metric_default]);
871   abuf_json_mark_object(false, false, abuf, NULL);
872
873
874   abuf_json_mark_object(true, false, abuf, "hysteresis");
875   abuf_json_boolean(abuf, "enabled", olsr_cnf->use_hysteresis);
876   abuf_json_float(abuf, "scaling", olsr_cnf->hysteresis_param.scaling);
877   abuf_json_float(abuf, "thresholdLow", olsr_cnf->hysteresis_param.thr_low);
878   abuf_json_float(abuf, "thresholdHigh", olsr_cnf->hysteresis_param.thr_high);
879   abuf_json_mark_object(false, false, abuf, NULL);
880
881   // plugins: later
882   // hna_entries
883   {
884     struct ip_prefix_list *hna;
885
886     abuf_json_mark_object(true, true, abuf, "hna");
887
888     /* Announced HNA entries */
889     for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
890         print_hna_array_entry( //
891             abuf, //
892             &olsr_cnf->main_addr, //
893             &hna->net.prefix, //
894             hna->net.prefix_len, //
895             0);
896     }
897     abuf_json_mark_object(false, true, abuf, NULL);
898   }
899   // ipc_nets: later
900   // interface_defaults: later
901   // interfaces: later
902   abuf_json_float(abuf, "pollrate", olsr_cnf->pollrate);
903   abuf_json_float(abuf, "nicChgsPollInt", olsr_cnf->nic_chgs_pollrate);
904   abuf_json_boolean(abuf, "clearScreen", olsr_cnf->clear_screen);
905   abuf_json_int(abuf, "tcRedundancy", olsr_cnf->tc_redundancy);
906   abuf_json_int(abuf, "mprCoverage", olsr_cnf->mpr_coverage);
907
908
909   abuf_json_mark_object(true, false, abuf, "linkQuality");
910   abuf_json_int(abuf, "level", olsr_cnf->lq_level);
911   abuf_json_boolean(abuf, "fishEye", olsr_cnf->lq_fish);
912   abuf_json_float(abuf, "aging", olsr_cnf->lq_aging);
913   abuf_json_string(abuf, "algorithm", olsr_cnf->lq_algorithm);
914   abuf_json_mark_object(false, false, abuf, NULL);
915
916   abuf_json_float(abuf, "minTCVTime", olsr_cnf->min_tc_vtime);
917
918   abuf_json_boolean(abuf, "setIpForward", olsr_cnf->set_ip_forward);
919
920   abuf_json_string(abuf, "lockFile", olsr_cnf->lock_file);
921   abuf_json_boolean(abuf, "useNiit", olsr_cnf->use_niit);
922
923   abuf_json_mark_object(true, false, abuf, "smartGateway");
924   abuf_json_boolean(abuf, "enabled", olsr_cnf->smart_gw_active);
925   abuf_json_boolean(abuf, "alwaysRemoveServerTunnel", olsr_cnf->smart_gw_always_remove_server_tunnel);
926   abuf_json_boolean(abuf, "allowNAT", olsr_cnf->smart_gw_allow_nat);
927   abuf_json_boolean(abuf, "uplinkNAT", olsr_cnf->smart_gw_uplink_nat);
928   abuf_json_int(abuf, "useCount", olsr_cnf->smart_gw_use_count);
929   abuf_json_int(abuf, "takeDownPercentage", olsr_cnf->smart_gw_takedown_percentage);
930   abuf_json_string(abuf, "instanceId", olsr_cnf->smart_gw_instance_id);
931   abuf_json_string(abuf, "policyRoutingScript", olsr_cnf->smart_gw_policyrouting_script);
932
933   abuf_json_mark_object(true, false, abuf, "egress");
934   // smart_gw_egress_interfaces
935   {
936     struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
937
938     abuf_json_mark_object(true, true, abuf, "interfaces");
939     while (egressif) {
940       abuf_json_string(abuf, NULL, egressif->name);
941       egressif = egressif->next;
942     }
943     abuf_json_mark_object(false, true, abuf, NULL);
944   }
945   abuf_json_int(abuf, "interfacesCount", olsr_cnf->smart_gw_egress_interfaces_count);
946   abuf_json_string(abuf, "file", olsr_cnf->smart_gw_egress_file);
947   abuf_json_int(abuf, "filePeriod", olsr_cnf->smart_gw_egress_file_period);
948   abuf_json_mark_object(false, false, abuf, NULL);
949
950   abuf_json_string(abuf, "statusFile", olsr_cnf->smart_gw_status_file);
951   abuf_json_int(abuf, "tablesOffset", olsr_cnf->smart_gw_offset_tables);
952   abuf_json_int(abuf, "rulesOffset", olsr_cnf->smart_gw_offset_rules);
953   abuf_json_int(abuf, "period", olsr_cnf->smart_gw_period);
954   abuf_json_int(abuf, "stableCount", olsr_cnf->smart_gw_stablecount);
955   abuf_json_int(abuf, "threshold", olsr_cnf->smart_gw_thresh);
956
957   abuf_json_mark_object(true, false, abuf, "costsCalculation");
958   abuf_json_int(abuf, "exitLinkUp", olsr_cnf->smart_gw_weight_exitlink_up);
959   abuf_json_int(abuf, "exitLinkDown", olsr_cnf->smart_gw_weight_exitlink_down);
960   abuf_json_int(abuf, "etx", olsr_cnf->smart_gw_weight_etx);
961   abuf_json_int(abuf, "dividerEtx", olsr_cnf->smart_gw_divider_etx);
962   abuf_json_mark_object(false, false, abuf, NULL);
963
964   abuf_json_int(abuf, "maxCostMaxEtx", olsr_cnf->smart_gw_path_max_cost_etx_max);
965   abuf_json_string(abuf, "uplink", ((olsr_cnf->smart_gw_type < GW_UPLINK_NONE) || (olsr_cnf->smart_gw_type >= GW_UPLINK_CNT)) ? "" : GW_UPLINK_TXT[olsr_cnf->smart_gw_type]);
966
967   abuf_json_mark_object(true, false, abuf, "bandwidth");
968   abuf_json_int(abuf, "uplinkKbps", olsr_cnf->smart_gw_uplink);
969   abuf_json_int(abuf, "downlinkKbps", olsr_cnf->smart_gw_downlink);
970   abuf_json_mark_object(false, false, abuf, NULL);
971
972   abuf_json_mark_object(true, false, abuf, "prefix");
973   abuf_json_ip_address(abuf, "prefix", &olsr_cnf->smart_gw_prefix.prefix);
974   abuf_json_int(abuf, "length", olsr_cnf->smart_gw_prefix.prefix_len);
975   abuf_json_mark_object(false, false, abuf, NULL);
976
977   abuf_json_mark_object(false, false, abuf, NULL);
978
979
980   abuf_json_ip_address(abuf, "mainIp", &olsr_cnf->main_addr);
981   abuf_json_ip_address(abuf, "unicastSourceIpAddress", &olsr_cnf->unicast_src_ip);
982   abuf_json_boolean(abuf, "srcIpRoutes", olsr_cnf->use_src_ip_routes);
983
984
985   abuf_json_int(abuf, "maxPrefixLength", olsr_cnf->maxplen);
986   abuf_json_int(abuf, "ipSize", olsr_cnf->ipsize);
987   abuf_json_boolean(abuf, "delgw", olsr_cnf->del_gws);
988   abuf_json_float(abuf, "maxSendMessageJitter", olsr_cnf->max_jitter);
989   abuf_json_int(abuf, "exitValue", olsr_cnf->exit_value);
990   abuf_json_float(abuf, "maxTcValidTime", olsr_cnf->max_tc_vtime);
991
992   abuf_json_int(abuf, "niit4to6InterfaceIndex", olsr_cnf->niit4to6_if_index);
993   abuf_json_int(abuf, "niit6to4InterfaceIndex", olsr_cnf->niit6to4_if_index);
994
995
996   abuf_json_boolean(abuf, "hasIpv4Gateway", olsr_cnf->has_ipv4_gateway);
997   abuf_json_boolean(abuf, "hasIpv6Gateway", olsr_cnf->has_ipv6_gateway);
998
999   abuf_json_int(abuf, "ioctlSocket", olsr_cnf->ioctl_s);
1000 #ifdef __linux__
1001   abuf_json_int(abuf, "routeNetlinkSocket", olsr_cnf->rtnl_s);
1002   abuf_json_int(abuf, "routeMonitorSocket", olsr_cnf->rt_monitor_socket);
1003 #endif /* __linux__ */
1004
1005 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
1006   abuf_json_int(abuf, "routeChangeSocket", olsr_cnf->rts);
1007 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
1008   abuf_json_float(abuf, "linkQualityNatThreshold", olsr_cnf->lq_nat_thresh);
1009
1010
1011   // Other settings
1012   abuf_json_int(abuf, "brokenLinkCost", LINK_COST_BROKEN);
1013   abuf_json_int(abuf, "brokenRouteCost", ROUTE_COST_BROKEN);
1014
1015
1016   // IpcConnect section
1017   abuf_json_int(abuf, "ipcConnectMaxConnections", olsr_cnf->ipc_connections);
1018   {
1019     struct ip_prefix_list *ipc_nets;
1020
1021     abuf_json_mark_object(true, true, abuf, "ipcConnectAllowed");
1022     for (ipc_nets = olsr_cnf->ipc_nets; ipc_nets; ipc_nets = ipc_nets->next) {
1023       print_ipc_net_array_entry(abuf, ipc_nets);
1024     }
1025     abuf_json_mark_object(false, true, abuf, NULL);
1026   }
1027
1028
1029   // plugins section: use /plugins
1030
1031
1032   // InterfaceDefaults section
1033   print_interface_config(abuf, "interfaceDefaults", olsr_cnf->interface_defaults);
1034
1035
1036   // Interface(s) section: use /interfaces
1037
1038
1039   // OS section
1040 #if defined _WIN32 || defined _WIN64
1041   abuf_json_string(abuf, "os", "Windows");
1042 #elif defined __gnu_linux__
1043   abuf_json_string(abuf, "os", "GNU/Linux");
1044 #elif defined __ANDROID__
1045   abuf_json_string(abuf, "os", "Android");
1046 #elif defined __APPLE__
1047   abuf_json_string(abuf, "os", "Mac OS X");
1048 #elif defined __NetBSD__
1049   abuf_json_string(abuf, "os", "NetBSD");
1050 #elif defined __OpenBSD__
1051   abuf_json_string(abuf, "os", "OpenBSD");
1052 #elif defined __FreeBSD__ || defined __FreeBSD_kernel__
1053   abuf_json_string(abuf, "os", "FreeBSD");
1054 #else /* OS detection */
1055   abuf_json_string(abuf, "os", "Undefined");
1056 #endif /* OS detection */
1057
1058   abuf_json_int(abuf, "startTime", start_time.tv_sec);
1059
1060   abuf_json_mark_object(false, false, abuf, NULL);
1061 }
1062
1063 void ipc_print_plugins(struct autobuf *abuf) {
1064   abuf_json_mark_object(true, true, abuf, "plugins");
1065   if (olsr_cnf->plugins) {
1066     struct plugin_entry *plugin;
1067
1068     for (plugin = olsr_cnf->plugins; plugin; plugin = plugin->next) {
1069       struct plugin_param *param;
1070
1071       abuf_json_mark_array_entry(true, abuf);
1072       abuf_json_string(abuf, "plugin", plugin->name);
1073
1074       abuf_json_mark_object(true, false, abuf, "parameters");
1075       for (param = plugin->params; param; param = param->next) {
1076         abuf_json_string(abuf, param->key, param->value);
1077       }
1078       abuf_json_mark_object(false, false, abuf, NULL);
1079
1080       abuf_json_mark_array_entry(false, abuf);
1081     }
1082   }
1083   abuf_json_mark_object(false, true, abuf, NULL);
1084 }