Use the host compiler for build tool c-ify.
[darkstat-debian] / hosts_db.c
index c2d7ae4..c1193a1 100644 (file)
@@ -1,5 +1,5 @@
 /* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
  *
  * hosts_db.c: database of hosts, ports, protocols.
  *
@@ -20,7 +20,7 @@
 #include "opt.h"
 #include "str.h"
 
-#include <netdb.h>     /* struct addrinfo */
+#include <netdb.h>  /* struct addrinfo */
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
@@ -91,9 +91,7 @@ static const double phi_1 =
    0.61803398874989490252573887119069695472717285156250;
 
 /* Co-prime of u, using phi^-1 */
-inline static uint32_t
-coprime(const uint32_t u)
-{
+static uint32_t coprime(const uint32_t u) {
    return ( (uint32_t)( (double)(u) * phi_1 ) | 1U );
 }
 
@@ -101,9 +99,7 @@ coprime(const uint32_t u)
  * This is the "recommended" IPv4 hash function, as seen in FreeBSD's
  * src/sys/netinet/tcp_hostcache.c 1.1
  */
-inline static uint32_t
-ipv4_hash(const struct addr *const a)
-{
+static uint32_t ipv4_hash(const struct addr *const a) {
    uint32_t ip = a->ip.v4;
    return ( (ip) ^ ((ip) >> 7) ^ ((ip) >> 17) );
 }
@@ -125,9 +121,7 @@ ipv4_hash(const struct addr *const a)
  * This is the IPv6 hash function used by FreeBSD in the same file as above,
  * svn rev 122922.
  */
-inline static uint32_t
-ipv6_hash(const struct addr *const a)
-{
+static uint32_t ipv6_hash(const struct addr *const a) {
    const struct in6_addr *const ip6 = &(a->ip.v6);
    return ( ip6->s6_addr32[0] ^ ip6->s6_addr32[1] ^
             ip6->s6_addr32[2] ^ ip6->s6_addr32[3] );
@@ -240,7 +234,9 @@ make_func_host(const void *key)
    h->last_seen_mono = 0;
    memset(&h->mac_addr, 0, sizeof(h->mac_addr));
    h->ports_tcp = NULL;
+   h->ports_tcp_remote = NULL;
    h->ports_udp = NULL;
+   h->ports_udp_remote = NULL;
    h->ip_protos = NULL;
    return (b);
 }
@@ -251,7 +247,9 @@ free_func_host(struct bucket *b)
    struct host *h = &(b->u.host);
    if (h->dns != NULL) free(h->dns);
    hashtable_free(h->ports_tcp);
+   hashtable_free(h->ports_tcp_remote);
    hashtable_free(h->ports_udp);
+   hashtable_free(h->ports_udp_remote);
    hashtable_free(h->ip_protos);
 }
 
@@ -342,21 +340,26 @@ format_row_host(struct str *buf, const struct bucket *b,
       " <td class=\"num\">%'qu</td>\n"
       " <td class=\"num\">%'qu</td>\n"
       " <td class=\"num\">%'qu</td>\n",
-      b->in, b->out, b->total);
+      (qu)b->in,
+      (qu)b->out,
+      (qu)b->total);
 
    if (opt_want_lastseen) {
-      long last = b->u.host.last_seen_mono;
+      int64_t last = b->u.host.last_seen_mono;
+      int64_t now = (int64_t)now_mono();
       struct str *last_str = NULL;
 
-      if ((now_mono() >= last) && (last > 0))
-         last_str = length_of_time(now_mono() - last);
+      if ((now >= last) && (last != 0))
+         last_str = length_of_time(now - last);
 
       str_append(buf, " <td class=\"num\">");
       if (last_str == NULL) {
          if (last == 0)
             str_append(buf, "(never)");
          else
-            str_append(buf, "(clock error)");
+            str_appendf(buf, "(clock error: last = %qd, now = %qu)",
+                        (qd)last,
+                        (qu)now);
       } else {
          str_appendstr(buf, last_str);
          str_free(last_str);
@@ -403,7 +406,12 @@ format_row_port_tcp(struct str *buf, const struct bucket *b,
       " <td class=\"num\">%'qu</td>\n"
       "</tr>\n",
       css_class,
-      p->port, getservtcp(p->port), b->in, b->out, b->total, p->syn
+      p->port,
+      getservtcp(p->port),
+      (qu)b->in,
+      (qu)b->out,
+      (qu)b->total,
+      (qu)p->syn
    );
 }
 
@@ -437,7 +445,11 @@ format_row_port_udp(struct str *buf, const struct bucket *b,
       " <td class=\"num\">%'qu</td>\n"
       "</tr>\n",
       css_class,
-      p->port, getservudp(p->port), b->in, b->out, b->total
+      p->port,
+      getservudp(p->port),
+      (qu)b->in,
+      (qu)b->out,
+      (qu)b->total
    );
 }
 
@@ -471,8 +483,11 @@ format_row_ip_proto(struct str *buf, const struct bucket *b,
       " <td class=\"num\">%'qu</td>\n"
       "</tr>\n",
       css_class,
-      p->proto, getproto(p->proto),
-      b->in, b->out, b->total
+      p->proto,
+      getproto(p->proto),
+      (qu)b->in,
+      (qu)b->out,
+      (qu)b->total
    );
 }
 
