Copy preferences to capture options after the preferences are initially loaded.
[metze/wireshark/wip.git] / wireshark-qt.cpp
1 /* wireshark-qt.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0+
8  */
9
10 #include <config.h>
11
12 #include <glib.h>
13
14 #ifdef Q_OS_UNIX
15 #include <signal.h>
16 #endif
17
18 #include <locale.h>
19
20 #ifdef HAVE_GETOPT_H
21 #include <getopt.h>
22 #endif
23
24 #ifndef HAVE_GETOPT_LONG
25 #include "wsutil/wsgetopt.h"
26 #endif
27
28 #ifndef _WIN32
29 #include <wsutil/glib-compat.h>
30 #endif
31
32 #include <wsutil/clopts_common.h>
33 #include <wsutil/cmdarg_err.h>
34 #include <wsutil/crash_info.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/privileges.h>
37 #ifdef HAVE_PLUGINS
38 #include <wsutil/plugins.h>
39 #endif
40 #include <wsutil/report_message.h>
41 #include <wsutil/unicode-utils.h>
42 #include <version_info.h>
43
44 #include <epan/addr_resolv.h>
45 #include <epan/ex-opt.h>
46 #include <epan/tap.h>
47 #include <epan/stat_tap_ui.h>
48 #include <epan/column.h>
49 #include <epan/disabled_protos.h>
50 #include <epan/prefs.h>
51
52 #ifdef HAVE_KERBEROS
53 #include <epan/packet.h>
54 #include <epan/asn1.h>
55 #include <epan/dissectors/packet-kerberos.h>
56 #endif
57
58 #include <codecs/codecs.h>
59
60 #include <extcap.h>
61
62 /* general (not Qt specific) */
63 #include "file.h"
64 #include "epan/color_filters.h"
65 #include "log.h"
66
67 #include "epan/rtd_table.h"
68 #include "epan/srt_table.h"
69
70 #include "ui/alert_box.h"
71 #include "ui/console.h"
72 #include "ui/iface_lists.h"
73 #include "ui/language.h"
74 #include "ui/persfilepath_opt.h"
75 #include "ui/recent.h"
76 #include "ui/simple_dialog.h"
77 #include "ui/util.h"
78 #include "ui/dissect_opts.h"
79 #include "ui/commandline.h"
80 #include "ui/capture_ui_utils.h"
81 #include "ui/preference_utils.h"
82 #include "ui/taps.h"
83
84 #include "ui/qt/conversation_dialog.h"
85 #include "ui/qt/utils/color_utils.h"
86 #include "ui/qt/coloring_rules_dialog.h"
87 #include "ui/qt/endpoint_dialog.h"
88 #include "ui/qt/main_window.h"
89 #include "ui/qt/response_time_delay_dialog.h"
90 #include "ui/qt/service_response_time_dialog.h"
91 #include "ui/qt/simple_dialog.h"
92 #include "ui/qt/simple_statistics_dialog.h"
93 #include "ui/qt/splash_overlay.h"
94 #include "ui/qt/wireshark_application.h"
95
96 #include "caputils/capture-pcap-util.h"
97
98 #include <QMessageBox>
99
100 #ifdef _WIN32
101 #  include "caputils/capture-wpcap.h"
102 #  include "caputils/capture_wpcap_packet.h"
103 #  include <tchar.h> /* Needed for Unicode */
104 #  include <wsutil/file_util.h>
105 #  include <wsutil/os_version_info.h>
106 #endif /* _WIN32 */
107
108 #ifdef HAVE_AIRPCAP
109 #  include <caputils/airpcap.h>
110 #  include <caputils/airpcap_loader.h>
111 //#  include "airpcap_dlg.h"
112 //#  include "airpcap_gui_utils.h"
113 #endif
114
115 #include "epan/crypt/airpdcap_ws.h"
116
117 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
118 #include <QTextCodec>
119 #endif
120
121 #include <ui/qt/utils/qt_ui_utils.h>
122
123 #define INVALID_OPTION 1
124 #define INIT_FAILED 2
125 #define INVALID_CAPABILITY 2
126 #define INVALID_LINK_TYPE 2
127
128 //#define DEBUG_STARTUP_TIME 1
129 /*
130 # Log level
131 # Console log level (for debugging)
132 # A bitmask of log levels:
133 # ERROR    = 4
134 # CRITICAL = 8
135 # WARNING  = 16
136 # MESSAGE  = 32
137 # INFO     = 64
138 # DEBUG    = 128
139
140 */
141 #define DEBUG_STARTUP_TIME_LOGLEVEL 252
142
143 /* update the main window */
144 void main_window_update(void)
145 {
146     WiresharkApplication::processEvents();
147 }
148
149 #ifdef HAVE_LIBPCAP
150
151 /* quit a nested main window */
152 void main_window_nested_quit(void)
153 {
154 //    if (gtk_main_level() > 0)
155     wsApp->quit();
156 }
157
158 /* quit the main window */
159 void main_window_quit(void)
160 {
161     wsApp->quit();
162 }
163
164 #endif /* HAVE_LIBPCAP */
165
166 /*
167  * Report an error in command-line arguments.
168  * Creates a console on Windows.
169  */
170 // xxx copied from ../gtk/main.c
171 static void
172 wireshark_cmdarg_err(const char *fmt, va_list ap)
173 {
174 #ifdef _WIN32
175     create_console();
176 #endif
177     fprintf(stderr, "wireshark: ");
178     vfprintf(stderr, fmt, ap);
179     fprintf(stderr, "\n");
180 }
181
182 /*
183  * Report additional information for an error in command-line arguments.
184  * Creates a console on Windows.
185  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
186  * terminal isn't the standard error?
187  */
188 // xxx copied from ../gtk/main.c
189 static void
190 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
191 {
192 #ifdef _WIN32
193     create_console();
194 #endif
195     vfprintf(stderr, fmt, ap);
196     fprintf(stderr, "\n");
197 }
198
199 // xxx based from ../gtk/main.c:get_gtk_compiled_info
200 void
201 get_wireshark_qt_compiled_info(GString *str)
202 {
203     g_string_append(str, "with ");
204     g_string_append_printf(str,
205 #ifdef QT_VERSION
206                     "Qt %s", QT_VERSION_STR);
207 #else
208                     "Qt (version unknown)");
209 #endif
210
211     /* Capture libraries */
212     g_string_append(str, ", ");
213     get_compiled_caplibs_version(str);
214 }
215
216 // xxx copied from ../gtk/main.c
217 void
218 get_gui_compiled_info(GString *str)
219 {
220     epan_get_compiled_version_info(str);
221
222     g_string_append(str, ", ");
223 #ifdef QT_MULTIMEDIA_LIB
224     g_string_append(str, "with QtMultimedia");
225 #else
226     g_string_append(str, "without QtMultimedia");
227 #endif
228
229 #ifdef _WIN32
230     g_string_append(str, ", ");
231 #ifdef HAVE_AIRPCAP
232     get_compiled_airpcap_version(str);
233 #else
234     g_string_append(str, "without AirPcap");
235 #endif
236 #endif /* _WIN32 */
237
238     codec_get_compiled_version_info(str);
239 }
240
241 // xxx copied from ../gtk/main.c
242 void
243 get_wireshark_runtime_info(GString *str)
244 {
245 #ifdef HAVE_LIBPCAP
246     /* Capture libraries */
247     g_string_append(str, ", ");
248     get_runtime_caplibs_version(str);
249 #endif
250
251     /* stuff used by libwireshark */
252     epan_get_runtime_version_info(str);
253
254 #ifdef HAVE_AIRPCAP
255     g_string_append(str, ", ");
256     get_runtime_airpcap_version(str);
257 #endif
258 }
259
260 static void
261 g_log_message_handler(QtMsgType type, const QMessageLogContext &, const QString &msg)
262 {
263     GLogLevelFlags log_level = G_LOG_LEVEL_DEBUG;
264
265     switch (type) {
266     case QtDebugMsg:
267     default:
268         break;
269 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
270     case QtInfoMsg:
271         log_level = G_LOG_LEVEL_INFO;
272         break;
273 #endif
274     case QtWarningMsg:
275         log_level = G_LOG_LEVEL_WARNING;
276         break;
277     case QtCriticalMsg:
278         log_level = G_LOG_LEVEL_CRITICAL;
279         break;
280     case QtFatalMsg:
281         log_level = G_LOG_FLAG_FATAL;
282         break;
283     }
284     g_log(LOG_DOMAIN_MAIN, log_level, "%s", qUtf8Printable(msg));
285 }
286
287 #ifdef HAVE_LIBPCAP
288 /*  Check if there's something important to tell the user during startup.
289  *  We want to do this *after* showing the main window so that any windows
290  *  we pop up will be above the main window.
291  */
292 static void
293 check_and_warn_user_startup(const QString &cf_name)
294 {
295 #ifndef _WIN32
296     Q_UNUSED(cf_name)
297 #endif
298     gchar               *cur_user, *cur_group;
299
300     /* Tell the user not to run as root. */
301     if (running_with_special_privs() && recent.privs_warn_if_elevated) {
302         cur_user = get_cur_username();
303         cur_group = get_cur_groupname();
304         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
305         "Running as user \"%s\" and group \"%s\".\n"
306         "This could be dangerous.\n\n"
307         "If you're running Wireshark this way in order to perform live capture, "
308         "you may want to be aware that there is a better way documented at\n"
309         "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
310         g_free(cur_user);
311         g_free(cur_group);
312     }
313
314 #ifdef _WIN32
315     /* Warn the user if npf.sys isn't loaded. */
316     if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
317         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
318         "The NPF driver isn't running. You may have trouble\n"
319         "capturing or listing interfaces.");
320     }
321 #endif
322
323 }
324 #endif
325
326 #ifdef _WIN32
327 // Try to avoid library search path collisions. QCoreApplication will
328 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
329 // the application directory. If
330 //
331 // - You have Qt version 5.x.y installed in the default location
332 //   (C:\Qt\5.x) on your machine.
333 //
334 // and
335 //
336 // - You install Wireshark that was built on a machine with Qt version
337 //   5.x.z installed in the default location.
338 //
339 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
340 // directory. This may not be compatible with qwindows.dll from that
341 // same path on the build machine. At any rate, loading DLLs from paths
342 // you don't control is ill-advised. We work around this by removing every
343 // path except our application directory.
344
345 static inline void
346 reset_library_path(void)
347 {
348     QString app_path = QDir(get_progfile_dir()).path();
349     foreach (QString path, QCoreApplication::libraryPaths()) {
350         QCoreApplication::removeLibraryPath(path);
351     }
352     QCoreApplication::addLibraryPath(app_path);
353 }
354 #endif
355
356 /* And now our feature presentation... [ fade to music ] */
357 int main(int argc, char *qt_argv[])
358 {
359     MainWindow *main_w;
360
361 #ifdef _WIN32
362     int                  opt;
363 #endif
364     int                  ret_val = EXIT_SUCCESS;
365     char               **argv = qt_argv;
366
367 #ifdef _WIN32
368     int                  result;
369     WSADATA              wsaData;
370 #endif  /* _WIN32 */
371
372     char                *rf_path;
373     int                  rf_open_errno;
374 #ifdef HAVE_LIBPCAP
375     gchar               *err_str;
376 #else
377 #ifdef _WIN32
378 #ifdef HAVE_AIRPCAP
379     gchar               *err_str;
380 #endif
381 #endif
382 #endif
383     gchar               *err_msg = NULL;
384     GString             *comp_info_str = NULL;
385     GString             *runtime_info_str = NULL;
386
387     QString              dfilter, read_filter;
388 #ifdef HAVE_LIBPCAP
389     int                  caps_queries = 0;
390 #endif
391     /* Start time in microseconds*/
392     guint64 start_time = g_get_monotonic_time();
393 #ifdef DEBUG_STARTUP_TIME
394     /* At least on Windows there is a problem with the loging as the preferences is taken
395      * into account and the preferences are loaded pretty late in the startup process.
396      */
397     prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
398     prefs.gui_console_open = console_open_always;
399 #endif /* DEBUG_STARTUP_TIME */
400     cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
401
402     // In Qt 5, C strings are treated always as UTF-8 when converted to
403     // QStrings; in Qt 4, the codec must be set to make that happen
404 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
405     // Hopefully we won't have to use QString::fromUtf8() in as many places.
406     QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
407     QTextCodec::setCodecForCStrings(utf8codec);
408     // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
409     QTextCodec::setCodecForTr(utf8codec);
410 #endif
411
412     /* Set the C-language locale to the native environment. */
413     setlocale(LC_ALL, "");
414
415 #ifdef _WIN32
416     // QCoreApplication clobbers argv. Let's have a local copy.
417     argv = (char **) g_malloc(sizeof(char *) * argc);
418     for (opt = 0; opt < argc; opt++) {
419         argv[opt] = qt_argv[opt];
420     }
421     arg_list_utf_16to8(argc, argv);
422     create_app_running_mutex();
423 #endif /* _WIN32 */
424
425     /*
426      * Get credential information for later use, and drop privileges
427      * before doing anything else.
428      * Let the user know if anything happened.
429      */
430     init_process_policies();
431     relinquish_special_privs_perm();
432
433     /*
434      * Attempt to get the pathname of the directory containing the
435      * executable file.
436      */
437     /* init_progfile_dir_error = */ init_progfile_dir(argv[0],
438         (int (*)(int, char **)) get_gui_compiled_info);
439     g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
440
441 #ifdef _WIN32
442     ws_init_dll_search_path();
443     /* Load wpcap if possible. Do this before collecting the run-time version information */
444     load_wpcap();
445
446     /* ... and also load the packet.dll from wpcap */
447     wpcap_packet_load();
448
449 #ifdef HAVE_AIRPCAP
450     /* Load the airpcap.dll.  This must also be done before collecting
451      * run-time version information. */
452     load_airpcap();
453 #if 0
454     airpcap_dll_ret_val = load_airpcap();
455
456     switch (airpcap_dll_ret_val) {
457     case AIRPCAP_DLL_OK:
458         /* load the airpcap interfaces */
459         g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
460
461         if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
462             if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
463                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
464                 g_free(err_str);
465             }
466             airpcap_if_active = NULL;
467
468         } else {
469
470             /* select the first ad default (THIS SHOULD BE CHANGED) */
471             airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
472         }
473         break;
474     /*
475      * XXX - Maybe we need to warn the user if one of the following happens???
476      */
477     case AIRPCAP_DLL_OLD:
478         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
479         break;
480
481     case AIRPCAP_DLL_ERROR:
482         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
483         break;
484
485     case AIRPCAP_DLL_NOT_FOUND:
486         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
487         break;
488     }
489 #endif
490 #endif /* HAVE_AIRPCAP */
491 #endif /* _WIN32 */
492
493     /* Get the compile-time version information string */
494     comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
495                                               get_gui_compiled_info);
496
497     /* Assemble the run-time version information string */
498     runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
499
500     /* Create the user profiles directory */
501     if (create_profiles_dir(&rf_path) == -1) {
502         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
503                       "Could not create profiles directory\n\"%s\"",
504                       rf_path);
505         g_free (rf_path);
506     }
507
508     profile_store_persconffiles(TRUE);
509     recent_init();
510
511     /* Read the profile independent recent file.  We have to do this here so we can */
512     /* set the profile before it can be set from the command line parameter */
513     if (!recent_read_static(&rf_path, &rf_open_errno)) {
514         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
515                       "Could not open common recent file\n\"%s\": %s.",
516                       rf_path, strerror(rf_open_errno));
517         g_free(rf_path);
518     }
519
520     commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
521
522 #ifdef _WIN32
523     reset_library_path();
524 #endif
525
526     // Handle DPI scaling on Windows. This causes problems in at least
527     // one case on X11 and we don't yet support Android.
528     // We do the equivalent on macOS by setting NSHighResolutionCapable
529     // in Info.plist.
530     // http://doc.qt.io/qt-5/scalability.html
531     // http://doc.qt.io/qt-5/highdpi.html
532     // https://bugreports.qt.io/browse/QTBUG-53022 - The device pixel ratio is pretty much bogus on Windows.
533     // https://bugreports.qt.io/browse/QTBUG-55510 - Windows have wrong size
534 #if defined(Q_OS_WIN) && QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
535      QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
536 #endif
537
538     /* Create The Wireshark app */
539     WiresharkApplication ws_app(argc, qt_argv);
540
541     /* initialize the funnel mini-api */
542     // xxx qtshark
543     //initialize_funnel_ops();
544
545     AirPDcapInitContext(&airpdcap_ctx);
546
547     QString cf_name;
548     unsigned int in_file_type = WTAP_TYPE_AUTO;
549
550     /* Add it to the information to be reported on a crash. */
551     ws_add_crash_info("Wireshark %s\n"
552            "\n"
553            "%s"
554            "\n"
555            "%s",
556         get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
557     g_string_free(comp_info_str, TRUE);
558     g_string_free(runtime_info_str, TRUE);
559
560 #ifdef _WIN32
561     /* Start windows sockets */
562     result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
563     if (result != 0)
564     {
565         ret_val = INIT_FAILED;
566         goto clean_exit;
567     }
568 #endif  /* _WIN32 */
569
570     /* Read the profile dependent (static part) of the recent file. */
571     /* Only the static part of it will be read, as we don't have the gui now to fill the */
572     /* recent lists which is done in the dynamic part. */
573     /* We have to do this already here, so command line parameters can overwrite these values. */
574     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
575         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
576                       "Could not open recent file\n\"%s\": %s.",
577                       rf_path, g_strerror(rf_open_errno));
578         g_free(rf_path);
579     }
580     wsApp->applyCustomColorsFromRecent();
581
582     // Initialize our language
583     read_language_prefs();
584     wsApp->loadLanguage(language);
585
586     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
587
588     // Init the main window (and splash)
589     main_w = new(MainWindow);
590     main_w->show();
591     // We may not need a queued connection here but it would seem to make sense
592     // to force the issue.
593     main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
594             main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
595     main_w->connect(&ws_app, SIGNAL(openCaptureOptions()),
596             main_w, SLOT(on_actionCaptureOptions_triggered()));
597
598     /* Init the "Open file" dialog directory */
599     /* (do this after the path settings are processed) */
600     if (recent.gui_fileopen_remembered_dir &&
601         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
602       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
603     } else {
604       wsApp->setLastOpenDir(get_persdatafile_dir());
605     }
606
607 #ifdef Q_OS_UNIX
608     // Replicates behavior in gtk_init();
609     signal(SIGPIPE, SIG_IGN);
610 #endif
611
612     set_console_log_handler();
613     qInstallMessageHandler(g_log_message_handler);
614 #ifdef DEBUG_STARTUP_TIME
615     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);
616 #endif
617
618 #ifdef HAVE_LIBPCAP
619     /* Set the initial values in the capture options. This might be overwritten
620        by preference settings and then again by the command line parameters. */
621     capture_opts_init(&global_capture_opts);
622 #endif
623
624     init_report_message(vfailure_alert_box, vwarning_alert_box,
625                         open_failure_alert_box, read_failure_alert_box,
626                         write_failure_alert_box);
627
628     wtap_init();
629
630     splash_update(RA_DISSECTORS, NULL, NULL);
631 #ifdef DEBUG_STARTUP_TIME
632     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);
633 #endif
634     /* Register all dissectors; we must do this before checking for the
635        "-G" flag, as the "-G" flag dumps information registered by the
636        dissectors, and we must do it before we read the preferences, in
637        case any dissectors register preferences. */
638     if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
639                    splash_update, NULL)) {
640         SimpleDialog::displayQueuedMessages(main_w);
641         ret_val = INIT_FAILED;
642         goto clean_exit;
643     }
644 #ifdef DEBUG_STARTUP_TIME
645     /* epan_init resets the preferences */
646     prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
647     prefs.gui_console_open = console_open_always;
648     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
649 #endif
650
651     /* Register all audio codecs. */
652     codecs_init();
653
654     // Read the dynamic part of the recent file. This determines whether or
655     // not the recent list appears in the main window so the earlier we can
656     // call this the better.
657     if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
658         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
659                       "Could not open recent file\n\"%s\": %s.",
660                       rf_path, g_strerror(rf_open_errno));
661         g_free(rf_path);
662     }
663     wsApp->refreshRecentCaptures();
664
665     splash_update(RA_LISTENERS, NULL, NULL);
666 #ifdef DEBUG_STARTUP_TIME
667     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);
668 #endif
669     /* Register all tap listeners; we do this before we parse the arguments,
670        as the "-z" argument can specify a registered tap. */
671
672     /* we register the plugin taps before the other taps because
673             stats_tree taps plugins will be registered as tap listeners
674             by stats_tree_stat.c and need to registered before that */
675 #ifdef HAVE_PLUGINS
676     register_all_plugin_tap_listeners();
677 #endif
678
679     /* Register all tap listeners. */
680     for (tap_reg_t *t = tap_reg_listener; t->cb_func != NULL; t++) {
681         t->cb_func();
682     }
683     conversation_table_set_gui_info(init_conversation_table);
684     hostlist_table_set_gui_info(init_endpoint_table);
685     srt_table_iterate_tables(register_service_response_tables, NULL);
686     rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
687     new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
688
689     if (ex_opt_count("read_format") > 0) {
690         in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
691     }
692
693 #ifdef DEBUG_STARTUP_TIME
694     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);
695 #endif
696     splash_update(RA_EXTCAP, NULL, NULL);
697     extcap_register_preferences();
698     splash_update(RA_PREFERENCES, NULL, NULL);
699     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);
700
701     global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
702
703     /* Now get our args */
704     commandline_other_options(argc, argv, TRUE);
705
706     /* Convert some command-line parameters to QStrings */
707     if (global_commandline_info.cf_name != NULL)
708         cf_name = QString(global_commandline_info.cf_name);
709     if (global_commandline_info.rfilter != NULL)
710         read_filter = QString(global_commandline_info.rfilter);
711     if (global_commandline_info.dfilter != NULL)
712         dfilter = QString(global_commandline_info.dfilter);
713
714     /* Removed thread code:
715      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
716      */
717
718     timestamp_set_type(recent.gui_time_format);
719     timestamp_set_precision(recent.gui_time_precision);
720     timestamp_set_seconds_type (recent.gui_seconds_format);
721
722 #ifdef HAVE_LIBPCAP
723 #ifdef DEBUG_STARTUP_TIME
724     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);
725 #endif
726     splash_update(RA_INTERFACES, NULL, NULL);
727
728     fill_in_local_interfaces(main_window_update);
729
730     if  (global_commandline_info.list_link_layer_types)
731         caps_queries |= CAPS_QUERY_LINK_TYPES;
732      if (global_commandline_info.list_timestamp_types)
733         caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
734
735     if (global_commandline_info.start_capture || caps_queries) {
736         /* We're supposed to do a live capture or get a list of link-layer/timestamp
737            types for a live capture device; if the user didn't specify an
738            interface to use, pick a default. */
739         ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
740         ((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);
741         if (ret_val != 0) {
742             goto clean_exit;
743         }
744     }
745
746     if (caps_queries) {
747         /* Get the list of link-layer types for the capture devices. */
748         if_capabilities_t *caps;
749         guint i;
750         interface_t *device;
751         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
752             int if_caps_queries = caps_queries;
753             device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
754             if (device->selected) {
755 #if defined(HAVE_PCAP_CREATE)
756                 caps = capture_get_if_capabilities(device->name, device->monitor_mode_supported, NULL, &err_str, main_window_update);
757 #else
758                 caps = capture_get_if_capabilities(device->name, FALSE, NULL, &err_str,main_window_update);
759 #endif
760                 if (caps == NULL) {
761                     cmdarg_err("%s", err_str);
762                     g_free(err_str);
763                     ret_val = INVALID_CAPABILITY;
764                     goto clean_exit;
765                 }
766             if (caps->data_link_types == NULL) {
767                 cmdarg_err("The capture device \"%s\" has no data link types.", device->name);
768                 ret_val = INVALID_LINK_TYPE;
769                 goto clean_exit;
770             }
771 #ifdef _WIN32
772             create_console();
773 #endif /* _WIN32 */
774 #if defined(HAVE_PCAP_CREATE)
775             if (device->monitor_mode_supported)
776                 if_caps_queries |= CAPS_MONITOR_MODE;
777 #endif
778             capture_opts_print_if_capabilities(caps, device->name, if_caps_queries);
779 #ifdef _WIN32
780             destroy_console();
781 #endif /* _WIN32 */
782             free_if_capabilities(caps);
783             }
784         }
785         ret_val = EXIT_SUCCESS;
786         goto clean_exit;
787     }
788
789     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
790     capture_opts_trim_ring_num_files(&global_capture_opts);
791 #endif /* HAVE_LIBPCAP */
792
793     /* Notify all registered modules that have had any of their preferences
794        changed either from one of the preferences file or from the command
795        line that their preferences have changed. */
796 #ifdef DEBUG_STARTUP_TIME
797     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);
798 #endif
799     prefs_apply_all();
800     prefs_to_capture_opts();
801     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
802
803 #ifdef HAVE_LIBPCAP
804     if ((global_capture_opts.num_selected == 0) &&
805             (prefs.capture_device != NULL)) {
806         guint i;
807         interface_t *device;
808         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
809             device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
810             if (!device->hidden && strcmp(device->display_name, prefs.capture_device) == 0) {
811                 device->selected = TRUE;
812                 global_capture_opts.num_selected++;
813                 break;
814             }
815         }
816     }
817 #endif
818
819     /*
820      * Enabled and disabled protocols and heuristic dissectors as per
821      * command-line options.
822      */
823     if (!setup_enabled_and_disabled_protocols()) {
824         ret_val = INVALID_OPTION;
825         goto clean_exit;
826     }
827
828     build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
829     wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
830     wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
831
832     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
833
834     /* For update of WindowTitle (When use gui.window_title preference) */
835     main_w->setWSWindowTitle();
836 ////////
837
838     packet_list_enable_color(recent.packet_list_colorize);
839
840     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
841     packet_list_enable_color(TRUE);
842
843 ////////
844
845
846 ////////
847     if (!color_filters_init(&err_msg, color_filter_add_cb)) {
848         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
849         g_free(err_msg);
850     }
851
852 ////////
853
854 #ifdef HAVE_LIBPCAP
855     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
856     if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
857         global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
858     }
859 #else /* HAVE_LIBPCAP */
860     ////////
861 #endif /* HAVE_LIBPCAP */
862
863     wsApp->allSystemsGo();
864     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);
865     SimpleDialog::displayQueuedMessages(main_w);
866
867     /* User could specify filename, or display filter, or both */
868     if (!dfilter.isEmpty())
869         main_w->filterPackets(dfilter, false);
870     if (!cf_name.isEmpty()) {
871         if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
872
873             /* Open stat windows; we do so after creating the main window,
874                to avoid Qt warnings, and after successfully opening the
875                capture file, so we know we have something to compute stats
876                on, and after registering all dissectors, so that MATE will
877                have registered its field array and we can have a tap filter
878                with one of MATE's late-registered fields as part of the
879                filter. */
880             start_requested_stats();
881
882             if(global_commandline_info.go_to_packet != 0) {
883                 /* Jump to the specified frame number, kept for backward
884                    compatibility. */
885                 cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
886             } else if (global_commandline_info.jfilter != NULL) {
887                 dfilter_t *jump_to_filter = NULL;
888                 /* try to compile given filter */
889                 if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
890                     // Similar code in MainWindow::mergeCaptureFile().
891                     QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
892                                          QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
893                                                  .arg(global_commandline_info.jfilter, err_msg),
894                                          QMessageBox::Ok);
895                     g_free(err_msg);
896                 } else {
897                     /* Filter ok, jump to the first packet matching the filter
898                        conditions. Default search direction is forward, but if
899                        option d was given, search backwards */
900                     cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
901                 }
902             }
903         }
904     }
905 #ifdef HAVE_LIBPCAP
906     else {
907         if (global_commandline_info.start_capture) {
908             if (global_capture_opts.save_file != NULL) {
909                 /* Save the directory name for future file dialogs. */
910                 /* (get_dirname overwrites filename) */
911                 gchar *s = g_strdup(global_capture_opts.save_file);
912                 set_last_open_dir(get_dirname(s));
913                 g_free(s);
914             }
915             /* "-k" was specified; start a capture. */
916 //            show_main_window(FALSE);
917             check_and_warn_user_startup(cf_name);
918
919             /* If no user interfaces were specified on the command line,
920                copy the list of selected interfaces to the set of interfaces
921                to use for this capture. */
922             if (global_capture_opts.ifaces->len == 0)
923                 collect_ifaces(&global_capture_opts);
924             CaptureFile::globalCapFile()->window = main_w;
925             if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
926                 /* The capture started.  Open stat windows; we do so after creating
927                    the main window, to avoid GTK warnings, and after successfully
928                    opening the capture file, so we know we have something to compute
929                    stats on, and after registering all dissectors, so that MATE will
930                    have registered its field array and we can have a tap filter with
931                    one of MATE's late-registered fields as part of the filter. */
932                 start_requested_stats();
933             }
934         }
935     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
936         if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
937             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
938         }
939     }
940 #endif /* HAVE_LIBPCAP */
941
942     // UAT files used in configuration profiles which are used in Qt dialogs
943     // are not registered during startup because they only get loaded when
944     // the dialog is shown.  Register them here.
945     g_free(get_persconffile_path("io_graphs", TRUE));
946
947     profile_store_persconffiles(FALSE);
948
949     ret_val = wsApp->exec();
950
951     delete main_w;
952     recent_cleanup();
953     epan_cleanup();
954
955     extcap_cleanup();
956
957     AirPDcapDestroyContext(&airpdcap_ctx);
958
959 #ifdef _WIN32
960     /* Shutdown windows sockets */
961     WSACleanup();
962
963     /* For some unknown reason, the "atexit()" call in "create_console()"
964        doesn't arrange that "destroy_console()" be called when we exit,
965        so we call it here if a console was created. */
966     destroy_console();
967 #endif /* _WIN32 */
968
969 clean_exit:
970 #ifdef HAVE_LIBPCAP
971     capture_opts_cleanup(&global_capture_opts);
972 #endif
973     col_cleanup(&CaptureFile::globalCapFile()->cinfo);
974     codecs_cleanup();
975     wtap_cleanup();
976     free_progdirs();
977     return ret_val;
978 }
979
980 /*
981  * Editor modelines
982  *
983  * Local Variables:
984  * c-basic-offset: 4
985  * tab-width: 8
986  * indent-tabs-mode: nil
987  * End:
988  *
989  * ex: set shiftwidth=4 tabstop=8 expandtab:
990  * :indentSize=4:tabSize=8:noTabs=true:
991  */