json_info: do not loop forever on smart gateway egress interfaces
[olsrd.git] / lib / jsoninfo / src / olsrd_jsoninfo.c
index 551739b..f143b2a 100644 (file)
@@ -53,7 +53,7 @@
 #include <sys/socket.h>
 #ifndef _WIN32
 #include <sys/select.h>
-#endif
+#endif /* _WIN32 */
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <sys/time.h>
@@ -69,7 +69,7 @@
 
 #ifdef __linux__
 #include <fcntl.h>
-#endif
+#endif /* __linux__ */
 
 #include "ipcalc.h"
 #include "olsr.h"
@@ -91,7 +91,7 @@
 
 #ifdef _WIN32
 #define close(x) closesocket(x)
-#endif
+#endif /* _WIN32 */
 
 static int ipc_socket;
 
@@ -157,7 +157,7 @@ static size_t outbuffer_written[MAX_CLIENTS];
 static int outbuffer_socket[MAX_CLIENTS];
 static int outbuffer_count;
 
-char uuid[UUIDLEN];
+char uuid[UUIDLEN + 1];
 char uuidfile[FILENAME_MAX];
 
 static struct timeval start_time;
@@ -354,13 +354,13 @@ plugin_ipc_init(void)
   if ((ipc_socket = socket(olsr_cnf->ip_version, SOCK_STREAM, 0)) == -1) {
 #ifndef NODEBUG
     olsr_printf(1, "(JSONINFO) socket()=%s\n", strerror(errno));
-#endif
+#endif /* NODEBUG */
     return 0;
   } else {
     if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
 #ifndef NODEBUG
       olsr_printf(1, "(JSONINFO) setsockopt()=%s\n", strerror(errno));
-#endif
+#endif /* NODEBUG */
       return 0;
     }
 #if (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE
@@ -368,7 +368,7 @@ plugin_ipc_init(void)
       perror("SO_REUSEADDR failed");
       return 0;
     }
-#endif
+#endif /* (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE */
     /* Bind the socket */
 
     /* complete the socket structure */
@@ -378,7 +378,7 @@ plugin_ipc_init(void)
       addrlen = sizeof(struct sockaddr_in);
 #ifdef SIN6_LEN
       sst.in4.sin_len = addrlen;
-#endif
+#endif /* SIN6_LEN */
       sst.in4.sin_addr.s_addr = jsoninfo_listen_ip.v4.s_addr;
       sst.in4.sin_port = htons(ipc_port);
     } else {
@@ -386,7 +386,7 @@ plugin_ipc_init(void)
       addrlen = sizeof(struct sockaddr_in6);
 #ifdef SIN6_LEN
       sst.in6.sin6_len = addrlen;
-#endif
+#endif /* SIN6_LEN */
       sst.in6.sin6_addr = jsoninfo_listen_ip.v6;
       sst.in6.sin6_port = htons(ipc_port);
     }
@@ -395,7 +395,7 @@ plugin_ipc_init(void)
     if (bind(ipc_socket, &sst.in, addrlen) == -1) {
 #ifndef NODEBUG
       olsr_printf(1, "(JSONINFO) bind()=%s\n", strerror(errno));
-#endif
+#endif /* NODEBUG */
       return 0;
     }
 
@@ -403,7 +403,7 @@ plugin_ipc_init(void)
     if (listen(ipc_socket, 1) == -1) {
 #ifndef NODEBUG
       olsr_printf(1, "(JSONINFO) listen()=%s\n", strerror(errno));
-#endif
+#endif /* NODEBUG */
       return 0;
     }
 
@@ -412,7 +412,7 @@ plugin_ipc_init(void)
 
 #ifndef NODEBUG
     olsr_printf(2, "(JSONINFO) listening on port %d\n", ipc_port);
-#endif
+#endif /* NODEBUG */
   }
   return 1;
 }
@@ -422,8 +422,10 @@ read_uuid_from_file(const char *file)
 {
   FILE *f;
   char* end;
+  int r = 0;
+  size_t chars;
 
-  *uuid = 0;
+  memset(uuid, 0, sizeof(uuid));
 
   f = fopen(file, "r");
   olsr_printf(1, "(JSONINFO) Reading UUID from '%s'\n", file);
@@ -432,21 +434,23 @@ read_uuid_from_file(const char *file)
                 file, strerror(errno));
     return -1;
   }
