jsoninfo: move http header related functions into common code
[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 /*
43  * Dynamic linked library for the olsr.org olsr daemon
44  */
45
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #ifndef _WIN32
49 #include <sys/select.h>
50 #endif /* _WIN32 */
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <sys/time.h>
54 #include <time.h>
55 #include <math.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60 #include <errno.h>
61 #include <assert.h>
62
63 #include "ipcalc.h"
64 #include "olsr.h"
65 #include "builddata.h"
66 #include "olsr_types.h"
67 #include "neighbor_table.h"
68 #include "two_hop_neighbor_table.h"
69 #include "mpr_selector_set.h"
70 #include "tc_set.h"
71 #include "hna_set.h"
72 #include "mid_set.h"
73 #include "link_set.h"
74 #include "net_olsr.h"
75 #include "lq_plugin.h"
76 #include "common/autobuf.h"
77 #include "gateway.h"
78 #include "../../info/http_headers.h"
79
80 #include <ctype.h>
81 #include <libgen.h>
82 #include "egressTypes.h"
83 #include "olsrd_jsoninfo_helpers.h"
84
85 #include "olsrd_jsoninfo.h"
86 #include "olsrd_plugin.h"
87
88 #ifdef _WIN32
89 #define close(x) closesocket(x)
90 #endif /* _WIN32 */
91
92 /* defines to make txtinfo and jsoninfo look alike */
93 #define PLUGIN_NAME "JSONINFO"
94 #define info_accept_ip jsoninfo_accept_ip
95 #define info_listen_ip jsoninfo_listen_ip
96 #define info_ipv6_only jsoninfo_ipv6_only
97 #ifdef JSONINFO_ALLOW_LOCALHOST
98 #define INFO_ALLOW_LOCALHOST JSONINFO_ALLOW_LOCALHOST
99 #endif
100
101 static int ipc_socket;
102
103 /* IPC initialization function */
104 static int plugin_ipc_init(void);
105
106 static void send_info(unsigned int /*send_what*/, int /*socket*/);
107
108 static void ipc_action(int, void *, unsigned int);
109
110 #define TXT_IPC_BUFSIZE 256
111
112 /* these provide all of the runtime status info */
113 #define SIW_NEIGHBORS 0x0001
114 #define SIW_LINKS 0x0002
115 #define SIW_ROUTES 0x0004
116 #define SIW_HNA 0x0008
117 #define SIW_MID 0x0010
118 #define SIW_TOPOLOGY 0x0020
119 #define SIW_GATEWAYS 0x0040
120 #define SIW_INTERFACES 0x0080
121 #define SIW_2HOP 0x0100
122 #define SIW_SGW 0x0200
123 #define SIW_RUNTIME_ALL (SIW_NEIGHBORS | SIW_LINKS | SIW_ROUTES | SIW_HNA | SIW_MID | SIW_TOPOLOGY | SIW_GATEWAYS | SIW_INTERFACES | SIW_2HOP | SIW_SGW)
124
125 /* these only change at olsrd startup */
126 #define SIW_VERSION 0x0400
127 #define SIW_CONFIG 0x0800
128 #define SIW_PLUGINS 0x1000
129 #define SIW_STARTUP_ALL (SIW_VERSION | SIW_CONFIG | SIW_PLUGINS)
130
131 /* this is everything in normal format */
132 #define SIW_ALL (SIW_RUNTIME_ALL | SIW_STARTUP_ALL)
133
134 /* this data is not normal format but olsrd.conf format */
135 #define SIW_OLSRD_CONF 0x2000
136
137 #define MAX_CLIENTS 3
138
139 static char *outbuffer[MAX_CLIENTS];
140 static size_t outbuffer_size[MAX_CLIENTS];
141 static size_t outbuffer_written[MAX_CLIENTS];
142 static int outbuffer_socket[MAX_CLIENTS];
143 static int outbuffer_count = 0;
144
145 static struct timer_entry *writetimer_entry;
146 static struct timeval start_time;
147
148 /**
149  *Do initialization here
150  *
151  *This function is called by the my_init
152  *function in uolsrd_plugin.c
153  */
154 int olsrd_plugin_init(void) {
155   /* Initial IPC value */
156   ipc_socket = -1;
157
158   /* Get start time */
159   gettimeofday(&start_time, NULL);
160
161   if (!strlen(uuidfile))
162     strscpy(uuidfile, "uuid.txt", sizeof(uuidfile));
163   read_uuid_from_file(PLUGIN_NAME, uuidfile);
164
165   plugin_ipc_init();
166   return 1;
167 }
168
169 /**
170  * destructor - called at unload
171  */
172 void olsr_plugin_exit(void) {
173   if (ipc_socket != -1)
174     close(ipc_socket);
175 }
176
177 static int plugin_ipc_init(void) {
178   union olsr_sockaddr sst;
179   uint32_t yes = 1;
180   socklen_t addrlen;
181
182   /* Init ipc socket */
183   if ((ipc_socket = socket(olsr_cnf->ip_version, SOCK_STREAM, 0)) == -1) {
184 #ifndef NODEBUG
185     olsr_printf(1, "("PLUGIN_NAME") socket()=%s\n", strerror(errno));
186 #endif /* NODEBUG */
187     return 0;
188   } else {
189     if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(yes)) < 0) {
190 #ifndef NODEBUG
191       olsr_printf(1, "("PLUGIN_NAME") setsockopt()=%s\n", strerror(errno));
192 #endif /* NODEBUG */
193       return 0;
194     }
195 #if (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE
196     if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *) &yes, sizeof(yes)) < 0) {
197       perror("SO_REUSEADDR failed");
198       return 0;
199     }
200 #endif /* (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE */
201 #if defined linux && defined IPV6_V6ONLY
202     if (info_ipv6_only && olsr_cnf->ip_version == AF_INET6) {
203       if (setsockopt(ipc_socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, sizeof(yes)) < 0) {
204         perror("IPV6_V6ONLY failed");
205         return 0;
206       }
207     }
208 #endif /* defined linux && defined IPV6_V6ONLY */
209     /* Bind the socket */
210
211     /* complete the socket structure */
212     memset(&sst, 0, sizeof(sst));
213     if (olsr_cnf->ip_version == AF_INET) {
214       sst.in4.sin_family = AF_INET;
215       addrlen = sizeof(struct sockaddr_in);
216 #ifdef SIN6_LEN
217       sst.in4.sin_len = addrlen;
218 #endif /* SIN6_LEN */
219       sst.in4.sin_addr.s_addr = info_listen_ip.v4.s_addr;
220       sst.in4.sin_port = htons(ipc_port);
221     } else {
222       sst.in6.sin6_family = AF_INET6;
223       addrlen = sizeof(struct sockaddr_in6);
224 #ifdef SIN6_LEN
225       sst.in6.sin6_len = addrlen;
226 #endif /* SIN6_LEN */
227       sst.in6.sin6_addr = info_listen_ip.v6;
228       sst.in6.sin6_port = htons(ipc_port);
229     }
230
231     /* bind the socket to the port number */
232     if (bind(ipc_socket, &sst.in, addrlen) == -1) {
233 #ifndef NODEBUG
234       olsr_printf(1, "("PLUGIN_NAME") bind()=%s\n", strerror(errno));
235 #endif /* NODEBUG */
236       return 0;
237     }
238
239     /* show that we are willing to listen */
240     if (listen(ipc_socket, 1) == -1) {
241 #ifndef NODEBUG
242       olsr_printf(1, "("PLUGIN_NAME") listen()=%s\n", strerror(errno));
243 #endif /* NODEBUG */
244       return 0;
245     }
246
247     /* Register with olsrd */
248     add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
249
250 #ifndef NODEBUG
251     olsr_printf(2, "("PLUGIN_NAME") listening on port %d\n", ipc_port);
252 #endif /* NODEBUG */
253   }
254   return 1;
255 }
256
257 static void ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
258   union olsr_sockaddr pin;
259
260   char addr[INET6_ADDRSTRLEN];
261   fd_set rfds;
262   struct timeval tv;
263   unsigned int send_what = 0;
264   int ipc_connection;
265
266   socklen_t addrlen = sizeof(pin);
267
268   if (outbuffer_count >= MAX_CLIENTS) {
269     return;
270   }
271
272   if ((ipc_connection = accept(fd, &pin.in, &addrlen)) == -1) {
273 #ifndef NODEBUG
274     olsr_printf(1, "("PLUGIN_NAME") accept()=%s\n", strerror(errno));
275 #endif /* NODEBUG */
276     return;
277   }
278
279   tv.tv_sec = tv.tv_usec = 0;
280   if (olsr_cnf->ip_version == AF_INET) {
281     if (inet_ntop(olsr_cnf->ip_version, &pin.in4.sin_addr, addr, INET6_ADDRSTRLEN) == NULL)
282       addr[0] = '\0';
283     if (!ip4equal(&pin.in4.sin_addr, &info_accept_ip.v4) && info_accept_ip.v4.s_addr != INADDR_ANY) {
284 #ifdef INFO_ALLOW_LOCALHOST
285       if (ntohl(pin.in4.sin_addr.s_addr) != INADDR_LOOPBACK) {
286 #endif /* INFO_ALLOW_LOCALHOST */
287         olsr_printf(1, "("PLUGIN_NAME") From host(%s) not allowed!\n", addr);
288         close(ipc_connection);
289         return;
290 #ifdef INFO_ALLOW_LOCALHOST
291       }
292 #endif /* INFO_ALLOW_LOCALHOST */
293     }
294   } else {
295     if (inet_ntop(olsr_cnf->ip_version, &pin.in6.sin6_addr, addr, INET6_ADDRSTRLEN) == NULL)
296       addr[0] = '\0';
297     /* Use in6addr_any (::) in olsr.conf to allow anybody. */
298     if (!ip6equal(&in6addr_any, &info_accept_ip.v6) && !ip6equal(&pin.in6.sin6_addr, &info_accept_ip.v6)) {
299       olsr_printf(1, "("PLUGIN_NAME") From host(%s) not allowed!\n", addr);
300       close(ipc_connection);
301       return;
302     }
303   }
304
305 #ifndef NODEBUG
306   olsr_printf(2, "("PLUGIN_NAME") Connect from %s\n", addr);
307 #endif /* NODEBUG */
308
309   /* purge read buffer to prevent blocking on linux */
310   FD_ZERO(&rfds);
311   FD_SET((unsigned int )ipc_connection, &rfds); /* Win32 needs the cast here */
312   if (0 <= select(ipc_connection + 1, &rfds, NULL, NULL, &tv)) {
313     char requ[1024];
314     ssize_t s = recv(ipc_connection, (void *) &requ, sizeof(requ) - 1, 0); /* Win32 needs the cast here */
315
316     if (s == sizeof(requ) - 1) {
317       /* input was much too long, just skip the rest */
318       char dummy[1024];
319
320       while (recv(ipc_connection, (void *) &dummy, sizeof(dummy), 0) == sizeof(dummy))
321         ;
322     }
323
324     if (0 < s) {
325       requ[s] = 0;
326       /* print out the requested tables */
327       if (strstr(requ, "/olsrd.conf"))
328         send_what |= SIW_OLSRD_CONF;
329       else if (strstr(requ, "/all"))
330         send_what = SIW_ALL;
331       else {
332         // these are the two overarching categories
333         if (strstr(requ, "/runtime"))
334           send_what |= SIW_RUNTIME_ALL;
335         if (strstr(requ, "/startup"))
336           send_what |= SIW_STARTUP_ALL;
337
338         // these are the individual sections
339         if (strstr(requ, "/neighbors"))
340           send_what |= SIW_NEIGHBORS;
341         if (strstr(requ, "/links"))
342           send_what |= SIW_LINKS;
343         if (strstr(requ, "/routes"))
344           send_what |= SIW_ROUTES;
345         if (strstr(requ, "/hna"))
346           send_what |= SIW_HNA;
347         if (strstr(requ, "/mid"))
348           send_what |= SIW_MID;
349         if (strstr(requ, "/topology"))
350           send_what |= SIW_TOPOLOGY;
351         if (strstr(requ, "/gateways"))
352           send_what |= SIW_GATEWAYS;
353         if (strstr(requ, "/interfaces"))
354           send_what |= SIW_INTERFACES;
355         if (strstr(requ, "/2hop"))
356           send_what |= SIW_2HOP;
357         if (strstr(requ, "/sgw"))
358           send_what |= SIW_SGW;
359
360         // specials
361         if (strstr(requ, "/version"))
362           send_what |= SIW_VERSION;
363         if (strstr(requ, "/config"))
364           send_what |= SIW_CONFIG;
365         if (strstr(requ, "/plugins"))
366           send_what |= SIW_PLUGINS;
367
368         /* To print out neighbours only on the Freifunk Status
369          * page the normal output is somewhat lengthy. The
370          * header parsing is sufficient for standard wget.
371          */
372         if (strstr(requ, "/neighbours"))
373           send_what = SIW_NEIGHBORS | SIW_LINKS;
374       }
375     }
376
377     if (!send_what)
378       send_what = SIW_ALL;
379   }
380
381   send_info(send_what, ipc_connection);
382 }
383
384 static void ipc_print_neighbors(struct autobuf *abuf, bool list_2hop) {
385   struct ipaddr_str buf1;
386   struct neighbor_entry *neigh;
387   struct neighbor_2_list_entry *list_2;
388   int thop_cnt;
389
390   if (!list_2hop)
391     abuf_json_mark_object(true, true, abuf, "neighbors");
392   else
393     abuf_json_mark_object(true, true, abuf, "2hop");
394
395   /* Neighbors */
396   OLSR_FOR_ALL_NBR_ENTRIES(neigh)
397       {
398         abuf_json_mark_array_entry(true, abuf);
399
400         abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf1, &neigh->neighbor_main_addr));
401         abuf_json_boolean(abuf, "symmetric", (neigh->status == SYM));
402         abuf_json_boolean(abuf, "multiPointRelay", neigh->is_mpr);
403         abuf_json_boolean(abuf, "multiPointRelaySelector", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) != NULL);
404         abuf_json_int(abuf, "willingness", neigh->willingness);
405         thop_cnt = 0;
406
407         if (!list_2hop) {
408           for (list_2 = neigh->neighbor_2_list.next; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next) {
409             thop_cnt++;
410           }
411           abuf_json_int(abuf, "twoHopNeighborCount", thop_cnt);
412         } else {
413           abuf_json_mark_object(true, true, abuf, "twoHopNeighbors");
414           for (list_2 = neigh->neighbor_2_list.next; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next) {
415             abuf_json_mark_array_entry(true, abuf);
416             abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf1, &list_2->neighbor_2->neighbor_2_addr));
417             abuf_json_mark_array_entry(false, abuf);
418           }
419           abuf_json_mark_object(false, true, abuf, false);
420         }
421
422         abuf_json_mark_array_entry(false, abuf);
423       }OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
424   abuf_json_mark_object(false, true, abuf, NULL);
425 }
426
427 static void ipc_print_links(struct autobuf *abuf) {
428   struct ipaddr_str buf1, buf2;
429   struct lqtextbuffer lqbuffer1;
430
431   struct link_entry *my_link = NULL;
432
433   abuf_json_mark_object(true, true, abuf, "links");
434
435   OLSR_FOR_ALL_LINK_ENTRIES(my_link)
436       {
437         const char* lqs;
438         int diff = (unsigned int) (my_link->link_timer->timer_clock - now_times);
439
440         abuf_json_mark_array_entry(true, abuf);
441         abuf_json_string(abuf, "localIP", olsr_ip_to_string(&buf1, &my_link->local_iface_addr));
442         abuf_json_string(abuf, "remoteIP", olsr_ip_to_string(&buf2, &my_link->neighbor_iface_addr));
443         abuf_json_int(abuf, "validityTime", diff);
444         lqs = get_link_entry_text(my_link, '\t', &lqbuffer1);
445         abuf_json_float(abuf, "linkQuality", atof(lqs));
446         abuf_json_float(abuf, "neighborLinkQuality", atof(strrchr(lqs, '\t')));
447         if (my_link->linkcost >= LINK_COST_BROKEN)
448           abuf_json_int(abuf, "linkCost", LINK_COST_BROKEN);
449         else
450           abuf_json_int(abuf, "linkCost", my_link->linkcost);
451         abuf_json_mark_array_entry(false, abuf);
452       }OLSR_FOR_ALL_LINK_ENTRIES_END(my_link);
453   abuf_json_mark_object(false, true, abuf, NULL);
454 }
455
456 static void ipc_print_routes(struct autobuf *abuf) {
457   struct ipaddr_str buf1, buf2;
458   struct rt_entry *rt;
459
460   abuf_json_mark_object(true, true, abuf, "routes");
461
462   /* Walk the route table */
463   OLSR_FOR_ALL_RT_ENTRIES(rt)
464       {
465         abuf_json_mark_array_entry(true, abuf);
466         abuf_json_string(abuf, "destination", olsr_ip_to_string(&buf1, &rt->rt_dst.prefix));
467         abuf_json_int(abuf, "genmask", rt->rt_dst.prefix_len);
468         abuf_json_string(abuf, "gateway", olsr_ip_to_string(&buf2, &rt->rt_best->rtp_nexthop.gateway));
469         abuf_json_int(abuf, "metric", rt->rt_best->rtp_metric.hops);
470         if (rt->rt_best->rtp_metric.cost >= ROUTE_COST_BROKEN)
471           abuf_json_int(abuf, "rtpMetricCost", ROUTE_COST_BROKEN);
472         else
473           abuf_json_int(abuf, "rtpMetricCost", rt->rt_best->rtp_metric.cost);
474         abuf_json_string(abuf, "networkInterface", if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
475         abuf_json_mark_array_entry(false, abuf);
476       }OLSR_FOR_ALL_RT_ENTRIES_END(rt);
477
478   abuf_json_mark_object(false, true, abuf, NULL);
479 }
480
481 static void ipc_print_topology(struct autobuf *abuf) {
482   struct tc_entry *tc;
483
484   abuf_json_mark_object(true, true, abuf, "topology");
485
486   /* Topology */
487   OLSR_FOR_ALL_TC_ENTRIES(tc)
488       {
489         struct tc_edge_entry *tc_edge;
490         OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge)
491             {
492               if (tc_edge->edge_inv) {
493                 struct ipaddr_str dstbuf, addrbuf;
494                 struct lqtextbuffer lqbuffer1;
495                 uint32_t vt = tc->validity_timer != NULL ? (tc->validity_timer->timer_clock - now_times) : 0;
496                 int diff = (int) (vt);
497                 const char* lqs;
498                 abuf_json_mark_array_entry(true, abuf);
499                 abuf_json_string(abuf, "destinationIP", olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr));
500                 abuf_json_string(abuf, "lastHopIP", olsr_ip_to_string(&addrbuf, &tc->addr));
501                 lqs = get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1);
502                 abuf_json_float(abuf, "linkQuality", atof(lqs));
503                 abuf_json_float(abuf, "neighborLinkQuality", atof(strrchr(lqs, '\t')));
504                 if (tc_edge->cost >= LINK_COST_BROKEN)
505                   abuf_json_int(abuf, "tcEdgeCost", LINK_COST_BROKEN);
506                 else
507                   abuf_json_int(abuf, "tcEdgeCost", tc_edge->cost);
508                 abuf_json_int(abuf, "validityTime", diff);
509                 abuf_json_mark_array_entry(false, abuf);
510               }
511             }OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
512       }OLSR_FOR_ALL_TC_ENTRIES_END(tc);
513
514   abuf_json_mark_object(false, true, abuf, NULL);
515 }
516
517 static void ipc_print_hna(struct autobuf *abuf) {
518   struct hna_entry *tmp_hna;
519   struct hna_net *tmp_net;
520   struct ipaddr_str buf, mainaddrbuf;
521
522   abuf_json_mark_object(true, true, abuf, "hna");
523
524   OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna)
525         {
526
527           /* Check all networks */
528           for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
529             uint32_t vt = tmp_net->hna_net_timer != NULL ? (tmp_net->hna_net_timer->timer_clock - now_times) : 0;
530             int diff = (int) (vt);
531             abuf_json_mark_array_entry(true, abuf);
532             abuf_json_string(abuf, "destination", olsr_ip_to_string(&buf, &tmp_net->hna_prefix.prefix)), abuf_json_int(abuf, "genmask",
533                 tmp_net->hna_prefix.prefix_len);
534             abuf_json_string(abuf, "gateway", olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
535             abuf_json_int(abuf, "validityTime", diff);
536             abuf_json_mark_array_entry(false, abuf);
537           }
538         }OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
539
540   abuf_json_mark_object(false, true, abuf, NULL);
541 }
542
543 static void ipc_print_mid(struct autobuf *abuf) {
544   int idx;
545   struct mid_entry *entry;
546   struct mid_address *alias;
547
548   abuf_json_mark_object(true, true, abuf, "mid");
549
550   /* MID */
551   for (idx = 0; idx < HASHSIZE; idx++) {
552     entry = mid_set[idx].next;
553
554     while (entry != &mid_set[idx]) {
555       struct ipaddr_str buf, buf2;
556       abuf_json_mark_array_entry(true, abuf);
557       abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf, &entry->main_addr));
558
559       abuf_json_mark_object(true, true, abuf, "aliases");
560       alias = entry->aliases;
561       while (alias) {
562         uint32_t vt = alias->vtime - now_times;
563         int diff = (int) (vt);
564
565         abuf_json_mark_array_entry(true, abuf);
566         abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf2, &alias->alias));
567         abuf_json_int(abuf, "validityTime", diff);
568         abuf_json_mark_array_entry(false, abuf);
569
570         alias = alias->next_alias;
571       }
572       abuf_json_mark_object(false, true, abuf, NULL); // aliases
573       abuf_json_mark_array_entry(false, abuf);
574       entry = entry->next;
575     }
576   }
577   abuf_json_mark_object(false, true, abuf, NULL); // mid
578 }
579
580 static void ipc_print_gateways(struct autobuf *abuf) {
581 #ifndef __linux__
582   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
583 #else /* __linux__ */
584
585   struct ipaddr_str buf;
586   struct gateway_entry *gw;
587
588   abuf_json_mark_object(true, true, abuf, "gateways");
589   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw)
590       {
591         const char *v4 = "", *v6 = "";
592         bool autoV4 = false, autoV6 = false;
593         const char *ipType = "";
594         struct tc_entry *tc;
595
596         if ((tc = olsr_lookup_tc_entry(&gw->originator)) == NULL) {
597           continue;
598         }
599
600         if (gw == olsr_get_inet_gateway(false)) {
601           v4 = "s";
602         } else if (gw->ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit) && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat)) {
603           v4 = "u";
604         }
605
606         if (gw == olsr_get_inet_gateway(true)) {
607           v6 = "s";
608         } else if (gw->ipv6 && olsr_cnf->ip_version == AF_INET6) {
609           v6 = "u";
610         }
611
612         abuf_json_mark_array_entry(true, abuf);
613         if (gw->ipv4) {
614           ipType = "ipv4";
615           abuf_json_string(abuf, "ipv4Status", v4);
616         } else if (gw->ipv6) {
617           ipType = "ipv6";
618           abuf_json_string(abuf, "ipv6Status", v6);
619         }
620         abuf_json_string(abuf, "ipType", ipType);
621         abuf_json_boolean(abuf, "ipv4", gw->ipv4);
622         abuf_json_boolean(abuf, "ipv4Nat", gw->ipv4nat);
623         abuf_json_boolean(abuf, "ipv6", gw->ipv6);
624         abuf_json_boolean(abuf, "autoIpv4", autoV4);
625         abuf_json_boolean(abuf, "autoIpv6", autoV6);
626         abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&buf, &gw->originator));
627         if (tc->path_cost >= ROUTE_COST_BROKEN)
628           abuf_json_int(abuf, "tcPathCost", ROUTE_COST_BROKEN);
629         else
630           abuf_json_int(abuf, "tcPathCost", tc->path_cost);
631         abuf_json_int(abuf, "hopCount", tc->hops);
632         abuf_json_int(abuf, "uplinkSpeed", gw->uplink);
633         abuf_json_int(abuf, "downlinkSpeed", gw->downlink);
634         if (!gw->external_prefix.prefix_len)
635           abuf_json_string(abuf, "externalPrefix", olsr_ip_prefix_to_string(&gw->external_prefix));
636         abuf_json_mark_array_entry(false, abuf);
637       }OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
638   abuf_json_mark_object(false, true, abuf, NULL);
639 #endif /* __linux__ */
640 }
641
642 static void ipc_print_plugins(struct autobuf *abuf) {
643   struct plugin_entry *pentry;
644   struct plugin_param *pparam;
645   abuf_json_mark_object(true, true, abuf, "plugins");
646   if (olsr_cnf->plugins)
647     for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
648       abuf_json_mark_array_entry(true, abuf);
649       abuf_json_string(abuf, "plugin", pentry->name);
650       for (pparam = pentry->params; pparam; pparam = pparam->next) {
651         int i, keylen = strlen(pparam->key);
652         char key[keylen + 1];
653         long value;
654         char valueTest[256];
655         strcpy(key, pparam->key);
656         for (i = 0; i < keylen; i++)
657           key[i] = tolower(key[i]);
658
659         // test if a int/long and set as such in JSON
660         value = atol(pparam->value);
661         snprintf(valueTest, 255, "%li", value);
662         if (!strcmp(valueTest, pparam->value))
663           abuf_json_int(abuf, key, value);
664         else
665           abuf_json_string(abuf, key, pparam->value);
666       }
667       abuf_json_mark_array_entry(false, abuf);
668     }
669   abuf_json_mark_object(false, true, abuf, NULL);
670 }
671
672 #ifdef __linux__
673
674 /** interface names for smart gateway tunnel interfaces, IPv4 */
675 extern struct interfaceName * sgwTunnel4InterfaceNames;
676
677 /** interface names for smart gateway tunnel interfaces, IPv6 */
678 extern struct interfaceName * sgwTunnel6InterfaceNames;
679
680 /**
681  * Construct the sgw table for a given ip version
682  *
683  * @param abuf the string buffer
684  * @param ipv6 true for IPv6, false for IPv4
685  * @param fmtv the format for printing
686  */
687 static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
688   struct interfaceName * sgwTunnelInterfaceNames;
689
690   abuf_json_mark_object(true, true, abuf, ipv6 ? "ipv6" : "ipv4");
691
692   sgwTunnelInterfaceNames = !ipv6 ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
693   if (olsr_cnf->smart_gw_active && sgwTunnelInterfaceNames) {
694     struct gateway_entry * current_gw = olsr_get_inet_gateway(ipv6);
695     int i;
696     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
697       struct interfaceName * node = &sgwTunnelInterfaceNames[i];
698       struct gateway_entry * gw = node->gw;
699
700       if (!gw) {
701         continue;
702       }
703
704       abuf_json_mark_array_entry(true, abuf);
705       {
706         struct tc_entry* tc = olsr_lookup_tc_entry(&gw->originator);
707
708         struct ipaddr_str originatorStr;
709         const char * originator = olsr_ip_to_string(&originatorStr, &gw->originator);
710         struct ipaddr_str prefixIpStr;
711         const char * prefix = olsr_ip_to_string(&prefixIpStr, &gw->external_prefix.prefix);
712
713         abuf_json_boolean(abuf, "selected", current_gw && (current_gw == gw));
714         abuf_json_string(abuf, "originator", originator);
715         abuf_json_string(abuf, "prefix", prefix);
716         abuf_json_int(abuf, "prefixLen", gw->external_prefix.prefix_len);
717         abuf_json_int(abuf, "uplink", gw->uplink);
718         abuf_json_int(abuf, "downlink", gw->downlink);
719         abuf_json_int(abuf, "pathcost", !tc ? ROUTE_COST_BROKEN : tc->path_cost);
720         abuf_json_boolean(abuf, "IPv4", gw->ipv4);
721         abuf_json_boolean(abuf, "IPv4-NAT", gw->ipv4nat);
722         abuf_json_boolean(abuf, "IPv6", gw->ipv6);
723         abuf_json_string(abuf, "tunnel", node->name);
724         abuf_json_string(abuf, "destination", originator);
725         abuf_json_int(abuf, "cost", gw->path_cost);
726         abuf_json_int(abuf, "tableNr", node->tableNr);
727         abuf_json_int(abuf, "ruleNr", node->ruleNr);
728         abuf_json_int(abuf, "bypassRuleNr", node->bypassRuleNr);
729       }
730       abuf_json_mark_array_entry(false, abuf);
731     }
732   }
733
734   abuf_json_mark_object(false, true, abuf, NULL);
735 }
736 #endif /* __linux__ */
737
738 static void ipc_print_sgw(struct autobuf *abuf) {
739 #ifndef __linux__
740   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
741 #else
742   abuf_json_mark_object(true, false, abuf, "sgw");
743
744   sgw_ipvx(abuf, false);
745   sgw_ipvx(abuf, true);
746
747   abuf_json_mark_object(false, false, abuf, NULL);
748 #endif /* __linux__ */
749 }
750
751 static void ipc_print_version(struct autobuf *abuf) {
752   abuf_json_mark_object(true, false, abuf, "version");
753
754   abuf_json_string(abuf, "version", olsrd_version);
755   abuf_json_string(abuf, "date", build_date);
756   abuf_json_string(abuf, "host", build_host);
757
758   abuf_json_mark_object(false, false, abuf, NULL);
759 }
760
761 static void ipc_print_olsrd_conf(struct autobuf *abuf) {
762   olsrd_write_cnf_autobuf(abuf, olsr_cnf);
763 }
764
765 static void ipc_print_config(struct autobuf *abuf) {
766   struct ip_prefix_list *hna;
767   struct ipaddr_str buf, mainaddrbuf;
768   struct ip_prefix_list *ipcn;
769   struct olsr_lq_mult *mult;
770   char ipv6_buf[INET6_ADDRSTRLEN]; /* buffer for IPv6 inet_htop */
771
772   abuf_json_mark_object(true, false, abuf, "config");
773
774   abuf_json_int(abuf, "olsrPort", olsr_cnf->olsrport);
775   abuf_json_int(abuf, "debugLevel", olsr_cnf->debug_level);
776   abuf_json_boolean(abuf, "noFork", olsr_cnf->no_fork);
777   abuf_json_boolean(abuf, "hostEmulation", olsr_cnf->host_emul);
778   abuf_json_int(abuf, "ipVersion", olsr_cnf->ip_version);
779   abuf_json_boolean(abuf, "allowNoInterfaces", olsr_cnf->allow_no_interfaces);
780   abuf_json_int(abuf, "typeOfService", olsr_cnf->tos);
781   abuf_json_int(abuf, "rtProto", olsr_cnf->rt_proto);
782   abuf_json_int(abuf, "rtTable", olsr_cnf->rt_table);
783   abuf_json_int(abuf, "rtTableDefault", olsr_cnf->rt_table_default);
784   abuf_json_int(abuf, "rtTableTunnel", olsr_cnf->rt_table_tunnel);
785   abuf_json_int(abuf, "rtTablePriority", olsr_cnf->rt_table_pri);
786   abuf_json_int(abuf, "rtTableTunnelPriority", olsr_cnf->rt_table_tunnel_pri);
787   abuf_json_int(abuf, "rtTableDefauiltOlsrPriority", olsr_cnf->rt_table_defaultolsr_pri);
788   abuf_json_int(abuf, "rtTableDefaultPriority", olsr_cnf->rt_table_default_pri);
789   abuf_json_int(abuf, "willingness", olsr_cnf->willingness);
790   abuf_json_boolean(abuf, "willingnessAuto", olsr_cnf->willingness_auto);
791
792   abuf_json_int(abuf, "brokenLinkCost", LINK_COST_BROKEN);
793   abuf_json_int(abuf, "brokenRouteCost", ROUTE_COST_BROKEN);
794
795   abuf_json_string(abuf, "fibMetrics", FIB_METRIC_TXT[olsr_cnf->fib_metric]);
796
797   abuf_json_string(abuf, "defaultIpv6Multicast", inet_ntop(AF_INET6, &olsr_cnf->interface_defaults->ipv6_multicast.v6, ipv6_buf, sizeof(ipv6_buf)));
798   if (olsr_cnf->interface_defaults->ipv4_multicast.v4.s_addr)
799     abuf_json_string(abuf, "defaultIpv4Broadcast", inet_ntoa(olsr_cnf->interface_defaults->ipv4_multicast.v4));
800   else
801     abuf_json_string(abuf, "defaultIpv4Broadcast", "auto");
802
803   if (olsr_cnf->interface_defaults->mode == IF_MODE_ETHER)
804     abuf_json_string(abuf, "defaultInterfaceMode", "ether");
805   else
806     abuf_json_string(abuf, "defaultInterfaceMode", "mesh");
807
808   abuf_json_float(abuf, "defaultHelloEmissionInterval", olsr_cnf->interface_defaults->hello_params.emission_interval);
809   abuf_json_float(abuf, "defaultHelloValidityTime", olsr_cnf->interface_defaults->hello_params.validity_time);
810   abuf_json_float(abuf, "defaultTcEmissionInterval", olsr_cnf->interface_defaults->tc_params.emission_interval);
811   abuf_json_float(abuf, "defaultTcValidityTime", olsr_cnf->interface_defaults->tc_params.validity_time);
812   abuf_json_float(abuf, "defaultMidEmissionInterval", olsr_cnf->interface_defaults->mid_params.emission_interval);
813   abuf_json_float(abuf, "defaultMidValidityTime", olsr_cnf->interface_defaults->mid_params.validity_time);
814   abuf_json_float(abuf, "defaultHnaEmissionInterval", olsr_cnf->interface_defaults->hna_params.emission_interval);
815   abuf_json_float(abuf, "defaultHnaValidityTime", olsr_cnf->interface_defaults->hna_params.validity_time);
816   abuf_json_boolean(abuf, "defaultAutoDetectChanges", olsr_cnf->interface_defaults->autodetect_chg);
817
818   abuf_json_mark_object(true, true, abuf, "defaultLinkQualityMultipliers");
819   for (mult = olsr_cnf->interface_defaults->lq_mult; mult != NULL ; mult = mult->next) {
820     abuf_json_mark_array_entry(true, abuf);
821     abuf_json_string(abuf, "route", inet_ntop(olsr_cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)));
822     abuf_json_float(abuf, "multiplier", mult->value / 65535.0);
823     abuf_json_mark_array_entry(false, abuf);
824   }
825   abuf_json_mark_object(false, true, abuf, NULL);
826
827   abuf_json_mark_object(true, true, abuf, "hna");
828   for (hna = olsr_cnf->hna_entries; hna != NULL ; hna = hna->next) {
829     abuf_json_mark_array_entry(true, abuf);
830     abuf_json_string(abuf, "destination", olsr_ip_to_string(&buf, &hna->net.prefix));
831     abuf_json_int(abuf, "genmask", hna->net.prefix_len);
832     abuf_json_string(abuf, "gateway", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
833     abuf_json_mark_array_entry(false, abuf);
834   }
835   abuf_json_mark_object(false, true, abuf, NULL);
836
837   abuf_json_int(abuf, "totalIpcConnectionsAllowed", olsr_cnf->ipc_connections);
838   abuf_json_mark_object(true, true, abuf, "ipcAllowedAddresses");
839   if (olsr_cnf->ipc_connections) {
840     for (ipcn = olsr_cnf->ipc_nets; ipcn != NULL ; ipcn = ipcn->next) {
841       abuf_json_mark_array_entry(true, abuf);
842       abuf_json_string(abuf, "ipAddress", olsr_ip_to_string(&mainaddrbuf, &ipcn->net.prefix));
843       abuf_json_int(abuf, "netmask", ipcn->net.prefix_len);
844       abuf_json_mark_array_entry(false, abuf);
845     }
846   }
847   abuf_json_mark_object(false, true, abuf, NULL);
848
849   // keep all time in ms, so convert these two, which are in seconds
850   abuf_json_int(abuf, "pollRate", olsr_cnf->pollrate * 1000);
851   abuf_json_int(abuf, "nicChangePollInterval", olsr_cnf->nic_chgs_pollrate * 1000);
852   abuf_json_boolean(abuf, "clearScreen", olsr_cnf->clear_screen);
853   abuf_json_int(abuf, "tcRedundancy", olsr_cnf->tc_redundancy);
854   abuf_json_int(abuf, "mprCoverage", olsr_cnf->mpr_coverage);
855
856   if (!olsr_cnf->lq_level) {
857     abuf_json_boolean(abuf, "useHysteresis", olsr_cnf->use_hysteresis);
858     if (olsr_cnf->use_hysteresis) {
859       abuf_json_float(abuf, "hysteresisScaling", olsr_cnf->hysteresis_param.scaling);
860       abuf_json_float(abuf, "hysteresisLowThreshold", olsr_cnf->hysteresis_param.thr_low);
861       abuf_json_float(abuf, "hysteresisHighThreshold", olsr_cnf->hysteresis_param.thr_high);
862     }
863   }
864   abuf_json_int(abuf, "linkQualityLevel", olsr_cnf->lq_level);
865   abuf_json_float(abuf, "linkQualityAging", olsr_cnf->lq_aging);
866   abuf_json_boolean(abuf, "linkQualityFisheye", olsr_cnf->lq_fish);
867   abuf_json_string(abuf, "linkQualityAlgorithm", olsr_cnf->lq_algorithm);
868   // keep all time in ms, so convert this from seconds
869   abuf_json_int(abuf, "minTcValidTime", olsr_cnf->min_tc_vtime * 1000);
870   abuf_json_boolean(abuf, "setIpForward", olsr_cnf->set_ip_forward);
871   abuf_json_string(abuf, "lockFile", olsr_cnf->lock_file);
872   abuf_json_boolean(abuf, "useNiit", olsr_cnf->use_niit);
873
874 #ifdef __linux__
875   abuf_json_boolean(abuf, "smartGateway", olsr_cnf->smart_gw_active);
876   if (olsr_cnf->smart_gw_active) {
877     abuf_json_boolean(abuf, "smartGatewayAlwaysRemoveServerTunnel", olsr_cnf->smart_gw_always_remove_server_tunnel);
878     abuf_json_int(abuf, "smartGatewayUseCount", olsr_cnf->smart_gw_use_count);
879     abuf_json_string(abuf, "smartGatewayInstanceId", olsr_cnf->smart_gw_instance_id);
880     abuf_json_string(abuf, "smartGatewayPolicyRoutingScript", olsr_cnf->smart_gw_policyrouting_script);
881     {
882       struct autobuf egressbuf;
883       struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
884
885       abuf_init(&egressbuf, (olsr_cnf->smart_gw_egress_interfaces_count * IFNAMSIZ) /* interface names */
886       + (olsr_cnf->smart_gw_egress_interfaces_count - 1) /* commas */);
887       while (egressif) {
888         if (egressbuf.len) {
889           abuf_puts(&egressbuf, ",");
890         }
891         abuf_appendf(&egressbuf, "%s", egressif->name);
892         egressif = egressif->next;
893       }
894       abuf_json_string(abuf, "smartGatewayEgressInterfaces", egressbuf.buf);
895       abuf_free(&egressbuf);
896     }
897     abuf_json_int(abuf, "smartGatewayTablesOffset", olsr_cnf->smart_gw_offset_tables);
898     abuf_json_int(abuf, "smartGatewayRulesOffset", olsr_cnf->smart_gw_offset_rules);
899     abuf_json_boolean(abuf, "smartGatewayAllowNat", olsr_cnf->smart_gw_allow_nat);
900     abuf_json_boolean(abuf, "smartGatewayUplinkNat", olsr_cnf->smart_gw_uplink_nat);
901     abuf_json_int(abuf, "smartGatewayPeriod", olsr_cnf->smart_gw_period);
902     abuf_json_int(abuf, "smartGatewayStableCount", olsr_cnf->smart_gw_stablecount);
903     abuf_json_int(abuf, "smartGatewayThreshold", olsr_cnf->smart_gw_thresh);
904     abuf_json_int(abuf, "smartGatewayUplink", olsr_cnf->smart_gw_uplink);
905     abuf_json_int(abuf, "smartGatewayDownlink", olsr_cnf->smart_gw_downlink);
906     abuf_json_int(abuf, "smartGatewayType", olsr_cnf->smart_gw_type);
907     abuf_json_string(abuf, "smartGatewayPrefix", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->smart_gw_prefix.prefix));
908     abuf_json_int(abuf, "smartGatewayPrefixLength", olsr_cnf->smart_gw_prefix.prefix_len);
909   }
910 #endif /* __linux__ */
911
912   abuf_json_string(abuf, "mainIpAddress", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
913   abuf_json_string(abuf, "unicastSourceIpAddress", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->unicast_src_ip));
914
915   abuf_json_boolean(abuf, "useSourceIpRoutes", olsr_cnf->use_src_ip_routes);
916
917   abuf_json_int(abuf, "maxPrefixLength", olsr_cnf->maxplen);
918   abuf_json_int(abuf, "ipSize", olsr_cnf->ipsize);
919   abuf_json_boolean(abuf, "deleteInternetGatewaysAtStartup", olsr_cnf->del_gws);
920   // keep all time in ms, so convert this from seconds
921   abuf_json_int(abuf, "willingnessUpdateInterval", olsr_cnf->will_int * 1000);
922   abuf_json_float(abuf, "maxSendMessageJitter", olsr_cnf->max_jitter);
923   abuf_json_int(abuf, "exitValue", olsr_cnf->exit_value);
924   // keep all time in ms, so convert this from seconds
925   abuf_json_int(abuf, "maxTcValidTime", olsr_cnf->max_tc_vtime * 1000);
926
927   abuf_json_int(abuf, "niit4to6InterfaceIndex", olsr_cnf->niit4to6_if_index);
928   abuf_json_int(abuf, "niit6to4InterfaceIndex", olsr_cnf->niit6to4_if_index);
929
930   abuf_json_boolean(abuf, "hasIpv4Gateway", olsr_cnf->has_ipv4_gateway);
931   abuf_json_boolean(abuf, "hasIpv6Gateway", olsr_cnf->has_ipv6_gateway);
932
933   abuf_json_int(abuf, "ioctlSocket", olsr_cnf->ioctl_s);
934 #ifdef __linux__
935   abuf_json_int(abuf, "routeNetlinkSocket", olsr_cnf->rtnl_s);
936   abuf_json_int(abuf, "routeMonitorSocket", olsr_cnf->rt_monitor_socket);
937 #endif /* __linux__ */
938
939 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
940   abuf_json_int(abuf, "routeChangeSocket", olsr_cnf->rts);
941 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
942   abuf_json_float(abuf, "linkQualityNatThreshold", olsr_cnf->lq_nat_thresh);
943
944   abuf_json_string(abuf, "olsrdVersion", olsrd_version);
945   abuf_json_string(abuf, "olsrdBuildDate", build_date);
946   abuf_json_string(abuf, "olsrdBuildHost", build_host);
947
948 #if defined _WIN32 || defined _WIN64
949   abuf_json_string(abuf, "os", "Windows");
950 #elif defined __gnu_linux__
951   abuf_json_string(abuf, "os", "GNU/Linux");
952 #elif defined __ANDROID__
953   abuf_json_string(abuf, "os", "Android");
954 #elif defined __APPLE__
955   abuf_json_string(abuf, "os", "Mac OS X");
956 #elif defined __NetBSD__
957   abuf_json_string(abuf, "os", "NetBSD");
958 #elif defined __OpenBSD__
959   abuf_json_string(abuf, "os", "OpenBSD");
960 #elif defined __FreeBSD__ || defined __FreeBSD_kernel__
961   abuf_json_string(abuf, "os", "FreeBSD");
962 #else /* OS detection */
963   abuf_json_string(abuf, "os", "Undefined");
964 #endif /* OS detection */
965
966   abuf_json_int(abuf, "startTime", start_time.tv_sec);
967
968   abuf_json_mark_object(false, false, abuf, NULL);
969 }
970
971 static void ipc_print_interfaces(struct autobuf *abuf) {
972 #ifdef __linux__
973   int linklen;
974   char path[PATH_MAX], linkpath[PATH_MAX];
975 #endif /* __linux__ */
976   char ipv6_buf[INET6_ADDRSTRLEN]; /* buffer for IPv6 inet_htop */
977   struct olsr_lq_mult *mult;
978   const struct olsr_if *ifs;
979   abuf_json_mark_object(true, true, abuf, "interfaces");
980   for (ifs = olsr_cnf->interfaces; ifs != NULL ; ifs = ifs->next) {
981     const struct interface_olsr * const rifs = ifs->interf;
982     abuf_json_mark_array_entry(true, abuf);
983     abuf_json_string(abuf, "name", ifs->name);
984
985     abuf_json_mark_object(true, true, abuf, "linkQualityMultipliers");
986     for (mult = ifs->cnf->lq_mult; mult != NULL ; mult = mult->next) {
987       abuf_json_mark_array_entry(true, abuf);
988       abuf_json_string(abuf, "route", inet_ntop(olsr_cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)));
989       abuf_json_float(abuf, "multiplier", mult->value / 65535.0);
990       abuf_json_mark_array_entry(false, abuf);
991     }
992     abuf_json_mark_object(false, true, abuf, NULL);
993
994     if (!rifs) {
995       abuf_json_string(abuf, "state", "down");
996     } else {
997       abuf_json_string(abuf, "state", "up");
998       abuf_json_string(abuf, "nameFromKernel", rifs->int_name);
999       abuf_json_int(abuf, "interfaceMode", rifs->mode);
1000       abuf_json_boolean(abuf, "emulatedHostClientInterface", rifs->is_hcif);
1001       abuf_json_boolean(abuf, "sendTcImmediately", rifs->immediate_send_tc);
1002       abuf_json_int(abuf, "fishEyeTtlIndex", rifs->ttl_index);
1003       abuf_json_int(abuf, "olsrForwardingTimeout", rifs->fwdtimer);
1004       abuf_json_int(abuf, "olsrMessageSequenceNumber", rifs->olsr_seqnum);
1005       abuf_json_int(abuf, "olsrInterfaceMetric", rifs->int_metric);
1006       abuf_json_int(abuf, "olsrMTU", rifs->int_mtu);
1007       abuf_json_int(abuf, "helloEmissionInterval", rifs->hello_etime);
1008       abuf_json_int(abuf, "helloValidityTime", me_to_reltime(rifs->valtimes.hello));
1009       abuf_json_int(abuf, "tcValidityTime", me_to_reltime(rifs->valtimes.tc));
1010       abuf_json_int(abuf, "midValidityTime", me_to_reltime(rifs->valtimes.mid));
1011       abuf_json_int(abuf, "hnaValidityTime", me_to_reltime(rifs->valtimes.hna));
1012       abuf_json_boolean(abuf, "wireless", rifs->is_wireless);
1013
1014 #ifdef __linux__
1015       abuf_json_boolean(abuf, "icmpRedirect", rifs->nic_state.redirect);
1016       abuf_json_boolean(abuf, "spoofFilter", rifs->nic_state.spoof);
1017 #endif /* __linux__ */
1018
1019       if (olsr_cnf->ip_version == AF_INET) {
1020         struct ipaddr_str addrbuf, maskbuf, bcastbuf;
1021         abuf_json_string(abuf, "ipv4Address", ip4_to_string(&addrbuf, rifs->int_addr.sin_addr));
1022         abuf_json_string(abuf, "netmask", ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr));
1023         abuf_json_string(abuf, "broadcast", ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
1024       } else {
1025         struct ipaddr_str addrbuf, maskbuf;
1026         abuf_json_string(abuf, "ipv6Address", ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr));
1027         abuf_json_string(abuf, "multicast", ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
1028       }
1029     }
1030 #ifdef __linux__
1031     snprintf(path, PATH_MAX, "/sys/class/net/%s/device/driver/module", ifs->name);
1032     linklen = readlink(path, linkpath, PATH_MAX - 1);
1033     if (linklen > 1) {
1034       linkpath[linklen] = '\0';
1035       abuf_json_string(abuf, "kernelModule", basename(linkpath));
1036     }
1037
1038     abuf_json_sys_class_net(abuf, "addressLength", ifs->name, "addr_len");
1039     abuf_json_sys_class_net(abuf, "carrier", ifs->name, "carrier");
1040     abuf_json_sys_class_net(abuf, "dormant", ifs->name, "dormant");
1041     abuf_json_sys_class_net(abuf, "features", ifs->name, "features");
1042     abuf_json_sys_class_net(abuf, "flags", ifs->name, "flags");
1043     abuf_json_sys_class_net(abuf, "linkMode", ifs->name, "link_mode");
1044     abuf_json_sys_class_net(abuf, "macAddress", ifs->name, "address");
1045     abuf_json_sys_class_net(abuf, "ethernetMTU", ifs->name, "mtu");
1046     abuf_json_sys_class_net(abuf, "operationalState", ifs->name, "operstate");
1047     abuf_json_sys_class_net(abuf, "txQueueLength", ifs->name, "tx_queue_len");
1048     abuf_json_sys_class_net(abuf, "collisions", ifs->name, "statistics/collisions");
1049     abuf_json_sys_class_net(abuf, "multicastPackets", ifs->name, "statistics/multicast");
1050     abuf_json_sys_class_net(abuf, "rxBytes", ifs->name, "statistics/rx_bytes");
1051     abuf_json_sys_class_net(abuf, "rxCompressed", ifs->name, "statistics/rx_compressed");
1052     abuf_json_sys_class_net(abuf, "rxCrcErrors", ifs->name, "statistics/rx_crc_errors");
1053     abuf_json_sys_class_net(abuf, "rxDropped", ifs->name, "statistics/rx_dropped");
1054     abuf_json_sys_class_net(abuf, "rxErrors", ifs->name, "statistics/rx_errors");
1055     abuf_json_sys_class_net(abuf, "rxFifoErrors", ifs->name, "statistics/rx_fifo_errors");
1056     abuf_json_sys_class_net(abuf, "rxFrameErrors", ifs->name, "statistics/rx_frame_errors");
1057     abuf_json_sys_class_net(abuf, "rxLengthErrors", ifs->name, "statistics/rx_length_errors");
1058     abuf_json_sys_class_net(abuf, "rxMissedErrors", ifs->name, "statistics/rx_missed_errors");
1059     abuf_json_sys_class_net(abuf, "rxOverErrors", ifs->name, "statistics/rx_over_errors");
1060     abuf_json_sys_class_net(abuf, "rxPackets", ifs->name, "statistics/rx_packets");
1061     abuf_json_sys_class_net(abuf, "txAbortedErrors", ifs->name, "statistics/tx_aborted_errors");
1062     abuf_json_sys_class_net(abuf, "txBytes", ifs->name, "statistics/tx_bytes");
1063     abuf_json_sys_class_net(abuf, "txCarrierErrors", ifs->name, "statistics/tx_carrier_errors");
1064     abuf_json_sys_class_net(abuf, "txCompressed", ifs->name, "statistics/tx_compressed");
1065     abuf_json_sys_class_net(abuf, "txDropped", ifs->name, "statistics/tx_dropped");
1066     abuf_json_sys_class_net(abuf, "txErrors", ifs->name, "statistics/tx_errors");
1067     abuf_json_sys_class_net(abuf, "txFifoErrors", ifs->name, "statistics/tx_fifo_errors");
1068     abuf_json_sys_class_net(abuf, "txHeartbeatErrors", ifs->name, "statistics/tx_heartbeat_errors");
1069     abuf_json_sys_class_net(abuf, "txPackets", ifs->name, "statistics/tx_packets");
1070     abuf_json_sys_class_net(abuf, "txWindowErrors", ifs->name, "statistics/tx_window_errors");
1071     abuf_json_sys_class_net(abuf, "beaconing", ifs->name, "wireless/beacon");
1072     abuf_json_sys_class_net(abuf, "encryptionKey", ifs->name, "wireless/crypt");
1073     abuf_json_sys_class_net(abuf, "fragmentationThreshold", ifs->name, "wireless/fragment");
1074     abuf_json_sys_class_net(abuf, "signalLevel", ifs->name, "wireless/level");
1075     abuf_json_sys_class_net(abuf, "linkQuality", ifs->name, "wireless/link");
1076     abuf_json_sys_class_net(abuf, "misc", ifs->name, "wireless/misc");
1077     abuf_json_sys_class_net(abuf, "noiseLevel", ifs->name, "wireless/noise");
1078     abuf_json_sys_class_net(abuf, "nwid", ifs->name, "wireless/nwid");
1079     abuf_json_sys_class_net(abuf, "wirelessRetries", ifs->name, "wireless/retries");
1080     abuf_json_sys_class_net(abuf, "wirelessStatus", ifs->name, "wireless/status");
1081 #endif /* __linux__ */
1082     abuf_json_mark_array_entry(false, abuf);
1083   }
1084   abuf_json_mark_object(false, true, abuf, NULL);
1085 }
1086
1087 static void info_write_data(void *foo __attribute__ ((unused))) {
1088   fd_set set;
1089   int result, i, j, max;
1090   struct timeval tv;
1091
1092   FD_ZERO(&set);
1093   max = 0;
1094   for (i = 0; i < outbuffer_count; i++) {
1095     /* And we cast here since we get a warning on Win32 */
1096     FD_SET((unsigned int )(outbuffer_socket[i]), &set);
1097
1098     if (outbuffer_socket[i] > max) {
1099       max = outbuffer_socket[i];
1100     }
1101   }
1102
1103   tv.tv_sec = 0;
1104   tv.tv_usec = 0;
1105
1106   result = select(max + 1, NULL, &set, NULL, &tv);
1107   if (result <= 0) {
1108     return;
1109   }
1110
1111   for (i = 0; i < outbuffer_count; i++) {
1112     if (FD_ISSET(outbuffer_socket[i], &set)) {
1113       result = send(outbuffer_socket[i], outbuffer[i] + outbuffer_written[i], outbuffer_size[i] - outbuffer_written[i], 0);
1114       if (result > 0) {
1115         outbuffer_written[i] += result;
1116       }
1117
1118       if (result <= 0 || outbuffer_written[i] == outbuffer_size[i]) {
1119         /* close this socket and cleanup*/
1120         close(outbuffer_socket[i]);
1121         free(outbuffer[i]);
1122
1123         for (j = i + 1; j < outbuffer_count; j++) {
1124           outbuffer[j - 1] = outbuffer[j];
1125           outbuffer_size[j - 1] = outbuffer_size[j];
1126           outbuffer_socket[j - 1] = outbuffer_socket[j];
1127           outbuffer_written[j - 1] = outbuffer_written[j];
1128         }
1129         outbuffer_count--;
1130       }
1131     }
1132   }
1133   if (!outbuffer_count) {
1134     olsr_stop_timer(writetimer_entry);
1135   }
1136 }
1137
1138 static void send_info(unsigned int send_what, int the_socket) {
1139   struct autobuf abuf;
1140
1141   const char *content_type = (send_what & SIW_ALL) ? "application/json; charset=utf-8" : "text/plain; charset=utf-8";
1142   int contentLengthPlaceholderStart = 0;
1143   int headerLength = 0;
1144
1145   /* global variables for tracking when to put a comma in for JSON */
1146   abuf_json_reset_entry_number_and_depth();
1147
1148   abuf_init(&abuf, 2 * 4096);
1149
1150   if (http_headers) {
1151     build_http_header(PLUGIN_NAME, HTTP_200, content_type, &abuf, &contentLengthPlaceholderStart);
1152     headerLength = abuf.len;
1153   }
1154
1155   // only add if normal format
1156   if (send_what & SIW_ALL) {
1157     abuf_json_mark_output(true, &abuf);
1158
1159     abuf_json_int(&abuf, "systemTime", time(NULL));
1160     abuf_json_int(&abuf, "timeSinceStartup", now_times);
1161     if (*uuid)
1162       abuf_json_string(&abuf, "uuid", uuid);
1163
1164     if (send_what & SIW_LINKS)
1165       ipc_print_links(&abuf);
1166     if (send_what & SIW_NEIGHBORS)
1167       ipc_print_neighbors(&abuf, false);
1168     if (send_what & SIW_TOPOLOGY)
1169       ipc_print_topology(&abuf);
1170     if (send_what & SIW_HNA)
1171       ipc_print_hna(&abuf);
1172     if (send_what & SIW_SGW)
1173       ipc_print_sgw(&abuf);
1174     if (send_what & SIW_MID)
1175       ipc_print_mid(&abuf);
1176     if (send_what & SIW_ROUTES)
1177       ipc_print_routes(&abuf);
1178     if (send_what & SIW_GATEWAYS)
1179       ipc_print_gateways(&abuf);
1180     if (send_what & SIW_CONFIG)
1181       ipc_print_config(&abuf);
1182     if (send_what & SIW_INTERFACES)
1183       ipc_print_interfaces(&abuf);
1184     if (send_what & SIW_2HOP)
1185       ipc_print_neighbors(&abuf, true);
1186     if (send_what & SIW_VERSION)
1187       ipc_print_version(&abuf);
1188     if (send_what & SIW_PLUGINS)
1189       ipc_print_plugins(&abuf);
1190
1191     abuf_json_mark_output(false, &abuf);
1192     abuf_puts(&abuf, "\n");
1193   } else if (send_what & SIW_OLSRD_CONF) {
1194     /* this outputs the olsrd.conf text directly, not normal format */
1195     ipc_print_olsrd_conf(&abuf);
1196   }
1197
1198   if (http_headers) {
1199     http_header_adjust_content_length(&abuf, contentLengthPlaceholderStart, abuf.len - headerLength);
1200   }
1201
1202   /* avoid a memcpy: just move the abuf.buf pointer and clear abuf */
1203   outbuffer[outbuffer_count] = abuf.buf;
1204   outbuffer_size[outbuffer_count] = abuf.len;
1205   outbuffer_written[outbuffer_count] = 0;
1206   outbuffer_socket[outbuffer_count] = the_socket;
1207   abuf.buf = NULL;
1208   abuf.len = 0;
1209   abuf.size = 0;
1210
1211   outbuffer_count++;
1212
1213   if (outbuffer_count == 1) {
1214     writetimer_entry = olsr_start_timer(100, 0, OLSR_TIMER_PERIODIC, &info_write_data, NULL, 0);
1215   }
1216
1217   abuf_free(&abuf);
1218 }
1219
1220 /*
1221  * Local Variables:
1222  * mode: c
1223  * style: linux
1224  * c-basic-offset: 2
1225  * indent-tabs-mode: nil
1226  * End:
1227  */