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