Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / ui / commandline.c
blobcff5f02fc68ed7c9264f52cbd93d90211b44d88a
1 /* commandline.c
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 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
13 #include <glib.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdlib.h>
20 #include <ws_exit_codes.h>
21 #include <wsutil/ws_getopt.h>
23 #include <wsutil/version_info.h>
25 #include <wsutil/application_flavor.h>
26 #include <wsutil/clopts_common.h>
27 #include <wsutil/cmdarg_err.h>
28 #include <wsutil/filesystem.h>
29 #include <wsutil/ws_assert.h>
30 #ifdef _WIN32
31 #include <wsutil/console_win32.h>
32 #endif
34 #include <epan/ex-opt.h>
35 #include <epan/packet.h>
36 #include <epan/proto.h>
37 #include <epan/prefs.h>
38 #include <epan/prefs-int.h>
39 #include <epan/stat_tap_ui.h>
41 #include "persfilepath_opt.h"
42 #include "preference_utils.h"
43 #include "recent.h"
44 #include "decode_as_utils.h"
46 #include "../file.h"
48 #include "ui/capture_opts.h"
50 #include "ui/dissect_opts.h"
52 #include "ui/commandline.h"
54 commandline_param_info_t global_commandline_info;
56 capture_options global_capture_opts;
58 static void
59 commandline_print_usage(bool for_help_option) {
60 FILE *output;
62 #ifdef _WIN32
63 create_console();
64 #endif
66 if (for_help_option) {
67 show_help_header("Interactively dump and analyze network traffic.");
68 output = stdout;
69 } else {
70 output = stderr;
72 fprintf(output, "\n");
73 fprintf(output, "Usage: %s [options] ... [ <infile> ]\n", g_get_prgname());
74 fprintf(output, "\n");
76 #ifdef HAVE_LIBPCAP
77 fprintf(output, "Capture interface:\n");
78 fprintf(output, " -i <interface>, --interface <interface>\n");
79 fprintf(output, " name or idx of interface (def: first non-loopback)\n");
80 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
81 fprintf(output, " -s <snaplen>, --snapshot-length <snaplen>\n");
82 #ifdef HAVE_PCAP_CREATE
83 fprintf(output, " packet snapshot length (def: appropriate maximum)\n");
84 #else
85 fprintf(output, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD);
86 #endif
87 fprintf(output, " -p, --no-promiscuous-mode\n");
88 fprintf(output, " don't capture in promiscuous mode\n");
89 #ifdef HAVE_PCAP_CREATE
90 fprintf(output, " -I, --monitor-mode capture in monitor mode, if available\n");
91 #endif
92 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
93 fprintf(output, " -B <buffer size>, --buffer-size <buffer size>\n");
94 fprintf(output, " size of kernel buffer in MiB (def: %dMiB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
95 #endif
96 fprintf(output, " -y <link type>, --linktype <link type>\n");
97 fprintf(output, " link layer type (def: first appropriate)\n");
98 fprintf(output, " --time-stamp-type <type> timestamp method for interface\n");
99 fprintf(output, " -D, --list-interfaces print list of interfaces and exit\n");
100 fprintf(output, " -L, --list-data-link-types\n");
101 fprintf(output, " print list of link-layer types of iface and exit\n");
102 fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
103 fprintf(output, "\n");
104 fprintf(output, "Capture display:\n");
105 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
106 fprintf(output, " -S update packet display when new packets are captured\n");
107 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
108 fprintf(output, " --update-interval interval between updates with new packets, in milliseconds (def: %dms)\n", DEFAULT_UPDATE_INTERVAL);
109 fprintf(output, "Capture stop conditions:\n");
110 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
111 fprintf(output, " -a <autostop cond.> ..., --autostop <autostop cond.> ...\n");
112 fprintf(output, " duration:NUM - stop after NUM seconds\n");
113 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
114 fprintf(output, " files:NUM - stop after NUM files\n");
115 fprintf(output, " packets:NUM - stop after NUM packets\n");
116 /*fprintf(output, "\n");*/
117 fprintf(output, "Capture output:\n");
118 fprintf(output, " -b <ringbuffer opt.> ..., --ring-buffer <ringbuffer opt.>\n");
119 fprintf(output, " duration:NUM - switch to next file after NUM secs\n");
120 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
121 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
122 fprintf(output, " packets:NUM - switch to next file after NUM packets\n");
123 fprintf(output, " interval:NUM - switch to next file when the time is\n");
124 fprintf(output, " an exact multiple of NUM secs\n");
125 #endif /* HAVE_LIBPCAP */
126 #ifdef HAVE_PCAP_REMOTE
127 fprintf(output, "RPCAP options:\n");
128 fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
129 #endif
130 /*fprintf(output, "\n");*/
131 fprintf(output, "Input file:\n");
132 fprintf(output, " -r <infile>, --read-file <infile>\n");
133 fprintf(output, " 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>, --read-filter <read filter>\n");
138 fprintf(output, " packet filter in display filter (wireshark-filter(4)) syntax\n");
139 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
140 // Note: the order of the flags here matches the options in the settings dialog e.g. "dsN" only have an effect if "n" is set
141 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mtndsNvg\"\n");
142 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
143 fprintf(output, " \"Decode As\", see the man page for details\n");
144 fprintf(output, " Example: tcp.port==8888,http\n");
145 fprintf(output, " --enable-protocol <proto_name>\n");
146 fprintf(output, " enable dissection of proto_name\n");
147 fprintf(output, " --disable-protocol <proto_name>\n");
148 fprintf(output, " disable dissection of proto_name\n");
149 fprintf(output, " --only-protocols <protocols>\n");
150 fprintf(output, " Only enable dissection of these protocols, comma\n");
151 fprintf(output, " separated. Disable everything else\n");
152 fprintf(output, " --disable-all-protocols\n");
153 fprintf(output, " Disable dissection of all protocols\n");
154 fprintf(output, " --enable-heuristic <short_name>\n");
155 fprintf(output, " enable dissection of heuristic protocol\n");
156 fprintf(output, " --disable-heuristic <short_name>\n");
157 fprintf(output, " disable dissection of heuristic protocol\n");
159 fprintf(output, "\n");
160 fprintf(output, "User interface:\n");
161 fprintf(output, " -C <config profile> start with specified configuration profile\n");
162 fprintf(output, " -H hide the capture info dialog during packet capture\n");
163 fprintf(output, " -Y <display filter>, --display-filter <display filter>\n");
164 fprintf(output, " start with the given display filter\n");
165 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
166 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
167 fprintf(output, " filter\n");
168 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
169 fprintf(output, " -t (a|ad|adoy|d|dd|e|r|u|ud|udoy)[.[N]]|.[N]\n");
170 fprintf(output, " format of time stamps (def: r: rel. to first)\n");
171 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
172 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
173 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
175 fprintf(output, "\n");
176 fprintf(output, "Output:\n");
177 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
178 #ifdef HAVE_LIBPCAP
179 fprintf(output, " -F <capture type> set the output file type; default is pcapng.\n");
180 fprintf(output, " an empty \"-F\" option will list the file types.\n");
181 fprintf(output, " --capture-comment <comment>\n");
182 fprintf(output, " add a capture file comment, if supported\n");
183 #endif
184 fprintf(output, " --temp-dir <directory> write temporary files to this directory\n");
185 fprintf(output, " (default: %s)\n", g_get_tmp_dir());
186 fprintf(output, "\n");
188 ws_log_print_usage(output);
190 fprintf(output, "\n");
191 fprintf(output, "Miscellaneous:\n");
192 fprintf(output, " -h, --help display this help and exit\n");
193 fprintf(output, " -v, --version display version info and exit\n");
194 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
195 fprintf(output, " persdata:path - personal data files\n");
196 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
197 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
198 #ifndef _WIN32
199 fprintf(output, " --display <X display> X display to use\n");
200 #endif
201 fprintf(output, " --fullscreen start %s in full screen\n", application_flavor_name_proper());
203 #ifdef _WIN32
204 destroy_console();
205 #endif
208 #define LONGOPT_FULL_SCREEN LONGOPT_BASE_GUI+1
209 #define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_GUI+2
211 #define OPTSTRING OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON OPTSTRING_READ_CAPTURE_COMMON "C:g:HhjJ:klm:o:P:Svw:X:z:"
212 static const struct ws_option long_options[] = {
213 {"help", ws_no_argument, NULL, 'h'},
214 {"version", ws_no_argument, NULL, 'v'},
215 {"fullscreen", ws_no_argument, NULL, LONGOPT_FULL_SCREEN },
216 {"capture-comment", ws_required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
217 LONGOPT_CAPTURE_COMMON
218 LONGOPT_DISSECT_COMMON
219 LONGOPT_READ_CAPTURE_COMMON
220 {0, 0, 0, 0 }
222 static const char optstring[] = OPTSTRING;
224 #ifndef HAVE_LIBPCAP
225 static void print_no_capture_support_error(void)
227 cmdarg_err("This version of %s was not built with support for capturing packets.", application_flavor_name_proper());
229 #endif
231 void commandline_early_options(int argc, char *argv[])
233 int opt;
234 #ifdef HAVE_LIBPCAP
235 int err;
236 GList *if_list;
237 char *err_str;
238 int exit_status;
239 #else
240 bool capture_option_specified;
241 #endif
244 * In order to have the -X opts assigned before the wslua machine starts
245 * we need to call getopt_long before epan_init() gets called.
247 * In addition, we process "console only" parameters (ones where we
248 * send output to the console and exit) here, so we don't start GUI
249 * if we're only showing command-line help or version information.
251 * XXX - this pre-scan is done before we start GUI, so we haven't
252 * run "GUI init function" on the arguments. That means that GUI-specific
253 * arguments have not been removed from the argument list; those arguments
254 * begin with "--", and will be treated as an error by getopt_long().
256 * We thus ignore errors - *and* set "ws_opterr" to 0 to suppress the
257 * error messages.
259 * In order to handle, for example, -o options, we also need to call it
260 * *after* epan_init() gets called, so that the dissectors have had a
261 * chance to register their preferences, so we have another getopt_long()
262 * call later.
264 * XXX - can we do this all with one getopt_long() call, saving the
265 * arguments we can't handle until after initializing libwireshark,
266 * and then process them after initializing libwireshark?
268 * Note that we don't want to initialize libwireshark until after the
269 * GUI is up, as that can take a while, and we want a window of some
270 * sort up to show progress while that's happening.
272 ws_opterr = 0;
274 #ifndef HAVE_LIBPCAP
275 capture_option_specified = false;
276 #endif
277 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
278 switch (opt) {
279 case 'C': /* Configuration Profile */
280 if (profile_exists (ws_optarg, false)) {
281 set_profile_name (ws_optarg);
282 } else if (profile_exists (ws_optarg, true)) {
283 char *pf_dir_path, *pf_dir_path2, *pf_filename;
284 /* Copy from global profile */
285 if (create_persconffile_profile(ws_optarg, &pf_dir_path) == -1) {
286 cmdarg_err("Can't create directory\n\"%s\":\n%s.",
287 pf_dir_path, g_strerror(errno));
289 g_free(pf_dir_path);
290 exit(WS_EXIT_INVALID_FILE);
292 if (copy_persconffile_profile(ws_optarg, ws_optarg, true, &pf_filename,
293 &pf_dir_path, &pf_dir_path2) == -1) {
294 cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
295 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
297 g_free(pf_filename);
298 g_free(pf_dir_path);
299 g_free(pf_dir_path2);
300 exit(WS_EXIT_INVALID_FILE);
302 set_profile_name (ws_optarg);
303 } else {
304 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg);
305 exit(1);
307 break;
308 case 'D': /* Print a list of capture devices and exit */
309 #ifdef HAVE_LIBPCAP
310 exit_status = EXIT_SUCCESS;
311 if_list = capture_interface_list(&err, &err_str, NULL);
312 if (err != 0) {
314 * An error occurred when fetching the local
315 * interfaces. Report it.
317 #ifdef _WIN32
318 create_console();
319 #endif /* _WIN32 */
320 cmdarg_err("%s", err_str);
321 g_free(err_str);
322 exit_status = WS_EXIT_PCAP_ERROR;
324 if (if_list == NULL) {
326 * No interfaces were found. If that's not the
327 * result of an error when fetching the local
328 * interfaces, let the user know.
330 if (err == 0) {
331 cmdarg_err("There are no interfaces on which a capture can be done");
332 exit_status = WS_EXIT_NO_INTERFACES;
334 exit(exit_status);
336 #ifdef _WIN32
337 create_console();
338 #endif /* _WIN32 */
339 capture_opts_print_interfaces(if_list);
340 free_interface_list(if_list);
341 #ifdef _WIN32
342 destroy_console();
343 #endif /* _WIN32 */
344 exit(exit_status);
345 #else /* HAVE_LIBPCAP */
346 capture_option_specified = true;
347 #endif /* HAVE_LIBPCAP */
348 break;
349 case 'h': /* Print help and exit */
350 commandline_print_usage(true);
351 exit(EXIT_SUCCESS);
352 break;
353 #ifdef _WIN32
354 case 'i':
355 if (strcmp(ws_optarg, "-") == 0)
356 set_stdin_capture(true);
357 break;
358 #endif
359 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
360 if (!persfilepath_opt(opt, ws_optarg)) {
361 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", ws_optarg);
362 exit(EXIT_SUCCESS);
364 break;
365 case 'v': /* Show version and exit */
366 #ifdef _WIN32
367 create_console();
368 #endif
369 show_version();
370 #ifdef _WIN32
371 destroy_console();
372 #endif
373 exit(EXIT_SUCCESS);
374 break;
375 case 'X':
377 * Extension command line options have to be processed before
378 * we call epan_init() as they are supposed to be used by dissectors
379 * or taps very early in the registration process.
381 ex_opt_add(ws_optarg);
382 break;
383 case '?': /* Ignore errors - the "real" scan will catch them. */
384 break;
388 #ifndef HAVE_LUA
389 if (ex_opt_count("lua_script") > 0) {
390 cmdarg_err("This version of %s was not built with support for Lua scripting.", application_flavor_name_proper());
391 exit(1);
393 #endif
395 #ifndef HAVE_LIBPCAP
396 if (capture_option_specified) {
397 print_no_capture_support_error();
398 commandline_print_usage(false);
399 exit(EXIT_SUCCESS);
401 #endif
404 void commandline_override_prefs(int argc, char *argv[], bool opt_reset)
406 int opt;
409 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
411 * Ignore errors and keep ws_opterr as 0; error messages will be printed
412 * later by command_other_options()
414 if (opt_reset) {
415 ws_optreset = 1;
416 ws_optind = 1;
417 ws_opterr = 0;
420 /* Initialize with default values */
421 global_commandline_info.user_opts = NULL;
423 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
424 switch (opt) {
425 case 'o': /* Override preference from command line */
427 char *errmsg = NULL;
429 switch (prefs_set_pref(ws_optarg, &errmsg)) {
430 case PREFS_SET_OK:
431 global_commandline_info.user_opts =
432 g_slist_prepend(global_commandline_info.user_opts,
433 g_strdup(ws_optarg));
434 break;
435 case PREFS_SET_SYNTAX_ERR:
436 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
437 errmsg ? ": " : "", errmsg ? errmsg : "");
438 g_free(errmsg);
439 exit_application(1);
440 break;
441 case PREFS_SET_NO_SUCH_PREF:
442 /* not a preference, might be a recent setting */
443 switch (recent_set_arg(ws_optarg)) {
444 case PREFS_SET_OK:
445 break;
446 case PREFS_SET_SYNTAX_ERR:
447 /* shouldn't happen, checked already above */
448 cmdarg_err("Invalid -o flag \"%s\"", ws_optarg);
449 exit_application(1);
450 break;
451 case PREFS_SET_NO_SUCH_PREF:
452 case PREFS_SET_OBSOLETE:
453 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
454 ws_optarg);
455 exit_application(1);
456 break;
457 default:
458 ws_assert_not_reached();
460 break;
461 case PREFS_SET_OBSOLETE:
462 /* obsolete preference, might be a recent setting */
463 if (recent_set_arg(ws_optarg) != PREFS_SET_OK) {
464 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
465 ws_optarg);
466 exit_application(1);
468 break;
469 default:
470 ws_assert_not_reached();
472 break;
474 default:
475 case '?': /* Ignore errors - the "real" scan will catch them. */
476 break;
480 /* Since we prepended each option when processing `-o`, reverse the list
481 * in case the order of options becomes meaningful.
483 global_commandline_info.user_opts = g_slist_reverse(global_commandline_info.user_opts);
487 void commandline_other_options(int argc, char *argv[], bool opt_reset)
489 int opt;
490 bool arg_error = false;
491 #ifdef HAVE_LIBPCAP
492 const char *list_option_supplied = NULL;
493 int status;
494 #else
495 bool capture_option_specified;
496 #endif
499 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
501 * Also reset ws_opterr to 1, so that error messages are printed by
502 * getopt_long().
504 * XXX - if we want to control all the command-line option errors, so
505 * that we can display them where we choose (e.g., in a window), we'd
506 * want to leave ws_opterr as 0, and produce our own messages using ws_optopt.
507 * We'd have to check the value of ws_optopt to see if it's a valid option
508 * letter, in which case *presumably* the error is "this option requires
509 * an argument but none was specified", or not a valid option letter,
510 * in which case *presumably* the error is "this option isn't valid".
511 * Some versions of getopt() let you supply a option string beginning
512 * with ':', which means that getopt() will return ':' rather than '?'
513 * for "this option requires an argument but none was specified", but
514 * not all do. But we're now using getopt_long() - what does it do?
516 if (opt_reset) {
517 ws_optreset = 1;
518 ws_optind = 1;
519 ws_opterr = 1;
522 /* Initialize with default values */
523 global_commandline_info.jump_backwards = SD_FORWARD;
524 global_commandline_info.go_to_packet = 0;
525 global_commandline_info.jfilter = NULL;
526 global_commandline_info.cf_name = NULL;
527 global_commandline_info.rfilter = NULL;
528 global_commandline_info.dfilter = NULL;
529 #ifdef HAVE_LIBPCAP
530 global_commandline_info.start_capture = false;
531 global_commandline_info.list_link_layer_types = false;
532 global_commandline_info.list_timestamp_types = false;
533 global_commandline_info.quit_after_cap = getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? true : false;
534 global_commandline_info.capture_comments = NULL;
535 #endif
536 global_commandline_info.full_screen = false;
538 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
539 switch (opt) {
540 /*** capture option specific ***/
541 case 'a': /* autostop criteria */
542 case 'b': /* Ringbuffer option */
543 case 'c': /* Capture xxx packets */
544 case 'f': /* capture filter */
545 case 'F': /* capture file type */
546 case 'H': /* Hide capture info dialog box */
547 case 'p': /* Don't capture in promiscuous mode */
548 case 'i': /* Use interface x */
549 case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
550 case LONGOPT_CAPTURE_TMPDIR: /* capture temp directory */
551 case LONGOPT_UPDATE_INTERVAL: /* sync pipe update interval */
552 #ifdef HAVE_PCAP_CREATE
553 case 'I': /* Capture in monitor mode, if available */
554 #endif
555 #ifdef HAVE_PCAP_REMOTE
556 case 'A': /* Authentication */
557 #endif
558 case 's': /* Set the snapshot (capture) length */
559 case 'S': /* "Sync" mode: used for following file ala tail -f */
560 case 'w': /* Write to capture file xxx */
561 case 'y': /* Set the pcap data link type */
562 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
563 case 'B': /* Buffer size */
564 #endif
565 #ifdef HAVE_LIBPCAP
566 status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg);
567 if(status != 0) {
568 exit_application(status);
570 #else
571 capture_option_specified = true;
572 arg_error = true;
573 #endif
574 break;
576 /*** all non capture option specific ***/
577 case 'C':
578 /* Configuration profile settings were already processed just ignore them this time*/
579 break;
580 case 'j': /* Search backwards for a matching packet from filter in option J */
581 global_commandline_info.jump_backwards = SD_BACKWARD;
582 break;
583 case 'g': /* Go to packet with the given packet number */
584 global_commandline_info.go_to_packet = get_nonzero_uint32(ws_optarg, "go to packet");
585 break;
586 case 'J': /* Jump to the first packet which matches the filter criteria */
587 global_commandline_info.jfilter = ws_optarg;
588 break;
589 case 'k': /* Start capture immediately */
590 #ifdef HAVE_LIBPCAP
591 global_commandline_info.start_capture = true;
592 #else
593 capture_option_specified = true;
594 arg_error = true;
595 #endif
596 break;
597 case 'l': /* Automatic scrolling in live capture mode */
598 #ifdef HAVE_LIBPCAP
599 recent.capture_auto_scroll = true;
600 #else
601 capture_option_specified = true;
602 arg_error = true;
603 #endif
604 break;
605 case 'L': /* Print list of link-layer types and exit */
606 #ifdef HAVE_LIBPCAP
607 global_commandline_info.list_link_layer_types = true;
608 list_option_supplied = "-L";
609 #else
610 capture_option_specified = true;
611 arg_error = true;
612 #endif
613 break;
614 case LONGOPT_LIST_TSTAMP_TYPES:
615 #ifdef HAVE_LIBPCAP
616 global_commandline_info.list_timestamp_types = true;
617 list_option_supplied = "--list-time-stamp-types";
618 #else
619 capture_option_specified = true;
620 arg_error = true;
621 #endif
622 break;
623 case 'o': /* Override preference from command line */
624 /* Pref overrides were already processed just ignore them this time*/
625 break;
626 case 'P':
627 /* Path settings were already processed just ignore them this time*/
628 break;
629 case 'r': /* Read capture file xxx */
630 /* We may set "last_open_dir" to "cf_name", and if we change
631 "last_open_dir" later, we free the old value, so we have to
632 set "cf_name" to something that's been allocated. */
633 global_commandline_info.cf_name = g_strdup(ws_optarg);
634 break;
635 case 'R': /* Read file filter */
636 global_commandline_info.rfilter = ws_optarg;
637 break;
638 case 'X':
639 /* ext ops were already processed just ignore them this time*/
640 break;
641 case 'Y':
642 global_commandline_info.dfilter = ws_optarg;
643 break;
644 case 'z':
645 /* We won't call the init function for the stat this soon
646 as it would disallow MATE's fields (which are registered
647 by the preferences set callback) from being used as
648 part of a tap filter. Instead, we just add the argument
649 to a list of stat arguments. */
650 if (strcmp("help", ws_optarg) == 0) {
651 fprintf(stderr, "%s: The available statistics for the \"-z\" option are:\n", g_get_prgname());
652 list_stat_cmd_args();
653 exit_application(0);
655 if (!process_stat_cmd_arg(ws_optarg)) {
656 cmdarg_err("Invalid -z argument.");
657 cmdarg_err_cont(" -z argument must be one of :");
658 list_stat_cmd_args();
659 exit_application(1);
661 break;
662 case 'd': /* Decode as rule */
663 case 'K': /* Kerberos keytab file */
664 case 'n': /* No name resolution */
665 case 'N': /* Select what types of addresses/port #s to resolve */
666 case 't': /* time stamp type */
667 case 'u': /* Seconds type */
668 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
669 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
670 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
671 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
672 case LONGOPT_ONLY_PROTOCOLS: /* enable dissection of these comma separated protocols only */
673 case LONGOPT_DISABLE_ALL_PROTOCOLS: /* disable dissection of all protocols */
674 if (!dissect_opts_handle_opt(opt, ws_optarg))
675 exit_application(1);
676 break;
677 case LONGOPT_FULL_SCREEN:
678 global_commandline_info.full_screen = true;
679 break;
680 #ifdef HAVE_LIBPCAP
681 case LONGOPT_CAPTURE_COMMENT: /* capture comment */
682 if (global_commandline_info.capture_comments == NULL) {
683 global_commandline_info.capture_comments = g_ptr_array_new_with_free_func(g_free);
685 g_ptr_array_add(global_commandline_info.capture_comments, g_strdup(ws_optarg));
686 #else
687 capture_option_specified = true;
688 arg_error = true;
689 #endif
690 break;
691 default:
692 case '?': /* Bad flag - print usage message */
693 arg_error = true;
694 break;
698 if (!arg_error) {
699 argc -= ws_optind;
700 argv += ws_optind;
701 if (argc >= 1) {
702 if (global_commandline_info.cf_name != NULL) {
704 * Input file name specified with "-r" *and* specified as a regular
705 * command-line argument.
707 cmdarg_err("File name specified both with -r and regular argument");
708 arg_error = true;
709 } else {
711 * Input file name not specified with "-r", and a command-line argument
712 * was specified; treat it as the input file name.
714 * Yes, this is different from tshark, where non-flag command-line
715 * arguments are a filter, but this works better on GUI desktops
716 * where a command can be specified to be run to open a particular
717 * file - yes, you could have "-r" as the last part of the command,
718 * but that's a bit ugly.
720 global_commandline_info.cf_name = g_strdup(argv[0]);
722 argc--;
723 argv++;
726 if (argc != 0) {
728 * Extra command line arguments were specified; complain.
730 cmdarg_err("Invalid argument: %s", argv[0]);
731 arg_error = true;
735 if (arg_error) {
736 #ifdef HAVE_LIBPCAP
737 if (ws_optopt == 'F') {
738 capture_opts_list_file_types();
739 exit_application(1);
741 #else
742 if (capture_option_specified) {
743 print_no_capture_support_error();
745 #endif
746 commandline_print_usage(false);
747 exit_application(1);
750 #ifdef HAVE_LIBPCAP
751 if (global_commandline_info.start_capture && list_option_supplied) {
752 /* Specifying *both* is bogus. */
753 cmdarg_err("You can't specify both %s and a live capture.", list_option_supplied);
754 exit_application(1);
757 if (list_option_supplied) {
758 /* We're supposed to list the link-layer types for an interface;
759 did the user also specify a capture file to be read? */
760 if (global_commandline_info.cf_name) {
761 /* Yes - that's bogus. */
762 cmdarg_err("You can't specify %s and a capture file to be read.", list_option_supplied);
763 exit_application(1);
765 /* No - did they specify a ring buffer option? */
766 if (global_capture_opts.multi_files_on) {
767 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
768 exit_application(1);
770 } else {
771 /* We're supposed to do a live capture; did the user also specify
772 a capture file to be read? */
773 if (global_commandline_info.start_capture && global_commandline_info.cf_name) {
774 /* Yes - that's bogus. */
775 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
776 exit_application(1);
779 /* No - was the ring buffer option specified and, if so, does it make
780 sense? */
781 if (global_capture_opts.multi_files_on) {
782 /* Ring buffer works only under certain conditions:
783 a) ring buffer does not work with temporary files;
784 b) real_time_mode and multi_files_on are mutually exclusive -
785 real_time_mode takes precedence;
786 c) it makes no sense to enable the ring buffer if the maximum
787 file size is set to "infinite". */
788 if (global_capture_opts.save_file == NULL) {
789 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
790 global_capture_opts.multi_files_on = false;
792 if (!global_capture_opts.has_autostop_filesize &&
793 !global_capture_opts.has_file_duration &&
794 !global_capture_opts.has_file_interval &&
795 !global_capture_opts.has_file_packets) {
796 cmdarg_err("Ring buffer requested, but no maximum capture file size, duration, interval or packets were specified.");
797 /* XXX - this must be redesigned as the conditions changed */
801 #endif
804 /* Local function used by commandline_options_drop */
805 static int cl_find_custom(const void *elem_data, const void *search_data) {
806 return memcmp(elem_data, search_data, strlen((char *)search_data));
809 /* Drop any options the user specified on the command line with `-o`
810 * that have the given module and preference names
812 void commandline_options_drop(const char *module_name, const char *pref_name) {
813 GSList *elem;
814 char *opt_prefix;
816 if (global_commandline_info.user_opts == NULL) return;
818 opt_prefix = ws_strdup_printf("%s.%s:", module_name, pref_name);
820 while (NULL != (elem = g_slist_find_custom(global_commandline_info.user_opts,
821 (const void *)opt_prefix, cl_find_custom))) {
822 global_commandline_info.user_opts =
823 g_slist_remove_link(global_commandline_info.user_opts, elem);
824 g_free(elem->data);
825 g_slist_free_1(elem);
827 g_free(opt_prefix);
830 /* Reapply any options the user specified on the command line with `-o`
831 * Called in the Qt UI when reloading Lua plugins
832 * For https://gitlab.com/wireshark/wireshark/-/issues/12331
834 void commandline_options_reapply(void) {
835 char *errmsg = NULL;
836 GSList *entry = NULL;
838 for (entry = global_commandline_info.user_opts; entry != NULL; entry = g_slist_next(entry)) {
839 /* Although these options are from the user-supplied command line,
840 * they were checked for validity before we added them to user_opts,
841 * so we don't check them again here. In the worst case, a pref is
842 * specified for a lua plugin which has been edited after Wireshark
843 * started and has had that pref removed; not worth exiting over.
844 * See #12331
846 prefs_set_pref((char *)entry->data, &errmsg);
847 if (errmsg != NULL) {
848 g_free(errmsg);
849 errmsg = NULL;
854 void commandline_options_apply_extcap(void) {
855 char *errmsg = NULL;
856 GSList *entry = NULL;
857 char *pref_arg;
859 if (prefs.capture_no_extcap)
860 return;
862 for (entry = global_commandline_info.user_opts; entry != NULL; entry = g_slist_next(entry)) {
863 pref_arg = (char *)entry->data;
864 if (g_str_has_prefix(pref_arg, "extcap.")) {
865 switch (prefs_set_pref(pref_arg, &errmsg)) {
866 case PREFS_SET_OK:
867 break;
868 case PREFS_SET_SYNTAX_ERR:
869 cmdarg_err("Invalid -o flag \"%s\"%s%s", pref_arg,
870 errmsg ? ": " : "", errmsg ? errmsg : "");
871 g_free(errmsg);
872 exit_application(1);
873 break;
874 case PREFS_SET_NO_SUCH_PREF:
875 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
876 pref_arg);
877 exit_application(1);
878 break;
879 case PREFS_SET_OBSOLETE:
880 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
881 pref_arg);
882 exit_application(1);
883 break;
884 default:
885 ws_assert_not_reached();
891 /* Free memory used to hold user-specified command line options */
892 void commandline_options_free(void) {
893 g_slist_free_full(g_steal_pointer(&global_commandline_info.user_opts), g_free);