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/ws_version_info.h>
54 #include <epan/addr_resolv.h>
55 #include <epan/ex-opt.h>
57 #include <epan/stat_tap_ui.h>
58 #include <epan/column.h>
59 #include <epan/disabled_protos.h>
62 #include <epan/packet.h>
63 #include <epan/asn1.h>
64 #include <epan/dissectors/packet-kerberos.h>
68 #include <codecs/codecs.h>
71 /* general (not Qt specific) */
74 #include "color_filters.h"
78 #include "ui/alert_box.h"
79 #include "ui/console.h"
80 #include "ui/iface_lists.h"
81 #include "ui/language.h"
82 #include "ui/persfilepath_opt.h"
83 #include "ui/recent.h"
84 #include "ui/simple_dialog.h"
86 #include "ui/qt/simple_dialog.h"
87 #include "ui/qt/main_window.h"
88 #include "ui/qt/splash_overlay.h"
89 #include "ui/qt/wireshark_application.h"
91 #include "caputils/capture-pcap-util.h"
94 # include "caputils/capture-wpcap.h"
95 # include "caputils/capture_wpcap_packet.h"
96 # include <tchar.h> /* Needed for Unicode */
97 # include <wsutil/file_util.h>
98 # include <wsutil/os_version_info.h>
102 # include <caputils/airpcap.h>
103 # include <caputils/airpcap_loader.h>
104 //# include "airpcap_dlg.h"
105 //# include "airpcap_gui_utils.h"
108 #include "epan/crypt/airpdcap_ws.h"
110 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
111 #include <QTextCodec>
114 #include "ui/qt/conversation_dialog.h"
115 #include "ui/qt/endpoint_dialog.h"
118 capture_options global_capture_opts;
122 int airpcap_dll_ret_val = -1;
125 GString *comp_info_str, *runtime_info_str;
127 /* update the main window */
128 void main_window_update(void)
130 WiresharkApplication::processEvents();
135 /* quit a nested main window */
136 void main_window_nested_quit(void)
138 // if (gtk_main_level() > 0)
142 /* quit the main window */
143 void main_window_quit(void)
148 #endif /* HAVE_LIBPCAP */
151 // xxx copied from ../gtk/main.c
153 print_usage(gboolean for_help_option) {
160 if (for_help_option) {
162 fprintf(output, "Wireshark %s\n"
163 "Interactively dump and analyze network traffic.\n"
164 "See http://www.wireshark.org for more information.\n",
165 get_ws_vcs_version_info());
169 fprintf(output, "\n");
170 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
171 fprintf(output, "\n");
174 fprintf(output, "Capture interface:\n");
175 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
176 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
177 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
178 fprintf(output, " -p don't capture in promiscuous mode\n");
179 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
180 fprintf(output, " -S update packet display when new packets are captured\n");
181 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
182 #ifdef HAVE_PCAP_CREATE
183 fprintf(output, " -I capture in monitor mode, if available\n");
185 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
186 fprintf(output, " -B <buffer size> size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
188 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
189 fprintf(output, " -D print list of interfaces and exit\n");
190 fprintf(output, " -L print list of link-layer types of iface and exit\n");
191 fprintf(output, "\n");
192 fprintf(output, "Capture stop conditions:\n");
193 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
194 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
195 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
196 fprintf(output, " files:NUM - stop after NUM files\n");
197 /*fprintf(output, "\n");*/
198 fprintf(output, "Capture output:\n");
199 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
200 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
201 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
202 #endif /* HAVE_LIBPCAP */
203 #ifdef HAVE_PCAP_REMOTE
204 fprintf(output, "RPCAP options:\n");
205 fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
207 /*fprintf(output, "\n");*/
208 fprintf(output, "Input file:\n");
209 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
211 fprintf(output, "\n");
212 fprintf(output, "Processing:\n");
213 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
214 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
215 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
217 fprintf(output, "\n");
218 fprintf(output, "User interface:\n");
219 fprintf(output, " -C <config profile> start with specified configuration profile\n");
220 fprintf(output, " -Y <display filter> start with the given display filter\n");
221 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
222 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
223 fprintf(output, " filter\n");
224 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
225 fprintf(output, " -m <font> set the font name used for most text\n");
226 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
227 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
228 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
229 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
231 fprintf(output, "\n");
232 fprintf(output, "Output:\n");
233 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
235 fprintf(output, "\n");
236 fprintf(output, "Miscellaneous:\n");
237 fprintf(output, " -h display this help and exit\n");
238 fprintf(output, " -v display version info and exit\n");
239 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
240 fprintf(output, " persdata:path - personal data files\n");
241 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
242 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
244 fprintf(output, " --display=DISPLAY X display to use\n");
246 fprintf(output, "\nNOTE: Not all options are implemented in the Qt port.\n");
254 * Report an error in command-line arguments.
255 * Creates a console on Windows.
257 // xxx copied from ../gtk/main.c
259 wireshark_cmdarg_err(const char *fmt, va_list ap)
264 fprintf(stderr, "wireshark: ");
265 vfprintf(stderr, fmt, ap);
266 fprintf(stderr, "\n");
270 * Report additional information for an error in command-line arguments.
271 * Creates a console on Windows.
272 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
273 * terminal isn't the standard error?
275 // xxx copied from ../gtk/main.c
277 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
282 vfprintf(stderr, fmt, ap);
283 fprintf(stderr, "\n");
286 // xxx based from ../gtk/main.c:get_gtk_compiled_info
288 get_wireshark_qt_compiled_info(GString *str)
290 g_string_append(str, "with ");
291 g_string_append_printf(str,
293 "Qt %s", QT_VERSION_STR);
295 "Qt (version unknown)");
298 /* Capture libraries */
299 g_string_append(str, ", ");
300 get_compiled_caplibs_version(str);
303 g_string_append(str, ", ");
305 g_string_append(str, "with libz ");
307 g_string_append(str, ZLIB_VERSION);
308 #else /* ZLIB_VERSION */
309 g_string_append(str, "(version unknown)");
310 #endif /* ZLIB_VERSION */
311 #else /* HAVE_LIBZ */
312 g_string_append(str, "without libz");
313 #endif /* HAVE_LIBZ */
316 // xxx copied from ../gtk/main.c
318 get_gui_compiled_info(GString *str)
320 epan_get_compiled_version_info(str);
322 g_string_append(str, ", ");
323 g_string_append(str, "without PortAudio");
325 g_string_append(str, ", ");
327 get_compiled_airpcap_version(str);
329 g_string_append(str, "without AirPcap");
333 // xxx copied from ../gtk/main.c
335 get_wireshark_runtime_info(GString *str)
338 /* Capture libraries */
339 g_string_append(str, ", ");
340 get_runtime_caplibs_version(str);
344 #if defined(HAVE_LIBZ) && !defined(_WIN32)
345 g_string_append_printf(str, ", with libz %s", zlibVersion());
348 /* stuff used by libwireshark */
349 epan_get_runtime_version_info(str);
352 g_string_append(str, ", ");
353 get_runtime_airpcap_version(str);
357 g_string_append(str, ", ");
358 u3_runtime_info(str);
363 /* Check if there's something important to tell the user during startup.
364 * We want to do this *after* showing the main window so that any windows
365 * we pop up will be above the main window.
368 check_and_warn_user_startup(const QString &cf_name)
373 gchar *cur_user, *cur_group;
375 /* Tell the user not to run as root. */
376 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
377 cur_user = get_cur_username();
378 cur_group = get_cur_groupname();
379 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
380 "Running as user \"%s\" and group \"%s\".\n"
381 "This could be dangerous.\n\n"
382 "If you're running Wireshark this way in order to perform live capture, "
383 "you may want to be aware that there is a better way documented at\n"
384 "http://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
390 /* Warn the user if npf.sys isn't loaded. */
391 if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
392 simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
393 "The NPF driver isn't running. You may have trouble\n"
394 "capturing or listing interfaces.");
402 // Try to avoid library search path collisions. QCoreApplication will
403 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
404 // the application directory. If
406 // - You have Qt version 5.x.y installed in the default location
407 // (C:\Qt\5.x) on your machine.
411 // - You install Wireshark that was built on a machine with Qt version
412 // 5.x.z installed in the default location.
414 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
415 // directory. This may not be compatible with qwindows.dll from that
416 // same path on the build machine. At any rate, loading DLLs from paths
417 // you don't control is ill-advised. We work around this by removing every
418 // path except our application directory.
421 reset_library_path(void)
423 QString app_path = QDir(get_progfile_dir()).path();
424 foreach (QString path, QCoreApplication::libraryPaths()) {
425 QCoreApplication::removeLibraryPath(path);
427 QCoreApplication::addLibraryPath(app_path);
431 /* And now our feature presentation... [ fade to music ] */
432 int main(int argc, char *argv[])
437 gboolean arg_error = FALSE;
445 char *gdp_path, *dp_path;
448 gboolean start_capture = FALSE;
449 gboolean list_link_layer_types = FALSE;
454 gboolean capture_option_specified = FALSE;
463 guint go_to_packet = 0;
465 QString dfilter, read_filter;
467 cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
470 create_app_running_mutex();
474 * Get credential information for later use, and drop privileges
475 * before doing anything else.
476 * Let the user know if anything happened.
478 init_process_policies();
479 relinquish_special_privs_perm();
482 * Attempt to get the pathname of the executable file.
484 /* init_progfile_dir_error = */ init_progfile_dir(argv[0], main);
485 g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
487 /* Get the compile-time version information string */
489 comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
490 get_gui_compiled_info);
492 /* Assemble the run-time version information string */
494 runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
497 * In order to have the -X opts assigned before the wslua machine starts
498 * we need to call getopt_long before epan_init() gets called.
500 * In addition, we process "console only" parameters (ones where we
501 * send output to the console and exit) here, so we don't start Qt
502 * if we're only showing command-line help or version information.
504 * XXX - this pre-scan is done before we start Qt, so we haven't
505 * run WiresharkApplication's constructor on the arguments. That
506 * means that Qt arguments have not been removed from the argument
507 * list; those arguments begin with "-", and may be treated as
508 * errors by getopt_long().
510 * We thus ignore errors - *and* set "opterr" to 0 to suppress the
513 * XXX - is there some way to parse and remove Qt arguments without
514 * starting up the GUI, which we can call before calling this?
516 * In order to handle, for example, -o options, we also need to call it
517 * *after* epan_init() gets called, so that the dissectors have had a
518 * chance to register their preferences, so we have another getopt_long()
521 * XXX - can we do this all with one getopt_long() call, saving the
522 * arguments we can't handle until after initializing libwireshark,
523 * and then process them after initializing libwireshark?
525 * Note that we don't want to initialize libwireshark until after the
526 * GUI is up, as that can take a while, and we want a window of some
527 * sort up to show progress while that's happening.
529 // XXX Should the remaining code be in WiresharkApplcation::WiresharkApplication?
530 #define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:g:Hh" "jJ:kK:lm:nN:o:P:r:R:St:u:vw:X:Y:z:"
531 static const struct option long_options[] = {
532 {(char *)"help", no_argument, NULL, 'h'},
533 {(char *)"read-file", required_argument, NULL, 'r' },
534 {(char *)"read-filter", required_argument, NULL, 'R' },
535 {(char *)"display-filter", required_argument, NULL, 'Y' },
536 {(char *)"version", no_argument, NULL, 'v'},
537 LONGOPT_CAPTURE_COMMON
540 static const char optstring[] = OPTSTRING;
544 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
546 case 'C': /* Configuration Profile */
547 if (profile_exists (optarg, FALSE)) {
548 set_profile_name (optarg);
550 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
554 case 'D': /* Print a list of capture devices and exit */
556 if_list = capture_interface_list(&err, &err_str, NULL);
557 if (if_list == NULL) {
559 cmdarg_err("There are no interfaces on which a capture can be done");
561 cmdarg_err("%s", err_str);
569 capture_opts_print_interfaces(if_list);
570 free_interface_list(if_list);
575 #else /* HAVE_LIBPCAP */
576 capture_option_specified = TRUE;
578 #endif /* HAVE_LIBPCAP */
580 case 'h': /* Print help and exit */
586 if (strcmp(optarg, "-") == 0)
587 set_stdin_capture(TRUE);
590 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
591 if (!persfilepath_opt(opt, optarg)) {
592 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
596 case 'v': /* Show version and exit */
600 show_version("Wireshark", comp_info_str, runtime_info_str);
608 * Extension command line options have to be processed before
609 * we call epan_init() as they are supposed to be used by dissectors
610 * or taps very early in the registration process.
614 case '?': /* Ignore errors - the "real" scan will catch them. */
620 reset_library_path();
623 /* Create The Wireshark app */
624 WiresharkApplication ws_app(argc, argv);
626 /* initialize the funnel mini-api */
628 //initialize_funnel_ops();
630 AirPDcapInitContext(&airpdcap_ctx);
634 /* Load wpcap if possible. Do this before collecting the run-time version information */
637 /* ... and also load the packet.dll from wpcap */
641 /* Load the airpcap.dll. This must also be done before collecting
642 * run-time version information. */
643 airpcap_dll_ret_val = load_airpcap();
645 switch (airpcap_dll_ret_val) {
647 /* load the airpcap interfaces */
648 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
650 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
651 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
652 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
655 airpcap_if_active = NULL;
659 /* select the first ad default (THIS SHOULD BE CHANGED) */
660 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
665 * XXX - Maybe we need to warn the user if one of the following happens???
667 case AIRPCAP_DLL_OLD:
668 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
671 case AIRPCAP_DLL_ERROR:
672 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
675 case AIRPCAP_DLL_NOT_FOUND:
676 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
680 #endif /* HAVE_AIRPCAP */
685 unsigned int in_file_type = WTAP_TYPE_AUTO;
687 // In Qt 5, C strings are treated always as UTF-8 when converted to
688 // QStrings; in Qt 4, the codec must be set to make that happen
689 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
690 // Hopefully we won't have to use QString::fromUtf8() in as many places.
691 QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
692 QTextCodec::setCodecForCStrings(utf8codec);
693 // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
694 QTextCodec::setCodecForTr(utf8codec);
697 /* Add it to the information to be reported on a crash. */
698 ws_add_crash_info("Wireshark %s\n"
703 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
706 /* Start windows sockets */
707 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
710 profile_store_persconffiles(TRUE);
712 /* Read the profile independent recent file. We have to do this here so we can */
713 /* set the profile before it can be set from the command line parameter */
714 recent_read_static(&rf_path, &rf_open_errno);
715 if (rf_path != NULL && rf_open_errno != 0) {
716 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
717 "Could not open common recent file\n\"%s\": %s.",
718 rf_path, strerror(rf_open_errno));
720 wsApp->emitAppSignal(WiresharkApplication::StaticRecentFilesRead);
722 /* Init the "Open file" dialog directory */
723 /* (do this after the path settings are processed) */
725 /* Read the profile dependent (static part) of the recent file. */
726 /* Only the static part of it will be read, as we don't have the gui now to fill the */
727 /* recent lists which is done in the dynamic part. */
728 /* We have to do this already here, so command line parameters can overwrite these values. */
729 recent_read_profile_static(&rf_path, &rf_open_errno);
730 if (rf_path != NULL && rf_open_errno != 0) {
731 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
732 "Could not open recent file\n\"%s\": %s.",
733 rf_path, g_strerror(rf_open_errno));
736 // Initialize our language
737 read_language_prefs();
738 locale = QString(language);
739 wsApp->loadLanguage(locale);
741 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
743 // Init the main window (and splash)
744 main_w = new(MainWindow);
746 // We may not need a queued connection here but it would seem to make sense
747 // to force the issue.
748 main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString&,QString&,unsigned int)),
749 main_w, SLOT(openCaptureFile(QString&,QString&,unsigned int)));
751 /* Init the "Open file" dialog directory */
752 /* (do this after the path settings are processed) */
754 /* Read the profile dependent (static part) of the recent file. */
755 /* Only the static part of it will be read, as we don't have the gui now to fill the */
756 /* recent lists which is done in the dynamic part. */
757 /* We have to do this already here, so command line parameters can overwrite these values. */
758 recent_read_profile_static(&rf_path, &rf_open_errno);
759 if (rf_path != NULL && rf_open_errno != 0) {
760 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
761 "Could not open recent file\n\"%s\": %s.",
762 rf_path, g_strerror(rf_open_errno));
764 wsApp->emitAppSignal(WiresharkApplication::StaticRecentFilesRead);
766 if (recent.gui_fileopen_remembered_dir &&
767 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
768 wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
770 wsApp->setLastOpenDir(get_persdatafile_dir());
774 // Replicates behavior in gtk_init();
775 signal(SIGPIPE, SIG_IGN);
778 set_console_log_handler();
781 /* Set the initial values in the capture options. This might be overwritten
782 by preference settings and then again by the command line parameters. */
783 capture_opts_init(&global_capture_opts);
786 init_report_err(failure_alert_box, open_failure_alert_box,
787 read_failure_alert_box, write_failure_alert_box);
789 init_open_routines();
792 /* Register all the plugin types we have. */
793 epan_register_plugin_types(); /* Types known to libwireshark */
794 wtap_register_plugin_types(); /* Types known to libwiretap */
795 codec_register_plugin_types(); /* Types known to libcodec */
797 /* Scan for plugins. This does *not* call their registration routines;
798 that's done later. */
801 /* Register all libwiretap plugin modules. */
802 register_all_wiretap_modules();
804 /* Register all audio codec plugins. */
805 register_all_codecs();
808 /* Register all dissectors; we must do this before checking for the
809 "-G" flag, as the "-G" flag dumps information registered by the
810 dissectors, and we must do it before we read the preferences, in
811 case any dissectors register preferences. */
812 epan_init(register_all_protocols,register_all_protocol_handoffs,
813 splash_update, NULL);
815 splash_update(RA_LISTENERS, NULL, NULL);
817 /* Register all tap listeners; we do this before we parse the arguments,
818 as the "-z" argument can specify a registered tap. */
820 /* we register the plugin taps before the other taps because
821 stats_tree taps plugins will be registered as tap listeners
822 by stats_tree_stat.c and need to registered before that */
824 g_log(NULL, G_LOG_LEVEL_DEBUG, "plugin_dir: %s", get_plugin_dir());
826 register_all_plugin_tap_listeners();
829 register_all_tap_listeners();
830 conversation_table_set_gui_info(init_conversation_table);
831 hostlist_table_set_gui_info(init_endpoint_table);
833 if (ex_opt_count("read_format") > 0) {
834 in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
837 splash_update(RA_PREFERENCES, NULL, NULL);
839 prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path);
842 * To reset the options parser, set optreset to 1 on platforms that
843 * have optreset (documented in *BSD and OS X, apparently present but
844 * not documented in Solaris - the Illumos repository seems to
845 * suggest that the first Solaris getopt_long(), at least as of 2004,
846 * was based on the NetBSD one, it had optreset) and set optind to 1,
847 * and set optind to 0 otherwise (documented as working in the GNU
848 * getopt_long(). Setting optind to 0 didn't originally work in the
849 * NetBSD one, but that was added later - we don't want to depend on
850 * it if we have optreset).
852 * Also reset opterr to 1, so that error messages are printed by
855 * XXX - if we want to control all the command-line option errors, so
856 * that we can display them where we choose (e.g., in a window), we'd
857 * want to leave opterr as 0, and produce our own messages using optopt.
858 * We'd have to check the value of optopt to see if it's a valid option
859 * letter, in which case *presumably* the error is "this option requires
860 * an argument but none was specified", or not a valid option letter,
861 * in which case *presumably* the error is "this option isn't valid".
862 * Some versions of getopt() let you supply a option string beginning
863 * with ':', which means that getopt() will return ':' rather than '?'
864 * for "this option requires an argument but none was specified", but
865 * not all do. But we're now using getopt_long() - what does it do?
875 /* Now get our args */
876 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
878 /*** capture option specific ***/
879 case 'a': /* autostop criteria */
880 case 'b': /* Ringbuffer option */
881 case 'c': /* Capture xxx packets */
882 case 'f': /* capture filter */
883 case 'k': /* Start capture immediately */
884 case 'H': /* Hide capture info dialog box */
885 case 'p': /* Don't capture in promiscuous mode */
886 case 'i': /* Use interface x */
887 #ifdef HAVE_PCAP_CREATE
888 case 'I': /* Capture in monitor mode, if available */
890 #ifdef HAVE_PCAP_REMOTE
891 case 'A': /* Authentication */
893 case 's': /* Set the snapshot (capture) length */
894 case 'S': /* "Sync" mode: used for following file ala tail -f */
895 case 'w': /* Write to capture file xxx */
896 case 'y': /* Set the pcap data link type */
897 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
898 case 'B': /* Buffer size */
899 #endif /* _WIN32 or HAVE_PCAP_CREATE */
901 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
907 capture_option_specified = TRUE;
912 case 'K': /* Kerberos keytab file */
913 read_keytab_file(optarg);
917 /*** all non capture option specific ***/
919 /* Configuration profile settings were already processed just ignore them this time*/
921 case 'j': /* Search backwards for a matching packet from filter in option J */
922 /* Not supported yet */
924 case 'g': /* Go to packet with the given packet number */
925 go_to_packet = get_positive_int(optarg, "go to packet");
927 case 'J': /* Jump to the first packet which matches the filter criteria */
928 /* Not supported yet */
930 case 'l': /* Automatic scrolling in live capture mode */
932 /* Not supported yet */
934 capture_option_specified = TRUE;
938 case 'L': /* Print list of link-layer types and exit */
940 list_link_layer_types = TRUE;
942 capture_option_specified = TRUE;
946 case 'm': /* Fixed-width font for the display */
947 /* Not supported yet */
949 case 'n': /* No name resolution */
950 gbl_resolv_flags.mac_name = FALSE;
951 gbl_resolv_flags.network_name = FALSE;
952 gbl_resolv_flags.transport_name = FALSE;
953 gbl_resolv_flags.concurrent_dns = FALSE;
955 case 'N': /* Select what types of addresses/port #s to resolve */
956 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
957 if (badopt != '\0') {
958 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
963 case 'o': /* Override preference from command line */
964 switch (prefs_set_pref(optarg)) {
967 case PREFS_SET_SYNTAX_ERR:
968 cmdarg_err("Invalid -o flag \"%s\"", optarg);
971 case PREFS_SET_NO_SUCH_PREF:
972 /* not a preference, might be a recent setting */
973 switch (recent_set_arg(optarg)) {
976 case PREFS_SET_SYNTAX_ERR:
977 /* shouldn't happen, checked already above */
978 cmdarg_err("Invalid -o flag \"%s\"", optarg);
981 case PREFS_SET_NO_SUCH_PREF:
982 case PREFS_SET_OBSOLETE:
983 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
988 g_assert_not_reached();
991 case PREFS_SET_OBSOLETE:
992 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
997 g_assert_not_reached();
1001 /* Path settings were already processed just ignore them this time*/
1006 case 'R': /* Read file filter */
1007 read_filter = QString(optarg);
1009 case 't': /* Time stamp type */
1010 if (strcmp(optarg, "r") == 0)
1011 timestamp_set_type(TS_RELATIVE);
1012 else if (strcmp(optarg, "a") == 0)
1013 timestamp_set_type(TS_ABSOLUTE);
1014 else if (strcmp(optarg, "ad") == 0)
1015 timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
1016 else if (strcmp(optarg, "adoy") == 0)
1017 timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
1018 else if (strcmp(optarg, "d") == 0)
1019 timestamp_set_type(TS_DELTA);
1020 else if (strcmp(optarg, "dd") == 0)
1021 timestamp_set_type(TS_DELTA_DIS);
1022 else if (strcmp(optarg, "e") == 0)
1023 timestamp_set_type(TS_EPOCH);
1024 else if (strcmp(optarg, "u") == 0)
1025 timestamp_set_type(TS_UTC);
1026 else if (strcmp(optarg, "ud") == 0)
1027 timestamp_set_type(TS_UTC_WITH_YMD);
1028 else if (strcmp(optarg, "udoy") == 0)
1029 timestamp_set_type(TS_UTC_WITH_YDOY);
1031 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
1033 "It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
1035 "\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
1037 "\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
1039 "\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
1041 "or \"udoy\" for absolute UTC with YYYY/DOY date.");
1045 case 'u': /* Seconds type */
1046 if (strcmp(optarg, "s") == 0)
1047 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
1048 else if (strcmp(optarg, "hms") == 0)
1049 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
1051 cmdarg_err("Invalid seconds type \"%s\"", optarg);
1053 "It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
1058 /* ext ops were already processed just ignore them this time*/
1061 dfilter = QString(optarg);
1064 /* We won't call the init function for the stat this soon
1065 as it would disallow MATE's fields (which are registered
1066 by the preferences set callback) from being used as
1067 part of a tap filter. Instead, we just add the argument
1068 to a list of stat arguments. */
1069 if (strcmp("help", optarg) == 0) {
1070 fprintf(stderr, "wireshark: The available statistics for the \"-z\" option are:\n");
1071 list_stat_cmd_args();
1074 if (!process_stat_cmd_arg(optarg)) {
1075 cmdarg_err("Invalid -z argument.");
1076 cmdarg_err_cont(" -z argument must be one of :");
1077 list_stat_cmd_args();
1082 case '?': /* Bad flag - print usage message */
1093 if (!cf_name.isEmpty()) {
1095 * Input file name specified with "-r" *and* specified as a regular
1096 * command-line argument.
1098 cmdarg_err("File name specified both with -r and regular argument");
1102 * Input file name not specified with "-r", and a command-line argument
1103 * was specified; treat it as the input file name.
1105 * Yes, this is different from tshark, where non-flag command-line
1106 * arguments are a filter, but this works better on GUI desktops
1107 * where a command can be specified to be run to open a particular
1108 * file - yes, you could have "-r" as the last part of the command,
1109 * but that's a bit ugly.
1120 * Extra command line arguments were specified; complain.
1122 cmdarg_err("Invalid argument: %s", argv[0]);
1127 #ifndef HAVE_LIBPCAP
1128 if (capture_option_specified) {
1129 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
1136 /* Removed thread code:
1137 * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
1140 // XXX Is there a better place to set the timestamp format & precision?
1141 timestamp_set_type(recent.gui_time_format);
1142 timestamp_set_precision(recent.gui_time_precision);
1143 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
1146 fill_in_local_interfaces(main_window_update);
1148 if (start_capture && list_link_layer_types) {
1149 /* Specifying *both* is bogus. */
1150 cmdarg_err("You can't specify both -L and a live capture.");
1154 if (list_link_layer_types) {
1155 /* We're supposed to list the link-layer types for an interface;
1156 did the user also specify a capture file to be read? */
1157 if (!cf_name.isEmpty()) {
1158 /* Yes - that's bogus. */
1159 cmdarg_err("You can't specify -L and a capture file to be read.");
1162 /* No - did they specify a ring buffer option? */
1163 if (global_capture_opts.multi_files_on) {
1164 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
1168 /* We're supposed to do a live capture; did the user also specify
1169 a capture file to be read? */
1170 if (start_capture && !cf_name.isEmpty()) {
1171 /* Yes - that's bogus. */
1172 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
1176 /* No - was the ring buffer option specified and, if so, does it make
1178 if (global_capture_opts.multi_files_on) {
1179 /* Ring buffer works only under certain conditions:
1180 a) ring buffer does not work with temporary files;
1181 b) real_time_mode and multi_files_on are mutually exclusive -
1182 real_time_mode takes precedence;
1183 c) it makes no sense to enable the ring buffer if the maximum
1184 file size is set to "infinite". */
1185 if (global_capture_opts.save_file == NULL) {
1186 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
1187 global_capture_opts.multi_files_on = FALSE;
1189 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
1190 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
1191 /* XXX - this must be redesigned as the conditions changed */
1196 if (start_capture || list_link_layer_types) {
1197 /* We're supposed to do a live capture or get a list of link-layer
1198 types for a live capture device; if the user didn't specify an
1199 interface to use, pick a default. */
1200 status = capture_opts_default_iface_if_necessary(&global_capture_opts,
1201 ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
1207 if (list_link_layer_types) {
1208 /* Get the list of link-layer types for the capture devices. */
1209 if_capabilities_t *caps;
1212 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
1214 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
1215 if (device.selected) {
1216 #if defined(HAVE_PCAP_CREATE)
1217 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str, main_window_update);
1219 caps = capture_get_if_capabilities(device.name, FALSE, &err_str,main_window_update);
1222 cmdarg_err("%s", err_str);
1226 if (caps->data_link_types == NULL) {
1227 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
1233 #if defined(HAVE_PCAP_CREATE)
1234 capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
1236 capture_opts_print_if_capabilities(caps, device.name, FALSE);
1241 free_if_capabilities(caps);
1247 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
1248 capture_opts_trim_ring_num_files(&global_capture_opts);
1249 #endif /* HAVE_LIBPCAP */
1251 /* Notify all registered modules that have had any of their preferences
1252 changed either from one of the preferences file or from the command
1253 line that their preferences have changed. */
1255 wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
1258 if ((global_capture_opts.num_selected == 0) &&
1259 (prefs.capture_device != NULL)) {
1262 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
1263 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
1264 if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
1265 device.selected = TRUE;
1266 global_capture_opts.num_selected++;
1267 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
1268 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
1275 /* disabled protocols as per configuration file */
1276 if (gdp_path == NULL && dp_path == NULL) {
1277 set_disabled_protos_list();
1280 build_column_format_array(&CaptureFile::globalCapFile()->cinfo, prefs_p->num_cols, TRUE);
1282 wsApp->setMonospaceFont(prefs.gui_qt_font_name);
1286 /* Read the dynamic part of the recent file, as we have the gui now ready for
1288 recent_read_dynamic(&rf_path, &rf_open_errno);
1289 if (rf_path != NULL && rf_open_errno != 0) {
1290 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1291 "Could not open recent file\n\"%s\": %s.",
1292 rf_path, g_strerror(rf_open_errno));
1295 color_filters_enable(recent.packet_list_colorize);
1297 g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
1298 color_filters_enable(TRUE);
1304 color_filters_init();
1309 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
1310 if (!start_capture && !global_capture_opts.default_options.cfilter) {
1311 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
1313 #else /* HAVE_LIBPCAP */
1315 #endif /* HAVE_LIBPCAP */
1317 // w->setEnabled(true);
1318 wsApp->allSystemsGo();
1319 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
1320 SimpleDialog::displayQueuedMessages(main_w);
1322 /* user could specify filename, or display filter, or both */
1323 if (!cf_name.isEmpty()) {
1325 /* Open stat windows; we do so after creating the main window,
1326 to avoid Qt warnings, and after successfully opening the
1327 capture file, so we know we have something to compute stats
1328 on, and after registering all dissectors, so that MATE will
1329 have registered its field array and we can have a tap filter
1330 with one of MATE's late-registered fields as part of the
1332 start_requested_stats();
1334 // XXX The GTK+ UI does error checking here.
1335 main_w->openCaptureFile(cf_name, read_filter, in_file_type);
1336 if (!dfilter.isEmpty())
1337 main_w->filterPackets(dfilter, false);
1338 if(go_to_packet != 0) {
1339 /* Jump to the specified frame number, kept for backward
1341 cf_goto_frame(CaptureFile::globalCapFile(), go_to_packet);
1346 if (start_capture) {
1347 if (global_capture_opts.save_file != NULL) {
1348 /* Save the directory name for future file dialogs. */
1349 /* (get_dirname overwrites filename) */
1350 gchar *s = get_dirname(g_strdup(global_capture_opts.save_file));
1351 set_last_open_dir(s);
1354 /* "-k" was specified; start a capture. */
1355 // show_main_window(FALSE);
1356 check_and_warn_user_startup(cf_name);
1358 /* If no user interfaces were specified on the command line,
1359 copy the list of selected interfaces to the set of interfaces
1360 to use for this capture. */
1361 if (global_capture_opts.ifaces->len == 0)
1362 collect_ifaces(&global_capture_opts);
1363 CaptureFile::globalCapFile()->window = main_w;
1364 if (capture_start(&global_capture_opts, main_w->captureSession(), main_window_update)) {
1365 /* The capture started. Open stat windows; we do so after creating
1366 the main window, to avoid GTK warnings, and after successfully
1367 opening the capture file, so we know we have something to compute
1368 stats on, and after registering all dissectors, so that MATE will
1369 have registered its field array and we can have a tap filter with
1370 one of MATE's late-registered fields as part of the filter. */
1371 start_requested_stats();
1374 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
1375 if (!start_capture && !global_capture_opts.default_options.cfilter) {
1376 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
1379 #endif /* HAVE_LIBPCAP */
1381 g_main_loop_new(NULL, FALSE);
1382 return wsApp->exec();
1391 * indent-tabs-mode: nil
1394 * ex: set shiftwidth=4 tabstop=8 expandtab:
1395 * :indentSize=4:tabSize=8:noTabs=true: