diff options
Diffstat (limited to 'ui/traffic_table_ui.c')
-rw-r--r-- | ui/traffic_table_ui.c | 176 |
1 files changed, 171 insertions, 5 deletions
diff --git a/ui/traffic_table_ui.c b/ui/traffic_table_ui.c index f24db5deee..03bd24d8c8 100644 --- a/ui/traffic_table_ui.c +++ b/ui/traffic_table_ui.c @@ -1,6 +1,5 @@ /* traffic_table_ui.c - * Copied from gtk/conversations_table.c 2003 Ronnie Sahlberg - * Helper routines common to all conversations taps. + * Helper routines common to conversation/endpoint tables. * * Wireshark - Network traffic analyzer * By Gerald Combs <gerald@wireshark.org> @@ -15,6 +14,14 @@ #include "traffic_table_ui.h" #include <wsutil/utf8_entities.h> +#ifdef HAVE_MAXMINDDB +#include <errno.h> + +#include "wsutil/filesystem.h" +#include "wsutil/file_util.h" +#include "wsutil/json_dumper.h" +#endif + const char *conv_column_titles[CONV_NUM_COLUMNS] = { "Address A", "Port A", @@ -53,15 +60,174 @@ const char *endp_column_titles[ENDP_NUM_GEO_COLUMNS] = { const char *endp_conn_title = "Connection"; +#ifdef HAVE_MAXMINDDB +gboolean +write_endpoint_geoip_map(FILE *fp, gboolean json_only, hostlist_talker_t *const *hosts, gchar **err_str) +{ + if (!json_only) { + char *base_html_path = get_datafile_path("ipmap.html"); + FILE *base_html_fp = ws_fopen(base_html_path, "rb"); + if (!base_html_fp) { + *err_str = g_strdup_printf("Could not open base file %s for reading: %s", + base_html_path, g_strerror(errno)); + g_free(base_html_path); + return FALSE; + } + g_free(base_html_path); + + /* Copy ipmap.html to map file. */ + size_t n; + char buf[4096]; + while ((n = fread(buf, 1, sizeof(buf), base_html_fp)) != 0) { + if (fwrite(buf, 1, n, fp) != n) { + *err_str = g_strdup_printf("Failed to write to map file: %s", g_strerror(errno)); + fclose(base_html_fp); + return FALSE; + } + } + if (ferror(base_html_fp)) { + *err_str = g_strdup_printf("Failed to read base file: %s", g_strerror(errno)); + fclose(base_html_fp); + return FALSE; + } + fclose(base_html_fp); + + fputs("<script id=\"ipmap-data\" type=\"application/json\">\n", fp); + } + + /* + * Writes a feature for each resolved address, the output will look like: + * { + * "type": "FeatureCollection", + * "features": [ + * { + * "type": "Feature", + * "geometry": { + * "type": "Point", + * "coordinates": [ -97.821999, 37.750999 ] + * }, + * "properties": { + * "ip": "8.8.4.4", + * "autonomous_system_number": 15169, + * "autonomous_system_organization": "Google LLC", + * "city": "(omitted, but key is shown for documentation reasons)", + * "country": "United States", + * "radius": 1000, + * "packets": 1, + * "bytes": 1543 + * } + * } + * ] + * } + */ + json_dumper dumper = { + .output_file = fp, + .flags = JSON_DUMPER_FLAGS_PRETTY_PRINT + }; + json_dumper_begin_object(&dumper); + json_dumper_set_member_name(&dumper, "type"); + json_dumper_value_string(&dumper, "FeatureCollection"); + json_dumper_set_member_name(&dumper, "features"); + json_dumper_begin_array(&dumper); + + /* Append map data. */ + size_t count = 0; + const hostlist_talker_t *host; + for (hostlist_talker_t *const *iter = hosts; (host = *iter) != NULL; ++iter) { + char addr[WS_INET6_ADDRSTRLEN]; + const mmdb_lookup_t *result = NULL; + if (host->myaddress.type == AT_IPv4) { + ws_in4_addr *ip4 = (ws_in4_addr *)host->myaddress.data; + result = maxmind_db_lookup_ipv4(ip4); + ws_inet_ntop4(ip4, addr, sizeof(addr)); + } else if (host->myaddress.type == AT_IPv6) { + ws_in6_addr *ip6 = (ws_in6_addr *)host->myaddress.data; + result = maxmind_db_lookup_ipv6(ip6); + ws_inet_ntop6(ip6, addr, sizeof(addr)); + } + if (!maxmind_db_has_coords(result)) { + // result could be NULL if the caller did not trigger a lookup + // before. result->found could be FALSE if no MMDB entry exists. + continue; + } + + ++count; + json_dumper_begin_object(&dumper); + + json_dumper_set_member_name(&dumper, "type"); + json_dumper_value_string(&dumper, "Feature"); + + json_dumper_set_member_name(&dumper, "geometry"); + { + json_dumper_begin_object(&dumper); + json_dumper_set_member_name(&dumper, "type"); + json_dumper_value_string(&dumper, "Point"); + json_dumper_set_member_name(&dumper, "coordinates"); + json_dumper_begin_array(&dumper); + json_dumper_value_double(&dumper, result->longitude); + json_dumper_value_double(&dumper, result->latitude); + json_dumper_end_array(&dumper); // end coordinates + } + json_dumper_end_object(&dumper); // end geometry + + json_dumper_set_member_name(&dumper, "properties"); + json_dumper_begin_object(&dumper); + { + json_dumper_set_member_name(&dumper, "ip"); + json_dumper_value_string(&dumper, addr); + if (result->as_number && result->as_org) { + json_dumper_set_member_name(&dumper, "autonomous_system_number"); + json_dumper_value_anyf(&dumper, "%u", result->as_number); + json_dumper_set_member_name(&dumper, "autonomous_system_organization"); + json_dumper_value_string(&dumper, result->as_org); + } + if (result->city) { + json_dumper_set_member_name(&dumper, "city"); + json_dumper_value_string(&dumper, result->city); + } + if (result->country) { + json_dumper_set_member_name(&dumper, "country"); + json_dumper_value_string(&dumper, result->country); + } + if (result->accuracy) { + json_dumper_set_member_name(&dumper, "radius"); + json_dumper_value_anyf(&dumper, "%u", result->accuracy); + } + json_dumper_set_member_name(&dumper, "packets"); + json_dumper_value_anyf(&dumper, "%" G_GUINT64_FORMAT, host->rx_frames + host->tx_frames); + json_dumper_set_member_name(&dumper, "bytes"); + json_dumper_value_anyf(&dumper, "%" G_GUINT64_FORMAT, host->rx_bytes + host->tx_bytes); + } + json_dumper_end_object(&dumper); // end properties + + json_dumper_end_object(&dumper); + } + + json_dumper_end_array(&dumper); // end features + json_dumper_end_object(&dumper); + json_dumper_finish(&dumper); + if (!json_only) { + fputs("</script>\n", fp); + } + + if (count == 0) { + *err_str = g_strdup("No endpoints available to map"); + return FALSE; + } + + return TRUE; +} +#endif + /* - * Editor modelines + * Editor modelines - https://www.wireshark.org/tools/modelines.html * - * Local Variables: + * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * - * ex: set shiftwidth=4 tabstop=8 expandtab: + * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */ |