3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * Rawshark - Raw field extractor by Gerald Combs <gerald@wireshark.org>
8 * and Loris Degioanni <loris.degioanni@cacetech.com>
9 * Based on TShark, by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 * Rawshark does the following:
17 * - Opens a specified file or named pipe
18 * - Applies a specified DLT or "decode as" encapsulation
19 * - Reads frames prepended with a libpcap packet header.
20 * - Prints a status line, followed by fields from a specified list.
24 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
34 #include <sys/resource.h>
39 #include <ws_exit_codes.h>
40 #include <wsutil/ws_getopt.h>
43 #include <epan/epan.h>
46 #include <wsutil/array.h>
47 #include <wsutil/cmdarg_err.h>
48 #include <wsutil/filesystem.h>
49 #include <wsutil/file_util.h>
50 #include <wsutil/socket.h>
51 #include <wsutil/privileges.h>
52 #include <wsutil/please_report_bug.h>
53 #include <wsutil/wslog.h>
54 #include <wsutil/clopts_common.h>
57 #include <wsutil/unicode-utils.h>
58 #include <wsutil/win32-utils.h>
62 #include <epan/packet.h>
63 #include <epan/ftypes/ftypes.h>
65 #include <epan/disabled_protos.h>
66 #include <epan/prefs.h>
67 #include <epan/column.h>
68 #include <epan/print.h>
69 #include <epan/addr_resolv.h>
71 #include "ui/capture_ui_utils.h"
74 #include "ui/dissect_opts.h"
75 #include "ui/failure_message.h"
76 #include <epan/epan_dissect.h>
77 #include <epan/stat_tap_ui.h>
78 #include <epan/timestamp.h>
79 #include "epan/column-utils.h"
80 #include "epan/proto.h"
83 #include <wiretap/wtap.h>
84 #include <wiretap/libpcap.h>
85 #include <wiretap/pcap-encap.h>
88 #include <wsutil/version_info.h>
90 #include "capture/capture-pcap-util.h"
95 #include "capture/capture-wpcap.h"
97 #endif /* HAVE_LIBPCAP */
101 * This is the template for the decode as option; it is shared between the
102 * various functions that output the usage for this parameter.
104 static const char decode_as_arg_template
[] = "<layer_type>==<selector>,<decode_as_protocol>";
107 /* Additional exit codes */
108 #define INVALID_DFILTER 2
109 #define FORMAT_ERROR 2
113 static uint32_t cum_bytes
;
114 static frame_data ref_frame
;
115 static frame_data prev_dis_frame
;
116 static frame_data prev_cap_frame
;
119 * The way the packet decode is to be written.
122 WRITE_TEXT
, /* summary or detail text */
123 WRITE_XML
/* PDML or PSML */
124 /* Add CSV and the like here */
127 static bool line_buffered
;
128 static print_format_e print_format
= PR_FMT_TEXT
;
130 static bool want_pcap_pkthdr
;
132 cf_status_t
raw_cf_open(capture_file
*cf
, const char *fname
);
133 static bool load_cap_file(capture_file
*cf
);
134 static bool process_packet(capture_file
*cf
, epan_dissect_t
*edt
, int64_t offset
,
135 wtap_rec
*rec
, Buffer
*buf
);
136 static void show_print_file_io_error(int err
);
138 static void protocolinfo_init(char *field
);
139 static bool parse_field_string_format(char *format
);
142 SF_NONE
, /* No format (placeholder) */
143 SF_NAME
, /* %D Field name / description */
144 SF_NUMVAL
, /* %N Numeric value */
145 SF_STRVAL
/* %S String value */
148 typedef struct string_fmt_s
{
150 string_fmt_e format
; /* Valid if plain is NULL */
155 dfilter_t
*rfcodes
[64];
157 dfilter_t
*rfieldfcodes
[64];
160 GPtrArray
*string_fmts
;
163 print_usage(FILE *output
)
165 fprintf(output
, "\n");
166 fprintf(output
, "Usage: rawshark [options] ...\n");
167 fprintf(output
, "\n");
169 fprintf(output
, "Input file:\n");
170 fprintf(output
, " -r <infile>, --read-file <infile>\n");
171 fprintf(output
," set the pipe or file name to read from\n");
173 fprintf(output
, "\n");
174 fprintf(output
, "Processing:\n");
175 fprintf(output
, " -d <encap:linktype>|<proto:protoname>\n");
176 fprintf(output
, " packet encapsulation or protocol\n");
177 fprintf(output
, " -F <field> field to display\n");
178 #if !defined(_WIN32) && defined(RLIMIT_AS)
179 fprintf(output
, " -m virtual memory limit, in bytes\n");
181 fprintf(output
, " -n disable all name resolutions (def: \"mNd\" enabled, or\n");
182 fprintf(output
, " as set in preferences)\n");
183 fprintf(output
, " -N <name resolve flags> enable specific name resolution(s): \"mnNtdv\"\n");
184 fprintf(output
, " -p use the system's packet header format\n");
185 fprintf(output
, " (which may have 64-bit timestamps)\n");
186 fprintf(output
, " -R <read filter>, --read-filter <read filter>\n");
187 fprintf(output
, " packet filter in Wireshark display filter syntax\n");
188 fprintf(output
, " -s skip PCAP header on input\n");
189 fprintf(output
, " -Y <display filter>, --display-filter <display filter>\n");
190 fprintf(output
, " packet filter in Wireshark display filter syntax\n");
191 fprintf(output
, " --enable-protocol <proto_name>\n");
192 fprintf(output
, " enable dissection of proto_name\n");
193 fprintf(output
, " --disable-protocol <proto_name>\n");
194 fprintf(output
, " disable dissection of proto_name\n");
195 fprintf(output
, " --only-protocols <protocols>\n");
196 fprintf(output
, " Only enable dissection of these protocols, comma\n");
197 fprintf(output
, " separated. Disable everything else\n");
198 fprintf(output
, " --disable-all-protocols\n");
199 fprintf(output
, " Disable dissection of all protocols\n");
200 fprintf(output
, " --enable-heuristic <short_name>\n");
201 fprintf(output
, " enable dissection of heuristic protocol\n");
202 fprintf(output
, " --disable-heuristic <short_name>\n");
203 fprintf(output
, " disable dissection of heuristic protocol\n");
205 fprintf(output
, "\n");
206 fprintf(output
, "Output:\n");
207 fprintf(output
, " -l flush output after each packet\n");
208 fprintf(output
, " -S format string for fields\n");
209 fprintf(output
, " (%%D - name, %%S - stringval, %%N numval)\n");
210 fprintf(output
, " -t (a|ad|adoy|d|dd|e|r|u|ud|udoy)[.[N]]|.[N]\n");
211 fprintf(output
, " output format of time stamps (def: r: rel. to first)\n");
212 fprintf(output
, " -u s|hms output format of seconds (def: s: seconds)\n");
213 fprintf(output
, "\n");
215 ws_log_print_usage(output
);
216 fprintf(output
, "\n");
218 fprintf(output
, "\n");
219 fprintf(output
, "Miscellaneous:\n");
220 fprintf(output
, " -h, --help display this help and exit\n");
221 fprintf(output
, " -v, --version display version info and exit\n");
222 fprintf(output
, " -o <name>:<value> ... override preference setting\n");
223 fprintf(output
, " -K <keytab> keytab file to use for kerberos decryption\n");
227 * Open a pipe for raw input. This is a stripped-down version of
228 * pcap_loop.c:cap_pipe_open_live().
229 * We check if "pipe_name" is "-" (stdin) or a FIFO, and open it.
230 * @param pipe_name The name of the pipe or FIFO.
231 * @return A POSIX file descriptor on success, or -1 on failure.
234 raw_pipe_open(const char *pipe_name
)
237 ws_statb64 pipe_stat
;
245 ws_log(LOG_DOMAIN_CAPCHILD
, LOG_LEVEL_DEBUG
, "open_raw_pipe: %s", pipe_name
);
248 * XXX Rawshark blocks until we return
250 if (strcmp(pipe_name
, "-") == 0) {
251 rfd
= 0; /* read from stdin */
254 * This is needed to set the stdin pipe into binary mode, otherwise
255 * CR/LF are mangled...
257 _setmode(0, _O_BINARY
);
261 if (ws_stat64(pipe_name
, &pipe_stat
) < 0) {
262 fprintf(stderr
, "rawshark: The pipe %s could not be checked: %s\n",
263 pipe_name
, g_strerror(errno
));
266 if (! S_ISFIFO(pipe_stat
.st_mode
)) {
267 if (S_ISCHR(pipe_stat
.st_mode
)) {
269 * Assume the user specified an interface on a system where
270 * interfaces are in /dev. Pretend we haven't seen it.
274 fprintf(stderr
, "rawshark: \"%s\" is neither an interface nor a pipe\n",
279 rfd
= ws_open(pipe_name
, O_RDONLY
| O_NONBLOCK
, 0000 /* no creation so don't matter */);
281 fprintf(stderr
, "rawshark: \"%s\" could not be opened: %s\n",
282 pipe_name
, g_strerror(errno
));
286 if (!win32_is_pipe_name(pipe_name
)) {
287 fprintf(stderr
, "rawshark: \"%s\" is neither an interface nor a pipe\n",
292 /* Wait for the pipe to appear */
294 hPipe
= CreateFile(utf_8to16(pipe_name
), GENERIC_READ
, 0, NULL
,
295 OPEN_EXISTING
, 0, NULL
);
297 if (hPipe
!= INVALID_HANDLE_VALUE
)
300 err
= GetLastError();
301 if (err
!= ERROR_PIPE_BUSY
) {
302 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_IGNORE_INSERTS
,
303 NULL
, err
, 0, (LPTSTR
) &err_str
, 0, NULL
);
304 fprintf(stderr
, "rawshark: \"%s\" could not be opened: %s (error %lu)\n",
305 pipe_name
, utf_16to8(err_str
), err
);
310 if (!WaitNamedPipe(utf_8to16(pipe_name
), 30 * 1000)) {
311 err
= GetLastError();
312 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_IGNORE_INSERTS
,
313 NULL
, err
, 0, (LPTSTR
) &err_str
, 0, NULL
);
314 fprintf(stderr
, "rawshark: \"%s\" could not be waited for: %s (error %lu)\n",
315 pipe_name
, utf_16to8(err_str
), err
);
321 rfd
= _open_osfhandle((intptr_t) hPipe
, _O_RDONLY
);
323 fprintf(stderr
, "rawshark: \"%s\" could not be opened: %s\n",
324 pipe_name
, g_strerror(errno
));
334 * Parse a link-type argument of the form "encap:<pcap linktype>" or
335 * "proto:<proto name>". "Pcap linktype" must be a name conforming to
336 * pcap_datalink_name_to_val() or an integer; the integer should be
337 * a LINKTYPE_ value supported by Wiretap. "Proto name" must be
338 * a protocol name, e.g. "http".
341 set_link_type(const char *lt_arg
) {
342 char *spec_ptr
= strchr(lt_arg
, ':');
346 dissector_handle_t dhandle
;
355 if (strncmp(lt_arg
, "encap:", strlen("encap:")) == 0) {
356 dlt_val
= linktype_name_to_val(spec_ptr
);
359 val
= strtol(spec_ptr
, &p
, 10);
360 if (p
== spec_ptr
|| *p
!= '\0' || errno
!= 0 || val
> INT_MAX
) {
366 * In those cases where a given link-layer header type
367 * has different LINKTYPE_ and DLT_ values, linktype_name_to_val()
368 * will return the OS's DLT_ value for that link-layer header
369 * type, not its OS-independent LINKTYPE_ value.
371 * On a given OS, wtap_pcap_encap_to_wtap_encap() should
372 * be able to map either LINKTYPE_ values or DLT_ values
373 * for the OS to the appropriate Wiretap encapsulation.
375 encap
= wtap_pcap_encap_to_wtap_encap(dlt_val
);
376 if (encap
== WTAP_ENCAP_UNKNOWN
) {
380 } else if (strncmp(lt_arg
, "proto:", strlen("proto:")) == 0) {
381 dhandle
= find_dissector(spec_ptr
);
383 encap
= WTAP_ENCAP_USER0
;
384 pref_str
= g_string_new("uat:user_dlts:");
385 /* This must match the format used in the user_dlts file */
386 g_string_append_printf(pref_str
,
387 "\"User 0 (DLT=147)\",\"%s\",\"0\",\"\",\"0\",\"\"",
389 if (prefs_set_pref(pref_str
->str
, &errmsg
) != PREFS_SET_OK
) {
390 g_string_free(pref_str
, TRUE
);
394 g_string_free(pref_str
, TRUE
);
402 main(int argc
, char *argv
[])
408 #if !defined(_WIN32) && defined(RLIMIT_AS)
412 char *pipe_name
= NULL
;
415 GPtrArray
*disp_fields
= g_ptr_array_new();
417 bool skip_pcap_header
= false;
418 int ret
= EXIT_SUCCESS
;
419 static const struct ws_option long_options
[] = {
420 {"help", ws_no_argument
, NULL
, 'h'},
421 {"version", ws_no_argument
, NULL
, 'v'},
422 LONGOPT_DISSECT_COMMON
423 LONGOPT_READ_CAPTURE_COMMON
427 #define OPTSTRING_INIT OPTSTRING_DISSECT_COMMON OPTSTRING_READ_CAPTURE_COMMON "F:hlm:o:psS:v"
429 static const char optstring
[] = OPTSTRING_INIT
;
431 /* Set the program name. */
432 g_set_prgname("rawshark");
435 * Set the C-language locale to the native environment and set the
436 * code page to UTF-8 on Windows.
439 setlocale(LC_ALL
, ".UTF-8");
441 setlocale(LC_ALL
, "");
444 cmdarg_err_init(stderr_cmdarg_err
, stderr_cmdarg_err_cont
);
446 /* Initialize log handler early so we can have proper logging during startup. */
447 ws_log_init(vcmdarg_err
);
449 /* Early logging command-line initialization. */
450 ws_log_parse_args(&argc
, argv
, vcmdarg_err
, WS_EXIT_INVALID_OPTION
);
452 ws_noisy("Finished log init and parsing command line log arguments");
455 create_app_running_mutex();
459 * Get credential information for later use.
461 init_process_policies();
464 * Clear the filters arrays
466 memset(rfilters
, 0, sizeof(rfilters
));
467 memset(rfcodes
, 0, sizeof(rfcodes
));
472 * Initialize our string format
474 string_fmts
= g_ptr_array_new();
477 * Attempt to get the pathname of the directory containing the
480 err_msg
= configuration_init(argv
[0]);
481 if (err_msg
!= NULL
) {
482 fprintf(stderr
, "rawshark: Can't get pathname of rawshark program: %s.\n",
486 /* Initialize the version information. */
487 ws_init_version_info("Rawshark",
488 epan_gather_compile_info
,
491 init_report_failure_message("rawshark");
493 timestamp_set_type(TS_RELATIVE
);
494 timestamp_set_precision(TS_PREC_AUTO
);
495 timestamp_set_seconds_type(TS_SECONDS_DEFAULT
);
498 * XXX - is this necessary, given that we're not reading a
499 * regular capture file, we're reading rawshark's packet
502 * If it is, note that libwiretap must be initialized before
503 * libwireshark is, so that dissection-time handlers for
504 * file-type-dependent blocks can register using the file
505 * type/subtype value for the file type.
509 /* Register all dissectors; we must do this before checking for the
510 "-G" flag, as the "-G" flag dumps information registered by the
511 dissectors, and we must do it before we read the preferences, in
512 case any dissectors register preferences. */
513 if (!epan_init(NULL
, NULL
, true)) {
514 ret
= WS_EXIT_INIT_FAILED
;
518 /* Load libwireshark settings from the current profile. */
519 prefs_p
= epan_load_settings();
522 ws_init_dll_search_path();
523 /* Load Wpcap, if possible */
527 cap_file_init(&cfile
);
529 /* Print format defaults to this. */
530 print_format
= PR_FMT_TEXT
;
532 /* Initialize our encapsulation type */
533 encap
= WTAP_ENCAP_UNKNOWN
;
535 /* Now get our args */
536 /* XXX - We should probably have an option to dump libpcap link types */
537 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
539 case 'd': /* Payload type */
540 /* XXX: This option should probably be changed so it doesn't
541 * conflict with the common dissection option for Decode As.
543 if (!set_link_type(ws_optarg
)) {
544 cmdarg_err("Invalid link type or protocol \"%s\"", ws_optarg
);
545 ret
= WS_EXIT_INVALID_OPTION
;
549 case 'F': /* Read field to display */
550 g_ptr_array_add(disp_fields
, g_strdup(ws_optarg
));
552 case 'h': /* Print help and exit */
553 show_help_header("Dump and analyze network traffic.");
557 case 'l': /* "Line-buffer" standard output */
558 /* This isn't line-buffering, strictly speaking, it's just
559 flushing the standard output after the information for
560 each packet is printed; however, that should be good
561 enough for all the purposes to which "-l" is put (and
562 is probably actually better for "-V", as it does fewer
565 See the comment in "process_packet()" for an explanation of
566 why we do that, and why we don't just use "setvbuf()" to
567 make the standard output line-buffered (short version: in
568 Windows, "line-buffered" is the same as "fully-buffered",
569 and the output buffer is only flushed when it fills up). */
570 line_buffered
= true;
572 #if !defined(_WIN32) && defined(RLIMIT_AS)
574 limit
.rlim_cur
= get_positive_int(ws_optarg
, "memory limit");
575 limit
.rlim_max
= get_positive_int(ws_optarg
, "memory limit");
577 if(setrlimit(RLIMIT_AS
, &limit
) != 0) {
578 cmdarg_err("setrlimit(RLIMIT_AS) failed: %s",
580 ret
= WS_EXIT_INVALID_OPTION
;
585 case 'o': /* Override preference from command line */
589 switch (prefs_set_pref(ws_optarg
, &errmsg
)) {
594 case PREFS_SET_SYNTAX_ERR
:
595 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg
,
596 errmsg
? ": " : "", errmsg
? errmsg
: "");
598 ret
= WS_EXIT_INVALID_OPTION
;
602 case PREFS_SET_NO_SUCH_PREF
:
603 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg
);
604 ret
= WS_EXIT_INVALID_OPTION
;
608 case PREFS_SET_OBSOLETE
:
609 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg
);
610 ret
= WS_EXIT_INVALID_OPTION
;
616 case 'p': /* Expect pcap_pkthdr packet headers, which may have 64-bit timestamps */
617 want_pcap_pkthdr
= true;
619 case 'r': /* Read capture file xxx */
620 pipe_name
= g_strdup(ws_optarg
);
622 case 'R': /* Read file filter */
623 case 'Y': /* Read file filter */
624 /* Read and display filters are the same for rawshark */
625 if(n_rfilters
< (int)array_length(rfilters
)) {
626 rfilters
[n_rfilters
++] = ws_optarg
;
629 cmdarg_err("Too many display filters");
630 ret
= WS_EXIT_INVALID_OPTION
;
634 case 's': /* Skip PCAP header */
635 skip_pcap_header
= true;
637 case 'S': /* Print string representations */
638 if (!parse_field_string_format(ws_optarg
)) {
639 cmdarg_err("Invalid field string format");
640 ret
= WS_EXIT_INVALID_OPTION
;
644 case 'v': /* Show version and exit */
649 /* Common dissection options - 'd' for Decode As also makes
650 * sense, but rawshark uses it for the payload link layer/
651 * dissector selection.
653 case 'K': /* Kerberos keytab file */
654 case 'n': /* No name resolution */
655 case 'N': /* Select what types of addresses/port #s to resolve */
656 case 't': /* Time stamp type */
657 case 'u': /* Seconds type */
658 case LONGOPT_DISABLE_PROTOCOL
: /* disable dissection of protocol */
659 case LONGOPT_ENABLE_HEURISTIC
: /* enable heuristic dissection of protocol */
660 case LONGOPT_DISABLE_HEURISTIC
: /* disable heuristic dissection of protocol */
661 case LONGOPT_ENABLE_PROTOCOL
: /* enable dissection of protocol (that is disabled by default) */
662 case LONGOPT_ONLY_PROTOCOLS
: /* enable dissection of only this comma separated list of protocols */
663 case LONGOPT_DISABLE_ALL_PROTOCOLS
: /* enable dissection of protocol (that is disabled by default) */
664 if (!dissect_opts_handle_opt(opt
, ws_optarg
)) {
665 ret
= WS_EXIT_INVALID_OPTION
;
670 case '?': /* Bad flag - print usage message */
672 ret
= WS_EXIT_INVALID_OPTION
;
677 /* Notify all registered modules that have had any of their preferences
678 changed either from one of the preferences file or from the command
679 line that their preferences have changed.
680 Initialize preferences before display filters, otherwise modules
681 like MATE won't work. */
684 /* Initialize our display fields */
685 for (fc
= 0; fc
< disp_fields
->len
; fc
++) {
686 protocolinfo_init((char *)g_ptr_array_index(disp_fields
, fc
));
688 g_ptr_array_free(disp_fields
, TRUE
);
692 /* If no capture filter or read filter has been specified, and there are
693 still command-line arguments, treat them as the tokens of a capture
694 filter (if no "-r" flag was specified) or a read filter (if a "-r"
695 flag was specified. */
696 if (ws_optind
< argc
) {
697 if (pipe_name
!= NULL
) {
698 if (n_rfilters
!= 0) {
699 cmdarg_err("Read filters were specified both with \"-R\" "
700 "and with additional command-line arguments");
701 ret
= WS_EXIT_INVALID_OPTION
;
704 rfilters
[n_rfilters
] = get_args_as_string(argc
, argv
, ws_optind
);
708 /* Make sure we got a dissector handle for our payload. */
709 if (encap
== WTAP_ENCAP_UNKNOWN
) {
710 cmdarg_err("No valid payload dissector specified.");
711 ret
= WS_EXIT_INVALID_OPTION
;
715 err_msg
= ws_init_sockets();
718 cmdarg_err("%s", err_msg
);
720 cmdarg_err_cont("%s", please_report_bug());
721 ret
= WS_EXIT_INIT_FAILED
;
725 if (global_dissect_options
.time_format
!= TS_NOT_SET
)
726 timestamp_set_type(global_dissect_options
.time_format
);
727 if (global_dissect_options
.time_precision
!= TS_PREC_NOT_SET
)
728 timestamp_set_precision(global_dissect_options
.time_precision
);
731 * Enabled and disabled protocols and heuristic dissectors as per
732 * command-line options.
734 if (!setup_enabled_and_disabled_protocols()) {
735 ret
= WS_EXIT_INVALID_OPTION
;
739 /* Build the column format array */
740 build_column_format_array(&cfile
.cinfo
, prefs_p
->num_cols
, true);
742 if (n_rfilters
!= 0) {
743 for (i
= 0; i
< n_rfilters
; i
++) {
744 if (!dfilter_compile(rfilters
[i
], &rfcodes
[n_rfcodes
], &df_err
)) {
745 cmdarg_err("%s", df_err
->msg
);
746 df_error_free(&df_err
);
747 ret
= INVALID_DFILTER
;
756 * We're reading a pipe (or capture file).
760 * Immediately relinquish any special privileges we have; we must not
761 * be allowed to read any capture files the user running Rawshark
764 relinquish_special_privs_perm();
766 if (raw_cf_open(&cfile
, pipe_name
) != CF_OK
) {
767 ret
= WS_EXIT_OPEN_ERROR
;
771 /* Do we need to PCAP header and magic? */
772 if (skip_pcap_header
) {
773 unsigned int bytes_left
= (unsigned int) sizeof(struct pcap_hdr
) + sizeof(uint32_t);
774 char buf
[sizeof(struct pcap_hdr
) + sizeof(uint32_t)];
775 while (bytes_left
!= 0) {
776 ssize_t bytes
= ws_read(fd
, buf
, bytes_left
);
778 cmdarg_err("Not enough bytes for pcap header.");
782 bytes_left
-= (unsigned int)bytes
;
786 /* Process the packets in the file */
787 if (!load_cap_file(&cfile
)) {
788 ret
= WS_EXIT_OPEN_ERROR
;
792 /* If you want to capture live packets, use TShark. */
793 cmdarg_err("Input file or pipe name not specified.");
794 ret
= WS_EXIT_OPEN_ERROR
;
800 epan_free(cfile
.epan
);
807 * Read data from a raw pipe. The "raw" data consists of a libpcap
808 * packet header followed by the payload.
809 * @param buf [IN] A POSIX file descriptor. Because that's _exactly_ the sort
810 * of thing you want to use in Windows.
811 * @param err [OUT] Error indicator. Uses wiretap values.
812 * @param err_info [OUT] Error message.
813 * @param data_offset [OUT] data offset in the pipe.
814 * @return true on success, false on failure.
817 raw_pipe_read(wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
, int64_t *data_offset
) {
818 struct pcap_pkthdr mem_hdr
;
819 struct pcaprec_hdr disk_hdr
;
820 ssize_t bytes_read
= 0;
821 unsigned int bytes_needed
= (unsigned int) sizeof(disk_hdr
);
822 unsigned char *ptr
= (unsigned char*) &disk_hdr
;
826 if (want_pcap_pkthdr
) {
827 bytes_needed
= sizeof(mem_hdr
);
828 ptr
= (unsigned char*) &mem_hdr
;
832 * Newer versions of the VC runtime do parameter validation. If stdin
833 * has been closed, calls to _read, _get_osfhandle, et al will trigger
834 * the invalid parameter handler and crash.
835 * We could alternatively use ReadFile or set an invalid parameter
837 * We could also tell callers not to close stdin prematurely.
841 if (fd
== 0 && GetHandleInformation(GetStdHandle(STD_INPUT_HANDLE
), &ghi_flags
) == 0) {
848 /* Copied from capture_loop.c */
849 while (bytes_needed
> 0) {
850 bytes_read
= ws_read(fd
, ptr
, bytes_needed
);
851 if (bytes_read
== 0) {
855 } else if (bytes_read
< 0) {
860 bytes_needed
-= (unsigned int)bytes_read
;
861 *data_offset
+= bytes_read
;
865 rec
->rec_type
= REC_TYPE_PACKET
;
866 rec
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
;
867 if (want_pcap_pkthdr
) {
868 rec
->ts
.secs
= mem_hdr
.ts
.tv_sec
;
869 rec
->ts
.nsecs
= (int32_t)mem_hdr
.ts
.tv_usec
* 1000;
870 rec
->rec_header
.packet_header
.caplen
= mem_hdr
.caplen
;
871 rec
->rec_header
.packet_header
.len
= mem_hdr
.len
;
873 rec
->ts
.secs
= disk_hdr
.ts_sec
;
874 rec
->ts
.nsecs
= disk_hdr
.ts_usec
* 1000;
875 rec
->rec_header
.packet_header
.caplen
= disk_hdr
.incl_len
;
876 rec
->rec_header
.packet_header
.len
= disk_hdr
.orig_len
;
878 bytes_needed
= rec
->rec_header
.packet_header
.caplen
;
880 rec
->rec_header
.packet_header
.pkt_encap
= encap
;
883 printf("mem_hdr: %lu disk_hdr: %lu\n", sizeof(mem_hdr
), sizeof(disk_hdr
));
884 printf("tv_sec: %d (%04x)\n", (unsigned int) rec
->ts
.secs
, (unsigned int) rec
->ts
.secs
);
885 printf("tv_nsec: %d (%04x)\n", rec
->ts
.nsecs
, rec
->ts
.nsecs
);
886 printf("caplen: %d (%04x)\n", rec
->rec_header
.packet_header
.caplen
, rec
->rec_header
.packet_header
.caplen
);
887 printf("len: %d (%04x)\n", rec
->rec_header
.packet_header
.len
, rec
->rec_header
.packet_header
.len
);
889 if (bytes_needed
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
890 *err
= WTAP_ERR_BAD_FILE
;
891 *err_info
= ws_strdup_printf("Bad packet length: %lu",
892 (unsigned long) bytes_needed
);
896 ws_buffer_assure_space(buf
, bytes_needed
);
897 ptr
= ws_buffer_start_ptr(buf
);
898 while (bytes_needed
> 0) {
899 bytes_read
= ws_read(fd
, ptr
, bytes_needed
);
900 if (bytes_read
== 0) {
901 *err
= WTAP_ERR_SHORT_READ
;
904 } else if (bytes_read
< 0) {
909 bytes_needed
-= (unsigned int)bytes_read
;
910 *data_offset
+= bytes_read
;
917 load_cap_file(capture_file
*cf
)
920 char *err_info
= NULL
;
921 int64_t data_offset
= 0;
928 ws_buffer_init(&buf
, 1514);
930 epan_dissect_init(&edt
, cf
->epan
, true, false);
932 while (raw_pipe_read(&rec
, &buf
, &err
, &err_info
, &data_offset
)) {
933 process_packet(cf
, &edt
, data_offset
, &rec
, &buf
);
936 epan_dissect_cleanup(&edt
);
938 wtap_rec_cleanup(&rec
);
939 ws_buffer_free(&buf
);
941 /* Print a message noting that the read failed somewhere along the line. */
942 cfile_read_failure_message(cf
->filename
, err
, err_info
);
950 process_packet(capture_file
*cf
, epan_dissect_t
*edt
, int64_t offset
,
951 wtap_rec
*rec
, Buffer
*buf
)
957 if(rec
->rec_header
.packet_header
.len
== 0)
959 /* The user sends an empty packet when he wants to get output from us even if we don't currently have
960 packets to process. We spit out a line with the timestamp and the text "void"
962 printf("%lu %" PRIu64
" %d void -\n", (unsigned long int)cf
->count
,
963 (uint64_t)rec
->ts
.secs
, rec
->ts
.nsecs
);
970 /* Count this packet. */
973 /* If we're going to print packet information, or we're going to
974 run a read filter, or we're going to process taps, set up to
975 do a dissection and do so. */
976 frame_data_init(&fdata
, cf
->count
, rec
, offset
, cum_bytes
);
980 /* If we're running a read filter, prime the epan_dissect_t with that
982 if (n_rfilters
> 0) {
983 for(i
= 0; i
< n_rfcodes
; i
++) {
984 epan_dissect_prime_with_dfilter(edt
, rfcodes
[i
]);
988 printf("%lu", (unsigned long int) cf
->count
);
990 frame_data_set_before_dissect(&fdata
, &cf
->elapsed_time
,
991 &cf
->provider
.ref
, cf
->provider
.prev_dis
);
993 if (cf
->provider
.ref
== &fdata
) {
995 cf
->provider
.ref
= &ref_frame
;
998 /* We only need the columns if we're printing packet info but we're
999 *not* verbose; in verbose mode, we print the protocol tree, not
1000 the protocol summary. */
1001 epan_dissect_run_with_taps(edt
, cf
->cd_t
, rec
,
1002 ws_buffer_start_ptr(buf
),
1003 &fdata
, &cf
->cinfo
);
1005 frame_data_set_after_dissect(&fdata
, &cum_bytes
);
1006 prev_dis_frame
= fdata
;
1007 cf
->provider
.prev_dis
= &prev_dis_frame
;
1009 prev_cap_frame
= fdata
;
1010 cf
->provider
.prev_cap
= &prev_cap_frame
;
1012 for(i
= 0; i
< n_rfilters
; i
++) {
1013 /* Run the read filter if we have one. */
1015 passed
= dfilter_apply_edt(rfcodes
[i
], edt
);
1019 /* Print a one-line summary */
1020 printf(" %d", passed
? 1 : 0);
1025 /* The ANSI C standard does not appear to *require* that a line-buffered
1026 stream be flushed to the host environment whenever a newline is
1027 written, it just says that, on such a stream, characters "are
1028 intended to be transmitted to or from the host environment as a
1029 block when a new-line character is encountered".
1031 The Visual C++ 6.0 C implementation doesn't do what is intended;
1032 even if you set a stream to be line-buffered, it still doesn't
1033 flush the buffer at the end of every line.
1035 So, if the "-l" flag was specified, we flush the standard output
1036 at the end of a packet. This will do the right thing if we're
1037 printing packet summary lines, and, as we print the entire protocol
1038 tree for a single packet without waiting for anything to happen,
1039 it should be as good as line-buffered mode if we're printing
1040 protocol trees. (The whole reason for the "-l" flag in either
1041 tcpdump or Rawshark is to allow the output of a live capture to
1042 be piped to a program or script and to have that script see the
1043 information for the packet as soon as it's printed, rather than
1044 having to wait until a standard I/O buffer fills up. */
1048 if (ferror(stdout
)) {
1049 show_print_file_io_error(errno
);
1053 epan_dissect_reset(edt
);
1054 frame_data_destroy(&fdata
);
1059 /****************************************************************************************
1060 * FIELD EXTRACTION ROUTINES
1061 ****************************************************************************************/
1062 typedef struct _pci_t
{
1068 static const char* ftenum_to_string(header_field_info
*hfi
)
1075 if (string_fmts
->len
> 0 && hfi
->strings
) {
1079 str
= ftype_name(hfi
->type
);
1087 static void field_display_to_string(header_field_info
*hfi
, char* buf
, int size
)
1089 if (hfi
->type
!= FT_BOOLEAN
)
1091 (void) g_strlcpy(buf
, proto_field_display_to_string(hfi
->display
), size
);
1095 snprintf(buf
, size
, "(Bit count: %d)", hfi
->display
);
1100 * Copied from various parts of proto.c
1102 #define FIELD_STR_INIT_LEN 256
1103 #define cVALS(x) (const value_string*)(x)
1104 static bool print_field_value(field_info
*finfo
, int cmd_line_index
)
1106 const header_field_info
*hfinfo
;
1108 char *fs_ptr
= NULL
;
1109 static GString
*label_s
= NULL
;
1118 hfinfo
= finfo
->hfinfo
;
1121 label_s
= g_string_new("");
1124 fs_buf
= fvalue_to_string_repr(NULL
, finfo
->value
,
1125 FTREPR_DFILTER
, finfo
->hfinfo
->display
);
1126 if (fs_buf
!= NULL
) {
1128 * this field has an associated value,
1131 fs_len
= strlen(fs_buf
);
1134 /* String types are quoted. Remove them. */
1135 if (FT_IS_STRING(fvalue_type_ftenum(finfo
->value
)) && fs_len
> 2) {
1136 fs_buf
[fs_len
- 1] = '\0';
1141 if (string_fmts
->len
> 0 && finfo
->hfinfo
->strings
) {
1142 g_string_truncate(label_s
, 0);
1143 for (i
= 0; i
< string_fmts
->len
; i
++) {
1144 sf
= (string_fmt_t
*)g_ptr_array_index(string_fmts
, i
);
1146 g_string_append(label_s
, sf
->plain
);
1148 switch (sf
->format
) {
1150 g_string_append(label_s
, hfinfo
->name
);
1153 g_string_append(label_s
, fs_ptr
);
1156 switch(hfinfo
->type
) {
1158 uvalue64
= fvalue_get_uinteger64(finfo
->value
);
1159 g_string_append(label_s
, tfs_get_string(!!uvalue64
, hfinfo
->strings
));
1165 DISSECTOR_ASSERT(!hfinfo
->bitmask
);
1166 svalue
= fvalue_get_sinteger(finfo
->value
);
1167 if (hfinfo
->display
& BASE_RANGE_STRING
) {
1168 g_string_append(label_s
, rval_to_str_const(svalue
, (const range_string
*) hfinfo
->strings
, "Unknown"));
1169 } else if (hfinfo
->display
& BASE_EXT_STRING
) {
1170 g_string_append(label_s
, val_to_str_ext_const(svalue
, (value_string_ext
*) hfinfo
->strings
, "Unknown"));
1172 g_string_append(label_s
, val_to_str_const(svalue
, cVALS(hfinfo
->strings
), "Unknown"));
1175 case FT_INT40
: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1179 DISSECTOR_ASSERT(!hfinfo
->bitmask
);
1180 svalue64
= fvalue_get_sinteger64(finfo
->value
);
1181 if (hfinfo
->display
& BASE_VAL64_STRING
) {
1182 g_string_append(label_s
, val64_to_str_const(svalue64
, (const val64_string
*)(hfinfo
->strings
), "Unknown"));
1189 DISSECTOR_ASSERT(!hfinfo
->bitmask
);
1190 uvalue
= fvalue_get_uinteger(finfo
->value
);
1191 if (!hfinfo
->bitmask
&& hfinfo
->display
& BASE_RANGE_STRING
) {
1192 g_string_append(label_s
, rval_to_str_const(uvalue
, (const range_string
*) hfinfo
->strings
, "Unknown"));
1193 } else if (hfinfo
->display
& BASE_EXT_STRING
) {
1194 g_string_append(label_s
, val_to_str_ext_const(uvalue
, (value_string_ext
*) hfinfo
->strings
, "Unknown"));
1196 g_string_append(label_s
, val_to_str_const(uvalue
, cVALS(hfinfo
->strings
), "Unknown"));
1199 case FT_UINT40
: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1203 DISSECTOR_ASSERT(!hfinfo
->bitmask
);
1204 uvalue64
= fvalue_get_uinteger64(finfo
->value
);
1205 if (hfinfo
->display
& BASE_VAL64_STRING
) {
1206 g_string_append(label_s
, val64_to_str_const(uvalue64
, (const val64_string
*)(hfinfo
->strings
), "Unknown"));
1218 printf(" %d=\"%s\"", cmd_line_index
, label_s
->str
);
1219 wmem_free(NULL
, fs_buf
);
1225 printf(" %d=\"%s\"", cmd_line_index
, fs_ptr
);
1226 wmem_free(NULL
, fs_buf
);
1231 * This field doesn't have an associated value,
1235 printf(" %d=\"n.a.\"", cmd_line_index
);
1239 static tap_packet_status
1240 protocolinfo_packet(void *prs
, packet_info
*pinfo _U_
, epan_dissect_t
*edt
, const void *dummy _U_
, tap_flags_t flags _U_
)
1242 pci_t
*rs
=(pci_t
*)prs
;
1246 gp
=proto_get_finfo_ptr_array(edt
->tree
, rs
->hf_index
);
1249 return TAP_PACKET_DONT_REDRAW
;
1253 * Print each occurrence of the field
1255 for (i
= 0; i
< gp
->len
; i
++) {
1256 print_field_value((field_info
*)gp
->pdata
[i
], rs
->cmd_line_index
);
1259 return TAP_PACKET_DONT_REDRAW
;
1262 int g_cmd_line_index
;
1265 * field must be persistent - we don't g_strdup() it below
1268 protocolinfo_init(char *field
)
1271 header_field_info
*hfi
;
1272 GString
*error_string
;
1275 hfi
=proto_registrar_get_byname(field
);
1277 fprintf(stderr
, "rawshark: Field \"%s\" doesn't exist.\n", field
);
1281 field_display_to_string(hfi
, hfibuf
, sizeof(hfibuf
));
1282 printf("%d %s %s - ",
1284 ftenum_to_string(hfi
),
1288 rs
->hf_index
=hfi
->id
;
1290 rs
->cmd_line_index
= g_cmd_line_index
++;
1292 error_string
=register_tap_listener("frame", rs
, rs
->filter
, TL_REQUIRES_PROTO_TREE
, NULL
, protocolinfo_packet
, NULL
, NULL
);
1294 /* error, we failed to attach to the tap. complain and clean up */
1295 fprintf(stderr
, "rawshark: Couldn't register field extraction tap: %s\n",
1297 g_string_free(error_string
, TRUE
);
1308 * Given a format string, split it into a GPtrArray of string_fmt_t structs
1309 * and fill in string_fmt_parts.
1313 add_string_fmt(string_fmt_e format
, char *plain
) {
1314 string_fmt_t
*sf
= g_new(string_fmt_t
, 1);
1316 sf
->format
= format
;
1317 sf
->plain
= g_strdup(plain
);
1319 g_ptr_array_add(string_fmts
, sf
);
1323 parse_field_string_format(char *format
) {
1331 GString
*plain_s
= g_string_new("");
1333 len
= strlen(format
);
1334 g_ptr_array_set_size(string_fmts
, 0);
1337 if (format
[pos
] == '%') {
1338 if (pos
>= (len
-1)) { /* There should always be a following specifier character */
1342 if (plain_s
->len
> 0) {
1343 add_string_fmt(SF_NONE
, plain_s
->str
);
1344 g_string_truncate(plain_s
, 0);
1346 switch (format
[pos
]) {
1348 add_string_fmt(SF_NAME
, NULL
);
1351 add_string_fmt(SF_NUMVAL
, NULL
);
1354 add_string_fmt(SF_STRVAL
, NULL
);
1357 g_string_append_c(plain_s
, '%');
1359 default: /* Invalid format */
1363 g_string_append_c(plain_s
, format
[pos
]);
1368 if (plain_s
->len
> 0) {
1369 add_string_fmt(SF_NONE
, plain_s
->str
);
1371 g_string_free(plain_s
, TRUE
);
1375 /****************************************************************************************
1376 * END OF FIELD EXTRACTION ROUTINES
1377 ****************************************************************************************/
1380 show_print_file_io_error(int err
)
1385 cmdarg_err("Not all the packets could be printed because there is "
1386 "no space left on the file system.");
1391 cmdarg_err("Not all the packets could be printed because you are "
1392 "too close to, or over your disk quota.");
1397 cmdarg_err("An error occurred while printing packets: %s.",
1404 raw_epan_new(capture_file
*cf
)
1406 static const struct packet_provider_funcs funcs
= {
1407 cap_file_provider_get_frame_ts
,
1408 cap_file_provider_get_interface_name
,
1409 cap_file_provider_get_interface_description
,
1413 return epan_new(&cf
->provider
, &funcs
);
1417 raw_cf_open(capture_file
*cf
, const char *fname
)
1419 if ((fd
= raw_pipe_open(fname
)) < 0)
1422 /* The open succeeded. Fill in the information for this file. */
1424 /* Create new epan session for dissection. */
1425 epan_free(cf
->epan
);
1426 cf
->epan
= raw_epan_new(cf
);
1428 cf
->provider
.wth
= NULL
;
1429 cf
->f_datalen
= 0; /* not used, but set it anyway */
1431 /* Set the file name because we need it to set the follow stream filter.
1432 XXX - is that still true? We need it for other reasons, though,
1434 cf
->filename
= g_strdup(fname
);
1436 /* Indicate whether it's a permanent or temporary file. */
1437 cf
->is_tempfile
= false;
1439 /* No user changes yet. */
1440 cf
->unsaved_changes
= false;
1442 cf
->cd_t
= WTAP_FILE_TYPE_SUBTYPE_UNKNOWN
;
1443 cf
->open_type
= WTAP_TYPE_AUTO
;
1445 cf
->drops_known
= false;
1448 nstime_set_zero(&cf
->elapsed_time
);
1449 cf
->provider
.ref
= NULL
;
1450 cf
->provider
.prev_dis
= NULL
;
1451 cf
->provider
.prev_cap
= NULL
;
1462 * indent-tabs-mode: nil
1465 * ex: set shiftwidth=4 tabstop=8 expandtab:
1466 * :indentSize=4:tabSize=8:noTabs=true: