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