3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
20 #ifndef HAVE_GETOPT_LONG
21 #include "wsutil/wsgetopt.h"
24 #include <wsutil/clopts_common.h>
25 #include <wsutil/cmdarg_err.h>
26 #include <wsutil/crash_info.h>
27 #include <wsutil/filesystem.h>
28 #include <wsutil/privileges.h>
30 #include <wsutil/plugins.h>
32 #include <wsutil/report_message.h>
33 #include <wsutil/unicode-utils.h>
34 #include <version_info.h>
36 #include <epan/addr_resolv.h>
37 #include <epan/ex-opt.h>
39 #include <epan/stat_tap_ui.h>
40 #include <epan/column.h>
41 #include <epan/disabled_protos.h>
42 #include <epan/prefs.h>
45 #include <epan/packet.h>
46 #include <epan/asn1.h>
47 #include <epan/dissectors/packet-kerberos.h>
50 #include <codecs/codecs.h>
54 /* general (not Qt specific) */
56 #include "epan/color_filters.h"
59 #include "epan/rtd_table.h"
60 #include "epan/srt_table.h"
62 #include "ui/alert_box.h"
63 #include "ui/console.h"
64 #include "ui/iface_lists.h"
65 #include "ui/language.h"
66 #include "ui/persfilepath_opt.h"
67 #include "ui/recent.h"
68 #include "ui/simple_dialog.h"
70 #include "ui/dissect_opts.h"
71 #include "ui/commandline.h"
72 #include "ui/capture_ui_utils.h"
73 #include "ui/preference_utils.h"
76 #include "ui/qt/conversation_dialog.h"
77 #include "ui/qt/utils/color_utils.h"
78 #include "ui/qt/coloring_rules_dialog.h"
79 #include "ui/qt/endpoint_dialog.h"
80 #include "ui/qt/main_window.h"
81 #include "ui/qt/response_time_delay_dialog.h"
82 #include "ui/qt/service_response_time_dialog.h"
83 #include "ui/qt/simple_dialog.h"
84 #include "ui/qt/simple_statistics_dialog.h"
85 #include "ui/qt/splash_overlay.h"
86 #include "ui/qt/wireshark_application.h"
88 #include "caputils/capture-pcap-util.h"
90 #include <QMessageBox>
93 # include "caputils/capture-wpcap.h"
94 # include "caputils/capture_wpcap_packet.h"
95 # include <tchar.h> /* Needed for Unicode */
96 # include <wsutil/file_util.h>
100 # include <caputils/airpcap.h>
101 # include <caputils/airpcap_loader.h>
102 //# include "airpcap_dlg.h"
103 //# include "airpcap_gui_utils.h"
106 #include "epan/crypt/dot11decrypt_ws.h"
108 /* Handle the addition of View menu items without request */
109 #if defined(Q_OS_MAC)
110 #include <ui/macosx/cocoa_bridge.h>
113 #include <ui/qt/utils/qt_ui_utils.h>
115 #define INVALID_OPTION 1
116 #define INIT_FAILED 2
117 #define INVALID_CAPABILITY 2
118 #define INVALID_LINK_TYPE 2
120 //#define DEBUG_STARTUP_TIME 1
123 # Console log level (for debugging)
124 # A bitmask of log levels:
133 #define DEBUG_STARTUP_TIME_LOGLEVEL 252
135 /* update the main window */
136 void main_window_update(void)
138 WiresharkApplication::processEvents();
143 /* quit the main window */
144 void main_window_quit(void)
149 #endif /* HAVE_LIBPCAP */
151 void exit_application(int status) {
159 * Report an error in command-line arguments.
160 * Creates a console on Windows.
162 // xxx copied from ../gtk/main.c
164 wireshark_cmdarg_err(const char *fmt, va_list ap)
169 fprintf(stderr, "wireshark: ");
170 vfprintf(stderr, fmt, ap);
171 fprintf(stderr, "\n");
175 * Report additional information for an error in command-line arguments.
176 * Creates a console on Windows.
177 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
178 * terminal isn't the standard error?
180 // xxx copied from ../gtk/main.c
182 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
187 vfprintf(stderr, fmt, ap);
188 fprintf(stderr, "\n");
191 // xxx based from ../gtk/main.c:get_gtk_compiled_info
193 get_wireshark_qt_compiled_info(GString *str)
195 g_string_append(str, "with ");
196 g_string_append_printf(str,
198 "Qt %s", QT_VERSION_STR);
200 "Qt (version unknown)");
203 /* Capture libraries */
204 g_string_append(str, ", ");
205 get_compiled_caplibs_version(str);
208 // xxx copied from ../gtk/main.c
210 get_gui_compiled_info(GString *str)
212 epan_get_compiled_version_info(str);
214 g_string_append(str, ", ");
215 #ifdef QT_MULTIMEDIA_LIB
216 g_string_append(str, "with QtMultimedia");
218 g_string_append(str, "without QtMultimedia");
222 g_string_append(str, ", ");
224 get_compiled_airpcap_version(str);
226 g_string_append(str, "without AirPcap");
230 codec_get_compiled_version_info(str);
233 // xxx copied from ../gtk/main.c
235 get_wireshark_runtime_info(GString *str)
238 /* Capture libraries */
239 g_string_append(str, ", ");
240 get_runtime_caplibs_version(str);
243 /* stuff used by libwireshark */
244 epan_get_runtime_version_info(str);
247 g_string_append(str, ", ");
248 get_runtime_airpcap_version(str);
253 g_log_message_handler(QtMsgType type, const QMessageLogContext &, const QString &msg)
255 GLogLevelFlags log_level = G_LOG_LEVEL_DEBUG;
261 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
263 log_level = G_LOG_LEVEL_INFO;
267 log_level = G_LOG_LEVEL_WARNING;
270 log_level = G_LOG_LEVEL_CRITICAL;
273 log_level = G_LOG_FLAG_FATAL;
276 g_log(LOG_DOMAIN_MAIN, log_level, "%s", qUtf8Printable(msg));
280 /* Check if there's something important to tell the user during startup.
281 * We want to do this *after* showing the main window so that any windows
282 * we pop up will be above the main window.
285 check_and_warn_user_startup(const QString &cf_name)
290 gchar *cur_user, *cur_group;
292 /* Tell the user not to run as root. */
293 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
294 cur_user = get_cur_username();
295 cur_group = get_cur_groupname();
296 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
297 "Running as user \"%s\" and group \"%s\".\n"
298 "This could be dangerous.\n\n"
299 "If you're running Wireshark this way in order to perform live capture, "
300 "you may want to be aware that there is a better way documented at\n"
301 "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
307 /* Warn the user if npf.sys isn't loaded. */
308 if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf) {
309 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
310 "The NPF driver isn't running. You may have trouble\n"
311 "capturing or listing interfaces.");
319 // Try to avoid library search path collisions. QCoreApplication will
320 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
321 // the application directory. If
323 // - You have Qt version 5.x.y installed in the default location
324 // (C:\Qt\5.x) on your machine.
328 // - You install Wireshark that was built on a machine with Qt version
329 // 5.x.z installed in the default location.
331 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
332 // directory. This may not be compatible with qwindows.dll from that
333 // same path on the build machine. At any rate, loading DLLs from paths
334 // you don't control is ill-advised. We work around this by removing every
335 // path except our application directory.
338 reset_library_path(void)
340 QString app_path = QDir(get_progfile_dir()).path();
341 foreach (QString path, QCoreApplication::libraryPaths()) {
342 QCoreApplication::removeLibraryPath(path);
344 QCoreApplication::addLibraryPath(app_path);
348 /* And now our feature presentation... [ fade to music ] */
349 int main(int argc, char *qt_argv[])
356 int ret_val = EXIT_SUCCESS;
357 char **argv = qt_argv;
375 gchar *err_msg = NULL;
376 GString *comp_info_str = NULL;
377 GString *runtime_info_str = NULL;
379 QString dfilter, read_filter;
381 int caps_queries = 0;
383 /* Start time in microseconds */
384 guint64 start_time = g_get_monotonic_time();
385 #ifdef DEBUG_STARTUP_TIME
386 /* At least on Windows there is a problem with the logging as the preferences is taken
387 * into account and the preferences are loaded pretty late in the startup process.
389 prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
390 prefs.gui_console_open = console_open_always;
391 #endif /* DEBUG_STARTUP_TIME */
392 cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
394 #if defined(Q_OS_MAC)
395 /* Disable automatic addition of tab menu entries in view menu */
396 CocoaBridge::cleanOSGeneratedMenuItems();
399 /* Set the C-language locale to the native environment. */
400 setlocale(LC_ALL, "");
403 // QCoreApplication clobbers argv. Let's have a local copy.
404 argv = (char **) g_malloc(sizeof(char *) * argc);
405 for (opt = 0; opt < argc; opt++) {
406 argv[opt] = qt_argv[opt];
408 arg_list_utf_16to8(argc, argv);
409 create_app_running_mutex();
413 * Get credential information for later use, and drop privileges
414 * before doing anything else.
415 * Let the user know if anything happened.
417 init_process_policies();
418 relinquish_special_privs_perm();
421 * Attempt to get the pathname of the directory containing the
424 /* init_progfile_dir_error = */ init_progfile_dir(argv[0]);
425 g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
428 ws_init_dll_search_path();
429 /* Load wpcap if possible. Do this before collecting the run-time version information */
432 /* ... and also load the packet.dll from wpcap */
436 /* Load the airpcap.dll. This must also be done before collecting
437 * run-time version information. */
440 airpcap_dll_ret_val = load_airpcap();
442 switch (airpcap_dll_ret_val) {
444 /* load the airpcap interfaces */
445 g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
447 if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
448 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
449 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
452 airpcap_if_active = NULL;
456 /* select the first ad default (THIS SHOULD BE CHANGED) */
457 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
461 * XXX - Maybe we need to warn the user if one of the following happens???
463 case AIRPCAP_DLL_OLD:
464 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
467 case AIRPCAP_DLL_ERROR:
468 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
471 case AIRPCAP_DLL_NOT_FOUND:
472 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
476 #endif /* HAVE_AIRPCAP */
479 /* Get the compile-time version information string */
480 comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
481 get_gui_compiled_info);
483 /* Assemble the run-time version information string */
484 runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
486 /* Create the user profiles directory */
487 if (create_profiles_dir(&rf_path) == -1) {
488 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
489 "Could not create profiles directory\n\"%s\"",
494 profile_store_persconffiles(TRUE);
497 /* Read the profile independent recent file. We have to do this here so we can */
498 /* set the profile before it can be set from the command line parameter */
499 if (!recent_read_static(&rf_path, &rf_open_errno)) {
500 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
501 "Could not open common recent file\n\"%s\": %s.",
502 rf_path, strerror(rf_open_errno));
506 commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
509 reset_library_path();
512 // Handle DPI scaling on Windows. This causes problems in at least
513 // one case on X11 and we don't yet support Android.
514 // We do the equivalent on macOS by setting NSHighResolutionCapable
516 // Note that this enables Windows 8.1-style Per-monitor DPI
517 // awareness but not Windows 10-style Per-monitor v2 awareness.
518 // http://doc.qt.io/qt-5/scalability.html
519 // http://doc.qt.io/qt-5/highdpi.html
520 // https://bugreports.qt.io/browse/QTBUG-53022 - The device pixel ratio is pretty much bogus on Windows.
521 // https://bugreports.qt.io/browse/QTBUG-55510 - Windows have wrong size
522 #if defined(Q_OS_WIN) && QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
523 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
526 /* Create The Wireshark app */
527 WiresharkApplication ws_app(argc, qt_argv);
529 /* initialize the funnel mini-api */
531 //initialize_funnel_ops();
533 Dot11DecryptInitContext(&dot11decrypt_ctx);
536 unsigned int in_file_type = WTAP_TYPE_AUTO;
538 /* Add it to the information to be reported on a crash. */
539 ws_add_crash_info("Wireshark %s\n"
544 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
545 g_string_free(comp_info_str, TRUE);
546 g_string_free(runtime_info_str, TRUE);
549 /* Start windows sockets */
550 result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
553 ret_val = INIT_FAILED;
558 /* Read the profile dependent (static part) of the recent file. */
559 /* Only the static part of it will be read, as we don't have the gui now to fill the */
560 /* recent lists which is done in the dynamic part. */
561 /* We have to do this already here, so command line parameters can overwrite these values. */
562 if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
563 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
564 "Could not open recent file\n\"%s\": %s.",
565 rf_path, g_strerror(rf_open_errno));
568 wsApp->applyCustomColorsFromRecent();
570 // Initialize our language
571 read_language_prefs();
572 wsApp->loadLanguage(language);
574 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
576 // Init the main window (and splash)
577 main_w = new(MainWindow);
579 // We may not need a queued connection here but it would seem to make sense
580 // to force the issue.
581 main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
582 main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
583 main_w->connect(&ws_app, SIGNAL(openCaptureOptions()),
584 main_w, SLOT(on_actionCaptureOptions_triggered()));
586 /* Init the "Open file" dialog directory */
587 /* (do this after the path settings are processed) */
588 if (recent.gui_fileopen_remembered_dir &&
589 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
590 wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
592 wsApp->setLastOpenDir(get_persdatafile_dir());
595 set_console_log_handler();
596 qInstallMessageHandler(g_log_message_handler);
597 #ifdef DEBUG_STARTUP_TIME
598 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);
602 /* Set the initial values in the capture options. This might be overwritten
603 by preference settings and then again by the command line parameters. */
604 capture_opts_init(&global_capture_opts);
607 init_report_message(vfailure_alert_box, vwarning_alert_box,
608 open_failure_alert_box, read_failure_alert_box,
609 write_failure_alert_box);
613 splash_update(RA_DISSECTORS, NULL, NULL);
614 #ifdef DEBUG_STARTUP_TIME
615 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling epan init, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
617 /* Register all dissectors; we must do this before checking for the
618 "-G" flag, as the "-G" flag dumps information registered by the
619 dissectors, and we must do it before we read the preferences, in
620 case any dissectors register preferences. */
621 if (!epan_init(splash_update, NULL, TRUE)) {
622 SimpleDialog::displayQueuedMessages(main_w);
623 ret_val = INIT_FAILED;
626 #ifdef DEBUG_STARTUP_TIME
627 /* epan_init resets the preferences */
628 prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
629 prefs.gui_console_open = console_open_always;
630 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
633 /* Register all audio codecs. */
636 // Read the dynamic part of the recent file. This determines whether or
637 // not the recent list appears in the main window so the earlier we can
638 // call this the better.
639 if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
640 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
641 "Could not open recent file\n\"%s\": %s.",
642 rf_path, g_strerror(rf_open_errno));
645 wsApp->refreshRecentCaptures();
647 splash_update(RA_LISTENERS, NULL, NULL);
648 #ifdef DEBUG_STARTUP_TIME
649 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Register all tap listeners, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
651 /* Register all tap listeners; we do this before we parse the arguments,
652 as the "-z" argument can specify a registered tap. */
654 /* we register the plugin taps before the other taps because
655 stats_tree taps plugins will be registered as tap listeners
656 by stats_tree_stat.c and need to registered before that */
658 register_all_plugin_tap_listeners();
661 /* Register all tap listeners. */
662 for (tap_reg_t *t = tap_reg_listener; t->cb_func != NULL; t++) {
665 conversation_table_set_gui_info(init_conversation_table);
666 hostlist_table_set_gui_info(init_endpoint_table);
667 srt_table_iterate_tables(register_service_response_tables, NULL);
668 rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
669 stat_tap_iterate_tables(register_simple_stat_tables, NULL);
671 if (ex_opt_count("read_format") > 0) {
672 in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
675 #ifdef DEBUG_STARTUP_TIME
676 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);
678 splash_update(RA_EXTCAP, NULL, NULL);
679 extcap_register_preferences();
680 splash_update(RA_PREFERENCES, NULL, NULL);
681 #ifdef DEBUG_STARTUP_TIME
682 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);
685 global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
687 /* Now get our args */
688 commandline_other_options(argc, argv, TRUE);
690 /* Convert some command-line parameters to QStrings */
691 if (global_commandline_info.cf_name != NULL)
692 cf_name = QString(global_commandline_info.cf_name);
693 if (global_commandline_info.rfilter != NULL)
694 read_filter = QString(global_commandline_info.rfilter);
695 if (global_commandline_info.dfilter != NULL)
696 dfilter = QString(global_commandline_info.dfilter);
698 timestamp_set_type(recent.gui_time_format);
699 timestamp_set_precision(recent.gui_time_precision);
700 timestamp_set_seconds_type (recent.gui_seconds_format);
703 #ifdef DEBUG_STARTUP_TIME
704 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling fill_in_local_interfaces, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
706 splash_update(RA_INTERFACES, NULL, NULL);
708 if (!global_commandline_info.cf_name && !prefs.capture_no_interface_load)
709 fill_in_local_interfaces(main_window_update);
711 if (global_commandline_info.list_link_layer_types)
712 caps_queries |= CAPS_QUERY_LINK_TYPES;
713 if (global_commandline_info.list_timestamp_types)
714 caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
716 if (global_commandline_info.start_capture || caps_queries) {
717 /* We're supposed to do a live capture or get a list of link-layer/timestamp
718 types for a live capture device; if the user didn't specify an
719 interface to use, pick a default. */
720 ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
721 ((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);
728 /* Get the list of link-layer types for the capture devices. */
729 if_capabilities_t *caps;
732 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
733 int if_caps_queries = caps_queries;
734 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
735 if (device->selected) {
736 #if defined(HAVE_PCAP_CREATE)
737 caps = capture_get_if_capabilities(device->name, device->monitor_mode_supported, NULL, &err_str, main_window_update);
739 caps = capture_get_if_capabilities(device->name, FALSE, NULL, &err_str,main_window_update);
742 cmdarg_err("%s", err_str);
744 ret_val = INVALID_CAPABILITY;
747 if (caps->data_link_types == NULL) {
748 cmdarg_err("The capture device \"%s\" has no data link types.", device->name);
749 ret_val = INVALID_LINK_TYPE;
755 #if defined(HAVE_PCAP_CREATE)
756 if (device->monitor_mode_supported)
757 if_caps_queries |= CAPS_MONITOR_MODE;
759 capture_opts_print_if_capabilities(caps, device->name, if_caps_queries);
763 free_if_capabilities(caps);
766 ret_val = EXIT_SUCCESS;
770 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
771 capture_opts_trim_ring_num_files(&global_capture_opts);
772 #endif /* HAVE_LIBPCAP */
774 /* Notify all registered modules that have had any of their preferences
775 changed either from one of the preferences file or from the command
776 line that their preferences have changed. */
777 #ifdef DEBUG_STARTUP_TIME
778 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);
781 prefs_to_capture_opts();
782 wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
785 if ((global_capture_opts.num_selected == 0) &&
786 (prefs.capture_device != NULL)) {
789 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
790 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
791 if (!device->hidden && strcmp(device->display_name, prefs.capture_device) == 0) {
792 device->selected = TRUE;
793 global_capture_opts.num_selected++;
801 * Enabled and disabled protocols and heuristic dissectors as per
802 * command-line options.
804 if (!setup_enabled_and_disabled_protocols()) {
805 ret_val = INVALID_OPTION;
809 build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
810 wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
811 wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
813 wsApp->setMonospaceFont(prefs.gui_qt_font_name);
815 /* For update of WindowTitle (When use gui.window_title preference) */
816 main_w->setWSWindowTitle();
818 if (!color_filters_init(&err_msg, color_filter_add_cb)) {
819 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
823 wsApp->allSystemsGo();
824 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);
825 SimpleDialog::displayQueuedMessages(main_w);
827 /* User could specify filename, or display filter, or both */
828 if (!dfilter.isEmpty())
829 main_w->filterPackets(dfilter, false);
830 if (!cf_name.isEmpty()) {
831 if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
833 /* Open stat windows; we do so after creating the main window,
834 to avoid Qt warnings, and after successfully opening the
835 capture file, so we know we have something to compute stats
836 on, and after registering all dissectors, so that MATE will
837 have registered its field array and we can have a tap filter
838 with one of MATE's late-registered fields as part of the
840 start_requested_stats();
842 if(global_commandline_info.go_to_packet != 0) {
843 /* Jump to the specified frame number, kept for backward
845 cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
846 } else if (global_commandline_info.jfilter != NULL) {
847 dfilter_t *jump_to_filter = NULL;
848 /* try to compile given filter */
849 if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
850 // Similar code in MainWindow::mergeCaptureFile().
851 QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
852 QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
853 .arg(global_commandline_info.jfilter, err_msg),
857 /* Filter ok, jump to the first packet matching the filter
858 conditions. Default search direction is forward, but if
859 option d was given, search backwards */
860 cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
867 if (global_commandline_info.start_capture) {
868 if (global_capture_opts.save_file != NULL) {
869 /* Save the directory name for future file dialogs. */
870 /* (get_dirname overwrites filename) */
871 gchar *s = g_strdup(global_capture_opts.save_file);
872 set_last_open_dir(get_dirname(s));
875 /* "-k" was specified; start a capture. */
876 check_and_warn_user_startup(cf_name);
878 /* If no user interfaces were specified on the command line,
879 copy the list of selected interfaces to the set of interfaces
880 to use for this capture. */
881 if (global_capture_opts.ifaces->len == 0)
882 collect_ifaces(&global_capture_opts);
883 CaptureFile::globalCapFile()->window = main_w;
884 if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
885 /* The capture started. Open stat windows; we do so after creating
886 the main window, to avoid GTK warnings, and after successfully
887 opening the capture file, so we know we have something to compute
888 stats on, and after registering all dissectors, so that MATE will
889 have registered its field array and we can have a tap filter with
890 one of MATE's late-registered fields as part of the filter. */
891 start_requested_stats();
894 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
895 if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
896 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
899 #endif /* HAVE_LIBPCAP */
901 // UAT files used in configuration profiles which are used in Qt dialogs
902 // are not registered during startup because they only get loaded when
903 // the dialog is shown. Register them here.
904 g_free(get_persconffile_path("io_graphs", TRUE));
906 profile_store_persconffiles(FALSE);
908 ret_val = wsApp->exec();
917 Dot11DecryptDestroyContext(&dot11decrypt_ctx);
920 /* Shutdown windows sockets */
923 /* For some unknown reason, the "atexit()" call in "create_console()"
924 doesn't arrange that "destroy_console()" be called when we exit,
925 so we call it here if a console was created. */
931 capture_opts_cleanup(&global_capture_opts);
933 col_cleanup(&CaptureFile::globalCapFile()->cinfo);
937 exit_application(ret_val);
946 * indent-tabs-mode: nil
949 * ex: set shiftwidth=4 tabstop=8 expandtab:
950 * :indentSize=4:tabSize=8:noTabs=true: