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