wsutil/wsgcrypt.c decrypt_des_ecb
[wireshark-sm.git] / rawshark.c
blobcfa092b41f3c35f192b97706e6171d807bed188e
1 /* rawshark.c
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
10 * <guy@alum.mit.edu>.
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.
23 #include <config.h>
24 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <locale.h>
30 #include <limits.h>
32 #ifndef _WIN32
33 #include <sys/time.h>
34 #include <sys/resource.h>
35 #endif
37 #include <errno.h>
39 #include <ws_exit_codes.h>
40 #include <wsutil/ws_getopt.h>
42 #include <glib.h>
43 #include <epan/epan.h>
45 #include <epan/tfs.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>
56 #ifdef _WIN32
57 #include <wsutil/unicode-utils.h>
58 #include <wsutil/win32-utils.h>
59 #endif
61 #include "globals.h"
62 #include <epan/packet.h>
63 #include <epan/ftypes/ftypes.h>
64 #include "file.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>
70 #ifdef HAVE_LIBPCAP
71 #include "ui/capture_ui_utils.h"
72 #endif
73 #include "ui/util.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"
81 #include <epan/tap.h>
83 #include <wiretap/wtap.h>
84 #include <wiretap/libpcap.h>
85 #include <wiretap/pcap-encap.h>
87 #include <cli_main.h>
88 #include <wsutil/version_info.h>
90 #include "capture/capture-pcap-util.h"
92 #ifdef HAVE_LIBPCAP
93 #include <setjmp.h>
94 #ifdef _WIN32
95 #include "capture/capture-wpcap.h"
96 #endif /* _WIN32 */
97 #endif /* HAVE_LIBPCAP */
99 #if 0
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>";
105 #endif
107 /* Additional exit codes */
108 #define INVALID_DFILTER 2
109 #define FORMAT_ERROR 2
111 capture_file cfile;
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.
121 typedef enum {
122 WRITE_TEXT, /* summary or detail text */
123 WRITE_XML /* PDML or PSML */
124 /* Add CSV and the like here */
125 } output_action_e;
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);
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);
141 typedef enum {
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 */
146 } string_fmt_e;
148 typedef struct string_fmt_s {
149 char *plain;
150 string_fmt_e format; /* Valid if plain is NULL */
151 } string_fmt_t;
153 int n_rfilters;
154 int n_rfcodes;
155 dfilter_t *rfcodes[64];
156 int n_rfieldfilters;
157 dfilter_t *rfieldfcodes[64];
158 int fd;
159 int encap;
160 GPtrArray *string_fmts;
162 static void
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");
180 #endif
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.
233 static int
234 raw_pipe_open(const char *pipe_name)
236 #ifndef _WIN32
237 ws_statb64 pipe_stat;
238 #else
239 DWORD err;
240 wchar_t *err_str;
241 HANDLE hPipe = NULL;
242 #endif
243 int rfd;
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 */
252 #ifdef _WIN32
254 * This is needed to set the stdin pipe into binary mode, otherwise
255 * CR/LF are mangled...
257 _setmode(0, _O_BINARY);
258 #endif /* _WIN32 */
259 } else {
260 #ifndef _WIN32
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));
264 return -1;
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.
272 } else
274 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
275 pipe_name);
277 return -1;
279 rfd = ws_open(pipe_name, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
280 if (rfd == -1) {
281 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
282 pipe_name, g_strerror(errno));
283 return -1;
285 #else /* _WIN32 */
286 if (!win32_is_pipe_name(pipe_name)) {
287 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
288 pipe_name);
289 return -1;
292 /* Wait for the pipe to appear */
293 while (1) {
294 hPipe = CreateFile(utf_8to16(pipe_name), GENERIC_READ, 0, NULL,
295 OPEN_EXISTING, 0, NULL);
297 if (hPipe != INVALID_HANDLE_VALUE)
298 break;
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);
306 LocalFree(err_str);
307 return -1;
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);
316 LocalFree(err_str);
317 return -1;
321 rfd = _open_osfhandle((intptr_t) hPipe, _O_RDONLY);
322 if (rfd == -1) {
323 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
324 pipe_name, g_strerror(errno));
325 return -1;
327 #endif /* _WIN32 */
330 return rfd;
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".
340 static bool
341 set_link_type(const char *lt_arg) {
342 char *spec_ptr = strchr(lt_arg, ':');
343 char *p;
344 int dlt_val;
345 long val;
346 dissector_handle_t dhandle;
347 GString *pref_str;
348 char *errmsg = NULL;
350 if (!spec_ptr)
351 return false;
353 spec_ptr++;
355 if (strncmp(lt_arg, "encap:", strlen("encap:")) == 0) {
356 dlt_val = linktype_name_to_val(spec_ptr);
357 if (dlt_val == -1) {
358 errno = 0;
359 val = strtol(spec_ptr, &p, 10);
360 if (p == spec_ptr || *p != '\0' || errno != 0 || val > INT_MAX) {
361 return false;
363 dlt_val = (int)val;
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) {
377 return false;
379 return true;
380 } else if (strncmp(lt_arg, "proto:", strlen("proto:")) == 0) {
381 dhandle = find_dissector(spec_ptr);
382 if (dhandle) {
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\",\"\"",
388 spec_ptr);
389 if (prefs_set_pref(pref_str->str, &errmsg) != PREFS_SET_OK) {
390 g_string_free(pref_str, TRUE);
391 g_free(errmsg);
392 return false;
394 g_string_free(pref_str, TRUE);
395 return true;
398 return false;
402 main(int argc, char *argv[])
404 char *err_msg;
405 int opt, i;
406 df_error_t *df_err;
408 #if !defined(_WIN32) && defined(RLIMIT_AS)
409 struct rlimit limit;
410 #endif /* !_WIN32 */
412 char *pipe_name = NULL;
413 char *rfilters[64];
414 e_prefs *prefs_p;
415 GPtrArray *disp_fields = g_ptr_array_new();
416 unsigned fc;
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
424 {0, 0, 0, 0 }
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.
438 #ifdef _WIN32
439 setlocale(LC_ALL, ".UTF-8");
440 #else
441 setlocale(LC_ALL, "");
442 #endif
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");
454 #ifdef _WIN32
455 create_app_running_mutex();
456 #endif /* _WIN32 */
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));
468 n_rfilters = 0;
469 n_rfcodes = 0;
472 * Initialize our string format
474 string_fmts = g_ptr_array_new();
477 * Attempt to get the pathname of the directory containing the
478 * executable file.
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",
483 err_msg);
486 /* Initialize the version information. */
487 ws_init_version_info("Rawshark",
488 epan_gather_compile_info,
489 NULL);
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
500 * stream format?
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.
507 wtap_init(false);
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;
515 goto clean_exit;
518 /* Load libwireshark settings from the current profile. */
519 prefs_p = epan_load_settings();
521 #ifdef _WIN32
522 ws_init_dll_search_path();
523 /* Load Wpcap, if possible */
524 load_wpcap();
525 #endif
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) {
538 switch (opt) {
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;
546 goto clean_exit;
548 break;
549 case 'F': /* Read field to display */
550 g_ptr_array_add(disp_fields, g_strdup(ws_optarg));
551 break;
552 case 'h': /* Print help and exit */
553 show_help_header("Dump and analyze network traffic.");
554 print_usage(stdout);
555 goto clean_exit;
556 break;
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
563 writes).
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;
571 break;
572 #if !defined(_WIN32) && defined(RLIMIT_AS)
573 case 'm':
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",
579 g_strerror(errno));
580 ret = WS_EXIT_INVALID_OPTION;
581 goto clean_exit;
583 break;
584 #endif
585 case 'o': /* Override preference from command line */
587 char *errmsg = NULL;
589 switch (prefs_set_pref(ws_optarg, &errmsg)) {
591 case PREFS_SET_OK:
592 break;
594 case PREFS_SET_SYNTAX_ERR:
595 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
596 errmsg ? ": " : "", errmsg ? errmsg : "");
597 g_free(errmsg);
598 ret = WS_EXIT_INVALID_OPTION;
599 goto clean_exit;
600 break;
602 case PREFS_SET_NO_SUCH_PREF:
603 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
604 ret = WS_EXIT_INVALID_OPTION;
605 goto clean_exit;
606 break;
608 case PREFS_SET_OBSOLETE:
609 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
610 ret = WS_EXIT_INVALID_OPTION;
611 goto clean_exit;
612 break;
614 break;
616 case 'p': /* Expect pcap_pkthdr packet headers, which may have 64-bit timestamps */
617 want_pcap_pkthdr = true;
618 break;
619 case 'r': /* Read capture file xxx */
620 pipe_name = g_strdup(ws_optarg);
621 break;
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;
628 else {
629 cmdarg_err("Too many display filters");
630 ret = WS_EXIT_INVALID_OPTION;
631 goto clean_exit;
633 break;
634 case 's': /* Skip PCAP header */
635 skip_pcap_header = true;
636 break;
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;
641 goto clean_exit;
643 break;
644 case 'v': /* Show version and exit */
646 show_version();
647 goto clean_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;
666 goto clean_exit;
668 break;
669 default:
670 case '?': /* Bad flag - print usage message */
671 print_usage(stderr);
672 ret = WS_EXIT_INVALID_OPTION;
673 goto clean_exit;
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. */
682 prefs_apply_all();
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);
689 printf("\n");
690 fflush(stdout);
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;
702 goto clean_exit;
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;
712 goto clean_exit;
715 err_msg = ws_init_sockets();
716 if (err_msg != NULL)
718 cmdarg_err("%s", err_msg);
719 g_free(err_msg);
720 cmdarg_err_cont("%s", please_report_bug());
721 ret = WS_EXIT_INIT_FAILED;
722 goto clean_exit;
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;
736 goto clean_exit;
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;
748 goto clean_exit;
750 n_rfcodes++;
754 if (pipe_name) {
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
762 * can't open.
764 relinquish_special_privs_perm();
766 if (raw_cf_open(&cfile, pipe_name) != CF_OK) {
767 ret = WS_EXIT_OPEN_ERROR;
768 goto clean_exit;
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);
777 if (bytes <= 0) {
778 cmdarg_err("Not enough bytes for pcap header.");
779 ret = FORMAT_ERROR;
780 goto clean_exit;
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;
789 goto clean_exit;
791 } else {
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;
795 goto clean_exit;
798 clean_exit:
799 g_free(pipe_name);
800 epan_free(cfile.epan);
801 epan_cleanup();
802 wtap_cleanup();
803 return ret;
807 * Read data from a raw pipe. The "raw" data consists of a libpcap
808 * packet header followed by the payload.
809 * @param rec [IN/OUT] A wtap_rec into which to read packet metadata
810 * and data.
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.
816 static bool
817 raw_pipe_read(wtap_rec *rec, 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;
824 *err = 0;
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
836 * handler.
837 * We could also tell callers not to close stdin prematurely.
839 #ifdef _WIN32
840 DWORD ghi_flags;
841 if (fd == 0 && GetHandleInformation(GetStdHandle(STD_INPUT_HANDLE), &ghi_flags) == 0) {
842 *err = 0;
843 *err_info = NULL;
844 return false;
846 #endif
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) {
852 *err = 0;
853 *err_info = NULL;
854 return false;
855 } else if (bytes_read < 0) {
856 *err = errno;
857 *err_info = NULL;
858 return false;
860 bytes_needed -= (unsigned int)bytes_read;
861 *data_offset += bytes_read;
862 ptr += 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;
872 } else {
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;
882 #if 0
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);
888 #endif
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);
893 return false;
896 ws_buffer_assure_space(&rec->data, bytes_needed);
897 ptr = ws_buffer_start_ptr(&rec->data);
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;
902 *err_info = NULL;
903 return false;
904 } else if (bytes_read < 0) {
905 *err = errno;
906 *err_info = NULL;
907 return false;
909 bytes_needed -= (unsigned int)bytes_read;
910 *data_offset += bytes_read;
911 ptr += bytes_read;
913 return true;
916 static bool
917 load_cap_file(capture_file *cf)
919 int err;
920 char *err_info = NULL;
921 int64_t data_offset = 0;
923 wtap_rec rec;
924 epan_dissect_t edt;
926 wtap_rec_init(&rec, 1514);
928 epan_dissect_init(&edt, cf->epan, true, false);
930 while (raw_pipe_read(&rec, &err, &err_info, &data_offset)) {
931 process_packet(cf, &edt, data_offset, &rec);
934 epan_dissect_cleanup(&edt);
936 wtap_rec_cleanup(&rec);
937 if (err != 0) {
938 /* Print a message noting that the read failed somewhere along the line. */
939 cfile_read_failure_message(cf->filename, err, err_info);
940 return false;
943 return true;
946 static bool
947 process_packet(capture_file *cf, epan_dissect_t *edt, int64_t offset,
948 wtap_rec *rec)
950 frame_data fdata;
951 bool passed;
952 int i;
954 if(rec->rec_header.packet_header.len == 0)
956 /* The user sends an empty packet when he wants to get output from us even if we don't currently have
957 packets to process. We spit out a line with the timestamp and the text "void"
959 printf("%lu %" PRIu64 " %d void -\n", (unsigned long int)cf->count,
960 (uint64_t)rec->ts.secs, rec->ts.nsecs);
962 fflush(stdout);
964 return false;
967 /* Count this packet. */
968 cf->count++;
970 /* If we're going to print packet information, or we're going to
971 run a read filter, or we're going to process taps, set up to
972 do a dissection and do so. */
973 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
975 passed = true;
977 /* If we're running a read filter, prime the epan_dissect_t with that
978 filter. */
979 if (n_rfilters > 0) {
980 for(i = 0; i < n_rfcodes; i++) {
981 epan_dissect_prime_with_dfilter(edt, rfcodes[i]);
985 printf("%lu", (unsigned long int) cf->count);
987 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
988 &cf->provider.ref, cf->provider.prev_dis);
990 if (cf->provider.ref == &fdata) {
991 ref_frame = fdata;
992 cf->provider.ref = &ref_frame;
995 /* We only need the columns if we're printing packet info but we're
996 *not* verbose; in verbose mode, we print the protocol tree, not
997 the protocol summary. */
998 epan_dissect_run_with_taps(edt, cf->cd_t, rec, &fdata, &cf->cinfo);
1000 frame_data_set_after_dissect(&fdata, &cum_bytes);
1001 prev_dis_frame = fdata;
1002 cf->provider.prev_dis = &prev_dis_frame;
1004 prev_cap_frame = fdata;
1005 cf->provider.prev_cap = &prev_cap_frame;
1007 for(i = 0; i < n_rfilters; i++) {
1008 /* Run the read filter if we have one. */
1009 if (rfcodes[i])
1010 passed = dfilter_apply_edt(rfcodes[i], edt);
1011 else
1012 passed = true;
1014 /* Print a one-line summary */
1015 printf(" %d", passed ? 1 : 0);
1018 printf(" -\n");
1020 /* The ANSI C standard does not appear to *require* that a line-buffered
1021 stream be flushed to the host environment whenever a newline is
1022 written, it just says that, on such a stream, characters "are
1023 intended to be transmitted to or from the host environment as a
1024 block when a new-line character is encountered".
1026 The Visual C++ 6.0 C implementation doesn't do what is intended;
1027 even if you set a stream to be line-buffered, it still doesn't
1028 flush the buffer at the end of every line.
1030 So, if the "-l" flag was specified, we flush the standard output
1031 at the end of a packet. This will do the right thing if we're
1032 printing packet summary lines, and, as we print the entire protocol
1033 tree for a single packet without waiting for anything to happen,
1034 it should be as good as line-buffered mode if we're printing
1035 protocol trees. (The whole reason for the "-l" flag in either
1036 tcpdump or Rawshark is to allow the output of a live capture to
1037 be piped to a program or script and to have that script see the
1038 information for the packet as soon as it's printed, rather than
1039 having to wait until a standard I/O buffer fills up. */
1040 if (line_buffered)
1041 fflush(stdout);
1043 if (ferror(stdout)) {
1044 show_print_file_io_error(errno);
1045 exit(2);
1048 epan_dissect_reset(edt);
1049 frame_data_destroy(&fdata);
1051 return passed;
1054 /****************************************************************************************
1055 * FIELD EXTRACTION ROUTINES
1056 ****************************************************************************************/
1057 typedef struct _pci_t {
1058 char *filter;
1059 int hf_index;
1060 int cmd_line_index;
1061 } pci_t;
1063 static const char* ftenum_to_string(header_field_info *hfi)
1065 const char* str;
1066 if (!hfi) {
1067 return "n.a.";
1070 if (string_fmts->len > 0 && hfi->strings) {
1071 return "FT_STRING";
1074 str = ftype_name(hfi->type);
1075 if (str == NULL) {
1076 str = "n.a.";
1079 return str;
1082 static void field_display_to_string(header_field_info *hfi, char* buf, int size)
1084 if (hfi->type != FT_BOOLEAN)
1086 (void) g_strlcpy(buf, proto_field_display_to_string(hfi->display), size);
1088 else
1090 snprintf(buf, size, "(Bit count: %d)", hfi->display);
1095 * Copied from various parts of proto.c
1097 #define FIELD_STR_INIT_LEN 256
1098 #define cVALS(x) (const value_string*)(x)
1099 static bool print_field_value(field_info *finfo, int cmd_line_index)
1101 const header_field_info *hfinfo;
1102 char *fs_buf;
1103 char *fs_ptr = NULL;
1104 static GString *label_s = NULL;
1105 size_t fs_len;
1106 unsigned i;
1107 string_fmt_t *sf;
1108 uint32_t uvalue;
1109 int32_t svalue;
1110 uint64_t uvalue64;
1111 int64_t svalue64;
1113 hfinfo = finfo->hfinfo;
1115 if (!label_s) {
1116 label_s = g_string_new("");
1119 fs_buf = fvalue_to_string_repr(NULL, finfo->value,
1120 FTREPR_DFILTER, finfo->hfinfo->display);
1121 if (fs_buf != NULL) {
1123 * this field has an associated value,
1124 * e.g: ip.hdr_len
1126 fs_len = strlen(fs_buf);
1127 fs_ptr = fs_buf;
1129 /* String types are quoted. Remove them. */
1130 if (FT_IS_STRING(fvalue_type_ftenum(finfo->value)) && fs_len > 2) {
1131 fs_buf[fs_len - 1] = '\0';
1132 fs_ptr++;
1136 if (string_fmts->len > 0 && finfo->hfinfo->strings) {
1137 g_string_truncate(label_s, 0);
1138 for (i = 0; i < string_fmts->len; i++) {
1139 sf = (string_fmt_t *)g_ptr_array_index(string_fmts, i);
1140 if (sf->plain) {
1141 g_string_append(label_s, sf->plain);
1142 } else {
1143 switch (sf->format) {
1144 case SF_NAME:
1145 g_string_append(label_s, hfinfo->name);
1146 break;
1147 case SF_NUMVAL:
1148 g_string_append(label_s, fs_ptr);
1149 break;
1150 case SF_STRVAL:
1151 switch(hfinfo->type) {
1152 case FT_BOOLEAN:
1153 uvalue64 = fvalue_get_uinteger64(finfo->value);
1154 g_string_append(label_s, tfs_get_string(!!uvalue64, hfinfo->strings));
1155 break;
1156 case FT_INT8:
1157 case FT_INT16:
1158 case FT_INT24:
1159 case FT_INT32:
1160 DISSECTOR_ASSERT(!hfinfo->bitmask);
1161 svalue = fvalue_get_sinteger(finfo->value);
1162 if (hfinfo->display & BASE_RANGE_STRING) {
1163 g_string_append(label_s, rval_to_str_const(svalue, (const range_string *) hfinfo->strings, "Unknown"));
1164 } else if (hfinfo->display & BASE_EXT_STRING) {
1165 g_string_append(label_s, val_to_str_ext_const(svalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1166 } else {
1167 g_string_append(label_s, val_to_str_const(svalue, cVALS(hfinfo->strings), "Unknown"));
1169 break;
1170 case FT_INT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1171 case FT_INT48:
1172 case FT_INT56:
1173 case FT_INT64:
1174 DISSECTOR_ASSERT(!hfinfo->bitmask);
1175 svalue64 = fvalue_get_sinteger64(finfo->value);
1176 if (hfinfo->display & BASE_VAL64_STRING) {
1177 g_string_append(label_s, val64_to_str_const(svalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1179 break;
1180 case FT_UINT8:
1181 case FT_UINT16:
1182 case FT_UINT24:
1183 case FT_UINT32:
1184 DISSECTOR_ASSERT(!hfinfo->bitmask);
1185 uvalue = fvalue_get_uinteger(finfo->value);
1186 if (!hfinfo->bitmask && hfinfo->display & BASE_RANGE_STRING) {
1187 g_string_append(label_s, rval_to_str_const(uvalue, (const range_string *) hfinfo->strings, "Unknown"));
1188 } else if (hfinfo->display & BASE_EXT_STRING) {
1189 g_string_append(label_s, val_to_str_ext_const(uvalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1190 } else {
1191 g_string_append(label_s, val_to_str_const(uvalue, cVALS(hfinfo->strings), "Unknown"));
1193 break;
1194 case FT_UINT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1195 case FT_UINT48:
1196 case FT_UINT56:
1197 case FT_UINT64:
1198 DISSECTOR_ASSERT(!hfinfo->bitmask);
1199 uvalue64 = fvalue_get_uinteger64(finfo->value);
1200 if (hfinfo->display & BASE_VAL64_STRING) {
1201 g_string_append(label_s, val64_to_str_const(uvalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1203 break;
1204 default:
1205 break;
1207 break;
1208 default:
1209 break;
1213 printf(" %d=\"%s\"", cmd_line_index, label_s->str);
1214 wmem_free(NULL, fs_buf);
1215 return true;
1218 if(fs_buf)
1220 printf(" %d=\"%s\"", cmd_line_index, fs_ptr);
1221 wmem_free(NULL, fs_buf);
1222 return true;
1226 * This field doesn't have an associated value,
1227 * e.g. http
1228 * We return n.a.
1230 printf(" %d=\"n.a.\"", cmd_line_index);
1231 return true;
1234 static tap_packet_status
1235 protocolinfo_packet(void *prs, packet_info *pinfo _U_, epan_dissect_t *edt, const void *dummy _U_, tap_flags_t flags _U_)
1237 pci_t *rs=(pci_t *)prs;
1238 GPtrArray *gp;
1239 unsigned i;
1241 gp=proto_get_finfo_ptr_array(edt->tree, rs->hf_index);
1242 if(!gp){
1243 printf(" n.a.");
1244 return TAP_PACKET_DONT_REDRAW;
1248 * Print each occurrence of the field
1250 for (i = 0; i < gp->len; i++) {
1251 print_field_value((field_info *)gp->pdata[i], rs->cmd_line_index);
1254 return TAP_PACKET_DONT_REDRAW;
1257 int g_cmd_line_index;
1260 * field must be persistent - we don't g_strdup() it below
1262 static void
1263 protocolinfo_init(char *field)
1265 pci_t *rs;
1266 header_field_info *hfi;
1267 GString *error_string;
1268 char hfibuf[100];
1270 hfi=proto_registrar_get_byname(field);
1271 if(!hfi){
1272 fprintf(stderr, "rawshark: Field \"%s\" doesn't exist.\n", field);
1273 exit(1);
1276 field_display_to_string(hfi, hfibuf, sizeof(hfibuf));
1277 printf("%d %s %s - ",
1278 g_cmd_line_index,
1279 ftenum_to_string(hfi),
1280 hfibuf);
1282 rs=g_new(pci_t, 1);
1283 rs->hf_index=hfi->id;
1284 rs->filter=field;
1285 rs->cmd_line_index = g_cmd_line_index++;
1287 error_string=register_tap_listener("frame", rs, rs->filter, TL_REQUIRES_PROTO_TREE, NULL, protocolinfo_packet, NULL, NULL);
1288 if(error_string){
1289 /* error, we failed to attach to the tap. complain and clean up */
1290 fprintf(stderr, "rawshark: Couldn't register field extraction tap: %s\n",
1291 error_string->str);
1292 g_string_free(error_string, TRUE);
1293 if(rs->filter){
1294 g_free(rs->filter);
1296 g_free(rs);
1298 exit(1);
1303 * Given a format string, split it into a GPtrArray of string_fmt_t structs
1304 * and fill in string_fmt_parts.
1307 static void
1308 add_string_fmt(string_fmt_e format, char *plain) {
1309 string_fmt_t *sf = g_new(string_fmt_t, 1);
1311 sf->format = format;
1312 sf->plain = g_strdup(plain);
1314 g_ptr_array_add(string_fmts, sf);
1317 static bool
1318 parse_field_string_format(char *format) {
1319 size_t len;
1320 size_t pos = 0;
1322 if (!format) {
1323 return false;
1326 GString *plain_s = g_string_new("");
1328 len = strlen(format);
1329 g_ptr_array_set_size(string_fmts, 0);
1331 while (pos < len) {
1332 if (format[pos] == '%') {
1333 if (pos >= (len-1)) { /* There should always be a following specifier character */
1334 return false;
1336 pos++;
1337 if (plain_s->len > 0) {
1338 add_string_fmt(SF_NONE, plain_s->str);
1339 g_string_truncate(plain_s, 0);
1341 switch (format[pos]) {
1342 case 'D':
1343 add_string_fmt(SF_NAME, NULL);
1344 break;
1345 case 'N':
1346 add_string_fmt(SF_NUMVAL, NULL);
1347 break;
1348 case 'S':
1349 add_string_fmt(SF_STRVAL, NULL);
1350 break;
1351 case '%':
1352 g_string_append_c(plain_s, '%');
1353 break;
1354 default: /* Invalid format */
1355 return false;
1357 } else {
1358 g_string_append_c(plain_s, format[pos]);
1360 pos++;
1363 if (plain_s->len > 0) {
1364 add_string_fmt(SF_NONE, plain_s->str);
1366 g_string_free(plain_s, TRUE);
1368 return true;
1370 /****************************************************************************************
1371 * END OF FIELD EXTRACTION ROUTINES
1372 ****************************************************************************************/
1374 static void
1375 show_print_file_io_error(int err)
1377 switch (err) {
1379 case ENOSPC:
1380 cmdarg_err("Not all the packets could be printed because there is "
1381 "no space left on the file system.");
1382 break;
1384 #ifdef EDQUOT
1385 case EDQUOT:
1386 cmdarg_err("Not all the packets could be printed because you are "
1387 "too close to, or over your disk quota.");
1388 break;
1389 #endif
1391 default:
1392 cmdarg_err("An error occurred while printing packets: %s.",
1393 g_strerror(err));
1394 break;
1398 static epan_t *
1399 raw_epan_new(capture_file *cf)
1401 static const struct packet_provider_funcs funcs = {
1402 cap_file_provider_get_frame_ts,
1403 cap_file_provider_get_interface_name,
1404 cap_file_provider_get_interface_description,
1405 NULL,
1408 return epan_new(&cf->provider, &funcs);
1411 cf_status_t
1412 raw_cf_open(capture_file *cf, const char *fname)
1414 if ((fd = raw_pipe_open(fname)) < 0)
1415 return CF_ERROR;
1417 /* The open succeeded. Fill in the information for this file. */
1419 /* Create new epan session for dissection. */
1420 epan_free(cf->epan);
1421 cf->epan = raw_epan_new(cf);
1423 cf->provider.wth = NULL;
1424 cf->f_datalen = 0; /* not used, but set it anyway */
1426 /* Set the file name because we need it to set the follow stream filter.
1427 XXX - is that still true? We need it for other reasons, though,
1428 in any case. */
1429 cf->filename = g_strdup(fname);
1431 /* Indicate whether it's a permanent or temporary file. */
1432 cf->is_tempfile = false;
1434 /* No user changes yet. */
1435 cf->unsaved_changes = false;
1437 cf->cd_t = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
1438 cf->open_type = WTAP_TYPE_AUTO;
1439 cf->count = 0;
1440 cf->drops_known = false;
1441 cf->drops = 0;
1442 cf->snap = 0;
1443 nstime_set_zero(&cf->elapsed_time);
1444 cf->provider.ref = NULL;
1445 cf->provider.prev_dis = NULL;
1446 cf->provider.prev_cap = NULL;
1448 return CF_OK;
1452 * Editor modelines
1454 * Local Variables:
1455 * c-basic-offset: 4
1456 * tab-width: 8
1457 * indent-tabs-mode: nil
1458 * End:
1460 * ex: set shiftwidth=4 tabstop=8 expandtab:
1461 * :indentSize=4:tabSize=8:noTabs=true: