[Diameter] Add a couple of command codes from IANA.
[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     /* Create the user profiles directory */
477     if (create_profiles_dir(&rf_path) == -1) {
478         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
479                       "Could not create profiles directory\n\"%s\"",
480                       rf_path);
481         g_free (rf_path);
482     }
483
484     profile_store_persconffiles(TRUE);
485
486     /* Read the profile independent recent file.  We have to do this here so we can */
487     /* set the profile before it can be set from the command line parameter */
488     if (!recent_read_static(&rf_path, &rf_open_errno)) {
489         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
490                       "Could not open common recent file\n\"%s\": %s.",
491                       rf_path, strerror(rf_open_errno));
492         g_free(rf_path);
493     }
494
495     commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
496
497 #ifdef _WIN32
498     reset_library_path();
499 #endif
500
501     /* Create The Wireshark app */
502     WiresharkApplication ws_app(argc, qt_argv);
503
504     /* initialize the funnel mini-api */
505     // xxx qtshark
506     //initialize_funnel_ops();
507
508     AirPDcapInitContext(&airpdcap_ctx);
509
510     QString cf_name;
511     unsigned int in_file_type = WTAP_TYPE_AUTO;
512
513     /* Add it to the information to be reported on a crash. */
514     ws_add_crash_info("Wireshark %s\n"
515            "\n"
516            "%s"
517            "\n"
518            "%s",
519         get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
520     g_string_free(comp_info_str, TRUE);
521     g_string_free(runtime_info_str, TRUE);
522
523 #ifdef _WIN32
524     /* Start windows sockets */
525     result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
526     if (result != 0)
527     {
528         ret_val = INIT_FAILED;
529         goto clean_exit;
530     }
531 #endif  /* _WIN32 */
532
533     /* Read the profile dependent (static part) of the recent file. */
534     /* Only the static part of it will be read, as we don't have the gui now to fill the */
535     /* recent lists which is done in the dynamic part. */
536     /* We have to do this already here, so command line parameters can overwrite these values. */
537     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
538         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
539                       "Could not open recent file\n\"%s\": %s.",
540                       rf_path, g_strerror(rf_open_errno));
541         g_free(rf_path);
542     }
543     wsApp->applyCustomColorsFromRecent();
544
545     // Initialize our language
546     read_language_prefs();
547     wsApp->loadLanguage(language);
548
549     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
550
551     // Init the main window (and splash)
552     main_w = new(MainWindow);
553     main_w->show();
554     // We may not need a queued connection here but it would seem to make sense
555     // to force the issue.
556     main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
557             main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
558     main_w->connect(&ws_app, SIGNAL(openCaptureOptions()),
559             main_w, SLOT(on_actionCaptureOptions_triggered()));
560
561     /* Init the "Open file" dialog directory */
562     /* (do this after the path settings are processed) */
563     if (recent.gui_fileopen_remembered_dir &&
564         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
565       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
566     } else {
567       wsApp->setLastOpenDir(get_persdatafile_dir());
568     }
569
570 #ifdef Q_OS_UNIX
571     // Replicates behavior in gtk_init();
572     signal(SIGPIPE, SIG_IGN);
573 #endif
574
575     set_console_log_handler();
576 #ifdef DEBUG_STARTUP_TIME
577     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);
578 #endif
579
580 #ifdef HAVE_LIBPCAP
581     /* Set the initial values in the capture options. This might be overwritten
582        by preference settings and then again by the command line parameters. */
583     capture_opts_init(&global_capture_opts);
584 #endif
585
586     init_report_message(vfailure_alert_box, vwarning_alert_box,
587                         open_failure_alert_box, read_failure_alert_box,
588                         write_failure_alert_box);
589
590     wtap_init();
591
592 #ifdef HAVE_PLUGINS
593     /* Register all the plugin types we have. */
594     epan_register_plugin_types(); /* Types known to libwireshark */
595     codec_register_plugin_types(); /* Types known to libwscodecs */
596
597     /* Scan for plugins.  This does *not* call their registration routines;
598        that's done later. */
599     scan_plugins(REPORT_LOAD_FAILURE);
600
601     /* Register all libwiretap plugin modules. */
602     register_all_wiretap_modules();
603 #endif
604
605     /* Register all audio codec plugins. */
606     register_all_codecs();
607
608     splash_update(RA_DISSECTORS, NULL, NULL);
609 #ifdef DEBUG_STARTUP_TIME
610     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);
611 #endif
612     /* Register all dissectors; we must do this before checking for the
613        "-G" flag, as the "-G" flag dumps information registered by the
614        dissectors, and we must do it before we read the preferences, in
615        case any dissectors register preferences. */
616     if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
617                    splash_update, NULL)) {
618         SimpleDialog::displayQueuedMessages(main_w);
619         ret_val = INIT_FAILED;
620         goto clean_exit;
621     }
622 #ifdef DEBUG_STARTUP_TIME
623     /* epan_init resets the preferences */
624     prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
625     prefs.gui_console_open = console_open_always;
626     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
627 #endif
628
629     // Read the dynamic part of the recent file. This determines whether or
630     // not the recent list appears in the main window so the earlier we can
631     // call this the better.
632     if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
633         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
634                       "Could not open recent file\n\"%s\": %s.",
635                       rf_path, g_strerror(rf_open_errno));
636         g_free(rf_path);
637     }
638
639     splash_update(RA_LISTENERS, NULL, NULL);
640 #ifdef DEBUG_STARTUP_TIME
641     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);
642 #endif
643     /* Register all tap listeners; we do this before we parse the arguments,
644        as the "-z" argument can specify a registered tap. */
645
646     /* we register the plugin taps before the other taps because
647             stats_tree taps plugins will be registered as tap listeners
648             by stats_tree_stat.c and need to registered before that */
649 #ifdef HAVE_PLUGINS
650     register_all_plugin_tap_listeners();
651 #endif
652
653     register_all_tap_listeners();
654     conversation_table_set_gui_info(init_conversation_table);
655     hostlist_table_set_gui_info(init_endpoint_table);
656     srt_table_iterate_tables(register_service_response_tables, NULL);
657     rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
658     new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
659
660     if (ex_opt_count("read_format") > 0) {
661         in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
662     }
663
664 #ifdef HAVE_EXTCAP
665 #ifdef DEBUG_STARTUP_TIME
666     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);
667 #endif
668     splash_update(RA_EXTCAP, NULL, NULL);
669     extcap_register_preferences();
670 #endif
671     splash_update(RA_PREFERENCES, NULL, NULL);
672     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);
673
674     global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
675
676     /* Now get our args */
677     commandline_other_options(argc, argv, TRUE);
678
679     /* Convert some command-line parameters to QStrings */
680     if (global_commandline_info.cf_name != NULL)
681         cf_name = QString(global_commandline_info.cf_name);
682     if (global_commandline_info.rfilter != NULL)
683         read_filter = QString(global_commandline_info.rfilter);
684     if (global_commandline_info.dfilter != NULL)
685         dfilter = QString(global_commandline_info.dfilter);
686
687     /* Removed thread code:
688      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
689      */
690
691     timestamp_set_type(recent.gui_time_format);
692     timestamp_set_precision(recent.gui_time_precision);
693     timestamp_set_seconds_type (recent.gui_seconds_format);
694
695 #ifdef HAVE_LIBPCAP
696 #ifdef DEBUG_STARTUP_TIME
697     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);
698 #endif
699     splash_update(RA_INTERFACES, NULL, NULL);
700
701     fill_in_local_interfaces(main_window_update);
702
703     if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
704         /* We're supposed to do a live capture or get a list of link-layer
705            types for a live capture device; if the user didn't specify an
706            interface to use, pick a default. */
707         ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
708         ((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);
709         if (ret_val != 0) {
710             goto clean_exit;
711         }
712     }
713
714     if (global_commandline_info.list_link_layer_types) {
715         /* Get the list of link-layer types for the capture devices. */
716         if_capabilities_t *caps;
717         guint i;
718         interface_t device;
719         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
720
721             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
722             if (device.selected) {
723 #if defined(HAVE_PCAP_CREATE)
724                 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
725 #else
726                 caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
727 #endif
728                 if (caps == NULL) {
729                     cmdarg_err("%s", err_str);
730                     g_free(err_str);
731                     ret_val = INVALID_CAPABILITY;
732                     goto clean_exit;
733                 }
734             if (caps->data_link_types == NULL) {
735                 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
736                 ret_val = INVALID_LINK_TYPE;
737                 goto clean_exit;
738             }
739 #ifdef _WIN32
740             create_console();
741 #endif /* _WIN32 */
742 #if defined(HAVE_PCAP_CREATE)
743             capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
744 #else
745             capture_opts_print_if_capabilities(caps, device.name, FALSE);
746 #endif
747 #ifdef _WIN32
748             destroy_console();
749 #endif /* _WIN32 */
750             free_if_capabilities(caps);
751             }
752         }
753         ret_val = EXIT_SUCCESS;
754         goto clean_exit;
755     }
756
757     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
758     capture_opts_trim_ring_num_files(&global_capture_opts);
759 #endif /* HAVE_LIBPCAP */
760
761
762     /* Notify all registered modules that have had any of their preferences
763        changed either from one of the preferences file or from the command
764        line that their preferences have changed. */
765 #ifdef DEBUG_STARTUP_TIME
766     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);
767 #endif
768     prefs_apply_all();
769     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
770
771 #ifdef HAVE_LIBPCAP
772     if ((global_capture_opts.num_selected == 0) &&
773             (prefs.capture_device != NULL)) {
774         guint i;
775         interface_t device;
776         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
777             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
778             if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
779                 device.selected = TRUE;
780                 global_capture_opts.num_selected++;
781                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
782                 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
783                 break;
784             }
785         }
786     }
787 #endif
788
789     /*
790      * Enabled and disabled protocols and heuristic dissectors as per
791      * command-line options.
792      */
793     if (!setup_enabled_and_disabled_protocols()) {
794         ret_val = INVALID_OPTION;
795         goto clean_exit;
796     }
797
798     build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
799     wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
800     wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
801
802     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
803
804     /* For update of WindowTitle (When use gui.window_title preference) */
805     main_w->setWSWindowTitle();
806 ////////
807
808     packet_list_enable_color(recent.packet_list_colorize);
809
810     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
811     packet_list_enable_color(TRUE);
812
813 ////////
814
815
816 ////////
817     if (!color_filters_init(&err_msg, color_filter_add_cb)) {
818         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
819         g_free(err_msg);
820     }
821
822 ////////
823
824 #ifdef HAVE_LIBPCAP
825     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
826     if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
827         global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
828     }
829 #else /* HAVE_LIBPCAP */
830     ////////
831 #endif /* HAVE_LIBPCAP */
832
833     wsApp->allSystemsGo();
834     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);
835     SimpleDialog::displayQueuedMessages(main_w);
836
837     /* User could specify filename, or display filter, or both */
838     if (!dfilter.isEmpty())
839         main_w->filterPackets(dfilter, false);
840     if (!cf_name.isEmpty()) {
841         if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
842
843             /* Open stat windows; we do so after creating the main window,
844                to avoid Qt warnings, and after successfully opening the
845                capture file, so we know we have something to compute stats
846                on, and after registering all dissectors, so that MATE will
847                have registered its field array and we can have a tap filter
848                with one of MATE's late-registered fields as part of the
849                filter. */
850             start_requested_stats();
851
852             if(global_commandline_info.go_to_packet != 0) {
853                 /* Jump to the specified frame number, kept for backward
854                    compatibility. */
855                 cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
856             } else if (global_commandline_info.jfilter != NULL) {
857                 dfilter_t *jump_to_filter = NULL;
858                 /* try to compile given filter */
859                 if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
860                     // Similar code in MainWindow::mergeCaptureFile().
861                     QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
862                                          QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
863                                                  .arg(global_commandline_info.jfilter, err_msg),
864                                          QMessageBox::Ok);
865                     g_free(err_msg);
866                 } else {
867                     /* Filter ok, jump to the first packet matching the filter
868                        conditions. Default search direction is forward, but if
869                        option d was given, search backwards */
870                     cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
871                 }
872             }
873         }
874     }
875 #ifdef HAVE_LIBPCAP
876     else {
877         if (global_commandline_info.start_capture) {
878             if (global_capture_opts.save_file != NULL) {
879                 /* Save the directory name for future file dialogs. */
880                 /* (get_dirname overwrites filename) */
881                 gchar *s = g_strdup(global_capture_opts.save_file);
882                 set_last_open_dir(get_dirname(s));
883                 g_free(s);
884             }
885             /* "-k" was specified; start a capture. */
886 //            show_main_window(FALSE);
887             check_and_warn_user_startup(cf_name);
888
889             /* If no user interfaces were specified on the command line,
890                copy the list of selected interfaces to the set of interfaces
891                to use for this capture. */
892             if (global_capture_opts.ifaces->len == 0)
893                 collect_ifaces(&global_capture_opts);
894             CaptureFile::globalCapFile()->window = main_w;
895             if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
896                 /* The capture started.  Open stat windows; we do so after creating
897                    the main window, to avoid GTK warnings, and after successfully
898                    opening the capture file, so we know we have something to compute
899                    stats on, and after registering all dissectors, so that MATE will
900                    have registered its field array and we can have a tap filter with
901                    one of MATE's late-registered fields as part of the filter. */
902                 start_requested_stats();
903             }
904         }
905     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
906         if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
907             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
908         }
909     }
910 #endif /* HAVE_LIBPCAP */
911
912     // UAT files used in configuration profiles which are used in Qt dialogs
913     // are not registered during startup because they only get loaded when
914     // the dialog is shown.  Register them here.
915     g_free(get_persconffile_path("io_graphs", TRUE));
916
917     profile_store_persconffiles(FALSE);
918
919     ret_val = wsApp->exec();
920
921     epan_cleanup();
922
923 #ifdef HAVE_EXTCAP
924     extcap_cleanup();
925 #endif
926
927     AirPDcapDestroyContext(&airpdcap_ctx);
928
929 #ifdef _WIN32
930     /* Shutdown windows sockets */
931     WSACleanup();
932
933     /* For some unknown reason, the "atexit()" call in "create_console()"
934        doesn't arrange that "destroy_console()" be called when we exit,
935        so we call it here if a console was created. */
936     destroy_console();
937 #endif /* _WIN32 */
938
939 clean_exit:
940 #ifdef HAVE_LIBPCAP
941     capture_opts_cleanup(&global_capture_opts);
942 #endif
943     col_cleanup(&CaptureFile::globalCapFile()->cinfo);
944     wtap_cleanup();
945     free_progdirs();
946 #ifdef HAVE_PLUGINS
947     plugins_cleanup();
948 #endif
949     return ret_val;
950 }
951
952 /*
953  * Editor modelines
954  *
955  * Local Variables:
956  * c-basic-offset: 4
957  * tab-width: 8
958  * indent-tabs-mode: nil
959  * End:
960  *
961  * ex: set shiftwidth=4 tabstop=8 expandtab:
962  * :indentSize=4:tabSize=8:noTabs=true:
963  */