X-Git-Url: https://unix4lyfe.org/gitweb/darkstat-debian/blobdiff_plain/4da209d9116b41ab59eeedc5823bc2cb64b5bc3e..HEAD:/hosts_db.c diff --git a/hosts_db.c b/hosts_db.c index c2d7ae4..c1193a1 100644 --- a/hosts_db.c +++ b/hosts_db.c @@ -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 /* struct addrinfo */ +#include /* struct addrinfo */ #include #include #include @@ -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, " %'qu\n" " %'qu\n" " %'qu\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, " "); 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, " %'qu\n" "\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, " %'qu\n" "\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, " %'qu\n" "\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) { "

\n" "Last seen: "); - 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, "

\n" @@ -1087,17 +1132,26 @@ static struct str *html_hosts_detail(const char *ip) { " Out: %'qu
\n" " Total: %'qu
\n" "

\n", - h->in, h->out, h->total); + (qu)h->in, + (qu)h->out, + (qu)h->total); - str_append(buf, "

TCP ports

\n"); + str_append(buf, "

TCP ports on this host

\n"); format_table(buf, h->u.host.ports_tcp, 0,TOTAL,0); - str_append(buf, "

UDP ports

\n"); + str_append(buf, "

TCP ports on remote hosts

\n"); + format_table(buf, h->u.host.ports_tcp_remote, 0,TOTAL,0); + + str_append(buf, "

UDP ports on this host

\n"); format_table(buf, h->u.host.ports_udp, 0,TOTAL,0); + str_append(buf, "

UDP ports on remote hosts

\n"); + format_table(buf, h->u.host.ports_udp_remote, 0,TOTAL,0); + str_append(buf, "

IP protocols

\n"); format_table(buf, h->u.host.ip_protos, 0,TOTAL,0); + str_append(buf, "
\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; iin = 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; iin = 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; isize; 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: */