-  if (fread(uuid, 1, UUIDLEN, f) > 0) {
-    fclose(f);
+  chars = fread(uuid, 1, UUIDLEN, f);
+  if (chars > 0) {
+    uuid[chars] = '\0'; /* null-terminate the string */
+
     /* we only use the first line of the file */
     end = strchr(uuid, '\n');
     if(end)
       *end = 0;
-    return 0;
+    r = 0;
   } else {
     olsr_printf(1, "(JSONINFO) Could not read UUID from '%s': %s\n",
                 file, strerror(errno));
-    return -1;
+    r = -1;
   }
 
   fclose(f);
-  return 1;
+  return r;
 }
 
 static void
@@ -465,7 +469,7 @@ ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __att
   if ((ipc_connection = accept(fd, &pin.in, &addrlen)) == -1) {
 #ifndef NODEBUG
     olsr_printf(1, "(JSONINFO) accept()=%s\n", strerror(errno));
-#endif
+#endif /* NODEBUG */
     return;
   }
 
@@ -476,13 +480,13 @@ ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __att
     if (!ip4equal(&pin.in4.sin_addr, &jsoninfo_accept_ip.v4) && jsoninfo_accept_ip.v4.s_addr != INADDR_ANY) {
 #ifdef JSONINFO_ALLOW_LOCALHOST
       if (pin.in4.sin_addr.s_addr != INADDR_LOOPBACK) {
-#endif
+#endif /* JSONINFO_ALLOW_LOCALHOST */
         olsr_printf(1, "(JSONINFO) From host(%s) not allowed!\n", addr);
         close(ipc_connection);
         return;
 #ifdef JSONINFO_ALLOW_LOCALHOST
       }
-#endif
+#endif /* JSONINFO_ALLOW_LOCALHOST */
     }
   } else {
     if (inet_ntop(olsr_cnf->ip_version, &pin.in6.sin6_addr, addr, INET6_ADDRSTRLEN) == NULL)
@@ -497,7 +501,7 @@ ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __att
 
 #ifndef NODEBUG
   olsr_printf(2, "(JSONINFO) Connect from %s\n", addr);
-#endif
+#endif /* NODEBUG */
 
   /* purge read buffer to prevent blocking on linux */
   FD_ZERO(&rfds);
@@ -630,7 +634,7 @@ ipc_print_routes(struct autobuf *abuf)
       abuf_json_int(abuf, "rtpMetricCost", ROUTE_COST_BROKEN);
     else
       abuf_json_int(abuf, "rtpMetricCost", rt->rt_best->rtp_metric.cost);
-    abuf_json_string(abuf, "interface",
+    abuf_json_string(abuf, "networkInterface",
                      if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
     abuf_json_close_array_entry(abuf);
   }
@@ -753,9 +757,9 @@ ipc_print_mid(struct autobuf *abuf)
 static void
 ipc_print_gateways(struct autobuf *abuf)
 {
-#ifndef linux
+#ifndef __linux__
   abuf_json_string(abuf, "error", "Gateway mode is only supported in Linux");
-#else
+#else /* __linux__ */
 
   struct ipaddr_str buf;
   struct gateway_entry *gw;
@@ -771,15 +775,15 @@ ipc_print_gateways(struct autobuf *abuf)
       continue;
     }
 
-    if (gw == olsr_get_ipv4_inet_gateway(&autoV4)) {
-      v4 = autoV4 ? "auto" : "s";
+    if (gw == olsr_get_inet_gateway(false)) {
+      v4 = "s";
     } else if (gw->ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit)
                && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat)) {
       v4 = "u";
     }
 
-    if (gw == olsr_get_ipv6_inet_gateway(&autoV6)) {
-      v6 = autoV6 ? "auto" : "s";
+    if (gw == olsr_get_inet_gateway(true)) {
+      v6 = "s";
     } else if (gw->ipv6 && olsr_cnf->ip_version == AF_INET6) {
       v6 = "u";
     }
@@ -814,7 +818,7 @@ ipc_print_gateways(struct autobuf *abuf)
   }
   OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
   abuf_json_close_array(abuf);
-#endif
+#endif /* __linux__ */
 }
 
 
@@ -940,6 +944,7 @@ ipc_print_config(struct autobuf *abuf)
   }
   abuf_json_close_array(abuf);
 
