2 * Common command line handling between GUIs
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #ifndef HAVE_GETOPT_LONG
36 #include "wsutil/wsgetopt.h"
39 #include <ws_version_info.h>
41 #include <wsutil/clopts_common.h>
42 #include <wsutil/cmdarg_err.h>
43 #include <wsutil/filesystem.h>
45 #include <epan/ex-opt.h>
46 #include <epan/addr_resolv.h>
47 #include <epan/packet.h>
48 #include <epan/proto.h>
49 #include <epan/prefs.h>
50 #include <epan/prefs-int.h>
51 #include <epan/timestamp.h>
52 #include <epan/stat_tap_ui.h>
54 #include "capture_opts.h"
55 #include "persfilepath_opt.h"
56 #include "preference_utils.h"
59 #include "decode_as_utils.h"
61 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
62 #include <epan/asn1.h>
63 #include <epan/dissectors/packet-kerberos.h>
68 #include "ui/commandline.h"
70 commandline_param_info_t global_commandline_info;
72 #if defined(HAVE_LIBPCAP) || defined(HAVE_EXTCAP)
73 capture_options global_capture_opts;
77 commandline_print_usage(gboolean for_help_option) {
84 if (for_help_option) {
86 fprintf(output, "Wireshark %s\n"
87 "Interactively dump and analyze network traffic.\n"
88 "See https://www.wireshark.org for more information.\n",
89 get_ws_vcs_version_info());
93 fprintf(output, "\n");
94 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
95 fprintf(output, "\n");
98 fprintf(output, "Capture interface:\n");
99 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
100 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
101 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
102 fprintf(output, " -p don't capture in promiscuous mode\n");
103 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
104 fprintf(output, " -S update packet display when new packets are captured\n");
105 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
106 #ifdef HAVE_PCAP_CREATE
107 fprintf(output, " -I capture in monitor mode, if available\n");
109 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
110 fprintf(output, " -B <buffer size> size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
112 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
113 fprintf(output, " -D print list of interfaces and exit\n");
114 fprintf(output, " -L print list of link-layer types of iface and exit\n");
115 fprintf(output, "\n");
116 fprintf(output, "Capture stop conditions:\n");
117 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
118 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
119 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
120 fprintf(output, " files:NUM - stop after NUM files\n");
121 /*fprintf(output, "\n");*/
122 fprintf(output, "Capture output:\n");
123 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
124 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
125 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
126 #endif /* HAVE_LIBPCAP */
127 #ifdef HAVE_PCAP_REMOTE
128 fprintf(output, "RPCAP options:\n");
129 fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
131 /*fprintf(output, "\n");*/
132 fprintf(output, "Input file:\n");
133 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
135 fprintf(output, "\n");
136 fprintf(output, "Processing:\n");
137 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
138 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
139 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mnNtd\"\n");
140 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
141 fprintf(output, " \"Decode As\", see the man page for details\n");
142 fprintf(output, " Example: tcp.port==8888,http\n");
143 fprintf(output, " --disable-protocol <proto_name>\n");
144 fprintf(output, " disable dissection of proto_name\n");
145 fprintf(output, " --enable-heuristic <short_name>\n");
146 fprintf(output, " enable dissection of heuristic protocol\n");
147 fprintf(output, " --disable-heuristic <short_name>\n");
148 fprintf(output, " disable dissection of heuristic protocol\n");
150 fprintf(output, "\n");
151 fprintf(output, "User interface:\n");
152 fprintf(output, " -C <config profile> start with specified configuration profile\n");
153 fprintf(output, " -Y <display filter> start with the given display filter\n");
154 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
155 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
156 fprintf(output, " filter\n");
157 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
158 fprintf(output, " -m <font> set the font name used for most text\n");
159 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
160 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
161 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
162 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
164 fprintf(output, "\n");
165 fprintf(output, "Output:\n");
166 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
168 fprintf(output, "\n");
169 fprintf(output, "Miscellaneous:\n");
170 fprintf(output, " -h display this help and exit\n");
171 fprintf(output, " -v display version info and exit\n");
172 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
173 fprintf(output, " persdata:path - personal data files\n");
174 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
175 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
177 fprintf(output, " --display=DISPLAY X display to use\n");
185 #define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:d:g:Hh" "jJ:kK:lm:nN:o:P:r:R:St:u:vw:X:Y:z:"
186 static const struct option long_options[] = {
187 {"help", no_argument, NULL, 'h'},
188 {"read-file", required_argument, NULL, 'r' },
189 {"read-filter", required_argument, NULL, 'R' },
190 {"display-filter", required_argument, NULL, 'Y' },
191 {"version", no_argument, NULL, 'v'},
192 LONGOPT_CAPTURE_COMMON
195 static const char optstring[] = OPTSTRING;
198 static void print_no_capture_support_error(void)
200 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
204 void commandline_early_options(int argc, char *argv[],
205 GString *comp_info_str, GString *runtime_info_str)
213 gboolean capture_option_specified;
217 * In order to have the -X opts assigned before the wslua machine starts
218 * we need to call getopt_long before epan_init() gets called.
220 * In addition, we process "console only" parameters (ones where we
221 * send output to the console and exit) here, so we don't start GUI
222 * if we're only showing command-line help or version information.
224 * XXX - this pre-scan is done before we start GUI, so we haven't
225 * run "GUI init function" on the arguments. That means that GUI-specific
226 * arguments have not been removed from the argument list; those arguments
227 * begin with "--", and will be treated as an error by getopt_long().
229 * We thus ignore errors - *and* set "opterr" to 0 to suppress the
232 * XXX - should we, instead, first call gtk_parse_args(), without
233 * calling gtk_init(), and then call this?
235 * In order to handle, for example, -o options, we also need to call it
236 * *after* epan_init() gets called, so that the dissectors have had a
237 * chance to register their preferences, so we have another getopt_long()
240 * XXX - can we do this all with one getopt_long() call, saving the
241 * arguments we can't handle until after initializing libwireshark,
242 * and then process them after initializing libwireshark?
244 * Note that we don't want to initialize libwireshark until after the
245 * GUI is up, as that can take a while, and we want a window of some
246 * sort up to show progress while that's happening.
251 capture_option_specified = FALSE;
253 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
255 case 'C': /* Configuration Profile */
256 if (profile_exists (optarg, FALSE)) {
257 set_profile_name (optarg);
259 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
263 case 'D': /* Print a list of capture devices and exit */
265 if_list = capture_interface_list(&err, &err_str, NULL);
266 if (if_list == NULL) {
268 cmdarg_err("There are no interfaces on which a capture can be done");
270 cmdarg_err("%s", err_str);
278 capture_opts_print_interfaces(if_list);
279 free_interface_list(if_list);
284 #else /* HAVE_LIBPCAP */
285 capture_option_specified = TRUE;
286 #endif /* HAVE_LIBPCAP */
288 case 'h': /* Print help and exit */
289 commandline_print_usage(TRUE);
294 if (strcmp(optarg, "-") == 0)
295 set_stdin_capture(TRUE);
298 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
299 if (!persfilepath_opt(opt, optarg)) {
300 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
304 case 'v': /* Show version and exit */
308 show_version("Wireshark", comp_info_str, runtime_info_str);
316 * Extension command line options have to be processed before
317 * we call epan_init() as they are supposed to be used by dissectors
318 * or taps very early in the registration process.
322 case '?': /* Ignore errors - the "real" scan will catch them. */
328 if (capture_option_specified) {
329 print_no_capture_support_error();
330 commandline_print_usage(FALSE);
336 void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
339 gboolean arg_error = FALSE;
343 gboolean capture_option_specified;
348 * To reset the options parser, set optreset to 1 on platforms that
349 * have optreset (documented in *BSD and OS X, apparently present but
350 * not documented in Solaris - the Illumos repository seems to
351 * suggest that the first Solaris getopt_long(), at least as of 2004,
352 * was based on the NetBSD one, it had optreset) and set optind to 1,
353 * and set optind to 0 otherwise (documented as working in the GNU
354 * getopt_long(). Setting optind to 0 didn't originally work in the
355 * NetBSD one, but that was added later - we don't want to depend on
356 * it if we have optreset).
358 * Also reset opterr to 1, so that error messages are printed by
361 * XXX - if we want to control all the command-line option errors, so
362 * that we can display them where we choose (e.g., in a window), we'd
363 * want to leave opterr as 0, and produce our own messages using optopt.
364 * We'd have to check the value of optopt to see if it's a valid option
365 * letter, in which case *presumably* the error is "this option requires
366 * an argument but none was specified", or not a valid option letter,
367 * in which case *presumably* the error is "this option isn't valid".
368 * Some versions of getopt() let you supply a option string beginning
369 * with ':', which means that getopt() will return ':' rather than '?'
370 * for "this option requires an argument but none was specified", but
371 * not all do. But we're now using getopt_long() - what does it do?
383 /* Initialize with default values */
384 global_commandline_info.jump_backwards = SD_FORWARD;
385 global_commandline_info.go_to_packet = 0;
386 global_commandline_info.jfilter = NULL;
387 global_commandline_info.cf_name = NULL;
388 global_commandline_info.rfilter = NULL;
389 global_commandline_info.dfilter = NULL;
390 global_commandline_info.time_format = TS_NOT_SET;
392 global_commandline_info.start_capture = FALSE;
393 global_commandline_info.list_link_layer_types = FALSE;
394 global_commandline_info.quit_after_cap = getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? TRUE : FALSE;
396 global_commandline_info.disable_protocol_slist = NULL;
397 global_commandline_info.enable_heur_slist = NULL;
398 global_commandline_info.disable_heur_slist = NULL;
400 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
402 /*** capture option specific ***/
403 case 'a': /* autostop criteria */
404 case 'b': /* Ringbuffer option */
405 case 'c': /* Capture xxx packets */
406 case 'f': /* capture filter */
407 case 'k': /* Start capture immediately */
408 case 'H': /* Hide capture info dialog box */
409 case 'p': /* Don't capture in promiscuous mode */
410 case 'i': /* Use interface x */
411 #ifdef HAVE_PCAP_CREATE
412 case 'I': /* Capture in monitor mode, if available */
414 #ifdef HAVE_PCAP_REMOTE
415 case 'A': /* Authentication */
417 case 's': /* Set the snapshot (capture) length */
418 case 'S': /* "Sync" mode: used for following file ala tail -f */
419 case 'w': /* Write to capture file xxx */
420 case 'y': /* Set the pcap data link type */
421 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
422 case 'B': /* Buffer size */
425 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
426 &global_commandline_info.start_capture);
431 capture_option_specified = TRUE;
436 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
437 case 'K': /* Kerberos keytab file */
438 read_keytab_file(optarg);
442 /*** all non capture option specific ***/
444 /* Configuration profile settings were already processed just ignore them this time*/
446 case 'd': /* Decode as rule */
447 if (!decode_as_command_option(optarg))
450 case 'j': /* Search backwards for a matching packet from filter in option J */
451 global_commandline_info.jump_backwards = SD_BACKWARD;
453 case 'g': /* Go to packet with the given packet number */
454 global_commandline_info.go_to_packet = get_nonzero_guint32(optarg, "go to packet");
456 case 'J': /* Jump to the first packet which matches the filter criteria */
457 global_commandline_info.jfilter = optarg;
459 case 'l': /* Automatic scrolling in live capture mode */
461 auto_scroll_live = TRUE;
463 capture_option_specified = TRUE;
467 case 'L': /* Print list of link-layer types and exit */
469 global_commandline_info.list_link_layer_types = TRUE;
471 capture_option_specified = TRUE;
475 case 'n': /* No name resolution */
476 disable_name_resolution();
478 case 'N': /* Select what types of addresses/port #s to resolve */
479 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
480 if (badopt != '\0') {
481 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'd', m', 'n', 'N', and 't'",
486 case 'o': /* Override preference from command line */
487 switch (prefs_set_pref(optarg)) {
490 case PREFS_SET_SYNTAX_ERR:
491 cmdarg_err("Invalid -o flag \"%s\"", optarg);
494 case PREFS_SET_NO_SUCH_PREF:
495 /* not a preference, might be a recent setting */
496 switch (recent_set_arg(optarg)) {
499 case PREFS_SET_SYNTAX_ERR:
500 /* shouldn't happen, checked already above */
501 cmdarg_err("Invalid -o flag \"%s\"", optarg);
504 case PREFS_SET_NO_SUCH_PREF:
505 case PREFS_SET_OBSOLETE:
506 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
511 g_assert_not_reached();
514 case PREFS_SET_OBSOLETE:
515 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
520 g_assert_not_reached();
524 /* Path settings were already processed just ignore them this time*/
526 case 'r': /* Read capture file xxx */
527 /* We may set "last_open_dir" to "cf_name", and if we change
528 "last_open_dir" later, we free the old value, so we have to
529 set "cf_name" to something that's been allocated. */
530 global_commandline_info.cf_name = g_strdup(optarg);
532 case 'R': /* Read file filter */
533 global_commandline_info.rfilter = optarg;
535 case 't': /* Time stamp type */
536 if (strcmp(optarg, "r") == 0)
537 global_commandline_info.time_format = TS_RELATIVE;
538 else if (strcmp(optarg, "a") == 0)
539 global_commandline_info.time_format = TS_ABSOLUTE;
540 else if (strcmp(optarg, "ad") == 0)
541 global_commandline_info.time_format = TS_ABSOLUTE_WITH_YMD;
542 else if (strcmp(optarg, "adoy") == 0)
543 global_commandline_info.time_format = TS_ABSOLUTE_WITH_YDOY;
544 else if (strcmp(optarg, "d") == 0)
545 global_commandline_info.time_format = TS_DELTA;
546 else if (strcmp(optarg, "dd") == 0)
547 global_commandline_info.time_format = TS_DELTA_DIS;
548 else if (strcmp(optarg, "e") == 0)
549 global_commandline_info.time_format = TS_EPOCH;
550 else if (strcmp(optarg, "u") == 0)
551 global_commandline_info.time_format = TS_UTC;
552 else if (strcmp(optarg, "ud") == 0)
553 global_commandline_info.time_format = TS_UTC_WITH_YMD;
554 else if (strcmp(optarg, "udoy") == 0)
555 global_commandline_info.time_format = TS_UTC_WITH_YDOY;
557 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
558 cmdarg_err_cont("It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
559 cmdarg_err_cont("\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
560 cmdarg_err_cont("\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
561 cmdarg_err_cont("\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
562 cmdarg_err_cont("or \"udoy\" for absolute UTC with YYYY/DOY date.");
566 case 'u': /* Seconds type */
567 if (strcmp(optarg, "s") == 0)
568 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
569 else if (strcmp(optarg, "hms") == 0)
570 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
572 cmdarg_err("Invalid seconds type \"%s\"", optarg);
573 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
578 /* ext ops were already processed just ignore them this time*/
581 global_commandline_info.dfilter = optarg;
584 /* We won't call the init function for the stat this soon
585 as it would disallow MATE's fields (which are registered
586 by the preferences set callback) from being used as
587 part of a tap filter. Instead, we just add the argument
588 to a list of stat arguments. */
589 if (strcmp("help", optarg) == 0) {
590 fprintf(stderr, "wireshark: The available statistics for the \"-z\" option are:\n");
591 list_stat_cmd_args();
594 if (!process_stat_cmd_arg(optarg)) {
595 cmdarg_err("Invalid -z argument.");
596 cmdarg_err_cont(" -z argument must be one of :");
597 list_stat_cmd_args();
601 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
602 global_commandline_info.disable_protocol_slist = g_slist_append(global_commandline_info.disable_protocol_slist, optarg);
604 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
605 global_commandline_info.enable_heur_slist = g_slist_append(global_commandline_info.enable_heur_slist, optarg);
607 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
608 global_commandline_info.disable_heur_slist = g_slist_append(global_commandline_info.disable_heur_slist, optarg);
611 case '?': /* Bad flag - print usage message */
621 if (global_commandline_info.cf_name != NULL) {
623 * Input file name specified with "-r" *and* specified as a regular
624 * command-line argument.
626 cmdarg_err("File name specified both with -r and regular argument");
630 * Input file name not specified with "-r", and a command-line argument
631 * was specified; treat it as the input file name.
633 * Yes, this is different from tshark, where non-flag command-line
634 * arguments are a filter, but this works better on GUI desktops
635 * where a command can be specified to be run to open a particular
636 * file - yes, you could have "-r" as the last part of the command,
637 * but that's a bit ugly.
639 #ifndef HAVE_GTKOSXAPPLICATION
641 * For GTK+ Mac Integration, file name passed as free argument passed
642 * through grag-and-drop and opened twice sometimes causing crashes.
643 * Subject to report to GTK+ MAC.
645 global_commandline_info.cf_name = g_strdup(argv[0]);
654 * Extra command line arguments were specified; complain.
656 cmdarg_err("Invalid argument: %s", argv[0]);
663 if (capture_option_specified) {
664 print_no_capture_support_error();
667 commandline_print_usage(FALSE);
672 if (global_commandline_info.start_capture && global_commandline_info.list_link_layer_types) {
673 /* Specifying *both* is bogus. */
674 cmdarg_err("You can't specify both -L and a live capture.");
678 if (global_commandline_info.list_link_layer_types) {
679 /* We're supposed to list the link-layer types for an interface;
680 did the user also specify a capture file to be read? */
681 if (global_commandline_info.cf_name) {
682 /* Yes - that's bogus. */
683 cmdarg_err("You can't specify -L and a capture file to be read.");
686 /* No - did they specify a ring buffer option? */
687 if (global_capture_opts.multi_files_on) {
688 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
692 /* We're supposed to do a live capture; did the user also specify
693 a capture file to be read? */
694 if (global_commandline_info.start_capture && global_commandline_info.cf_name) {
695 /* Yes - that's bogus. */
696 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
700 /* No - was the ring buffer option specified and, if so, does it make
702 if (global_capture_opts.multi_files_on) {
703 /* Ring buffer works only under certain conditions:
704 a) ring buffer does not work with temporary files;
705 b) real_time_mode and multi_files_on are mutually exclusive -
706 real_time_mode takes precedence;
707 c) it makes no sense to enable the ring buffer if the maximum
708 file size is set to "infinite". */
709 if (global_capture_opts.save_file == NULL) {
710 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
711 global_capture_opts.multi_files_on = FALSE;
713 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
714 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
715 /* XXX - this must be redesigned as the conditions changed */
728 * indent-tabs-mode: nil
731 * ex: set shiftwidth=4 tabstop=8 expandtab:
732 * :indentSize=4:tabSize=8:noTabs=true: