aboutsummaryrefslogtreecommitdiffstats
path: root/ui/traffic_table_ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui/traffic_table_ui.c')
-rw-r--r--ui/traffic_table_ui.c176
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:
*/