+
   abuf_json_int(abuf, "totalIpcConnectionsAllowed", olsr_cnf->ipc_connections);
   abuf_json_open_array(abuf, "ipcAllowedAddresses");
   if (olsr_cnf->ipc_connections) {
@@ -978,8 +983,30 @@ ipc_print_config(struct autobuf *abuf)
   abuf_json_string(abuf, "lockFile", olsr_cnf->lock_file);
   abuf_json_boolean(abuf, "useNiit", olsr_cnf->use_niit);
 
+#ifdef __linux__
   abuf_json_boolean(abuf, "smartGateway", olsr_cnf->smart_gw_active);
   if (olsr_cnf->smart_gw_active) {
+    abuf_json_boolean(abuf, "smartGatewayAlwaysRemoveServerTunnel", olsr_cnf->smart_gw_always_remove_server_tunnel);
+    abuf_json_int(abuf, "smartGatewayUseCount", olsr_cnf->smart_gw_use_count);
+    abuf_json_string(abuf, "smartGatewayPolicyRoutingScript", olsr_cnf->smart_gw_policyrouting_script);
+    {
+      struct autobuf egressbuf;
+      struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
+
+      abuf_init(&egressbuf, (olsr_cnf->smart_gw_egress_interfaces_count * IFNAMSIZ) /* interface names */
+          + (olsr_cnf->smart_gw_egress_interfaces_count - 1) /* commas */);
+      while (egressif) {
+        if (egressbuf.len) {
+          abuf_puts(&egressbuf, ",");
+        }
+        abuf_appendf(&egressbuf, "%s", egressif->name);
+        egressif = egressif->next;
+      }
+      abuf_json_string(abuf, "smartGatewayEgressInterfaces", egressbuf.buf);
+      abuf_free(&egressbuf);
+    }
+    abuf_json_int(abuf, "smartGatewayMarkOffsetEgress", olsr_cnf->smart_gw_mark_offset_egress);
+    abuf_json_int(abuf, "smartGatewayMarkOffsetTunnels", olsr_cnf->smart_gw_mark_offset_tunnels);
     abuf_json_boolean(abuf, "smartGatewayAllowNat", olsr_cnf->smart_gw_allow_nat);
     abuf_json_boolean(abuf, "smartGatewayUplinkNat", olsr_cnf->smart_gw_uplink_nat);
     abuf_json_int(abuf, "smartGatewayPeriod", olsr_cnf->smart_gw_period);
@@ -992,6 +1019,7 @@ ipc_print_config(struct autobuf *abuf)
                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->smart_gw_prefix.prefix));
     abuf_json_int(abuf, "smartGatewayPrefixLength", olsr_cnf->smart_gw_prefix.prefix_len);
   }