@@ -810,7 +825,6 @@ struct bucket *
 host_get_port_tcp(struct bucket *host, const uint16_t port)
 {
    struct host *h = &host->u.host;
-   assert(h != NULL);
    if (h->ports_tcp == NULL)
       h->ports_tcp = hashtable_make(PORT_BITS, opt_ports_max, opt_ports_keep,
          hash_func_short, free_func_simple, key_func_port_tcp,
@@ -819,6 +833,18 @@ host_get_port_tcp(struct bucket *host, const uint16_t port)
    return (hashtable_find_or_insert(h->ports_tcp, &port, ALLOW_REDUCE));
 }
 
+struct bucket *
+host_get_port_tcp_remote(struct bucket *host, const uint16_t port)
+{
+   struct host *h = &host->u.host;
+   if (h->ports_tcp_remote == NULL)
+      h->ports_tcp_remote = hashtable_make(
+          PORT_BITS, opt_ports_max, opt_ports_keep, hash_func_short,
+          free_func_simple, key_func_port_tcp, find_func_port_tcp,
+          make_func_port_tcp, format_cols_port_tcp, format_row_port_tcp);
+   return (hashtable_find_or_insert(h->ports_tcp_remote, &port, ALLOW_REDUCE));
+}
+
 /* ---------------------------------------------------------------------------
  * Find or create a port_udp inside a host.
  */
@@ -826,7 +852,6 @@ struct bucket *
 host_get_port_udp(struct bucket *host, const uint16_t port)
 {
    struct host *h = &host->u.host;
-   assert(h != NULL);
    if (h->ports_udp == NULL)
       h->ports_udp = hashtable_make(PORT_BITS, opt_ports_max, opt_ports_keep,
          hash_func_short, free_func_simple, key_func_port_udp,
@@ -835,6 +860,18 @@ host_get_port_udp(struct bucket *host, const uint16_t port)
    return (hashtable_find_or_insert(h->ports_udp, &port, ALLOW_REDUCE));
 }
 
+struct bucket *
+host_get_port_udp_remote(struct bucket *host, const uint16_t port)
+{
+   struct host *h = &host->u.host;
+   if (h->ports_udp_remote == NULL)
+      h->ports_udp_remote = hashtable_make(
+          PORT_BITS, opt_ports_max, opt_ports_keep, hash_func_short,
+          free_func_simple, key_func_port_udp, find_func_port_udp,
+          make_func_port_udp, format_cols_port_udp, format_row_port_udp);
+   return (hashtable_find_or_insert(h->ports_udp_remote, &port, ALLOW_REDUCE));
+}
+
 /* ---------------------------------------------------------------------------
  * Find or create an ip_proto inside a host.
  */
@@ -1027,7 +1064,7 @@ static struct str *html_hosts_detail(const char *ip) {
    struct str *buf, *ls_len;
    char ls_when[100];
    const char *canonical;
-   time_t last_real;
+   time_t last_seen_real;
 
    h = host_search(ip);
    if (h == NULL)
@@ -1065,20 +1102,28 @@ static struct str *html_hosts_detail(const char *ip) {
       "<p>\n"
       "<b>Last seen:</b> ");
 
-   last_real = mono_to_real(h->u.host.last_seen_mono);
-   if (strftime(ls_when, sizeof(ls_when),
-      "%Y-%m-%d %H:%M:%S %Z%z", localtime(&last_real)) != 0)
-         str_append(buf, ls_when);
-
-   if (h->u.host.last_seen_mono <= now_mono()) {
-      ls_len = length_of_time(now_mono() - h->u.host.last_seen_mono);
-      str_append(buf, " (");
-      str_appendstr(buf, ls_len);
-      str_free(ls_len);
-      str_append(buf, " ago)");
+   if (h->u.host.last_seen_mono == 0) {
+      str_append(buf, "(never)");
    } else {
-      str_append(buf, " (in the future, possible clock problem)");
-   }
+      last_seen_real = mono_to_real(h->u.host.last_seen_mono);
+      if (strftime(ls_when, sizeof(ls_when),
+         "%Y-%m-%d %H:%M:%S %Z%z", localtime(&last_seen_real)) != 0)
+            str_append(buf, ls_when);
+
+      if (h->u.host.last_seen_mono <= now_mono()) {
+         ls_len =
+             length_of_time((int64_t)now_mono() - h->u.host.last_seen_mono);
+         str_append(buf, " (");
+         str_appendstr(buf, ls_len);
+         str_free(ls_len);
+         str_append(buf, " ago)");
+      } else {
+         str_appendf(buf, " (in the future, possible clock problem, "
+                     "last = %qd, now = %qu)",
+                     (qd)h->u.host.last_seen_mono,
+                     (qu)now_mono());
+      }
+  }
 
    str_appendf(buf,
       "</p>\n"
@@ -1087,17 +1132,26 @@ static struct str *html_hosts_detail(const char *ip) {
       " <b>Out:</b> %'qu<br>\n"
       " <b>Total:</b> %'qu<br>\n"
       "</p>\n",
-      h->in, h->out, h->total);
+      (qu)h->in,
+      (qu)h->out,
+      (qu)h->total);
 
-   str_append(buf, "<h3>TCP ports</h3>\n");
+   str_append(buf, "<h3>TCP ports on this host</h3>\n");
    format_table(buf, h->u.host.ports_tcp, 0,TOTAL,0);
 
-   str_append(buf, "<h3>UDP ports</h3>\n");
+   str_append(buf, "<h3>TCP ports on remote hosts</h3>\n");
+   format_table(buf, h->u.host.ports_tcp_remote, 0,TOTAL,0);
+
+   str_append(buf, "<h3>UDP ports on this host</h3>\n");
    format_table(buf, h->u.host.ports_udp, 0,TOTAL,0);
 
+   str_append(buf, "<h3>UDP ports on remote hosts</h3>\n");
+   format_table(buf, h->u.host.ports_udp_remote, 0,TOTAL,0);
+
    str_append(buf, "<h3>IP protocols</h3>\n");
    format_table(buf, h->u.host.ip_protos, 0,TOTAL,0);
 
+   str_append(buf, "<br>\n");
    html_close(buf);
    return buf;
 }
@@ -1105,21 +1159,26 @@ static struct str *html_hosts_detail(const char *ip) {
 /* ---------------------------------------------------------------------------
  * Database import and export code:
  * Initially written and contributed by Ben Stewart.
- * copyright (c) 2007-2011 Ben Stewart, Emil Mikulic.
+ * copyright (c) 2007-2014 Ben Stewart, Emil Mikulic.
  */
 static int hosts_db_export_ip(const struct hashtable *h, const int fd);
-static int hosts_db_export_tcp(const struct hashtable *h, const int fd);
-static int hosts_db_export_udp(const struct hashtable *h, const int fd);
+static int hosts_db_export_tcp(const char magic, const struct hashtable *h,
+                               const int fd);
+static int hosts_db_export_udp(const char magic, const struct hashtable *h,
+                               const int fd);
 
 static const char
-   export_proto_ip  = 'P',
-   export_proto_tcp = 'T',
-   export_proto_udp = 'U';
+   export_proto_ip         = 'P',
+   export_proto_tcp        = 'T',
+   export_proto_tcp_remote = 't',
+   export_proto_udp        = 'U',
+   export_proto_udp_remote = 'u';
 
 static const unsigned char
    export_tag_host_ver1[] = {'H', 'S', 'T', 0x01},
    export_tag_host_ver2[] = {'H', 'S', 'T', 0x02},
-   export_tag_host_ver3[] = {'H', 'S', 'T', 0x03};
+   export_tag_host_ver3[] = {'H', 'S', 'T', 0x03},
+   export_tag_host_ver4[] = {'H', 'S', 'T', 0x04};
 
 /* ---------------------------------------------------------------------------
  * Load a host's ip_proto table from a file.
@@ -1153,15 +1212,16 @@ hosts_db_import_ip(const int fd, struct bucket *host)
 }
 
 /* ---------------------------------------------------------------------------
- * Load a host's port_tcp table from a file.
+ * Load a host's port_tcp{,_remote} table from a file.
  * Returns 0 on failure, 1 on success.
  */
-static int
-hosts_db_import_tcp(const int fd, struct bucket *host)
-{
+static int hosts_db_import_tcp(const int fd, const char magic,
+                               struct bucket *host,
+                               struct bucket *(get_port_fn)(struct bucket *host,
+                                                            uint16_t port)) {
    uint16_t count, i;
 
-   if (!expect8(fd, export_proto_tcp)) return 0;
+   if (!expect8(fd, magic)) return 0;
    if (!read16(fd, &count)) return 0;
 
    for (i=0; i<count; i++) {
@@ -1175,7 +1235,7 @@ hosts_db_import_tcp(const int fd, struct bucket *host)
       if (!read64(fd, &out)) return 0;
 
       /* Store data */
-      b = host_get_port_tcp(host, port);
+      b = get_port_fn(host, port);
       b->in = in;
       b->out = out;
       b->total = in + out;
@@ -1189,12 +1249,13 @@ hosts_db_import_tcp(const int fd, struct bucket *host)
  * Load a host's port_tcp table from a file.
  * Returns 0 on failure, 1 on success.
  */
-static int
-hosts_db_import_udp(const int fd, struct bucket *host)
-{
+static int hosts_db_import_udp(const int fd, const char magic,
+                               struct bucket *host,
+                               struct bucket *(get_port_fn)(struct bucket *host,
+                                                            uint16_t port)) {
    uint16_t count, i;
 
-   if (!expect8(fd, export_proto_udp)) return 0;
+   if (!expect8(fd, magic)) return 0;
    if (!read16(fd, &count)) return 0;
 
    for (i=0; i<count; i++) {
@@ -1207,7 +1268,7 @@ hosts_db_import_udp(const int fd, struct bucket *host)
       if (!read64(fd, &out)) return 0;
 
       /* Store data */
-      b = host_get_port_udp(host, port);
+      b = get_port_fn(host, port);
       b->in = in;
       b->out = out;
       b->total = in + out;
@@ -1232,7 +1293,9 @@ hosts_db_import_host(const int fd)
    int ver = 0;
 
    if (!readn(fd, hdr, sizeof(hdr))) return 0;
-   if (memcmp(hdr, export_tag_host_ver3, sizeof(hdr)) == 0)
+   if (memcmp(hdr, export_tag_host_ver4, sizeof(hdr)) == 0)
+      ver = 4;
+   else if (memcmp(hdr, export_tag_host_ver3, sizeof(hdr)) == 0)
       ver = 3;
    else if (memcmp(hdr, export_tag_host_ver2, sizeof(hdr)) == 0)
       ver = 2;
@@ -1244,7 +1307,7 @@ hosts_db_import_host(const int fd)
       return 0;
    }
 
-   if (ver == 3) {
+   if (ver >= 3) {
       if (!readaddr(fd, &a))
          return 0;
    } else {
@@ -1291,8 +1354,19 @@ hosts_db_import_host(const int fd)
 
    /* Host's port and proto subtables: */
    if (!hosts_db_import_ip(fd, host)) return 0;
-   if (!hosts_db_import_tcp(fd, host)) return 0;
-   if (!hosts_db_import_udp(fd, host)) return 0;
+   if (!hosts_db_import_tcp(fd, export_proto_tcp, host, host_get_port_tcp))
+      return 0;
+   if (!hosts_db_import_udp(fd, export_proto_udp, host, host_get_port_udp))
+      return 0;
+
+   if (ver == 4) {
+      if (!hosts_db_import_tcp(fd, export_proto_tcp_remote, host,
+                               host_get_port_tcp_remote))
+         return 0;
+      if (!hosts_db_import_udp(fd, export_proto_udp_remote, host,
+                               host_get_port_udp_remote))
+         return 0;
+   }
    return 1;
 }
 
@@ -1329,7 +1403,7 @@ int hosts_db_export(const int fd)
    for (i = 0; i<hosts_db->size; i++)
    for (b = hosts_db->table[i]; b != NULL; b = b->next) {
       /* For each host: */
-      if (!writen(fd, export_tag_host_ver3, sizeof(export_tag_host_ver3)))
+      if (!writen(fd, export_tag_host_ver4, sizeof(export_tag_host_ver4)))
          return 0;
 
       if (!writeaddr(fd, &(b->u.host.addr)))
@@ -1363,8 +1437,16 @@ int hosts_db_export(const int fd)
       if (!write64(fd, b->out)) return 0;
 
       if (!hosts_db_export_ip(b->u.host.ip_protos, fd)) return 0;
-      if (!hosts_db_export_tcp(b->u.host.ports_tcp, fd)) return 0;
-      if (!hosts_db_export_udp(b->u.host.ports_udp, fd)) return 0;
+      if (!hosts_db_export_tcp(export_proto_tcp, b->u.host.ports_tcp, fd))
+         return 0;
+      if (!hosts_db_export_udp(export_proto_udp, b->u.host.ports_udp, fd))
+         return 0;
+      if (!hosts_db_export_tcp(export_proto_tcp_remote,
+                               b->u.host.ports_tcp_remote, fd))
+         return 0;
+      if (!hosts_db_export_udp(export_proto_udp_remote,
+                               b->u.host.ports_udp_remote, fd))
+         return 0;
    }
    return 1;
 }
@@ -1407,13 +1489,13 @@ hosts_db_export_ip(const struct hashtable *h, const int fd)
  * Dump the port_tcp table of a host.
  */
 static int
-hosts_db_export_tcp(const struct hashtable *h, const int fd)
+hosts_db_export_tcp(const char magic, const struct hashtable *h, const int fd)
 {
    struct bucket *b;
    uint32_t i, written = 0;
 
    /* TCP DATA */
-   if (!write8(fd, export_proto_tcp)) return 0;
+   if (!write8(fd, magic)) return 0;
 
    /* If no data, write a count of 0 and we're done. */
    if (h == NULL) {
@@ -1440,13 +1522,13 @@ hosts_db_export_tcp(const struct hashtable *h, const int fd)
  * Dump the port_udp table of a host.
  */
 static int
-hosts_db_export_udp(const struct hashtable *h, const int fd)
+hosts_db_export_udp(const char magic, const struct hashtable *h, const int fd)
 {
    struct bucket *b;
    uint32_t i, written = 0;
 
    /* UDP DATA */
-   if (!write8(fd, export_proto_udp)) return 0;
+   if (!write8(fd, magic)) return 0;
 
    /* If no data, write a count of 0 and we're done. */
    if (h == NULL) {
@@ -1468,4 +1550,4 @@ hosts_db_export_udp(const struct hashtable *h, const int fd)
    return 1;
 }
 
-/* vim:set ts=3 sw=3 tw=78 expandtab: */
+/* vim:set ts=3 sw=3 tw=80 expandtab: */