summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt74
-rw-r--r--epan/geoip_db.c6
-rw-r--r--ui/gtk/hostlist_table.c247
-rw-r--r--ui/qt/conversation_dialog.h1
-rw-r--r--ui/qt/endpoint_dialog.cpp49
-rw-r--r--ui/qt/endpoint_dialog.h16
-rw-r--r--ui/qt/traffic_table_dialog.cpp4
-rw-r--r--ui/qt/traffic_table_dialog.h2
-rw-r--r--ui/traffic_table_ui.c222
-rw-r--r--ui/traffic_table_ui.h13
10 files changed, 364 insertions, 270 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd00eed83a..d546a05b07 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1078,7 +1078,7 @@ set(LIBEPAN_LIBS
${WINSPARKLE_LIBRARIES}
)
-if( (BUILD_wireshark_gtk AND GTK_FOUND) OR (BUILD_wireshark AND QT_FOUND) )
+if( (BUILD_wireshark AND QT_FOUND) OR (BUILD_wireshark_gtk AND GTK_FOUND) )
set(WIRESHARK_SRC
capture_info.c
capture_opts.c
@@ -1095,33 +1095,6 @@ if( (BUILD_wireshark_gtk AND GTK_FOUND) OR (BUILD_wireshark AND QT_FOUND) )
)
endif()
-if(BUILD_wireshark_gtk AND GTK_FOUND)
- set(wireshark_gtk_LIBS
- gtkui
- ui
- capchild
- caputils
- ${GTK2_LIBRARIES}
- ${GTK3_LIBRARIES}
- ${GTHREAD2_LIBRARIES}
- codecs
- ${PORTAUDIO_LIBRARIES}
- ${LIBEPAN_LIBS}
- ${APPLE_APPLICATION_SERVICES_LIBRARY}
- ${APPLE_CORE_SERVICES_LIBRARY}
- ${APPLE_SYSTEM_CONFIGURATION_LIBRARY}
- ${NL_LIBRARIES}
- ${WIN_COMCTL32_LIBRARY}
- )
- # wireshark and wireshark-gtk share wireshark_FILES
-
- add_executable(wireshark-gtk ${wireshark_FILES})
- set_target_properties(wireshark-gtk PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
- set_target_properties(wireshark-gtk PROPERTIES FOLDER "Executables")
- target_link_libraries(wireshark-gtk ${wireshark_gtk_LIBS})
- install(TARGETS wireshark-gtk RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-endif()
-
if(BUILD_wireshark AND QT_FOUND)
set(wireshark_LIBS
qtui
@@ -1149,6 +1122,51 @@ if(BUILD_wireshark AND QT_FOUND)
set_target_properties(wireshark PROPERTIES FOLDER "Executables")
target_link_libraries(wireshark ${wireshark_LIBS})
install(TARGETS wireshark RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+ # Map for endpoints dialog
+ ADD_CUSTOM_COMMAND(
+ TARGET wireshark
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${PROJECT_SOURCE_DIR}/ipmap.html"
+ $<TARGET_FILE_DIR:wireshark>
+ )
+endif()
+
+if(BUILD_wireshark_gtk AND GTK_FOUND)
+ set(wireshark_gtk_LIBS
+ gtkui
+ ui
+ capchild
+ caputils
+ ${GTK2_LIBRARIES}
+ ${GTK3_LIBRARIES}
+ ${GTHREAD2_LIBRARIES}
+ codecs
+ ${PORTAUDIO_LIBRARIES}
+ ${LIBEPAN_LIBS}
+ ${APPLE_APPLICATION_SERVICES_LIBRARY}
+ ${APPLE_CORE_SERVICES_LIBRARY}
+ ${APPLE_SYSTEM_CONFIGURATION_LIBRARY}
+ ${NL_LIBRARIES}
+ ${WIN_COMCTL32_LIBRARY}
+ )
+ # wireshark and wireshark-gtk share wireshark_FILES
+
+ add_executable(wireshark-gtk ${wireshark_FILES})
+ set_target_properties(wireshark-gtk PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
+ set_target_properties(wireshark-gtk PROPERTIES FOLDER "Executables")
+ target_link_libraries(wireshark-gtk ${wireshark_gtk_LIBS})
+ install(TARGETS wireshark-gtk RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+ # Map for endpoints dialog
+ ADD_CUSTOM_COMMAND(
+ TARGET wireshark-gtk
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${PROJECT_SOURCE_DIR}/ipmap.html"
+ $<TARGET_FILE_DIR:wireshark-gtk>
+ )
endif()
register_tap_files(tshark-tap-register.c
diff --git a/epan/geoip_db.c b/epan/geoip_db.c
index 6aeba65f8a..070460ff7e 100644
--- a/epan/geoip_db.c
+++ b/epan/geoip_db.c
@@ -312,6 +312,9 @@ geoip_db_lookup_ipv4(guint dbnum, guint32 addr, const char *not_found) {
const char *raw_val, *ret = not_found;
char *val;
+ if (dbnum > geoip_db_num_dbs()) {
+ return ret;
+ }
gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
if (gi) {
switch (gi->databaseType) {
@@ -423,6 +426,9 @@ geoip_db_lookup_ipv6(guint dbnum, struct e_in6_addr addr, const char *not_found)
#if NUM_DB_TYPES > 31
GeoIPRecord *gir;
#endif
+ if (dbnum > geoip_db_num_dbs()) {
+ return ret;
+ }
memcpy(&gaddr, &addr, sizeof(addr));
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, "'", "&#39;");
- 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, "'", "&#39;");
- 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, "'", "&#39;");
- 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, "'", "&#39;");
- 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, "'", "&#39;");
+ 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, "'", "&#39;");
+ 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, "'", "&#39;");
+ 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 */