+#endif /* __linux__ */
 
   abuf_json_string(abuf, "mainIpAddress",
                    olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
@@ -1020,11 +1048,11 @@ ipc_print_config(struct autobuf *abuf)
 #ifdef __linux__
   abuf_json_int(abuf, "routeNetlinkSocket", olsr_cnf->rtnl_s);
   abuf_json_int(abuf, "routeMonitorSocket", olsr_cnf->rt_monitor_socket);
-#endif
+#endif /* __linux__ */
 
 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
   abuf_json_int(abuf, "routeChangeSocket", olsr_cnf->rts);
-#endif
+#endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
   abuf_json_float(abuf, "linkQualityNatThreshold", olsr_cnf->lq_nat_thresh);
 
   abuf_json_string(abuf, "olsrdVersion", olsrd_version);
@@ -1045,9 +1073,9 @@ ipc_print_config(struct autobuf *abuf)
   abuf_json_string(abuf, "os", "OpenBSD");
 #elif defined __FreeBSD__ || defined __FreeBSD_kernel__
   abuf_json_string(abuf, "os", "FreeBSD");
-#else
+#else /* OS detection */
   abuf_json_string(abuf, "os", "Undefined");
-#endif
+#endif /* OS detection */
 
   abuf_json_int(abuf, "startTime", start_time.tv_sec);
 
@@ -1060,7 +1088,7 @@ ipc_print_interfaces(struct autobuf *abuf)
 #ifdef __linux__
   int linklen;
   char path[PATH_MAX], linkpath[PATH_MAX];
-#endif
+#endif /* __linux__ */
   char ipv6_buf[INET6_ADDRSTRLEN];                  /* buffer for IPv6 inet_htop */
   struct olsr_lq_mult *mult;
   const struct olsr_if *ifs;
@@ -1069,13 +1097,6 @@ ipc_print_interfaces(struct autobuf *abuf)
     const struct interface *const rifs = ifs->interf;
     abuf_json_open_array_entry(abuf);
     abuf_json_string(abuf, "name", ifs->name);
-    abuf_json_string(abuf, "nameFromKernel", ifs->interf->int_name);
-    abuf_json_int(abuf, "interfaceMode", ifs->interf->mode);
-    abuf_json_boolean(abuf, "emulatedHostClientInterface", ifs->interf->is_hcif);
-    abuf_json_boolean(abuf, "sendTcImmediately", ifs->interf->immediate_send_tc);
-    abuf_json_int(abuf, "fishEyeTtlIndex", ifs->interf->ttl_index);
-    abuf_json_int(abuf, "olsrForwardingTimeout", ifs->interf->fwdtimer);
-    abuf_json_int(abuf, "olsrMessageSequenceNumber", ifs->interf->olsr_seqnum);
 
     abuf_json_open_array(abuf, "linkQualityMultipliers");
     for (mult = ifs->cnf->lq_mult; mult != NULL; mult = mult->next) {
@@ -1091,6 +1112,13 @@ ipc_print_interfaces(struct autobuf *abuf)
       abuf_json_string(abuf, "state", "down");
     } else {
       abuf_json_string(abuf, "state", "up");
+      abuf_json_string(abuf, "nameFromKernel", rifs->int_name);
+      abuf_json_int(abuf, "interfaceMode", rifs->mode);
+      abuf_json_boolean(abuf, "emulatedHostClientInterface", rifs->is_hcif);
+      abuf_json_boolean(abuf, "sendTcImmediately", rifs->immediate_send_tc);
+      abuf_json_int(abuf, "fishEyeTtlIndex", rifs->ttl_index);
+      abuf_json_int(abuf, "olsrForwardingTimeout", rifs->fwdtimer);
+      abuf_json_int(abuf, "olsrMessageSequenceNumber", rifs->olsr_seqnum);
       abuf_json_int(abuf, "olsrInterfaceMetric", rifs->int_metric);
       abuf_json_int(abuf, "olsrMTU", rifs->int_mtu);
       abuf_json_int(abuf, "helloEmissionInterval", rifs->hello_etime);
@@ -1100,6 +1128,11 @@ ipc_print_interfaces(struct autobuf *abuf)
       abuf_json_int(abuf, "hnaValidityTime", rifs->valtimes.hna);
       abuf_json_boolean(abuf, "wireless", rifs->is_wireless);
 
+#ifdef __linux__
+      abuf_json_boolean(abuf, "icmpRedirect", rifs->nic_state.redirect);
+      abuf_json_boolean(abuf, "spoofFilter", rifs->nic_state.spoof);
+#endif /* __linux__ */
+
       if (olsr_cnf->ip_version == AF_INET) {
         struct ipaddr_str addrbuf, maskbuf, bcastbuf;
         abuf_json_string(abuf, "ipv4Address",
@@ -1117,12 +1150,9 @@ ipc_print_interfaces(struct autobuf *abuf)
       }
     }
 #ifdef __linux__
-    abuf_json_boolean(abuf, "icmpRedirect", rifs->nic_state.redirect);
-    abuf_json_boolean(abuf, "spoofFilter", rifs->nic_state.spoof);
-
     snprintf(path, PATH_MAX, "/sys/class/net/%s/device/driver/module", ifs->name);
     linklen = readlink(path, linkpath, PATH_MAX - 1);
-    if (linkpath != NULL && linklen > 1) {
+    if (linklen > 1) {
       linkpath[linklen] = '\0';
       abuf_json_string(abuf, "kernelModule", basename(linkpath));
     }
@@ -1170,7 +1200,7 @@ ipc_print_interfaces(struct autobuf *abuf)
     abuf_json_sys_class_net(abuf, "nwid", ifs->name, "wireless/nwid");
     abuf_json_sys_class_net(abuf, "wirelessRetries", ifs->name, "wireless/retries");
     abuf_json_sys_class_net(abuf, "wirelessStatus", ifs->name, "wireless/status");
-#endif
+#endif /* __linux__ */
     abuf_json_close_array_entry(abuf);
   }
   abuf_json_close_array(abuf);
@@ -1265,13 +1295,13 @@ send_info(unsigned int send_what, int the_socket)
   if ((send_what & SIW_CONFIG) == SIW_CONFIG) {
     if (send_what != SIW_CONFIG) abuf_puts(&abuf, ",");
     ipc_print_config(&abuf);
-    //if (send_what != SIW_CONFIG) abuf_puts(&abuf, ",");
   }
   if ((send_what & SIW_PLUGINS) == SIW_PLUGINS) ipc_print_plugins(&abuf);
 
   /* output overarching meta data last so we can use abuf_json_* functions, they add a comma at the beginning */
   if (send_what & SIW_ALL) {
     abuf_json_int(&abuf, "systemTime", time(NULL));
+    abuf_json_int(&abuf, "timeSinceStartup", now_times);
     if(*uuid != 0)
       abuf_json_string(&abuf, "uuid", uuid);
     abuf_puts(&abuf, "}\n");