3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
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.
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.
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.
31 #include <zlib.h> /* to get the libz version number */
38 #ifndef HAVE_GETOPT_LONG
39 #include "wsutil/wsgetopt.h"
42 #include <wsutil/clopts_common.h>
43 #include <wsutil/cmdarg_err.h>
44 #include <wsutil/crash_info.h>
45 #include <wsutil/filesystem.h>
46 #include <wsutil/privileges.h>
48 #include <wsutil/plugins.h>
50 #include <wsutil/report_err.h>
51 #include <wsutil/u3.h>
52 #include <wsutil/unicode-utils.h>
53 #include <wsutil/ws_diag_control.h>
54 #include <wsutil/ws_version_info.h>
56 #include <epan/addr_resolv.h>
57 #include <epan/ex-opt.h>
59 #include <epan/stat_tap_ui.h>
60 #include <epan/column.h>
61 #include <epan/disabled_protos.h>
64 #include <epan/packet.h>
65 #include <epan/asn1.h>
66 #include <epan/dissectors/packet-kerberos.h>
70 #include <codecs/codecs.h>
73 /* general (not Qt specific) */
75 #include "epan/color_filters.h"
78 #include "epan/rtd_table.h"
79 #include "epan/srt_table.h"
81 #include "ui/alert_box.h"
82 #include "ui/console.h"
83 #include "ui/iface_lists.h"
84 #include "ui/language.h"
85 #include "ui/persfilepath_opt.h"
86 #include "ui/recent.h"
87 #include "ui/simple_dialog.h"
90 #include "ui/qt/conversation_dialog.h"
91 #include "ui/qt/color_utils.h"
92 #include "ui/qt/coloring_rules_dialog.h"
93 #include "ui/qt/endpoint_dialog.h"
94 #include "ui/qt/main_window.h"
95 #include "ui/qt/response_time_delay_dialog.h"
96 #include "ui/qt/service_response_time_dialog.h"
97 #include "ui/qt/simple_dialog.h"
98 #include "ui/qt/simple_statistics_dialog.h"
99 #include "ui/qt/splash_overlay.h"
100 #include "ui/qt/wireshark_application.h"
102 #include "caputils/capture-pcap-util.h"
105 # include "caputils/capture-wpcap.h"
106 # include "caputils/capture_wpcap_packet.h"
107 # include <tchar.h> /* Needed for Unicode */
108 # include <wsutil/file_util.h>
109 # include <wsutil/os_version_info.h>
113 # include <caputils/airpcap.h>
114 # include <caputils/airpcap_loader.h>
115 //# include "airpcap_dlg.h"
116 //# include "airpcap_gui_utils.h"
119 #include "epan/crypt/airpdcap_ws.h"
121 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
122 #include <QTextCodec>
125 #if defined(HAVE_LIBPCAP) || defined(HAVE_EXTCAP)
126 capture_options global_capture_opts;
129 GString *comp_info_str, *runtime_info_str;
131 /* update the main window */
132 void main_window_update(void)
134 WiresharkApplication::processEvents();
139 /* quit a nested main window */
140 void main_window_nested_quit(void)
142 // if (gtk_main_level() > 0)
146 /* quit the main window */
147 void main_window_quit(void)
152 #endif /* HAVE_LIBPCAP */
155 // xxx copied from ../gtk/main.c
157 print_usage(gboolean for_help_option) {
164 if (for_help_option) {
166 fprintf(output, "Wireshark %s\n"
167 "Interactively dump and analyze network traffic.\n"
168 "See https://www.wireshark.org for more information.\n",
169 get_ws_vcs_version_info());
173 fprintf(output, "\n");
174 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
175 fprintf(output, "\n");
178 fprintf(output, "Capture interface:\n");
179 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
180 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
181 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
182 fprintf(output, " -p don't capture in promiscuous mode\n");
183 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
184 fprintf(output, " -S update packet display when new packets are captured\n");
185 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
186 #ifdef HAVE_PCAP_CREATE
187 fprintf(output, " -I capture in monitor mode, if available\n");
189 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
190 fprintf(output, " -B <buffer size> size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
192 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
193 fprintf(output, " -D print list of interfaces and exit\n");
194 fprintf(output, " -L print list of link-layer types of iface and exit\n");
195 fprintf(output, "\n");
196 fprintf(output, "Capture stop conditions:\n");
197 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
198 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
199 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
200 fprintf(output, " files:NUM - stop after NUM files\n");
201 /*fprintf(output, "\n");*/
202 fprintf(output, "Capture output:\n");
203 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
204 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
205 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
206 #endif /* HAVE_LIBPCAP */
207 #ifdef HAVE_PCAP_REMOTE
208 fprintf(output, "RPCAP options:\n");
209 fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
211 /*fprintf(output, "\n");*/
212 fprintf(output, "Input file:\n");
213 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
215 fprintf(output, "\n");
216 fprintf(output, "Processing:\n");
217 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
218 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
219 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mnNtCd\"\n");
220 fprintf(output, " --disable-protocol <proto_name>\n");
221 fprintf(output, " disable dissection of proto_name\n");
222 fprintf(output, " --enable-heuristic <short_name>\n");
223 fprintf(output, " enable dissection of heuristic protocol\n");
224 fprintf(output, " --disable-heuristic <short_name>\n");
225 fprintf(output, " disable dissection of heuristic protocol\n");
227 fprintf(output, "\n");
228 fprintf(output, "User interface:\n");
229 fprintf(output, " -C <config profile> start with specified configuration profile\n");
230 fprintf(output, " -Y <display filter> start with the given display filter\n");
231 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
232 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
233 fprintf(output, " filter\n");
234 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
235 fprintf(output, " -m <font> set the font name used for most text\n");
236 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
237 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
238 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
239 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
241 fprintf(output, "\n");
242 fprintf(output, "Output:\n");
243 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
245 fprintf(output, "\n");
246 fprintf(output, "Miscellaneous:\n");
247 fprintf(output, " -h display this help and exit\n");
248 fprintf(output, " -v display version info and exit\n");
249 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
250 fprintf(output, " persdata:path - personal data files\n");
251 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
252 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
254 fprintf(output, " --display=DISPLAY X display to use\n");
256 fprintf(output, "\nNOTE: Not all options are implemented in the Qt port.\n");
264 * Report an error in command-line arguments.
265 * Creates a console on Windows.
267 // xxx copied from ../gtk/main.c
269 wireshark_cmdarg_err(const char *fmt, va_list ap)
274 fprintf(stderr, "wireshark: ");
275 vfprintf(stderr, fmt, ap);
276 fprintf(stderr, "\n");
280 * Report additional information for an error in command-line arguments.
281 * Creates a console on Windows.
282 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
283 * terminal isn't the standard error?
285 // xxx copied from ../gtk/main.c
287 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
292 vfprintf(stderr, fmt, ap);
293 fprintf(stderr, "\n");
296 // xxx based from ../gtk/main.c:get_gtk_compiled_info
298 get_wireshark_qt_compiled_info(GString *str)
300 g_string_append(str, "with ");
301 g_string_append_printf(str,
303 "Qt %s", QT_VERSION_STR);
305 "Qt (version unknown)");
308 /* Capture libraries */
309 g_string_append(str, ", ");
310 get_compiled_caplibs_version(str);
313 g_string_append(str, ", ");
315 g_string_append(str, "with libz ");
317 g_string_append(str, ZLIB_VERSION);
318 #else /* ZLIB_VERSION */
319 g_string_append(str, "(version unknown)");
320 #endif /* ZLIB_VERSION */
321 #else /* HAVE_LIBZ */
322 g_string_append(str, "without libz");
323 #endif /* HAVE_LIBZ */
326 // xxx copied from ../gtk/main.c
328 get_gui_compiled_info(GString *str)
330 epan_get_compiled_version_info(str);
332 g_string_append(str, ", ");
333 #ifdef QT_MULTIMEDIA_LIB
334 g_string_append(str, "with QtMultimedia");
336 g_string_append(str, "without QtMultimedia");
339 g_string_append(str, ", ");
341 get_compiled_airpcap_version(str);
343 g_string_append(str, "without AirPcap");
347 // xxx copied from ../gtk/main.c
349 get_wireshark_runtime_info(GString *str)
352 /* Capture libraries */
353 g_string_append(str, ", ");
354 get_runtime_caplibs_version(str);
358 #if defined(HAVE_LIBZ) && !defined(_WIN32)
359 g_string_append_printf(str, ", with libz %s", zlibVersion());
362 /* stuff used by libwireshark */
363 epan_get_runtime_version_info(str);
366 g_string_append(str, ", ");
367 get_runtime_airpcap_version(str);
371 g_string_append(str, ", ");
372 u3_runtime_info(str);
377 /* Check if there's something important to tell the user during startup.
378 * We want to do this *after* showing the main window so that any windows
379 * we pop up will be above the main window.
382 check_and_warn_user_startup(const QString &cf_name)
387 gchar *cur_user, *cur_group;
389 /* Tell the user not to run as root. */
390 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
391 cur_user = get_cur_username();
392 cur_group = get_cur_groupname();
393 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
394 "Running as user \"%s\" and group \"%s\".\n"
395 "This could be dangerous.\n\n"
396 "If you're running Wireshark this way in order to perform live capture, "
397 "you may want to be aware that there is a better way documented at\n"
398 "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
404 /* Warn the user if npf.sys isn't loaded. */
405 if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
406 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
407 "The NPF driver isn't running. You may have trouble\n"
408 "capturing or listing interfaces.");
416 // Try to avoid library search path collisions. QCoreApplication will
417 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
418 // the application directory. If
420 // - You have Qt version 5.x.y installed in the default location
421 // (C:\Qt\5.x) on your machine.
425 // - You install Wireshark that was built on a machine with Qt version
426 // 5.x.z installed in the default location.
428 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
429 // directory. This may not be compatible with qwindows.dll from that
430 // same path on the build machine. At any rate, loading DLLs from paths
431 // you don't control is ill-advised. We work around this by removing every
432 // path except our application directory.
435 reset_library_path(void)
437 QString app_path = QDir(get_progfile_dir()).path();
438 foreach (QString path, QCoreApplication::libraryPaths()) {
439 QCoreApplication::removeLibraryPath(path);
441 QCoreApplication::addLibraryPath(app_path);
445 /* And now our feature presentation... [ fade to music ] */
446 int main(int argc, char *argv[])
451 gboolean arg_error = FALSE;
452 char **ws_argv = argv;
460 char *gdp_path, *dp_path;
463 gboolean start_capture = FALSE;
464 gboolean list_link_layer_types = FALSE;
469 gboolean capture_option_specified = FALSE;
478 guint go_to_packet = 0;
480 QString dfilter, read_filter;
481 GSList *disable_protocol_slist = NULL;
482 GSList *enable_heur_slist = NULL;
483 GSList *disable_heur_slist = NULL;
485 cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
487 // In Qt 5, C strings are treated always as UTF-8 when converted to
488 // QStrings; in Qt 4, the codec must be set to make that happen
489 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
490 // Hopefully we won't have to use QString::fromUtf8() in as many places.
491 QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
492 QTextCodec::setCodecForCStrings(utf8codec);
493 // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
494 QTextCodec::setCodecForTr(utf8codec);
497 /* Set the C-language locale to the native environment. */
498 // The GTK+ UI calls this. Should we as well?
499 //setlocale(LC_ALL, "");
501 // QCoreApplication clobbers argv. Let's have a local copy.
502 ws_argv = (char **) g_malloc(sizeof(char *) * argc);
503 for (opt = 0; opt < argc; opt++) {
504 ws_argv[opt] = argv[opt];
506 arg_list_utf_16to8(argc, ws_argv);
507 create_app_running_mutex();
511 * Get credential information for later use, and drop privileges
512 * before doing anything else.
513 * Let the user know if anything happened.
515 init_process_policies();
516 relinquish_special_privs_perm();
519 * Attempt to get the pathname of the executable file.
521 /* init_progfile_dir_error = */ init_progfile_dir(ws_argv[0],
522 (int (*)(int, char **)) get_gui_compiled_info);
523 g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
526 /* Load wpcap if possible. Do this before collecting the run-time version information */
529 /* ... and also load the packet.dll from wpcap */
533 /* Load the airpcap.dll. This must also be done before collecting
534 * run-time version information. */
537 airpcap_dll_ret_val = load_airpcap();
539 switch (airpcap_dll_ret_val) {
541 /* load the airpcap interfaces */
542 g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
544 if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
545 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
546 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
549 airpcap_if_active = NULL;
553 /* select the first ad default (THIS SHOULD BE CHANGED) */
554 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
558 * XXX - Maybe we need to warn the user if one of the following happens???
560 case AIRPCAP_DLL_OLD:
561 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
564 case AIRPCAP_DLL_ERROR:
565 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
568 case AIRPCAP_DLL_NOT_FOUND:
569 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
573 #endif /* HAVE_AIRPCAP */
576 /* Get the compile-time version information string */
578 comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
579 get_gui_compiled_info);
581 /* Assemble the run-time version information string */
583 runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
586 * In order to have the -X opts assigned before the wslua machine starts
587 * we need to call getopt_long before epan_init() gets called.
589 * In addition, we process "console only" parameters (ones where we
590 * send output to the console and exit) here, so we don't start Qt
591 * if we're only showing command-line help or version information.
593 * XXX - this pre-scan is done before we start Qt, so we haven't
594 * run WiresharkApplication's constructor on the arguments. That
595 * means that Qt arguments have not been removed from the argument
596 * list; those arguments begin with "-", and may be treated as
597 * errors by getopt_long().
599 * We thus ignore errors - *and* set "opterr" to 0 to suppress the
602 * XXX - is there some way to parse and remove Qt arguments without
603 * starting up the GUI, which we can call before calling this?
605 * In order to handle, for example, -o options, we also need to call it
606 * *after* epan_init() gets called, so that the dissectors have had a
607 * chance to register their preferences, so we have another getopt_long()
610 * XXX - can we do this all with one getopt_long() call, saving the
611 * arguments we can't handle until after initializing libwireshark,
612 * and then process them after initializing libwireshark?
614 * Note that we don't want to initialize libwireshark until after the
615 * GUI is up, as that can take a while, and we want a window of some
616 * sort up to show progress while that's happening.
618 // XXX Should the remaining code be in WiresharkApplcation::WiresharkApplication?
619 #define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:g:Hh" "jJ:kK:lm:nN:o:P:r:R:St:u:vw:X:Y:z:"
620 static const struct option long_options[] = {
621 {"help", no_argument, NULL, 'h'},
622 {"read-file", required_argument, NULL, 'r' },
623 {"read-filter", required_argument, NULL, 'R' },
624 {"display-filter", required_argument, NULL, 'Y' },
625 {"version", no_argument, NULL, 'v'},
626 LONGOPT_CAPTURE_COMMON
629 static const char optstring[] = OPTSTRING;
633 while ((opt = getopt_long(argc, ws_argv, optstring, long_options, NULL)) != -1) {
635 case 'C': /* Configuration Profile */
636 if (profile_exists (optarg, FALSE)) {
637 set_profile_name (optarg);
639 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
643 case 'D': /* Print a list of capture devices and exit */
645 if_list = capture_interface_list(&err, &err_str, NULL);
646 if (if_list == NULL) {
648 cmdarg_err("There are no interfaces on which a capture can be done");
650 cmdarg_err("%s", err_str);
658 capture_opts_print_interfaces(if_list);
659 free_interface_list(if_list);
664 #else /* HAVE_LIBPCAP */
665 capture_option_specified = TRUE;
667 #endif /* HAVE_LIBPCAP */
669 case 'h': /* Print help and exit */
675 if (strcmp(optarg, "-") == 0)
676 set_stdin_capture(TRUE);
679 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
680 if (!persfilepath_opt(opt, optarg)) {
681 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
685 case 'v': /* Show version and exit */
689 show_version("Wireshark", comp_info_str, runtime_info_str);
697 * Extension command line options have to be processed before
698 * we call epan_init() as they are supposed to be used by dissectors
699 * or taps very early in the registration process.
703 case '?': /* Ignore errors - the "real" scan will catch them. */
709 reset_library_path();
712 /* Create The Wireshark app */
713 WiresharkApplication ws_app(argc, argv);
715 /* initialize the funnel mini-api */
717 //initialize_funnel_ops();
719 AirPDcapInitContext(&airpdcap_ctx);
723 unsigned int in_file_type = WTAP_TYPE_AUTO;
725 /* Add it to the information to be reported on a crash. */
726 ws_add_crash_info("Wireshark %s\n"
731 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
734 /* Start windows sockets */
735 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
738 profile_store_persconffiles(TRUE);
740 /* Read the profile independent recent file. We have to do this here so we can */
741 /* set the profile before it can be set from the command line parameter */
742 if (!recent_read_static(&rf_path, &rf_open_errno)) {
743 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
744 "Could not open common recent file\n\"%s\": %s.",
745 rf_path, strerror(rf_open_errno));
749 /* Read the profile dependent (static part) of the recent file. */
750 /* Only the static part of it will be read, as we don't have the gui now to fill the */
751 /* recent lists which is done in the dynamic part. */
752 /* We have to do this already here, so command line parameters can overwrite these values. */
753 if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
754 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
755 "Could not open recent file\n\"%s\": %s.",
756 rf_path, g_strerror(rf_open_errno));
759 wsApp->applyCustomColorsFromRecent();
761 // Initialize our language
762 read_language_prefs();
763 locale = QString(language);
764 wsApp->loadLanguage(locale);
766 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
768 // Init the main window (and splash)
769 main_w = new(MainWindow);
771 // We may not need a queued connection here but it would seem to make sense
772 // to force the issue.
773 main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
774 main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
776 /* Init the "Open file" dialog directory */
777 /* (do this after the path settings are processed) */
778 if (recent.gui_fileopen_remembered_dir &&
779 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
780 wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
782 wsApp->setLastOpenDir(get_persdatafile_dir());
786 // Replicates behavior in gtk_init();
787 signal(SIGPIPE, SIG_IGN);
790 set_console_log_handler();
793 /* Set the initial values in the capture options. This might be overwritten
794 by preference settings and then again by the command line parameters. */
795 capture_opts_init(&global_capture_opts);
798 init_report_err(failure_alert_box, open_failure_alert_box,
799 read_failure_alert_box, write_failure_alert_box);
801 init_open_routines();
804 /* Register all the plugin types we have. */
805 epan_register_plugin_types(); /* Types known to libwireshark */
806 wtap_register_plugin_types(); /* Types known to libwiretap */
807 codec_register_plugin_types(); /* Types known to libwscodecs */
809 /* Scan for plugins. This does *not* call their registration routines;
810 that's done later. */
813 /* Register all libwiretap plugin modules. */
814 register_all_wiretap_modules();
816 /* Register all audio codec plugins. */
817 register_all_codecs();
820 /* Register all dissectors; we must do this before checking for the
821 "-G" flag, as the "-G" flag dumps information registered by the
822 dissectors, and we must do it before we read the preferences, in
823 case any dissectors register preferences. */
824 if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
825 splash_update, NULL)) {
826 SimpleDialog::displayQueuedMessages(main_w);
830 splash_update(RA_LISTENERS, NULL, NULL);
832 /* Register all tap listeners; we do this before we parse the arguments,
833 as the "-z" argument can specify a registered tap. */
835 /* we register the plugin taps before the other taps because
836 stats_tree taps plugins will be registered as tap listeners
837 by stats_tree_stat.c and need to registered before that */
839 register_all_plugin_tap_listeners();
842 register_all_tap_listeners();
843 conversation_table_set_gui_info(init_conversation_table);
844 hostlist_table_set_gui_info(init_endpoint_table);
845 srt_table_iterate_tables(register_service_response_tables, NULL);
846 rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
847 new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
849 if (ex_opt_count("read_format") > 0) {
850 in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
853 splash_update(RA_PREFERENCES, NULL, NULL);
855 prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
858 * To reset the options parser, set optreset to 1 on platforms that
859 * have optreset (documented in *BSD and OS X, apparently present but
860 * not documented in Solaris - the Illumos repository seems to
861 * suggest that the first Solaris getopt_long(), at least as of 2004,
862 * was based on the NetBSD one, it had optreset) and set optind to 1,
863 * and set optind to 0 otherwise (documented as working in the GNU
864 * getopt_long(). Setting optind to 0 didn't originally work in the
865 * NetBSD one, but that was added later - we don't want to depend on
866 * it if we have optreset).
868 * Also reset opterr to 1, so that error messages are printed by
871 * XXX - if we want to control all the command-line option errors, so
872 * that we can display them where we choose (e.g., in a window), we'd
873 * want to leave opterr as 0, and produce our own messages using optopt.
874 * We'd have to check the value of optopt to see if it's a valid option
875 * letter, in which case *presumably* the error is "this option requires
876 * an argument but none was specified", or not a valid option letter,
877 * in which case *presumably* the error is "this option isn't valid".
878 * Some versions of getopt() let you supply a option string beginning
879 * with ':', which means that getopt() will return ':' rather than '?'
880 * for "this option requires an argument but none was specified", but
881 * not all do. But we're now using getopt_long() - what does it do?
891 /* Now get our args */
892 while ((opt = getopt_long(argc, ws_argv, optstring, long_options, NULL)) != -1) {
894 /*** capture option specific ***/
895 case 'a': /* autostop criteria */
896 case 'b': /* Ringbuffer option */
897 case 'c': /* Capture xxx packets */
898 case 'f': /* capture filter */
899 case 'k': /* Start capture immediately */
900 case 'H': /* Hide capture info dialog box */
901 case 'p': /* Don't capture in promiscuous mode */
902 case 'i': /* Use interface x */
903 #ifdef HAVE_PCAP_CREATE
904 case 'I': /* Capture in monitor mode, if available */
906 #ifdef HAVE_PCAP_REMOTE
907 case 'A': /* Authentication */
909 case 's': /* Set the snapshot (capture) length */
910 case 'S': /* "Sync" mode: used for following file ala tail -f */
911 case 'w': /* Write to capture file xxx */
912 case 'y': /* Set the pcap data link type */
913 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
914 case 'B': /* Buffer size */
917 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
923 capture_option_specified = TRUE;
928 case 'K': /* Kerberos keytab file */
929 read_keytab_file(optarg);
933 /*** all non capture option specific ***/
935 /* Configuration profile settings were already processed just ignore them this time*/
937 case 'j': /* Search backwards for a matching packet from filter in option J */
938 /* Not supported yet */
940 case 'g': /* Go to packet with the given packet number */
941 go_to_packet = get_positive_int(optarg, "go to packet");
943 case 'J': /* Jump to the first packet which matches the filter criteria */
944 /* Not supported yet */
946 case 'l': /* Automatic scrolling in live capture mode */
948 /* Not supported yet */
950 capture_option_specified = TRUE;
954 case 'L': /* Print list of link-layer types and exit */
956 list_link_layer_types = TRUE;
958 capture_option_specified = TRUE;
962 case 'm': /* Fixed-width font for the display */
963 /* Not supported yet */
965 case 'n': /* No name resolution */
966 disable_name_resolution();
968 case 'N': /* Select what types of addresses/port #s to resolve */
969 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
970 if (badopt != '\0') {
971 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'C', 'd', m', 'n', 'N', and 't'",
976 case 'o': /* Override preference from command line */
977 switch (prefs_set_pref(optarg)) {
980 case PREFS_SET_SYNTAX_ERR:
981 cmdarg_err("Invalid -o flag \"%s\"", optarg);
984 case PREFS_SET_NO_SUCH_PREF:
985 /* not a preference, might be a recent setting */
986 switch (recent_set_arg(optarg)) {
989 case PREFS_SET_SYNTAX_ERR:
990 /* shouldn't happen, checked already above */
991 cmdarg_err("Invalid -o flag \"%s\"", optarg);
994 case PREFS_SET_NO_SUCH_PREF:
995 case PREFS_SET_OBSOLETE:
996 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
1001 g_assert_not_reached();
1004 case PREFS_SET_OBSOLETE:
1005 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
1010 g_assert_not_reached();
1014 /* Path settings were already processed just ignore them this time*/
1019 case 'R': /* Read file filter */
1020 read_filter = QString(optarg);
1022 case 't': /* Time stamp type */
1023 if (strcmp(optarg, "r") == 0)
1024 timestamp_set_type(TS_RELATIVE);
1025 else if (strcmp(optarg, "a") == 0)
1026 timestamp_set_type(TS_ABSOLUTE);
1027 else if (strcmp(optarg, "ad") == 0)
1028 timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
1029 else if (strcmp(optarg, "adoy") == 0)
1030 timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
1031 else if (strcmp(optarg, "d") == 0)
1032 timestamp_set_type(TS_DELTA);
1033 else if (strcmp(optarg, "dd") == 0)
1034 timestamp_set_type(TS_DELTA_DIS);
1035 else if (strcmp(optarg, "e") == 0)
1036 timestamp_set_type(TS_EPOCH);
1037 else if (strcmp(optarg, "u") == 0)
1038 timestamp_set_type(TS_UTC);
1039 else if (strcmp(optarg, "ud") == 0)
1040 timestamp_set_type(TS_UTC_WITH_YMD);
1041 else if (strcmp(optarg, "udoy") == 0)
1042 timestamp_set_type(TS_UTC_WITH_YDOY);
1044 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
1046 "It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
1048 "\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
1050 "\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
1052 "\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
1054 "or \"udoy\" for absolute UTC with YYYY/DOY date.");
1058 case 'u': /* Seconds type */
1059 if (strcmp(optarg, "s") == 0)
1060 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
1061 else if (strcmp(optarg, "hms") == 0)
1062 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
1064 cmdarg_err("Invalid seconds type \"%s\"", optarg);
1066 "It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
1071 /* ext ops were already processed just ignore them this time*/
1074 dfilter = QString(optarg);
1077 /* We won't call the init function for the stat this soon
1078 as it would disallow MATE's fields (which are registered
1079 by the preferences set callback) from being used as
1080 part of a tap filter. Instead, we just add the argument
1081 to a list of stat arguments. */
1082 if (strcmp("help", optarg) == 0) {
1083 fprintf(stderr, "wireshark: The available statistics for the \"-z\" option are:\n");
1084 list_stat_cmd_args();
1087 if (!process_stat_cmd_arg(optarg)) {
1088 cmdarg_err("Invalid -z argument.");
1089 cmdarg_err_cont(" -z argument must be one of :");
1090 list_stat_cmd_args();
1094 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
1095 disable_protocol_slist = g_slist_append(disable_protocol_slist, optarg);
1097 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
1098 enable_heur_slist = g_slist_append(enable_heur_slist, optarg);
1100 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
1101 disable_heur_slist = g_slist_append(disable_heur_slist, optarg);
1105 case '?': /* Bad flag - print usage message */
1116 if (!cf_name.isEmpty()) {
1118 * Input file name specified with "-r" *and* specified as a regular
1119 * command-line argument.
1121 cmdarg_err("File name specified both with -r and regular argument");
1125 * Input file name not specified with "-r", and a command-line argument
1126 * was specified; treat it as the input file name.
1128 * Yes, this is different from tshark, where non-flag command-line
1129 * arguments are a filter, but this works better on GUI desktops
1130 * where a command can be specified to be run to open a particular
1131 * file - yes, you could have "-r" as the last part of the command,
1132 * but that's a bit ugly.
1134 cf_name = ws_argv[0];
1143 * Extra command line arguments were specified; complain.
1145 cmdarg_err("Invalid argument: %s", ws_argv[0]);
1150 #ifndef HAVE_LIBPCAP
1151 if (capture_option_specified) {
1152 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
1159 /* Removed thread code:
1160 * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
1163 // XXX Is there a better place to set the timestamp format & precision?
1164 timestamp_set_type(recent.gui_time_format);
1165 timestamp_set_precision(recent.gui_time_precision);
1166 timestamp_set_seconds_type (recent.gui_seconds_format);
1169 fill_in_local_interfaces(main_window_update);
1171 if (start_capture && list_link_layer_types) {
1172 /* Specifying *both* is bogus. */
1173 cmdarg_err("You can't specify both -L and a live capture.");
1177 if (list_link_layer_types) {
1178 /* We're supposed to list the link-layer types for an interface;
1179 did the user also specify a capture file to be read? */
1180 if (!cf_name.isEmpty()) {
1181 /* Yes - that's bogus. */
1182 cmdarg_err("You can't specify -L and a capture file to be read.");
1185 /* No - did they specify a ring buffer option? */
1186 if (global_capture_opts.multi_files_on) {
1187 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
1191 /* We're supposed to do a live capture; did the user also specify
1192 a capture file to be read? */
1193 if (start_capture && !cf_name.isEmpty()) {
1194 /* Yes - that's bogus. */
1195 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
1199 /* No - was the ring buffer option specified and, if so, does it make
1201 if (global_capture_opts.multi_files_on) {
1202 /* Ring buffer works only under certain conditions:
1203 a) ring buffer does not work with temporary files;
1204 b) real_time_mode and multi_files_on are mutually exclusive -
1205 real_time_mode takes precedence;
1206 c) it makes no sense to enable the ring buffer if the maximum
1207 file size is set to "infinite". */
1208 if (global_capture_opts.save_file == NULL) {
1209 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
1210 global_capture_opts.multi_files_on = FALSE;
1212 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
1213 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
1214 /* XXX - this must be redesigned as the conditions changed */
1219 if (start_capture || list_link_layer_types) {
1220 /* We're supposed to do a live capture or get a list of link-layer
1221 types for a live capture device; if the user didn't specify an
1222 interface to use, pick a default. */
1223 status = capture_opts_default_iface_if_necessary(&global_capture_opts,
1224 ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
1230 if (list_link_layer_types) {
1231 /* Get the list of link-layer types for the capture devices. */
1232 if_capabilities_t *caps;
1235 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
1237 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
1238 if (device.selected) {
1239 #if defined(HAVE_PCAP_CREATE)
1240 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
1242 caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
1245 cmdarg_err("%s", err_str);
1249 if (caps->data_link_types == NULL) {
1250 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
1256 #if defined(HAVE_PCAP_CREATE)
1257 capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
1259 capture_opts_print_if_capabilities(caps, device.name, FALSE);
1264 free_if_capabilities(caps);
1270 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
1271 capture_opts_trim_ring_num_files(&global_capture_opts);
1272 #endif /* HAVE_LIBPCAP */
1274 /* Notify all registered modules that have had any of their preferences
1275 changed either from one of the preferences file or from the command
1276 line that their preferences have changed. */
1278 wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
1281 if ((global_capture_opts.num_selected == 0) &&
1282 (prefs.capture_device != NULL)) {
1285 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
1286 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
1287 if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
1288 device.selected = TRUE;
1289 global_capture_opts.num_selected++;
1290 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
1291 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
1298 /* disabled protocols as per configuration file */
1299 if (gdp_path == NULL && dp_path == NULL) {
1300 set_disabled_protos_list();
1301 set_disabled_heur_dissector_list();
1304 if(disable_protocol_slist) {
1305 GSList *proto_disable;
1306 for (proto_disable = disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
1308 proto_disable_proto_by_name((char*)proto_disable->data);
1312 if(enable_heur_slist) {
1313 GSList *heur_enable;
1314 for (heur_enable = enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
1316 proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
1320 if(disable_heur_slist) {
1321 GSList *heur_disable;
1322 for (heur_disable = disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
1324 proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
1328 build_column_format_array(&CaptureFile::globalCapFile()->cinfo, prefs_p->num_cols, TRUE);
1329 wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
1330 wsApp->emitAppSignal(WiresharkApplication::RecentFilesRead); // Must be emitted after PreferencesChanged.
1332 wsApp->setMonospaceFont(prefs.gui_qt_font_name);
1334 /* For update of WindowTitle (When use gui.window_title preference) */
1335 main_w->setWSWindowTitle();
1338 /* Read the dynamic part of the recent file, as we have the gui now ready for
1340 if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
1341 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1342 "Could not open recent file\n\"%s\": %s.",
1343 rf_path, g_strerror(rf_open_errno));
1347 packet_list_enable_color(recent.packet_list_colorize);
1349 g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
1350 packet_list_enable_color(TRUE);
1356 gchar* err_msg = NULL;
1357 if (!color_filters_init(&err_msg, color_filter_add_cb)) {
1358 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
1365 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
1366 if (!start_capture && !global_capture_opts.default_options.cfilter) {
1367 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
1369 #else /* HAVE_LIBPCAP */
1371 #endif /* HAVE_LIBPCAP */
1373 wsApp->allSystemsGo();
1374 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
1375 SimpleDialog::displayQueuedMessages(main_w);
1377 /* User could specify filename, or display filter, or both */
1378 if (!dfilter.isEmpty())
1379 main_w->filterPackets(dfilter, false);
1380 if (!cf_name.isEmpty()) {
1381 if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
1383 /* Open stat windows; we do so after creating the main window,
1384 to avoid Qt warnings, and after successfully opening the
1385 capture file, so we know we have something to compute stats
1386 on, and after registering all dissectors, so that MATE will
1387 have registered its field array and we can have a tap filter
1388 with one of MATE's late-registered fields as part of the
1390 start_requested_stats();
1392 if(go_to_packet != 0) {
1393 /* Jump to the specified frame number, kept for backward
1395 cf_goto_frame(CaptureFile::globalCapFile(), go_to_packet);
1401 if (start_capture) {
1402 if (global_capture_opts.save_file != NULL) {
1403 /* Save the directory name for future file dialogs. */
1404 /* (get_dirname overwrites filename) */
1405 gchar *s = get_dirname(g_strdup(global_capture_opts.save_file));
1406 set_last_open_dir(s);
1409 /* "-k" was specified; start a capture. */
1410 // show_main_window(FALSE);
1411 check_and_warn_user_startup(cf_name);
1413 /* If no user interfaces were specified on the command line,
1414 copy the list of selected interfaces to the set of interfaces
1415 to use for this capture. */
1416 if (global_capture_opts.ifaces->len == 0)
1417 collect_ifaces(&global_capture_opts);
1418 CaptureFile::globalCapFile()->window = main_w;
1419 if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
1420 /* The capture started. Open stat windows; we do so after creating
1421 the main window, to avoid GTK warnings, and after successfully
1422 opening the capture file, so we know we have something to compute
1423 stats on, and after registering all dissectors, so that MATE will
1424 have registered its field array and we can have a tap filter with
1425 one of MATE's late-registered fields as part of the filter. */
1426 start_requested_stats();
1429 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
1430 if (!start_capture && !global_capture_opts.default_options.cfilter) {
1431 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
1434 #endif /* HAVE_LIBPCAP */
1436 return wsApp->exec();
1445 * indent-tabs-mode: nil
1448 * ex: set shiftwidth=4 tabstop=8 expandtab:
1449 * :indentSize=4:tabSize=8:noTabs=true: