diff options
author | Gerald Combs <gerald@wireshark.org> | 2014-09-05 11:17:17 -0700 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2014-09-17 20:04:28 +0000 |
commit | 7e638057089bb9d599cd35d4673aef70e0ae58a1 (patch) | |
tree | ce2f546bac9c6c8bcac74b0d5ba0424ddefad0ca /ui | |
parent | 478fab5206bf30a639ec9ba71edff2fb6ec2cad4 (diff) |
Qt: Add the "Map" button to the Endpoints dialog.
Move the map creation code from ui/gtk/hostlist_table.c to
ui/traffic_table_ui.c.
Add CMake commands to copy ipmap.html to the run directory so that
WIRESHARK_RUN_FROM_BUILD_DIRECTORY works for the endpoint map. Not sure
if they're entirely correct but they appear to work.
Add boundary checkes to geoip_db_lookup_ipv[46].
To do:
- It looks like there are prettier maps and newer APIs that we
might want to use.
Change-Id: Ie06992c9bc9c9aa683328aecab3f5f69c9cab966
Reviewed-on: https://code.wireshark.org/review/4011
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gtk/hostlist_table.c | 247 | ||||
-rw-r--r-- | ui/qt/conversation_dialog.h | 1 | ||||
-rw-r--r-- | ui/qt/endpoint_dialog.cpp | 49 | ||||
-rw-r--r-- | ui/qt/endpoint_dialog.h | 16 | ||||
-rw-r--r-- | ui/qt/traffic_table_dialog.cpp | 4 | ||||
-rw-r--r-- | ui/qt/traffic_table_dialog.h | 2 | ||||
-rw-r--r-- | ui/traffic_table_ui.c | 222 | ||||
-rw-r--r-- | ui/traffic_table_ui.h | 13 |
8 files changed, 312 insertions, 242 deletions
diff --git a/ui/gtk/hostlist_table.c b/ui/gtk/hostlist_table.c index 171c371769..78dfa6b52d 100644 --- a/ui/gtk/hostlist_table.c +++ b/ui/gtk/hostlist_table.c @@ -25,7 +25,6 @@ #include <string.h> #include <stdlib.h> -#include <stdio.h> #include <math.h> #include <locale.h> @@ -38,17 +37,13 @@ #include <epan/strutil.h> #ifdef HAVE_GEOIP #include <GeoIP.h> -#include <epan/geoip_db.h> -#include <wsutil/pint.h> -#include <wsutil/filesystem.h> +#include "epan/geoip_db.h" +#include "wsutil/pint.h" #endif -#include <wsutil/file_util.h> - #include "ui/simple_dialog.h" #include "ui/alert_box.h" #include "ui/utf8_entities.h" -#include "wsutil/tempfile.h" #include "ui/gtk/hostlist_table.h" #include "ui/gtk/filter_utils.h" @@ -769,243 +764,27 @@ copy_as_csv_cb(GtkWindow *copy_bt, gpointer data _U_) } #ifdef HAVE_GEOIP -typedef struct { - int nb_cols; - gint32 col_lat, col_lon, col_country, col_city, col_as_num, col_ip, col_packets, col_bytes; - FILE *out_file; - gboolean hosts_written; - hostlist_table *talkers; -} map_t; - -static const char *map_endpoint_opener; - -static void -map_init(void) -{ - map_endpoint_opener = "{\n"; -} - -/* XXX output in C locale */ -static gboolean -map_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter, - gpointer data) -{ - map_t *map = (map_t *)data; - gchar *table_entry, *esc_entry; - guint64 value; - /* Add the column values to the TSV data */ - - /* check, if we have a geolocation available for this host */ - gtk_tree_model_get(model, iter, map->col_lat, &table_entry, -1); - if (strcmp(table_entry, "-") == 0) { - g_free(table_entry); - return FALSE; - } - - gtk_tree_model_get(model, iter, map->col_lon, &table_entry, -1); - if (strcmp(table_entry, "-") == 0) { - g_free(table_entry); - return FALSE; - } - -/* -{ - 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [-122.583889, 37.898889] }, - 'properties': { 'title': 'host.example.com', 'description': 'AS: AS12345 Ewok Holdings, Inc.<br/>Country: US<br/>City: Muir Woods, CA<br/>Packets: 6<br/>Bytes: 980' } -}, - */ - - fputs(map_endpoint_opener, map->out_file); - fputs(" 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [", map->out_file); - - /* Longitude */ - gtk_tree_model_get(model, iter, map->col_lon, &table_entry, -1); - fputs(table_entry, map->out_file); - g_free(table_entry); - fputs(", ", map->out_file); - - /* Latitude */ - gtk_tree_model_get(model, iter, map->col_lat, &table_entry, -1); - fputs(table_entry, map->out_file); - g_free(table_entry); - fputs("] },\n", map->out_file); - - fputs(" 'properties': { 'title': '", map->out_file); - - /* Title */ - gtk_tree_model_get(model, iter, map->col_ip, &table_entry, -1); - esc_entry = string_replace(table_entry, "'", "'"); - fputs(esc_entry, map->out_file); - g_free(table_entry); - g_free(esc_entry); - fputs("', 'description': '", map->out_file); - - /* Description */ - if (map->col_as_num >= 0) { - gtk_tree_model_get(model, iter, map->col_as_num, &table_entry, -1); - fputs("AS: ", map->out_file); - esc_entry = string_replace(table_entry, "'", "'"); - fputs(esc_entry, map->out_file); - g_free(table_entry); - g_free(esc_entry); - fputs("<br/>", map->out_file); - } - - if (map->col_country >= 0) { - gtk_tree_model_get(model, iter, map->col_country, &table_entry, -1); - fputs("Country: ", map->out_file); - esc_entry = string_replace(table_entry, "'", "'"); - fputs(esc_entry, map->out_file); - g_free(table_entry); - g_free(esc_entry); - fputs("<br/>", map->out_file); - } - - if (map->col_country >= 0) { - gtk_tree_model_get(model, iter, map->col_city, &table_entry, -1); - fputs("City: ", map->out_file); - esc_entry = string_replace(table_entry, "'", "'"); - fputs(esc_entry, map->out_file); - g_free(table_entry); - g_free(esc_entry); - fputs("<br/>", map->out_file); - } - - gtk_tree_model_get(model, iter, map->col_packets, &value, -1); - fprintf(map->out_file, "Packets: %" G_GINT64_MODIFIER "u<br/>", value); - - gtk_tree_model_get(model, iter, map->col_bytes, &value, -1); - fprintf(map->out_file, "Bytes: %" G_GINT64_MODIFIER "u", value); - - /* XXX - we could add specific icons, e.g. depending on the amount of packets or bytes */ - - fputs("' }\n", map->out_file); - fputs("}", map->out_file); - map_endpoint_opener = ",\n{\n"; - - map->hosts_written = TRUE; - - return FALSE; -} -#define MAX_TPL_LINE_LEN 4096 static void open_as_map_cb(GtkWindow *copy_bt, gpointer data _U_) { - guint32 i; - gchar *file_uri; - gboolean uri_open; - char *map_path, *map_filename; - char *tpl_filename; - char *tpl_line; - GList *columns, *list; - GtkTreeViewColumn *column; - GtkListStore *store; - map_t map; - FILE *tpl_file; - - map.talkers = (hostlist_table *)g_object_get_data(G_OBJECT(copy_bt), HOST_PTR_KEY); - if (!map.talkers) - return; - - map.col_lat = map.col_lon = map.col_country = map.col_city = map.col_as_num = map.col_ip = map.col_packets = map.col_bytes = -1; - map.hosts_written = FALSE; - /* Find the interesting columns */ - columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(map.talkers->table)); - list = columns; - map.nb_cols = 0; - while(columns) { - column = (GtkTreeViewColumn *)columns->data; - i = gtk_tree_view_column_get_sort_column_id(column); - if(strcmp(map.talkers->default_titles[i], "Latitude") == 0) { - map.col_lat = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "Longitude") == 0) { - map.col_lon = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "Country") == 0) { - map.col_country = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "City") == 0) { - map.col_city = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "AS Number") == 0) { - map.col_as_num = i; - } - if(strcmp(map.talkers->default_titles[i], "Address") == 0) { - map.col_ip = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "Packets") == 0) { - map.col_packets = i; - map.nb_cols++; - } - if(strcmp(map.talkers->default_titles[i], "Bytes") == 0) { - map.col_bytes = i; - map.nb_cols++; - } - columns = g_list_next(columns); - } - g_list_free(list); + gchar *err_str; + gchar *file_uri; + gboolean uri_open; + hostlist_table *talkers; + gchar *map_filename; - /* check for the minimum required data */ - if(map.col_lat == -1 || map.col_lon == -1) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Latitude/Longitude data not available (GeoIP installed?)"); - return; - } - /* Create a location map HTML file from a template */ - /* XXX - add error handling */ - tpl_filename = get_datafile_path("ipmap.html"); - tpl_file = ws_fopen(tpl_filename, "r"); - if(tpl_file == NULL) { - open_failure_alert_box(tpl_filename, errno, FALSE); - g_free(tpl_filename); + talkers = (hostlist_table *)g_object_get_data(G_OBJECT(copy_bt), HOST_PTR_KEY); + if (!talkers) { return; } - g_free(tpl_filename); - - /* We should probably create a file with a temporary name and a .html extension instead */ - if (! create_tempdir(&map_path, "Wireshark IP Map ")) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "Could not create temporary directory\n%s", - map_path); - fclose(tpl_file); - return; - } - - map_filename = g_strdup_printf("%s%cipmap.html", map_path, G_DIR_SEPARATOR); - map.out_file = ws_fopen(map_filename, "w"); - if(map.out_file == NULL) { - open_failure_alert_box(map_filename, errno, TRUE); - g_free(map_filename); - fclose(tpl_file); - return; - } - - store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(map.talkers->table))); - tpl_line = (char *)g_malloc(MAX_TPL_LINE_LEN); - - while (fgets(tpl_line, MAX_TPL_LINE_LEN, tpl_file) != NULL) { - fputs(tpl_line, map.out_file); - /* MUST match ipmap.html */ - if (strstr(tpl_line, "// Start endpoint list")) { - map_init(); - gtk_tree_model_foreach(GTK_TREE_MODEL(store), map_handle, &map); - } - } - g_free(tpl_line); - fclose(tpl_file); - fclose(map.out_file); + map_filename = create_endpoint_geoip_map(talkers->hash.conv_array, &err_str); - if(!map.hosts_written) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No latitude/longitude data found"); - g_free(map_filename); + if (!map_filename) { + simple_error_message_box("%s", err_str); + g_free(err_str); return; } diff --git a/ui/qt/conversation_dialog.h b/ui/qt/conversation_dialog.h index cfff90e9ee..e32e1e3c91 100644 --- a/ui/qt/conversation_dialog.h +++ b/ui/qt/conversation_dialog.h @@ -68,7 +68,6 @@ signals: void openTcpStreamGraph(int graph_type); private: - QList<QAction> conv_actions_; QPushButton *follow_bt_; QPushButton *graph_bt_; diff --git a/ui/qt/endpoint_dialog.cpp b/ui/qt/endpoint_dialog.cpp index 9855c11566..d6a2934964 100644 --- a/ui/qt/endpoint_dialog.cpp +++ b/ui/qt/endpoint_dialog.cpp @@ -36,12 +36,22 @@ #include "wireshark_application.h" +#include <QDesktopServices> #include <QMessageBox> +#include <QUrl> const QString table_name_ = QObject::tr("Endpoint"); EndpointDialog::EndpointDialog(QWidget *parent, capture_file *cf, int cli_proto_id, const char *filter) : TrafficTableDialog(parent, cf, filter, table_name_) { +#ifdef HAVE_GEOIP + map_bt_ = buttonBox()->addButton(tr("Map"), QDialogButtonBox::ActionRole); + map_bt_->setToolTip(tr("Draw IPv4 or IPv6 endpoints on a map.")); + connect(map_bt_, SIGNAL(clicked()), this, SLOT(createMap())); + + connect(trafficTableTabWidget(), SIGNAL(currentChanged(int)), this, SLOT(tabChanged())); +#endif + QList<int> endp_protos; for (GList *endp_tab = recent.endpoint_tabs; endp_tab; endp_tab = endp_tab->next) { int proto_id = proto_get_id_by_short_name((const char *)endp_tab->data); @@ -67,7 +77,7 @@ EndpointDialog::EndpointDialog(QWidget *parent, capture_file *cf, int cli_proto_ fillTypeMenu(endp_protos); - updateWidgets(); + tabChanged(); itemSelectionChanged(); if (cap_file_) { @@ -154,9 +164,37 @@ bool EndpointDialog::addTrafficTable(register_ct_t *table) g_string_free(error_string, TRUE); } +#ifdef HAVE_GEOIP + connect(endp_tree, SIGNAL(geoIPStatusChanged()), this, SLOT(tabChanged())); +#endif return true; } +#ifdef HAVE_GEOIP +void EndpointDialog::tabChanged() +{ + EndpointTreeWidget *cur_tree = qobject_cast<EndpointTreeWidget *>(trafficTableTabWidget()->currentWidget()); + map_bt_->setEnabled(cur_tree->hasGeoIPData()); +} +#endif + +void EndpointDialog::createMap() +{ + EndpointTreeWidget *cur_tree = qobject_cast<EndpointTreeWidget *>(trafficTableTabWidget()->currentWidget()); + if (!cur_tree) { + return; + } + + gchar *err_str; + gchar *map_path = create_endpoint_geoip_map(cur_tree->trafficTreeHash()->conv_array, &err_str); + if (!map_path) { + QMessageBox::warning(this, "Map file error", err_str); + g_free(err_str); + return; + } + QDesktopServices::openUrl(QUrl::fromLocalFile(gchar_free_to_qstring(map_path))); +} + void EndpointDialog::on_buttonBox_helpRequested() { wsApp->helpTopicAction(HELP_STATS_ENDPOINTS_DIALOG); @@ -280,12 +318,12 @@ public: } qulonglong ullval = text(col).toULongLong(&ok); - if (ok) { // Assume lat / lon + if (ok) { // Assume uint return ullval; } qlonglong llval = text(col).toLongLong(&ok); - if (ok) { // Assume lat / lon + if (ok) { // Assume int return llval; } @@ -360,6 +398,9 @@ public: EndpointTreeWidget::EndpointTreeWidget(QWidget *parent, register_ct_t *table) : TrafficTableTreeWidget(parent, table) +#ifdef HAVE_GEOIP + , has_geoip_data_(false) +#endif { setColumnCount(ENDP_NUM_COLUMNS); @@ -496,6 +537,8 @@ void EndpointTreeWidget::updateItems() for (unsigned i = 0; i < geoip_db_num_dbs(); i++) { showColumn(ENDP_NUM_COLUMNS + i); } + has_geoip_data_ = true; + emit geoIPStatusChanged(); } } #endif diff --git a/ui/qt/endpoint_dialog.h b/ui/qt/endpoint_dialog.h index b97cb53486..da54dd0f40 100644 --- a/ui/qt/endpoint_dialog.h +++ b/ui/qt/endpoint_dialog.h @@ -33,6 +33,10 @@ public: explicit EndpointTreeWidget(QWidget *parent, register_ct_t* table); ~EndpointTreeWidget(); +#ifdef HAVE_GEOIP + bool hasGeoIPData() const { return has_geoip_data_; } +#endif + static void tapReset(void *conv_hash_ptr); static void tapDraw(void *conv_hash_ptr); @@ -40,8 +44,12 @@ public: public: const QList<int> columnToDb(int column) const { return col_to_db_.value(column, QList<int>()); } +signals: + void geoIPStatusChanged(); + private: QMap<int, QList<int> > col_to_db_; // Map tree columns to GeoIP databases + bool has_geoip_data_; #endif private slots: @@ -69,11 +77,17 @@ public slots: void setCaptureFile(capture_file *cf); private: - QList<QAction> endp_actions_; +#ifdef HAVE_GEOIP + QPushButton *map_bt_; +#endif bool addTrafficTable(register_ct_t* table); private slots: +#ifdef HAVE_GEOIP + void tabChanged(); +#endif + void createMap(); void on_buttonBox_helpRequested(); }; diff --git a/ui/qt/traffic_table_dialog.cpp b/ui/qt/traffic_table_dialog.cpp index ac59560b8e..561c46f228 100644 --- a/ui/qt/traffic_table_dialog.cpp +++ b/ui/qt/traffic_table_dialog.cpp @@ -112,7 +112,7 @@ void TrafficTableDialog::fillTypeMenu(QList<int> &enabled_protos) endp_action->setData(qVariantFromValue(proto_id)); endp_action->setCheckable(true); endp_action->setChecked(enabled_protos.contains(proto_id)); - connect(endp_action, SIGNAL(triggered()), this, SLOT(toggleConversation())); + connect(endp_action, SIGNAL(triggered()), this, SLOT(toggleTable())); traffic_type_menu_.addAction(endp_action); } } @@ -177,7 +177,7 @@ void TrafficTableDialog::setTabText(QWidget *tree, const QString &text) } } -void TrafficTableDialog::toggleConversation() +void TrafficTableDialog::toggleTable() { QAction *ca = qobject_cast<QAction *>(QObject::sender()); if (!ca) { diff --git a/ui/qt/traffic_table_dialog.h b/ui/qt/traffic_table_dialog.h index 9c1bde51cf..601498d8b0 100644 --- a/ui/qt/traffic_table_dialog.h +++ b/ui/qt/traffic_table_dialog.h @@ -145,7 +145,7 @@ private slots: void on_nameResolutionCheckBox_toggled(bool checked); void on_displayFilterCheckBox_toggled(bool checked); void setTabText(QWidget *tree, const QString &text); - void toggleConversation(); + void toggleTable(); void copyAsCsv(); void copyAsYaml(); diff --git a/ui/traffic_table_ui.c b/ui/traffic_table_ui.c index 464ec621f5..c6c65b73d5 100644 --- a/ui/traffic_table_ui.c +++ b/ui/traffic_table_ui.c @@ -22,9 +22,30 @@ */ #include "config.h" +#include <glib.h> + #include "traffic_table_ui.h" #include "utf8_entities.h" +#ifdef HAVE_GEOIP +#include <GeoIP.h> +#include "epan/address.h" +#include "epan/addr_resolv.h" +#include "epan/geoip_db.h" +#include "epan/strutil.h" +#include "wsutil/pint.h" +#include "wsutil/str_util.h" + +#include "epan/packet_info.h" +#include "epan/conversation_table.h" + +#include <errno.h> +#include <stdio.h> +#include "wsutil/filesystem.h" +#include "wsutil/file_util.h" +#include "wsutil/tempfile.h" +#endif + const char *conv_column_titles[CONV_NUM_COLUMNS] = { "Address A", "Port A", @@ -58,6 +79,207 @@ const char *endp_column_titles[ENDP_NUM_COLUMNS] = { const char *endp_conn_title = "Connection"; +#ifdef HAVE_GEOIP +#define MAX_TPL_LINE_LEN 4096 +gchar * +create_endpoint_geoip_map(const GArray *endp_array, gchar **err_str) { + char *tpl_filename, *tpl_line; + FILE *tpl_file, *out_file; + char *map_path; + gchar *map_filename = NULL; + guint i; + GString *tpl_entry; + gchar *esc_entry; + int db_lon, db_lat, db_country4, db_country6, db_city4, db_city6, db_asn4, db_asn6; + guint cur_db; + const char *map_endpoint_opener = "{\n"; + + db_lon = db_lat = db_country4 = db_country6 = db_city4 = db_city6 = db_asn4 = db_asn6 = -1; + + /* Create a location map HTML file from a template */ + /* XXX - add error handling */ + tpl_filename = get_datafile_path("ipmap.html"); + tpl_file = ws_fopen(tpl_filename, "r"); + if(tpl_file == NULL) { + if (err_str) { + GString *err_descr = g_string_new(""); + g_string_printf(err_descr, file_open_error_message(errno, FALSE), tpl_filename); + *err_str = g_string_free(err_descr, FALSE); + } + g_free(tpl_filename); + return NULL; + } + g_free(tpl_filename); + +#if 1 + /* We should probably create a file with a temporary name and a .html extension instead */ + if (! create_tempdir(&map_path, "Wireshark IP Map ")) { + if (err_str) { + GString *err_descr = g_string_new(""); + g_string_printf(err_descr, "Could not create temporary directory\n%s", + map_path); + *err_str = g_string_free(err_descr, FALSE); + } + fclose(tpl_file); + return NULL; + } +#else + /* Debugging only */ + map_path = "/tmp"; +#endif + + map_filename = g_strdup_printf("%s%cipmap.html", map_path, G_DIR_SEPARATOR); + out_file = ws_fopen(map_filename, "w"); + if(out_file == NULL) { + if (err_str) { + GString *err_descr = g_string_new(""); + g_string_printf(err_descr, file_open_error_message(errno, FALSE), map_filename); + *err_str = g_string_free(err_descr, FALSE); + } + g_free(map_filename); + fclose(tpl_file); + return NULL; + } + + tpl_line = (char *)g_malloc(MAX_TPL_LINE_LEN); + + while (fgets(tpl_line, MAX_TPL_LINE_LEN, tpl_file) != NULL) { + fputs(tpl_line, out_file); + /* MUST match ipmap.html */ + if (strstr(tpl_line, "// Start endpoint list")) { + break; + } + } + + for (cur_db = 0; cur_db < geoip_db_num_dbs(); cur_db++) { + switch (geoip_db_type(cur_db)) { + case WS_LON_FAKE_EDITION: + db_lon = cur_db; + break; + case WS_LAT_FAKE_EDITION: + db_lat = cur_db; + break; + case GEOIP_COUNTRY_EDITION: + db_country4 = cur_db; + break; + case GEOIP_COUNTRY_EDITION_V6: + db_country6 = cur_db; + break; + case GEOIP_CITY_EDITION_REV0: + case GEOIP_CITY_EDITION_REV1: + db_city4 = cur_db; + break; + case GEOIP_CITY_EDITION_REV0_V6: + case GEOIP_CITY_EDITION_REV1_V6: + db_city6 = cur_db; + break; + } + } + + if(db_lon < 0 || db_lat < 0) { + if (err_str) { + *err_str = g_strdup("Unable to open GeoIP database"); + } + g_free(map_filename); + fclose(tpl_file); + return NULL; + } + + /* Fill in our map data */ + tpl_entry = g_string_new(""); + + for (i = 0; i < endp_array->len; i++) { + const char *lat, *lon, *country, *city, *asn; + hostlist_talker_t *endp_item = &g_array_index(endp_array, hostlist_talker_t, i); + + if (endp_item->myaddress.type == AT_IPv4) { + lon = geoip_db_lookup_ipv4(db_lon, pntoh32(endp_item->myaddress.data), NULL); + lat = geoip_db_lookup_ipv4(db_lat, pntoh32(endp_item->myaddress.data), NULL); + country = geoip_db_lookup_ipv4(db_country4, pntoh32(endp_item->myaddress.data), "-"); + city = geoip_db_lookup_ipv4(db_city4, pntoh32(endp_item->myaddress.data), "-"); + asn = geoip_db_lookup_ipv4(db_asn4, pntoh32(endp_item->myaddress.data), "-"); + } else if (endp_item->myaddress.type == AT_IPv6) { + const struct e_in6_addr *addr = (const struct e_in6_addr *) endp_item->myaddress.data; + lon = geoip_db_lookup_ipv6(db_lon, *addr, NULL); + lat = geoip_db_lookup_ipv6(db_lat, *addr, NULL); + country = geoip_db_lookup_ipv6(db_country6, *addr, "-"); + city = geoip_db_lookup_ipv6(db_city6, *addr, "-"); + asn = geoip_db_lookup_ipv6(db_asn6, *addr, "-"); + } else { + continue; + } + + /* + { + 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [-122.583889, 37.898889] }, + 'properties': { 'title': 'host.example.com', 'description': 'AS: AS12345 Ewok Holdings, Inc.<br/>Country: US<br/>City: Muir Woods, CA<br/>Packets: 6<br/>Bytes: 980' } + }, + */ + + if (lon && lat) { + g_string_printf(tpl_entry, "%s", map_endpoint_opener); + + /* Longitude + latitude */ + g_string_append_printf(tpl_entry, " 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [%s, %s] },\n", lon, lat); + + /* Address */ + g_string_append_printf(tpl_entry, " 'properties': { 'title': '%s', ", ep_address_to_display(&endp_item->myaddress)); + + /* Description */ + + /* City */ + esc_entry = string_replace(city, "'", "'"); + g_string_append_printf(tpl_entry, "'description': '<div class=\"geoip_property\">City: %s</div>", esc_entry); + g_free(esc_entry); + + /* Country */ + esc_entry = string_replace(country, "'", "'"); + g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Country: %s</div>", esc_entry); + g_free(esc_entry); + + /* Packets */ + esc_entry = format_size(endp_item->tx_frames + endp_item->rx_frames, + (format_size_flags_e)(format_size_unit_none|format_size_prefix_si)); + g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Packets: %s</div>", esc_entry); + g_free(esc_entry); + + /* Bytes */ + esc_entry = format_size(endp_item->tx_bytes + endp_item->rx_bytes, + (format_size_flags_e)(format_size_unit_none|format_size_prefix_si)); + g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Bytes: %s</div>", esc_entry); + g_free(esc_entry); + + /* ASN */ + esc_entry = string_replace(asn, "'", "'"); + g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">AS Number: %s</div>", esc_entry); + g_free(esc_entry); + + /* XXX - We could add specific icons, e.g. depending on the amount of packets or bytes */ + g_string_append(tpl_entry, "' }\n"); + g_string_append(tpl_entry, "}"); + + fputs(tpl_entry->str, out_file); + map_endpoint_opener = ",\n{\n"; + } + + /* XXX Display an error if we we have no entries */ + + } + + while (fgets(tpl_line, MAX_TPL_LINE_LEN, tpl_file) != NULL) { + fputs(tpl_line, out_file); + } + g_free(tpl_line); + + fclose(tpl_file); + fclose(out_file); + + return map_filename; + + +} +#endif + /* * Editor modelines * diff --git a/ui/traffic_table_ui.h b/ui/traffic_table_ui.h index 9f3bd061ba..3edf13b0fd 100644 --- a/ui/traffic_table_ui.h +++ b/ui/traffic_table_ui.h @@ -72,6 +72,19 @@ extern const char *endp_column_titles[ENDP_NUM_COLUMNS]; extern const char *endp_conn_title; +#ifdef HAVE_GEOIP +/** Create an HTML file containing a map showing the geograpical + * locations of IPv4 and IPv6 addresses. The map is named "ipmap.html". + * + * @param [in] endp_array GArray of hostlist_talker_t structs. + * @param [in,out] err_str Set to error string on failure. Error string must + * be g_freed. May be NULL. + * @return Path of the map file if it was successfully written or NULL + * on failure. The path must be g_freed. + */ +gchar *create_endpoint_geoip_map(const GArray *endp_array, gchar **err_str); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ |