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