* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config.h>
#include <glib.h>
-#ifdef Q_OS_UNIX
-#include <signal.h>
-#endif
-
#include <locale.h>
#ifdef HAVE_GETOPT_H
#ifdef HAVE_PLUGINS
#include <wsutil/plugins.h>
#endif
-#include <wsutil/report_err.h>
+#include <wsutil/report_message.h>
#include <wsutil/unicode-utils.h>
-#include <ws_version_info.h>
+#include <version_info.h>
#include <epan/addr_resolv.h>
#include <epan/ex-opt.h>
#include <codecs/codecs.h>
-#ifdef HAVE_EXTCAP
#include <extcap.h>
-#endif
/* general (not Qt specific) */
#include "file.h"
#include "ui/dissect_opts.h"
#include "ui/commandline.h"
#include "ui/capture_ui_utils.h"
+#include "ui/preference_utils.h"
+#include "ui/taps.h"
#include "ui/qt/conversation_dialog.h"
-#include "ui/qt/color_utils.h"
+#include "ui/qt/utils/color_utils.h"
#include "ui/qt/coloring_rules_dialog.h"
#include "ui/qt/endpoint_dialog.h"
#include "ui/qt/main_window.h"
#include "caputils/capture-pcap-util.h"
+#include <QMessageBox>
+
#ifdef _WIN32
# include "caputils/capture-wpcap.h"
# include "caputils/capture_wpcap_packet.h"
//# include "airpcap_gui_utils.h"
#endif
-#include "epan/crypt/airpdcap_ws.h"
+#include "epan/crypt/dot11decrypt_ws.h"
-#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
-#include <QTextCodec>
+/* Handle the addition of View menu items without request */
+#if defined(Q_OS_MAC)
+#include <ui/macosx/cocoa_bridge.h>
#endif
+#include <ui/qt/utils/qt_ui_utils.h>
+
+#define INVALID_OPTION 1
+#define INIT_FAILED 2
+#define INVALID_CAPABILITY 2
+#define INVALID_LINK_TYPE 2
+
//#define DEBUG_STARTUP_TIME 1
/*
# Log level
#ifdef HAVE_LIBPCAP
-/* quit a nested main window */
-void main_window_nested_quit(void)
-{
-// if (gtk_main_level() > 0)
- wsApp->quit();
-}
-
/* quit the main window */
void main_window_quit(void)
{
#endif /* HAVE_LIBPCAP */
+void exit_application(int status) {
+ if (wsApp) {
+ wsApp->quit();
+ }
+ exit(status);
+}
+
/*
* Report an error in command-line arguments.
* Creates a console on Windows.
g_string_append(str, "without QtMultimedia");
#endif
+#ifdef _WIN32
g_string_append(str, ", ");
#ifdef HAVE_AIRPCAP
get_compiled_airpcap_version(str);
#else
g_string_append(str, "without AirPcap");
#endif
+#endif /* _WIN32 */
codec_get_compiled_version_info(str);
}
#endif
}
+static void
+g_log_message_handler(QtMsgType type, const QMessageLogContext &, const QString &msg)
+{
+ GLogLevelFlags log_level = G_LOG_LEVEL_DEBUG;
+
+ switch (type) {
+ case QtDebugMsg:
+ default:
+ break;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
+ case QtInfoMsg:
+ log_level = G_LOG_LEVEL_INFO;
+ break;
+#endif
+ case QtWarningMsg:
+ log_level = G_LOG_LEVEL_WARNING;
+ break;
+ case QtCriticalMsg:
+ log_level = G_LOG_LEVEL_CRITICAL;
+ break;
+ case QtFatalMsg:
+ log_level = G_LOG_FLAG_FATAL;
+ break;
+ }
+ g_log(LOG_DOMAIN_MAIN, log_level, "%s", qUtf8Printable(msg));
+}
+
#ifdef HAVE_LIBPCAP
/* Check if there's something important to tell the user during startup.
* We want to do this *after* showing the main window so that any windows
#ifdef _WIN32
int opt;
#endif
- int ret_val;
+ int ret_val = EXIT_SUCCESS;
char **argv = qt_argv;
#ifdef _WIN32
+ int result;
WSADATA wsaData;
#endif /* _WIN32 */
char *rf_path;
int rf_open_errno;
- char *gdp_path, *dp_path;
#ifdef HAVE_LIBPCAP
gchar *err_str;
- int status;
#else
#ifdef _WIN32
#ifdef HAVE_AIRPCAP
#endif
#endif
#endif
+ gchar *err_msg = NULL;
GString *comp_info_str = NULL;
GString *runtime_info_str = NULL;
QString dfilter, read_filter;
- /* Start time in microseconds*/
+#ifdef HAVE_LIBPCAP
+ int caps_queries = 0;
+#endif
+ /* Start time in microseconds */
guint64 start_time = g_get_monotonic_time();
#ifdef DEBUG_STARTUP_TIME
- /* At least on Windows there is a problem with the loging as the preferences is taken
+ /* At least on Windows there is a problem with the logging as the preferences is taken
* into account and the preferences are loaded pretty late in the startup process.
*/
prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
#endif /* DEBUG_STARTUP_TIME */
cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
- // In Qt 5, C strings are treated always as UTF-8 when converted to
- // QStrings; in Qt 4, the codec must be set to make that happen
-#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
- // Hopefully we won't have to use QString::fromUtf8() in as many places.
- QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
- QTextCodec::setCodecForCStrings(utf8codec);
- // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
- QTextCodec::setCodecForTr(utf8codec);
+#if defined(Q_OS_MAC)
+ /* Disable automatic addition of tab menu entries in view menu */
+ CocoaBridge::cleanOSGeneratedMenuItems();
#endif
/* Set the C-language locale to the native environment. */
* Attempt to get the pathname of the directory containing the
* executable file.
*/
- /* init_progfile_dir_error = */ init_progfile_dir(argv[0],
- (int (*)(int, char **)) get_gui_compiled_info);
+ /* init_progfile_dir_error = */ init_progfile_dir(argv[0]);
g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
#ifdef _WIN32
/* Assemble the run-time version information string */
runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
+ /* Create the user profiles directory */
+ if (create_profiles_dir(&rf_path) == -1) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not create profiles directory\n\"%s\"",
+ rf_path);
+ g_free (rf_path);
+ }
+
profile_store_persconffiles(TRUE);
+ recent_init();
/* Read the profile independent recent file. We have to do this here so we can */
/* set the profile before it can be set from the command line parameter */
reset_library_path();
#endif
+ // Handle DPI scaling on Windows. This causes problems in at least
+ // one case on X11 and we don't yet support Android.
+ // We do the equivalent on macOS by setting NSHighResolutionCapable
+ // in Info.plist.
+ // Note that this enables Windows 8.1-style Per-monitor DPI
+ // awareness but not Windows 10-style Per-monitor v2 awareness.
+ // http://doc.qt.io/qt-5/scalability.html
+ // http://doc.qt.io/qt-5/highdpi.html
+ // https://bugreports.qt.io/browse/QTBUG-53022 - The device pixel ratio is pretty much bogus on Windows.
+ // https://bugreports.qt.io/browse/QTBUG-55510 - Windows have wrong size
+#if defined(Q_OS_WIN) && QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+
/* Create The Wireshark app */
WiresharkApplication ws_app(argc, qt_argv);
// xxx qtshark
//initialize_funnel_ops();
- AirPDcapInitContext(&airpdcap_ctx);
+ Dot11DecryptInitContext(&dot11decrypt_ctx);
QString cf_name;
unsigned int in_file_type = WTAP_TYPE_AUTO;
#ifdef _WIN32
/* Start windows sockets */
- WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
+ result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
+ if (result != 0)
+ {
+ ret_val = INIT_FAILED;
+ goto clean_exit;
+ }
#endif /* _WIN32 */
/* Read the profile dependent (static part) of the recent file. */
wsApp->setLastOpenDir(get_persdatafile_dir());
}
-#ifdef Q_OS_UNIX
- // Replicates behavior in gtk_init();
- signal(SIGPIPE, SIG_IGN);
-#endif
-
set_console_log_handler();
+ qInstallMessageHandler(g_log_message_handler);
#ifdef DEBUG_STARTUP_TIME
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "set_console_log_handler, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
capture_opts_init(&global_capture_opts);
#endif
- init_report_err(vfailure_alert_box, open_failure_alert_box,
- read_failure_alert_box, write_failure_alert_box);
-
- wtap_init();
-
-#ifdef HAVE_PLUGINS
- /* Register all the plugin types we have. */
- epan_register_plugin_types(); /* Types known to libwireshark */
- codec_register_plugin_types(); /* Types known to libwscodecs */
+ init_report_message(vfailure_alert_box, vwarning_alert_box,
+ open_failure_alert_box, read_failure_alert_box,
+ write_failure_alert_box);
- /* Scan for plugins. This does *not* call their registration routines;
- that's done later. */
- scan_plugins(REPORT_LOAD_FAILURE);
-
- /* Register all libwiretap plugin modules. */
- register_all_wiretap_modules();
-#endif
-
- /* Register all audio codec plugins. */
- register_all_codecs();
+ wtap_init(TRUE);
splash_update(RA_DISSECTORS, NULL, NULL);
#ifdef DEBUG_STARTUP_TIME
if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
splash_update, NULL)) {
SimpleDialog::displayQueuedMessages(main_w);
- return 2;
+ ret_val = INIT_FAILED;
+ goto clean_exit;
}
#ifdef DEBUG_STARTUP_TIME
/* epan_init resets the preferences */
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
+ /* Register all audio codecs. */
+ codecs_init();
+
// Read the dynamic part of the recent file. This determines whether or
// not the recent list appears in the main window so the earlier we can
// call this the better.
rf_path, g_strerror(rf_open_errno));
g_free(rf_path);
}
+ wsApp->refreshRecentCaptures();
splash_update(RA_LISTENERS, NULL, NULL);
#ifdef DEBUG_STARTUP_TIME
register_all_plugin_tap_listeners();
#endif
- register_all_tap_listeners();
+ /* Register all tap listeners. */
+ for (tap_reg_t *t = tap_reg_listener; t->cb_func != NULL; t++) {
+ t->cb_func();
+ }
conversation_table_set_gui_info(init_conversation_table);
hostlist_table_set_gui_info(init_endpoint_table);
srt_table_iterate_tables(register_service_response_tables, NULL);
rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
- new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
+ stat_tap_iterate_tables(register_simple_stat_tables, NULL);
if (ex_opt_count("read_format") > 0) {
in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
}
-#ifdef HAVE_EXTCAP
#ifdef DEBUG_STARTUP_TIME
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
splash_update(RA_EXTCAP, NULL, NULL);
extcap_register_preferences();
-#endif
splash_update(RA_PREFERENCES, NULL, NULL);
+#ifdef DEBUG_STARTUP_TIME
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling module preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
- global_commandline_info.prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
+ global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
/* Now get our args */
commandline_other_options(argc, argv, TRUE);
if (global_commandline_info.dfilter != NULL)
dfilter = QString(global_commandline_info.dfilter);
- /* Removed thread code:
- * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
- */
-
timestamp_set_type(recent.gui_time_format);
timestamp_set_precision(recent.gui_time_precision);
timestamp_set_seconds_type (recent.gui_seconds_format);
fill_in_local_interfaces(main_window_update);
- if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
- /* We're supposed to do a live capture or get a list of link-layer
+ if (global_commandline_info.list_link_layer_types)
+ caps_queries |= CAPS_QUERY_LINK_TYPES;
+ if (global_commandline_info.list_timestamp_types)
+ caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
+
+ if (global_commandline_info.start_capture || caps_queries) {
+ /* We're supposed to do a live capture or get a list of link-layer/timestamp
types for a live capture device; if the user didn't specify an
interface to use, pick a default. */
- status = capture_opts_default_iface_if_necessary(&global_capture_opts,
+ ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
((global_commandline_info.prefs_p->capture_device) && (*global_commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(global_commandline_info.prefs_p->capture_device) : NULL);
- if (status != 0) {
- exit(status);
+ if (ret_val != 0) {
+ goto clean_exit;
}
}
- if (global_commandline_info.list_link_layer_types) {
+ if (caps_queries) {
/* Get the list of link-layer types for the capture devices. */
if_capabilities_t *caps;
guint i;
- interface_t device;
+ interface_t *device;
for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
-
- device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
- if (device.selected) {
+ int if_caps_queries = caps_queries;
+ device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+ if (device->selected) {
#if defined(HAVE_PCAP_CREATE)
- caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
+ caps = capture_get_if_capabilities(device->name, device->monitor_mode_supported, NULL, &err_str, main_window_update);
#else
- caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
+ caps = capture_get_if_capabilities(device->name, FALSE, NULL, &err_str,main_window_update);
#endif
if (caps == NULL) {
cmdarg_err("%s", err_str);
g_free(err_str);
- exit(2);
+ ret_val = INVALID_CAPABILITY;
+ goto clean_exit;
}
if (caps->data_link_types == NULL) {
- cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
- exit(2);
+ cmdarg_err("The capture device \"%s\" has no data link types.", device->name);
+ ret_val = INVALID_LINK_TYPE;
+ goto clean_exit;
}
#ifdef _WIN32
create_console();
#endif /* _WIN32 */
#if defined(HAVE_PCAP_CREATE)
- capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
-#else
- capture_opts_print_if_capabilities(caps, device.name, FALSE);
+ if (device->monitor_mode_supported)
+ if_caps_queries |= CAPS_MONITOR_MODE;
#endif
+ capture_opts_print_if_capabilities(caps, device->name, if_caps_queries);
#ifdef _WIN32
destroy_console();
#endif /* _WIN32 */
free_if_capabilities(caps);
}
}
- exit(0);
+ ret_val = EXIT_SUCCESS;
+ goto clean_exit;
}
capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
capture_opts_trim_ring_num_files(&global_capture_opts);
#endif /* HAVE_LIBPCAP */
-
/* Notify all registered modules that have had any of their preferences
changed either from one of the preferences file or from the command
line that their preferences have changed. */
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling prefs_apply_all, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
prefs_apply_all();
+ prefs_to_capture_opts();
wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
#ifdef HAVE_LIBPCAP
if ((global_capture_opts.num_selected == 0) &&
(prefs.capture_device != NULL)) {
guint i;
- interface_t device;
+ interface_t *device;
for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
- device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
- if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
- device.selected = TRUE;
+ device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+ if (!device->hidden && strcmp(device->display_name, prefs.capture_device) == 0) {
+ device->selected = TRUE;
global_capture_opts.num_selected++;
- global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
- g_array_insert_val(global_capture_opts.all_ifaces, i, device);
break;
}
}
}
#endif
- /* disabled protocols as per configuration file */
- if (gdp_path == NULL && dp_path == NULL) {
- set_disabled_protos_list();
- set_enabled_protos_list();
- set_disabled_heur_dissector_list();
- }
-
- if(global_dissect_options.disable_protocol_slist) {
- GSList *proto_disable;
- for (proto_disable = global_dissect_options.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
- {
- proto_disable_proto_by_name((char*)proto_disable->data);
- }
- }
-
- if(global_dissect_options.enable_protocol_slist) {
- GSList *proto_enable;
- for (proto_enable = global_dissect_options.enable_protocol_slist; proto_enable != NULL; proto_enable = g_slist_next(proto_enable))
- {
- proto_enable_proto_by_name((char*)proto_enable->data);
- }
- }
-
- if(global_dissect_options.enable_heur_slist) {
- GSList *heur_enable;
- for (heur_enable = global_dissect_options.enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
- {
- proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
- }
- }
-
- if(global_dissect_options.disable_heur_slist) {
- GSList *heur_disable;
- for (heur_disable = global_dissect_options.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
- {
- proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
- }
+ /*
+ * Enabled and disabled protocols and heuristic dissectors as per
+ * command-line options.
+ */
+ if (!setup_enabled_and_disabled_protocols()) {
+ ret_val = INVALID_OPTION;
+ goto clean_exit;
}
build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
/* For update of WindowTitle (When use gui.window_title preference) */
main_w->setWSWindowTitle();
-////////
-
- packet_list_enable_color(recent.packet_list_colorize);
-
- g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
- packet_list_enable_color(TRUE);
-
-////////
-
-////////
- gchar* err_msg = NULL;
if (!color_filters_init(&err_msg, color_filter_add_cb)) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
g_free(err_msg);
}
-////////
-
-#ifdef HAVE_LIBPCAP
- /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
- if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
- global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
- }
-#else /* HAVE_LIBPCAP */
- ////////
-#endif /* HAVE_LIBPCAP */
-
wsApp->allSystemsGo();
- g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go, elapsed time %" G_GUINT64_FORMAT "us \n", g_get_monotonic_time() - start_time);
+ g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go, elapsed time %.3fs\n", (float) (g_get_monotonic_time() - start_time) / 1000000);
SimpleDialog::displayQueuedMessages(main_w);
/* User could specify filename, or display filter, or both */
g_free(s);
}
/* "-k" was specified; start a capture. */
-// show_main_window(FALSE);
check_and_warn_user_startup(cf_name);
/* If no user interfaces were specified on the command line,
start_requested_stats();
}
}
- /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
+ /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
}
}
#endif /* HAVE_LIBPCAP */
+ // UAT files used in configuration profiles which are used in Qt dialogs
+ // are not registered during startup because they only get loaded when
+ // the dialog is shown. Register them here.
+ g_free(get_persconffile_path("io_graphs", TRUE));
+
profile_store_persconffiles(FALSE);
ret_val = wsApp->exec();
+ wsApp = NULL;
+ delete main_w;
+ recent_cleanup();
epan_cleanup();
-#ifdef HAVE_EXTCAP
extcap_cleanup();
-#endif
- AirPDcapDestroyContext(&airpdcap_ctx);
+ Dot11DecryptDestroyContext(&dot11decrypt_ctx);
#ifdef _WIN32
/* Shutdown windows sockets */
destroy_console();
#endif /* _WIN32 */
- return ret_val;
+clean_exit:
+#ifdef HAVE_LIBPCAP
+ capture_opts_cleanup(&global_capture_opts);
+#endif
+ col_cleanup(&CaptureFile::globalCapFile()->cinfo);
+ codecs_cleanup();
+ wtap_cleanup();
+ free_progdirs();
+ exit_application(ret_val);
}
/*