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>
97 # include <wsutil/os_version_info.h>
101 # include <caputils/airpcap.h>
102 # include <caputils/airpcap_loader.h>
103 //# include "airpcap_dlg.h"
104 //# include "airpcap_gui_utils.h"
107 #include "epan/crypt/dot11decrypt_ws.h"
109 /* Handle the addition of View menu items without request */
110 #if defined(Q_OS_MAC)
111 #include <ui/macosx/cocoa_bridge.h>
114 #include <ui/qt/utils/qt_ui_utils.h>
116 #define INVALID_OPTION 1
117 #define INIT_FAILED 2
118 #define INVALID_CAPABILITY 2
119 #define INVALID_LINK_TYPE 2
121 //#define DEBUG_STARTUP_TIME 1
124 # Console log level (for debugging)
125 # A bitmask of log levels:
134 #define DEBUG_STARTUP_TIME_LOGLEVEL 252
136 /* update the main window */
137 void main_window_update(void)
139 WiresharkApplication::processEvents();
144 /* quit the main window */
145 void main_window_quit(void)
150 #endif /* HAVE_LIBPCAP */
152 void exit_application(int status) {
160 * Report an error in command-line arguments.
161 * Creates a console on Windows.
163 // xxx copied from ../gtk/main.c
165 wireshark_cmdarg_err(const char *fmt, va_list ap)
170 fprintf(stderr, "wireshark: ");
171 vfprintf(stderr, fmt, ap);
172 fprintf(stderr, "\n");
176 * Report additional information for an error in command-line arguments.
177 * Creates a console on Windows.
178 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
179 * terminal isn't the standard error?
181 // xxx copied from ../gtk/main.c
183 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
188 vfprintf(stderr, fmt, ap);
189 fprintf(stderr, "\n");
192 // xxx based from ../gtk/main.c:get_gtk_compiled_info
194 get_wireshark_qt_compiled_info(GString *str)
196 g_string_append(str, "with ");
197 g_string_append_printf(str,
199 "Qt %s", QT_VERSION_STR);
201 "Qt (version unknown)");
204 /* Capture libraries */
205 g_string_append(str, ", ");
206 get_compiled_caplibs_version(str);
209 // xxx copied from ../gtk/main.c
211 get_gui_compiled_info(GString *str)
213 epan_get_compiled_version_info(str);
215 g_string_append(str, ", ");
216 #ifdef QT_MULTIMEDIA_LIB
217 g_string_append(str, "with QtMultimedia");
219 g_string_append(str, "without QtMultimedia");
223 g_string_append(str, ", ");
225 get_compiled_airpcap_version(str);
227 g_string_append(str, "without AirPcap");
231 codec_get_compiled_version_info(str);
234 // xxx copied from ../gtk/main.c
236 get_wireshark_runtime_info(GString *str)
239 /* Capture libraries */
240 g_string_append(str, ", ");
241 get_runtime_caplibs_version(str);
244 /* stuff used by libwireshark */
245 epan_get_runtime_version_info(str);
248 g_string_append(str, ", ");
249 get_runtime_airpcap_version(str);
254 g_log_message_handler(QtMsgType type, const QMessageLogContext &, const QString &msg)
256 GLogLevelFlags log_level = G_LOG_LEVEL_DEBUG;
262 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
264 log_level = G_LOG_LEVEL_INFO;
268 log_level = G_LOG_LEVEL_WARNING;
271 log_level = G_LOG_LEVEL_CRITICAL;
274 log_level = G_LOG_FLAG_FATAL;
277 g_log(LOG_DOMAIN_MAIN, log_level, "%s", qUtf8Printable(msg));
281 /* Check if there's something important to tell the user during startup.
282 * We want to do this *after* showing the main window so that any windows
283 * we pop up will be above the main window.
286 check_and_warn_user_startup(const QString &cf_name)
291 gchar *cur_user, *cur_group;
293 /* Tell the user not to run as root. */
294 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
295 cur_user = get_cur_username();
296 cur_group = get_cur_groupname();
297 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
298 "Running as user \"%s\" and group \"%s\".\n"
299 "This could be dangerous.\n\n"
300 "If you're running Wireshark this way in order to perform live capture, "
301 "you may want to be aware that there is a better way documented at\n"
302 "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
308 /* Warn the user if npf.sys isn't loaded. */
309 if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
310 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
311 "The NPF driver isn't running. You may have trouble\n"
312 "capturing or listing interfaces.");
320 // Try to avoid library search path collisions. QCoreApplication will
321 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
322 // the application directory. If
324 // - You have Qt version 5.x.y installed in the default location
325 // (C:\Qt\5.x) on your machine.
329 // - You install Wireshark that was built on a machine with Qt version
330 // 5.x.z installed in the default location.
332 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
333 // directory. This may not be compatible with qwindows.dll from that
334 // same path on the build machine. At any rate, loading DLLs from paths
335 // you don't control is ill-advised. We work around this by removing every
336 // path except our application directory.
339 reset_library_path(void)
341 QString app_path = QDir(get_progfile_dir()).path();
342 foreach (QString path, QCoreApplication::libraryPaths()) {
343 QCoreApplication::removeLibraryPath(path);
345 QCoreApplication::addLibraryPath(app_path);
349 /* And now our feature presentation... [ fade to music ] */
350 int main(int argc, char *qt_argv[])
357 int ret_val = EXIT_SUCCESS;
358 char **argv = qt_argv;
376 gchar *err_msg = NULL;
377 GString *comp_info_str = NULL;
378 GString *runtime_info_str = NULL;
380 QString dfilter, read_filter;
382 int caps_queries = 0;
384 /* Start time in microseconds */
385 guint64 start_time = g_get_monotonic_time();
386 #ifdef DEBUG_STARTUP_TIME
387 /* At least on Windows there is a problem with the logging as the preferences is taken
388 * into account and the preferences are loaded pretty late in the startup process.
390 prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
391 prefs.gui_console_open = console_open_always;
392 #endif /* DEBUG_STARTUP_TIME */
393 cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
395 #if defined(Q_OS_MAC)
396 /* Disable automatic addition of tab menu entries in view menu */
397 CocoaBridge::cleanOSGeneratedMenuItems();
400 /* Set the C-language locale to the native environment. */
401 setlocale(LC_ALL, "");
404 // QCoreApplication clobbers argv. Let's have a local copy.
405 argv = (char **) g_malloc(sizeof(char *) * argc);
406 for (opt = 0; opt < argc; opt++) {
407 argv[opt] = qt_argv[opt];
409 arg_list_utf_16to8(argc, argv);
410 create_app_running_mutex();
414 * Get credential information for later use, and drop privileges
415 * before doing anything else.
416 * Let the user know if anything happened.
418 init_process_policies();
419 relinquish_special_privs_perm();
422 * Attempt to get the pathname of the directory containing the
425 /* init_progfile_dir_error = */ init_progfile_dir(argv[0]);
426 g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
429 ws_init_dll_search_path();
430 /* Load wpcap if possible. Do this before collecting the run-time version information */
433 /* ... and also load the packet.dll from wpcap */
437 /* Load the airpcap.dll. This must also be done before collecting
438 * run-time version information. */
441 airpcap_dll_ret_val = load_airpcap();
443 switch (airpcap_dll_ret_val) {
445 /* load the airpcap interfaces */
446 g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
448 if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
449 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
450 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
453 airpcap_if_active = NULL;
457 /* select the first ad default (THIS SHOULD BE CHANGED) */
458 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
462 * XXX - Maybe we need to warn the user if one of the following happens???
464 case AIRPCAP_DLL_OLD:
465 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
468 case AIRPCAP_DLL_ERROR:
469 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
472 case AIRPCAP_DLL_NOT_FOUND:
473 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
477 #endif /* HAVE_AIRPCAP */
480 /* Get the compile-time version information string */
481 comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
482 get_gui_compiled_info);
484 /* Assemble the run-time version information string */
485 runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
487 /* Create the user profiles directory */
488 if (create_profiles_dir(&rf_path) == -1) {
489 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
490 "Could not create profiles directory\n\"%s\"",
495 profile_store_persconffiles(TRUE);
498 /* Read the profile independent recent file. We have to do this here so we can */
499 /* set the profile before it can be set from the command line parameter */
500 if (!recent_read_static(&rf_path, &rf_open_errno)) {
501 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
502 "Could not open common recent file\n\"%s\": %s.",
503 rf_path, strerror(rf_open_errno));
507 commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
510 reset_library_path();
513 // Handle DPI scaling on Windows. This causes problems in at least
514 // one case on X11 and we don't yet support Android.
515 // We do the equivalent on macOS by setting NSHighResolutionCapable
517 // Note that this enables Windows 8.1-style Per-monitor DPI
518 // awareness but not Windows 10-style Per-monitor v2 awareness.
519 // http://doc.qt.io/qt-5/scalability.html
520 // http://doc.qt.io/qt-5/highdpi.html
521 // https://bugreports.qt.io/browse/QTBUG-53022 - The device pixel ratio is pretty much bogus on Windows.
522 // https://bugreports.qt.io/browse/QTBUG-55510 - Windows have wrong size
523 #if defined(Q_OS_WIN) && QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
524 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
527 /* Create The Wireshark app */
528 WiresharkApplication ws_app(argc, qt_argv);
530 /* initialize the funnel mini-api */
532 //initialize_funnel_ops();
534 Dot11DecryptInitContext(&dot11decrypt_ctx);
537 unsigned int in_file_type = WTAP_TYPE_AUTO;
539 /* Add it to the information to be reported on a crash. */
540 ws_add_crash_info("Wireshark %s\n"
545 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
546 g_string_free(comp_info_str, TRUE);
547 g_string_free(runtime_info_str, TRUE);
550 /* Start windows sockets */
551 result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
554 ret_val = INIT_FAILED;
559 /* Read the profile dependent (static part) of the recent file. */
560 /* Only the static part of it will be read, as we don't have the gui now to fill the */
561 /* recent lists which is done in the dynamic part. */
562 /* We have to do this already here, so command line parameters can overwrite these values. */
563 if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
564 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
565 "Could not open recent file\n\"%s\": %s.",
566 rf_path, g_strerror(rf_open_errno));
569 wsApp->applyCustomColorsFromRecent();
571 // Initialize our language
572 read_language_prefs();
573 wsApp->loadLanguage(language);
575 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
577 // Init the main window (and splash)
578 main_w = new(MainWindow);
580 // We may not need a queued connection here but it would seem to make sense
581 // to force the issue.
582 main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
583 main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
584 main_w->connect(&ws_app, SIGNAL(openCaptureOptions()),
585 main_w, SLOT(on_actionCaptureOptions_triggered()));
587 /* Init the "Open file" dialog directory */
588 /* (do this after the path settings are processed) */
589 if (recent.gui_fileopen_remembered_dir &&
590 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
591 wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
593 wsApp->setLastOpenDir(get_persdatafile_dir());
596 set_console_log_handler();
597 qInstallMessageHandler(g_log_message_handler);
598 #ifdef DEBUG_STARTUP_TIME
599 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);
603 /* Set the initial values in the capture options. This might be overwritten
604 by preference settings and then again by the command line parameters. */
605 capture_opts_init(&global_capture_opts);
608 init_report_message(vfailure_alert_box, vwarning_alert_box,
609 open_failure_alert_box, read_failure_alert_box,
610 write_failure_alert_box);
614 splash_update(RA_DISSECTORS, NULL, NULL);
615 #ifdef DEBUG_STARTUP_TIME
616 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);
618 /* Register all dissectors; we must do this before checking for the
619 "-G" flag, as the "-G" flag dumps information registered by the
620 dissectors, and we must do it before we read the preferences, in
621 case any dissectors register preferences. */
622 if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
623 splash_update, NULL)) {
624 SimpleDialog::displayQueuedMessages(main_w);
625 ret_val = INIT_FAILED;
628 #ifdef DEBUG_STARTUP_TIME
629 /* epan_init resets the preferences */
630 prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
631 prefs.gui_console_open = console_open_always;
632 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
635 /* Register all audio codecs. */
638 // Read the dynamic part of the recent file. This determines whether or
639 // not the recent list appears in the main window so the earlier we can
640 // call this the better.
641 if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
642 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
643 "Could not open recent file\n\"%s\": %s.",
644 rf_path, g_strerror(rf_open_errno));
647 wsApp->refreshRecentCaptures();
649 splash_update(RA_LISTENERS, NULL, NULL);
650 #ifdef DEBUG_STARTUP_TIME
651 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);
653 /* Register all tap listeners; we do this before we parse the arguments,
654 as the "-z" argument can specify a registered tap. */
656 /* we register the plugin taps before the other taps because
657 stats_tree taps plugins will be registered as tap listeners
658 by stats_tree_stat.c and need to registered before that */
660 register_all_plugin_tap_listeners();
663 /* Register all tap listeners. */
664 for (tap_reg_t *t = tap_reg_listener; t->cb_func != NULL; t++) {
667 conversation_table_set_gui_info(init_conversation_table);
668 hostlist_table_set_gui_info(init_endpoint_table);
669 srt_table_iterate_tables(register_service_response_tables, NULL);
670 rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
671 stat_tap_iterate_tables(register_simple_stat_tables, NULL);
673 if (ex_opt_count("read_format") > 0) {
674 in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
677 #ifdef DEBUG_STARTUP_TIME
678 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);
680 splash_update(RA_EXTCAP, NULL, NULL);
681 extcap_register_preferences();
682 splash_update(RA_PREFERENCES, NULL, NULL);
683 #ifdef DEBUG_STARTUP_TIME
684 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);
687 global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
689 /* Now get our args */
690 commandline_other_options(argc, argv, TRUE);
692 /* Convert some command-line parameters to QStrings */
693 if (global_commandline_info.cf_name != NULL)
694 cf_name = QString(global_commandline_info.cf_name);
695 if (global_commandline_info.rfilter != NULL)
696 read_filter = QString(global_commandline_info.rfilter);
697 if (global_commandline_info.dfilter != NULL)
698 dfilter = QString(global_commandline_info.dfilter);
700 timestamp_set_type(recent.gui_time_format);
701 timestamp_set_precision(recent.gui_time_precision);
702 timestamp_set_seconds_type (recent.gui_seconds_format);
705 #ifdef DEBUG_STARTUP_TIME
706 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);
708 splash_update(RA_INTERFACES, NULL, NULL);
710 fill_in_local_interfaces(main_window_update);
712 if (global_commandline_info.list_link_layer_types)
713 caps_queries |= CAPS_QUERY_LINK_TYPES;
714 if (global_commandline_info.list_timestamp_types)
715 caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
717 if (global_commandline_info.start_capture || caps_queries) {
718 /* We're supposed to do a live capture or get a list of link-layer/timestamp
719 types for a live capture device; if the user didn't specify an
720 interface to use, pick a default. */
721 ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
722 ((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);
729 /* Get the list of link-layer types for the capture devices. */
730 if_capabilities_t *caps;
733 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
734 int if_caps_queries = caps_queries;
735 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
736 if (device->selected) {
737 #if defined(HAVE_PCAP_CREATE)
738 caps = capture_get_if_capabilities(device->name, device->monitor_mode_supported, NULL, &err_str, main_window_update);
740 caps = capture_get_if_capabilities(device->name, FALSE, NULL, &err_str,main_window_update);
743 cmdarg_err("%s", err_str);
745 ret_val = INVALID_CAPABILITY;
748 if (caps->data_link_types == NULL) {
749 cmdarg_err("The capture device \"%s\" has no data link types.", device->name);
750 ret_val = INVALID_LINK_TYPE;
756 #if defined(HAVE_PCAP_CREATE)
757 if (device->monitor_mode_supported)
758 if_caps_queries |= CAPS_MONITOR_MODE;
760 capture_opts_print_if_capabilities(caps, device->name, if_caps_queries);
764 free_if_capabilities(caps);
767 ret_val = EXIT_SUCCESS;
771 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
772 capture_opts_trim_ring_num_files(&global_capture_opts);
773 #endif /* HAVE_LIBPCAP */
775 /* Notify all registered modules that have had any of their preferences
776 changed either from one of the preferences file or from the command
777 line that their preferences have changed. */
778 #ifdef DEBUG_STARTUP_TIME
779 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);
782 prefs_to_capture_opts();
783 wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
786 if ((global_capture_opts.num_selected == 0) &&
787 (prefs.capture_device != NULL)) {
790 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
791 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
792 if (!device->hidden && strcmp(device->display_name, prefs.capture_device) == 0) {
793 device->selected = TRUE;
794 global_capture_opts.num_selected++;
802 * Enabled and disabled protocols and heuristic dissectors as per
803 * command-line options.
805 if (!setup_enabled_and_disabled_protocols()) {
806 ret_val = INVALID_OPTION;
810 build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
811 wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
812 wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
814 wsApp->setMonospaceFont(prefs.gui_qt_font_name);
816 /* For update of WindowTitle (When use gui.window_title preference) */
817 main_w->setWSWindowTitle();
819 if (!color_filters_init(&err_msg, color_filter_add_cb)) {
820 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
824 wsApp->allSystemsGo();
825 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);
826 SimpleDialog::displayQueuedMessages(main_w);
828 /* User could specify filename, or display filter, or both */
829 if (!dfilter.isEmpty())
830 main_w->filterPackets(dfilter, false);
831 if (!cf_name.isEmpty()) {
832 if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
834 /* Open stat windows; we do so after creating the main window,
835 to avoid Qt warnings, and after successfully opening the
836 capture file, so we know we have something to compute stats
837 on, and after registering all dissectors, so that MATE will
838 have registered its field array and we can have a tap filter
839 with one of MATE's late-registered fields as part of the
841 start_requested_stats();
843 if(global_commandline_info.go_to_packet != 0) {
844 /* Jump to the specified frame number, kept for backward
846 cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
847 } else if (global_commandline_info.jfilter != NULL) {
848 dfilter_t *jump_to_filter = NULL;
849 /* try to compile given filter */
850 if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
851 // Similar code in MainWindow::mergeCaptureFile().
852 QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
853 QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
854 .arg(global_commandline_info.jfilter, err_msg),
858 /* Filter ok, jump to the first packet matching the filter
859 conditions. Default search direction is forward, but if
860 option d was given, search backwards */
861 cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
868 if (global_commandline_info.start_capture) {
869 if (global_capture_opts.save_file != NULL) {
870 /* Save the directory name for future file dialogs. */
871 /* (get_dirname overwrites filename) */
872 gchar *s = g_strdup(global_capture_opts.save_file);
873 set_last_open_dir(get_dirname(s));
876 /* "-k" was specified; start a capture. */
877 check_and_warn_user_startup(cf_name);
879 /* If no user interfaces were specified on the command line,
880 copy the list of selected interfaces to the set of interfaces
881 to use for this capture. */
882 if (global_capture_opts.ifaces->len == 0)
883 collect_ifaces(&global_capture_opts);
884 CaptureFile::globalCapFile()->window = main_w;
885 if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
886 /* The capture started. Open stat windows; we do so after creating
887 the main window, to avoid GTK warnings, and after successfully
888 opening the capture file, so we know we have something to compute
889 stats on, and after registering all dissectors, so that MATE will
890 have registered its field array and we can have a tap filter with
891 one of MATE's late-registered fields as part of the filter. */
892 start_requested_stats();
895 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
896 if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
897 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
900 #endif /* HAVE_LIBPCAP */
902 // UAT files used in configuration profiles which are used in Qt dialogs
903 // are not registered during startup because they only get loaded when
904 // the dialog is shown. Register them here.
905 g_free(get_persconffile_path("io_graphs", TRUE));
907 profile_store_persconffiles(FALSE);
909 ret_val = wsApp->exec();
918 Dot11DecryptDestroyContext(&dot11decrypt_ctx);
921 /* Shutdown windows sockets */
924 /* For some unknown reason, the "atexit()" call in "create_console()"
925 doesn't arrange that "destroy_console()" be called when we exit,
926 so we call it here if a console was created. */
932 capture_opts_cleanup(&global_capture_opts);
934 col_cleanup(&CaptureFile::globalCapFile()->cinfo);
938 exit_application(ret_val);
947 * indent-tabs-mode: nil
950 * ex: set shiftwidth=4 tabstop=8 expandtab:
951 * :indentSize=4:tabSize=8:noTabs=true: