wmem: allow wmem_destroy_list to ignore a NULL list.
[metze/wireshark/wip.git] / rawshark.c
1 /* rawshark.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
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>.
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14
15 /*
16  * Rawshark does the following:
17  * - Opens a specified file or named pipe
18  * - Applies a specfied 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.
21  */
22
23 #include <config.h>
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <locale.h>
29 #include <limits.h>
30
31 #ifndef _WIN32
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #endif
35
36 #ifdef HAVE_GETOPT_H
37 #include <getopt.h>
38 #endif
39
40 #include <errno.h>
41
42 #ifndef HAVE_GETOPT_LONG
43 #include "wsutil/wsgetopt.h"
44 #endif
45
46 #include <glib.h>
47 #include <epan/epan.h>
48
49 #include <ui/cmdarg_err.h>
50 #include <wsutil/filesystem.h>
51 #include <wsutil/file_util.h>
52 #include <wsutil/plugins.h>
53 #include <wsutil/privileges.h>
54 #include <wsutil/report_message.h>
55 #include <ui/clopts_common.h>
56
57 #include "globals.h"
58 #include <epan/packet.h>
59 #include <epan/ftypes/ftypes-int.h>
60 #include "file.h"
61 #include "frame_tvbuff.h"
62 #include <epan/disabled_protos.h>
63 #include <epan/prefs.h>
64 #include <epan/column.h>
65 #include <epan/print.h>
66 #include <epan/addr_resolv.h>
67 #ifdef HAVE_LIBPCAP
68 #include "ui/capture_ui_utils.h"
69 #endif
70 #include "ui/util.h"
71 #include "ui/dissect_opts.h"
72 #include "ui/failure_message.h"
73 #include <epan/epan_dissect.h>
74 #include <epan/stat_tap_ui.h>
75 #include <epan/timestamp.h>
76 #include "epan/column-utils.h"
77 #include "epan/proto.h"
78 #include <epan/tap.h>
79
80 #include <wiretap/wtap.h>
81 #include <wiretap/libpcap.h>
82 #include <wiretap/pcap-encap.h>
83
84 #include <cli_main.h>
85 #include <version_info.h>
86
87 #include "caputils/capture-pcap-util.h"
88
89 #include "extcap.h"
90
91 #ifdef HAVE_LIBPCAP
92 #include <setjmp.h>
93 #ifdef _WIN32
94 #include "caputils/capture-wpcap.h"
95 #endif /* _WIN32 */
96 #endif /* HAVE_LIBPCAP */
97 #include "log.h"
98
99 #if 0
100 /*
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.
103  */
104 static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
105 #endif
106
107 #define INVALID_OPTION 1
108 #define INIT_ERROR 2
109 #define INVALID_DFILTER 2
110 #define OPEN_ERROR 2
111 #define FORMAT_ERROR 2
112
113 capture_file cfile;
114
115 static guint32 cum_bytes;
116 static frame_data ref_frame;
117 static frame_data prev_dis_frame;
118 static frame_data prev_cap_frame;
119
120 /*
121  * The way the packet decode is to be written.
122  */
123 typedef enum {
124     WRITE_TEXT, /* summary or detail text */
125     WRITE_XML   /* PDML or PSML */
126     /* Add CSV and the like here */
127 } output_action_e;
128
129 static gboolean line_buffered;
130 static print_format_e print_format = PR_FMT_TEXT;
131
132 static gboolean want_pcap_pkthdr;
133
134 cf_status_t raw_cf_open(capture_file *cf, const char *fname);
135 static gboolean load_cap_file(capture_file *cf);
136 static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
137                                wtap_rec *rec, const guchar *pd);
138 static void show_print_file_io_error(int err);
139
140 static void failure_warning_message(const char *msg_format, va_list ap);
141 static void open_failure_message(const char *filename, int err,
142                                  gboolean for_writing);
143 static void read_failure_message(const char *filename, int err);
144 static void write_failure_message(const char *filename, int err);
145 static void rawshark_cmdarg_err(const char *fmt, va_list ap);
146 static void rawshark_cmdarg_err_cont(const char *fmt, va_list ap);
147 static void protocolinfo_init(char *field);
148 static gboolean parse_field_string_format(char *format);
149
150 typedef enum {
151     SF_NONE,    /* No format (placeholder) */
152     SF_NAME,    /* %D Field name / description */
153     SF_NUMVAL,  /* %N Numeric value */
154     SF_STRVAL   /* %S String value */
155 } string_fmt_e;
156
157 typedef struct string_fmt_s {
158     gchar *plain;
159     string_fmt_e format;    /* Valid if plain is NULL */
160 } string_fmt_t;
161
162 int n_rfilters;
163 int n_rfcodes;
164 dfilter_t *rfcodes[64];
165 int n_rfieldfilters;
166 dfilter_t *rfieldfcodes[64];
167 int fd;
168 int encap;
169 GPtrArray *string_fmts;
170
171 static void
172 print_usage(FILE *output)
173 {
174     fprintf(output, "\n");
175     fprintf(output, "Usage: rawshark [options] ...\n");
176     fprintf(output, "\n");
177
178     fprintf(output, "Input file:\n");
179     fprintf(output, "  -r <infile>              set the pipe or file name to read from\n");
180
181     fprintf(output, "\n");
182     fprintf(output, "Processing:\n");
183     fprintf(output, "  -d <encap:linktype>|<proto:protoname>\n");
184     fprintf(output, "                           packet encapsulation or protocol\n");
185     fprintf(output, "  -F <field>               field to display\n");
186 #ifndef _WIN32
187     fprintf(output, "  -m                       virtual memory limit, in bytes\n");
188 #endif
189     fprintf(output, "  -n                       disable all name resolution (def: all enabled)\n");
190     fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mnNtdv\"\n");
191     fprintf(output, "  -p                       use the system's packet header format\n");
192     fprintf(output, "                           (which may have 64-bit timestamps)\n");
193     fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
194     fprintf(output, "  -s                       skip PCAP header on input\n");
195
196     fprintf(output, "\n");
197     fprintf(output, "Output:\n");
198     fprintf(output, "  -l                       flush output after each packet\n");
199     fprintf(output, "  -S                       format string for fields\n");
200     fprintf(output, "                           (%%D - name, %%S - stringval, %%N numval)\n");
201     fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
202
203     fprintf(output, "\n");
204     fprintf(output, "Miscellaneous:\n");
205     fprintf(output, "  -h                       display this help and exit\n");
206     fprintf(output, "  -o <name>:<value> ...    override preference setting\n");
207     fprintf(output, "  -v                       display version info and exit\n");
208 }
209
210 static void
211 log_func_ignore (const gchar *log_domain _U_, GLogLevelFlags log_level _U_,
212                  const gchar *message _U_, gpointer user_data _U_)
213 {
214 }
215
216 /**
217  * Open a pipe for raw input.  This is a stripped-down version of
218  * pcap_loop.c:cap_pipe_open_live().
219  * We check if "pipe_name" is "-" (stdin) or a FIFO, and open it.
220  * @param pipe_name The name of the pipe or FIFO.
221  * @return A POSIX file descriptor on success, or -1 on failure.
222  */
223 static int
224 raw_pipe_open(const char *pipe_name)
225 {
226 #ifndef _WIN32
227     ws_statb64 pipe_stat;
228 #else
229     char *pncopy, *pos = NULL;
230     DWORD err;
231     wchar_t *err_str;
232     HANDLE hPipe = NULL;
233 #endif
234     int          rfd;
235
236     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "open_raw_pipe: %s", pipe_name);
237
238     /*
239      * XXX Rawshark blocks until we return
240      */
241     if (strcmp(pipe_name, "-") == 0) {
242         rfd = 0; /* read from stdin */
243 #ifdef _WIN32
244         /*
245          * This is needed to set the stdin pipe into binary mode, otherwise
246          * CR/LF are mangled...
247          */
248         _setmode(0, _O_BINARY);
249 #endif  /* _WIN32 */
250     } else {
251 #ifndef _WIN32
252         if (ws_stat64(pipe_name, &pipe_stat) < 0) {
253             fprintf(stderr, "rawshark: The pipe %s could not be checked: %s\n",
254                     pipe_name, g_strerror(errno));
255             return -1;
256         }
257         if (! S_ISFIFO(pipe_stat.st_mode)) {
258             if (S_ISCHR(pipe_stat.st_mode)) {
259                 /*
260                  * Assume the user specified an interface on a system where
261                  * interfaces are in /dev.  Pretend we haven't seen it.
262                  */
263             } else
264             {
265                 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
266                         pipe_name);
267             }
268             return -1;
269         }
270         rfd = ws_open(pipe_name, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
271         if (rfd == -1) {
272             fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
273                     pipe_name, g_strerror(errno));
274             return -1;
275         }
276 #else /* _WIN32 */
277 #define PIPE_STR "\\pipe\\"
278         /* Under Windows, named pipes _must_ have the form
279          * "\\<server>\pipe\<pipe_name>".  <server> may be "." for localhost.
280          */
281         pncopy = g_strdup(pipe_name);
282         if (strstr(pncopy, "\\\\") == pncopy) {
283             pos = strchr(pncopy + 3, '\\');
284             if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
285                 pos = NULL;
286         }
287
288         g_free(pncopy);
289
290         if (!pos) {
291             fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
292                     pipe_name);
293             return -1;
294         }
295
296         /* Wait for the pipe to appear */
297         while (1) {
298             hPipe = CreateFile(utf_8to16(pipe_name), GENERIC_READ, 0, NULL,
299                                OPEN_EXISTING, 0, NULL);
300
301             if (hPipe != INVALID_HANDLE_VALUE)
302                 break;
303
304             err = GetLastError();
305             if (err != ERROR_PIPE_BUSY) {
306                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
307                               NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
308                 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s (error %lu)\n",
309                         pipe_name, utf_16to8(err_str), err);
310                 LocalFree(err_str);
311                 return -1;
312             }
313
314             if (!WaitNamedPipe(utf_8to16(pipe_name), 30 * 1000)) {
315                 err = GetLastError();
316                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
317                               NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
318                 fprintf(stderr, "rawshark: \"%s\" could not be waited for: %s (error %lu)\n",
319                         pipe_name, utf_16to8(err_str), err);
320                 LocalFree(err_str);
321                 return -1;
322             }
323         }
324
325         rfd = _open_osfhandle((intptr_t) hPipe, _O_RDONLY);
326         if (rfd == -1) {
327             fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
328                     pipe_name, g_strerror(errno));
329             return -1;
330         }
331 #endif /* _WIN32 */
332     }
333
334     return rfd;
335 }
336
337 /**
338  * Parse a link-type argument of the form "encap:<pcap linktype>" or
339  * "proto:<proto name>".  "Pcap linktype" must be a name conforming to
340  * pcap_datalink_name_to_val() or an integer; the integer should be
341  * a LINKTYPE_ value supported by Wiretap.  "Proto name" must be
342  * a protocol name, e.g. "http".
343  */
344 static gboolean
345 set_link_type(const char *lt_arg) {
346     char *spec_ptr = strchr(lt_arg, ':');
347     char *p;
348     int dlt_val;
349     long val;
350     dissector_handle_t dhandle;
351     GString *pref_str;
352     char *errmsg = NULL;
353
354     if (!spec_ptr)
355         return FALSE;
356
357     spec_ptr++;
358
359     if (strncmp(lt_arg, "encap:", strlen("encap:")) == 0) {
360         dlt_val = linktype_name_to_val(spec_ptr);
361         if (dlt_val == -1) {
362             errno = 0;
363             val = strtol(spec_ptr, &p, 10);
364             if (p == spec_ptr || *p != '\0' || errno != 0 || val > INT_MAX) {
365                 return FALSE;
366             }
367             dlt_val = (int)val;
368         }
369         /*
370          * In those cases where a given link-layer header type
371          * has different LINKTYPE_ and DLT_ values, linktype_name_to_val()
372          * will return the OS's DLT_ value for that link-layer header
373          * type, not its OS-independent LINKTYPE_ value.
374          *
375          * On a given OS, wtap_pcap_encap_to_wtap_encap() should
376          * be able to map either LINKTYPE_ values or DLT_ values
377          * for the OS to the appropriate Wiretap encapsulation.
378          */
379         encap = wtap_pcap_encap_to_wtap_encap(dlt_val);
380         if (encap == WTAP_ENCAP_UNKNOWN) {
381             return FALSE;
382         }
383         return TRUE;
384     } else if (strncmp(lt_arg, "proto:", strlen("proto:")) == 0) {
385         dhandle = find_dissector(spec_ptr);
386         if (dhandle) {
387             encap = WTAP_ENCAP_USER0;
388             pref_str = g_string_new("uat:user_dlts:");
389             /* This must match the format used in the user_dlts file */
390             g_string_append_printf(pref_str,
391                                    "\"User 0 (DLT=147)\",\"%s\",\"0\",\"\",\"0\",\"\"",
392                                    spec_ptr);
393             if (prefs_set_pref(pref_str->str, &errmsg) != PREFS_SET_OK) {
394                 g_string_free(pref_str, TRUE);
395                 g_free(errmsg);
396                 return FALSE;
397             }
398             g_string_free(pref_str, TRUE);
399             return TRUE;
400         }
401     }
402     return FALSE;
403 }
404
405 int
406 main(int argc, char *argv[])
407 {
408     char                *init_progfile_dir_error;
409     int                  opt, i;
410
411 #ifdef _WIN32
412     int                  result;
413     WSADATA              wsaData;
414 #else
415     struct rlimit limit;
416 #endif  /* _WIN32 */
417
418     gchar               *pipe_name = NULL;
419     gchar               *rfilters[64];
420     e_prefs             *prefs_p;
421     char                 badopt;
422     int                  log_flags;
423     GPtrArray           *disp_fields = g_ptr_array_new();
424     guint                fc;
425     gboolean             skip_pcap_header = FALSE;
426     int                  ret = EXIT_SUCCESS;
427     static const struct option long_options[] = {
428       {"help", no_argument, NULL, 'h'},
429       {"version", no_argument, NULL, 'v'},
430       {0, 0, 0, 0 }
431     };
432
433 #define OPTSTRING_INIT "d:F:hlm:nN:o:pr:R:sS:t:v"
434
435     static const char    optstring[] = OPTSTRING_INIT;
436
437     /* Set the C-language locale to the native environment. */
438     setlocale(LC_ALL, "");
439
440     cmdarg_err_init(rawshark_cmdarg_err, rawshark_cmdarg_err_cont);
441
442     /* Initialize the version information. */
443     ws_init_version_info("Rawshark (Wireshark)", NULL,
444                          epan_get_compiled_version_info,
445                          NULL);
446
447 #ifdef _WIN32
448     create_app_running_mutex();
449 #endif /* _WIN32 */
450
451     /*
452      * Get credential information for later use.
453      */
454     init_process_policies();
455
456     /*
457      * Clear the filters arrays
458      */
459     memset(rfilters, 0, sizeof(rfilters));
460     memset(rfcodes, 0, sizeof(rfcodes));
461     n_rfilters = 0;
462     n_rfcodes = 0;
463
464     /*
465      * Initialize our string format
466      */
467     string_fmts = g_ptr_array_new();
468
469     /*
470      * Attempt to get the pathname of the directory containing the
471      * executable file.
472      */
473     init_progfile_dir_error = init_progfile_dir(argv[0]);
474     if (init_progfile_dir_error != NULL) {
475         fprintf(stderr, "rawshark: Can't get pathname of rawshark program: %s.\n",
476                 init_progfile_dir_error);
477     }
478
479     /* nothing more than the standard GLib handler, but without a warning */
480     log_flags =
481         G_LOG_LEVEL_WARNING |
482         G_LOG_LEVEL_MESSAGE |
483         G_LOG_LEVEL_INFO |
484         G_LOG_LEVEL_DEBUG;
485
486     g_log_set_handler(NULL,
487                       (GLogLevelFlags)log_flags,
488                       log_func_ignore, NULL /* user_data */);
489     g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
490                       (GLogLevelFlags)log_flags,
491                       log_func_ignore, NULL /* user_data */);
492
493     init_report_message(failure_warning_message, failure_warning_message,
494                         open_failure_message, read_failure_message,
495                         write_failure_message);
496
497     timestamp_set_type(TS_RELATIVE);
498     timestamp_set_precision(TS_PREC_AUTO);
499     timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
500
501     wtap_init(FALSE);
502
503     /* Register all dissectors; we must do this before checking for the
504        "-G" flag, as the "-G" flag dumps information registered by the
505        dissectors, and we must do it before we read the preferences, in
506        case any dissectors register preferences. */
507     if (!epan_init(NULL, NULL, TRUE)) {
508         ret = INIT_ERROR;
509         goto clean_exit;
510     }
511
512     /* Load libwireshark settings from the current profile. */
513     prefs_p = epan_load_settings();
514
515 #ifdef _WIN32
516     ws_init_dll_search_path();
517     /* Load Wpcap, if possible */
518     load_wpcap();
519 #endif
520
521     cap_file_init(&cfile);
522
523     /* Print format defaults to this. */
524     print_format = PR_FMT_TEXT;
525
526     /* Initialize our encapsulation type */
527     encap = WTAP_ENCAP_UNKNOWN;
528
529     /* Now get our args */
530     /* XXX - We should probably have an option to dump libpcap link types */
531     while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
532         switch (opt) {
533             case 'd':        /* Payload type */
534                 if (!set_link_type(optarg)) {
535                     cmdarg_err("Invalid link type or protocol \"%s\"", optarg);
536                     ret = INVALID_OPTION;
537                     goto clean_exit;
538                 }
539                 break;
540             case 'F':        /* Read field to display */
541                 g_ptr_array_add(disp_fields, g_strdup(optarg));
542                 break;
543             case 'h':        /* Print help and exit */
544                 show_help_header("Dump and analyze network traffic.");
545                 print_usage(stdout);
546                 goto clean_exit;
547                 break;
548             case 'l':        /* "Line-buffer" standard output */
549                 /* This isn't line-buffering, strictly speaking, it's just
550                    flushing the standard output after the information for
551                    each packet is printed; however, that should be good
552                    enough for all the purposes to which "-l" is put (and
553                    is probably actually better for "-V", as it does fewer
554                    writes).
555
556                    See the comment in "process_packet()" for an explanation of
557                    why we do that, and why we don't just use "setvbuf()" to
558                    make the standard output line-buffered (short version: in
559                    Windows, "line-buffered" is the same as "fully-buffered",
560                    and the output buffer is only flushed when it fills up). */
561                 line_buffered = TRUE;
562                 break;
563 #ifndef _WIN32
564             case 'm':
565                 limit.rlim_cur = get_positive_int(optarg, "memory limit");
566                 limit.rlim_max = get_positive_int(optarg, "memory limit");
567
568                 if(setrlimit(RLIMIT_AS, &limit) != 0) {
569                     cmdarg_err("setrlimit() returned error");
570                     ret = INVALID_OPTION;
571                     goto clean_exit;
572                 }
573                 break;
574 #endif
575             case 'n':        /* No name resolution */
576                 disable_name_resolution();
577                 break;
578             case 'N':        /* Select what types of addresses/port #s to resolve */
579                 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
580                 if (badopt != '\0') {
581                     cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'd', m', 'n', 'N', and 't'",
582                                badopt);
583                     ret = INVALID_OPTION;
584                     goto clean_exit;
585                 }
586                 break;
587             case 'o':        /* Override preference from command line */
588             {
589                 char *errmsg = NULL;
590
591                 switch (prefs_set_pref(optarg, &errmsg)) {
592
593                     case PREFS_SET_OK:
594                         break;
595
596                     case PREFS_SET_SYNTAX_ERR:
597                         cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
598                                 errmsg ? ": " : "", errmsg ? errmsg : "");
599                         g_free(errmsg);
600                         ret = INVALID_OPTION;
601                         goto clean_exit;
602                         break;
603
604                     case PREFS_SET_NO_SUCH_PREF:
605                     case PREFS_SET_OBSOLETE:
606                         cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
607                         ret = INVALID_OPTION;
608                         goto clean_exit;
609                         break;
610                 }
611                 break;
612             }
613             case 'p':        /* Expect pcap_pkthdr packet headers, which may have 64-bit timestamps */
614                 want_pcap_pkthdr = TRUE;
615                 break;
616             case 'r':        /* Read capture file xxx */
617                 pipe_name = g_strdup(optarg);
618                 break;
619             case 'R':        /* Read file filter */
620                 if(n_rfilters < (int) sizeof(rfilters) / (int) sizeof(rfilters[0])) {
621                     rfilters[n_rfilters++] = optarg;
622                 }
623                 else {
624                     cmdarg_err("Too many display filters");
625                     ret = INVALID_OPTION;
626                     goto clean_exit;
627                 }
628                 break;
629             case 's':        /* Skip PCAP header */
630                 skip_pcap_header = TRUE;
631                 break;
632             case 'S':        /* Print string representations */
633                 if (!parse_field_string_format(optarg)) {
634                     cmdarg_err("Invalid field string format");
635                     ret = INVALID_OPTION;
636                     goto clean_exit;
637                 }
638                 break;
639             case 't':        /* Time stamp type */
640                 if (strcmp(optarg, "r") == 0)
641                     timestamp_set_type(TS_RELATIVE);
642                 else if (strcmp(optarg, "a") == 0)
643                     timestamp_set_type(TS_ABSOLUTE);
644                 else if (strcmp(optarg, "ad") == 0)
645                     timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
646                 else if (strcmp(optarg, "adoy") == 0)
647                     timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
648                 else if (strcmp(optarg, "d") == 0)
649                     timestamp_set_type(TS_DELTA);
650                 else if (strcmp(optarg, "dd") == 0)
651                     timestamp_set_type(TS_DELTA_DIS);
652                 else if (strcmp(optarg, "e") == 0)
653                     timestamp_set_type(TS_EPOCH);
654                 else if (strcmp(optarg, "u") == 0)
655                     timestamp_set_type(TS_UTC);
656                 else if (strcmp(optarg, "ud") == 0)
657                     timestamp_set_type(TS_UTC_WITH_YMD);
658                 else if (strcmp(optarg, "udoy") == 0)
659                     timestamp_set_type(TS_UTC_WITH_YDOY);
660                 else {
661                     cmdarg_err("Invalid time stamp type \"%s\"",
662                                optarg);
663                     cmdarg_err_cont(
664 "It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
665                     cmdarg_err_cont(
666 "\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
667                     cmdarg_err_cont(
668 "\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
669                     cmdarg_err_cont(
670 "\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
671                     cmdarg_err_cont(
672 "or \"udoy\" for absolute UTC with YYYY/DOY date.");
673                     ret = INVALID_OPTION;
674                     goto clean_exit;
675                 }
676                 break;
677             case 'v':        /* Show version and exit */
678             {
679                 show_version();
680                 goto clean_exit;
681             }
682             default:
683             case '?':        /* Bad flag - print usage message */
684                 print_usage(stderr);
685                 ret = INVALID_OPTION;
686                 goto clean_exit;
687         }
688     }
689
690     /* Notify all registered modules that have had any of their preferences
691        changed either from one of the preferences file or from the command
692        line that their preferences have changed.
693        Initialize preferences before display filters, otherwise modules
694        like MATE won't work. */
695     prefs_apply_all();
696
697     /* Initialize our display fields */
698     for (fc = 0; fc < disp_fields->len; fc++) {
699         protocolinfo_init((char *)g_ptr_array_index(disp_fields, fc));
700     }
701     g_ptr_array_free(disp_fields, TRUE);
702     printf("\n");
703     fflush(stdout);
704
705     /* If no capture filter or read filter has been specified, and there are
706        still command-line arguments, treat them as the tokens of a capture
707        filter (if no "-r" flag was specified) or a read filter (if a "-r"
708        flag was specified. */
709     if (optind < argc) {
710         if (pipe_name != NULL) {
711             if (n_rfilters != 0) {
712                 cmdarg_err("Read filters were specified both with \"-R\" "
713                            "and with additional command-line arguments");
714                 ret = INVALID_OPTION;
715                 goto clean_exit;
716             }
717             rfilters[n_rfilters] = get_args_as_string(argc, argv, optind);
718         }
719     }
720
721     /* Make sure we got a dissector handle for our payload. */
722     if (encap == WTAP_ENCAP_UNKNOWN) {
723         cmdarg_err("No valid payload dissector specified.");
724         ret = INVALID_OPTION;
725         goto clean_exit;
726     }
727
728 #ifdef _WIN32
729     /* Start windows sockets */
730     result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
731     if (result != 0)
732     {
733         ret = INIT_ERROR;
734         goto clean_exit;
735     }
736 #endif /* _WIN32 */
737
738     /*
739      * Enabled and disabled protocols and heuristic dissectors as per
740      * command-line options.
741      */
742     setup_enabled_and_disabled_protocols();
743
744     /* Build the column format array */
745     build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
746
747     if (n_rfilters != 0) {
748         for (i = 0; i < n_rfilters; i++) {
749             gchar *err_msg;
750
751             if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &err_msg)) {
752                 cmdarg_err("%s", err_msg);
753                 g_free(err_msg);
754                 ret = INVALID_DFILTER;
755                 goto clean_exit;
756             }
757             n_rfcodes++;
758         }
759     }
760
761     if (pipe_name) {
762         /*
763          * We're reading a pipe (or capture file).
764          */
765
766         /*
767          * Immediately relinquish any special privileges we have; we must not
768          * be allowed to read any capture files the user running Rawshark
769          * can't open.
770          */
771         relinquish_special_privs_perm();
772
773         if (raw_cf_open(&cfile, pipe_name) != CF_OK) {
774             ret = OPEN_ERROR;
775             goto clean_exit;
776         }
777
778         /* Do we need to PCAP header and magic? */
779         if (skip_pcap_header) {
780             unsigned int bytes_left = (unsigned int) sizeof(struct pcap_hdr) + sizeof(guint32);
781             gchar buf[sizeof(struct pcap_hdr) + sizeof(guint32)];
782             while (bytes_left != 0) {
783                 ssize_t bytes = ws_read(fd, buf, bytes_left);
784                 if (bytes <= 0) {
785                     cmdarg_err("Not enough bytes for pcap header.");
786                     ret =  FORMAT_ERROR;
787                     goto clean_exit;
788                 }
789                 bytes_left -= (unsigned int)bytes;
790             }
791         }
792
793         /* Process the packets in the file */
794         if (!load_cap_file(&cfile)) {
795             ret = OPEN_ERROR;
796             goto clean_exit;
797         }
798     } else {
799         /* If you want to capture live packets, use TShark. */
800         cmdarg_err("Input file or pipe name not specified.");
801         ret = OPEN_ERROR;
802         goto clean_exit;
803     }
804
805 clean_exit:
806     g_free(pipe_name);
807     epan_free(cfile.epan);
808     epan_cleanup();
809     extcap_cleanup();
810     wtap_cleanup();
811     return ret;
812 }
813
814 /**
815  * Read data from a raw pipe.  The "raw" data consists of a libpcap
816  * packet header followed by the payload.
817  * @param pd [IN] A POSIX file descriptor.  Because that's _exactly_ the sort
818  *           of thing you want to use in Windows.
819  * @param err [OUT] Error indicator.  Uses wiretap values.
820  * @param err_info [OUT] Error message.
821  * @param data_offset [OUT] data offset in the pipe.
822  * @return TRUE on success, FALSE on failure.
823  */
824 static gboolean
825 raw_pipe_read(wtap_rec *rec, guchar * pd, int *err, gchar **err_info, gint64 *data_offset) {
826     struct pcap_pkthdr mem_hdr;
827     struct pcaprec_hdr disk_hdr;
828     ssize_t bytes_read = 0;
829     unsigned int bytes_needed = (unsigned int) sizeof(disk_hdr);
830     guchar *ptr = (guchar*) &disk_hdr;
831
832     *err = 0;
833
834     if (want_pcap_pkthdr) {
835         bytes_needed = sizeof(mem_hdr);
836         ptr = (guchar*) &mem_hdr;
837     }
838
839     /*
840      * Newer versions of the VC runtime do parameter validation. If stdin
841      * has been closed, calls to _read, _get_osfhandle, et al will trigger
842      * the invalid parameter handler and crash.
843      * We could alternatively use ReadFile or set an invalid parameter
844      * handler.
845      * We could also tell callers not to close stdin prematurely.
846      */
847 #ifdef _WIN32
848     DWORD ghi_flags;
849     if (fd == 0 && GetHandleInformation(GetStdHandle(STD_INPUT_HANDLE), &ghi_flags) == 0) {
850         *err = 0;
851         *err_info = NULL;
852         return FALSE;
853     }
854 #endif
855
856     /* Copied from capture_loop.c */
857     while (bytes_needed > 0) {
858         bytes_read = ws_read(fd, ptr, bytes_needed);
859         if (bytes_read == 0) {
860             *err = 0;
861             *err_info = NULL;
862             return FALSE;
863         } else if (bytes_read < 0) {
864             *err = errno;
865             *err_info = NULL;
866             return FALSE;
867         }
868         bytes_needed -= (unsigned int)bytes_read;
869         *data_offset += bytes_read;
870         ptr += bytes_read;
871     }
872
873     rec->rec_type = REC_TYPE_PACKET;
874     rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
875     if (want_pcap_pkthdr) {
876         rec->ts.secs = mem_hdr.ts.tv_sec;
877         rec->ts.nsecs = (gint32)mem_hdr.ts.tv_usec * 1000;
878         rec->rec_header.packet_header.caplen = mem_hdr.caplen;
879         rec->rec_header.packet_header.len = mem_hdr.len;
880     } else {
881         rec->ts.secs = disk_hdr.ts_sec;
882         rec->ts.nsecs = disk_hdr.ts_usec * 1000;
883         rec->rec_header.packet_header.caplen = disk_hdr.incl_len;
884         rec->rec_header.packet_header.len = disk_hdr.orig_len;
885     }
886     bytes_needed = rec->rec_header.packet_header.caplen;
887
888     rec->rec_header.packet_header.pkt_encap = encap;
889
890 #if 0
891     printf("mem_hdr: %lu disk_hdr: %lu\n", sizeof(mem_hdr), sizeof(disk_hdr));
892     printf("tv_sec: %u (%04x)\n", (unsigned int) rec->ts.secs, (unsigned int) rec->ts.secs);
893     printf("tv_nsec: %d (%04x)\n", rec->ts.nsecs, rec->ts.nsecs);
894     printf("caplen: %d (%04x)\n", rec->rec_header.packet_header.caplen, rec->rec_header.packet_header.caplen);
895     printf("len: %d (%04x)\n", rec->rec_header.packet_header.len, rec->rec_header.packet_header.len);
896 #endif
897     if (bytes_needed > WTAP_MAX_PACKET_SIZE_STANDARD) {
898         *err = WTAP_ERR_BAD_FILE;
899         *err_info = g_strdup_printf("Bad packet length: %lu\n",
900                    (unsigned long) bytes_needed);
901         return FALSE;
902     }
903
904     ptr = pd;
905     while (bytes_needed > 0) {
906         bytes_read = ws_read(fd, ptr, bytes_needed);
907         if (bytes_read == 0) {
908             *err = WTAP_ERR_SHORT_READ;
909             *err_info = NULL;
910             return FALSE;
911         } else if (bytes_read < 0) {
912             *err = errno;
913             *err_info = NULL;
914             return FALSE;
915         }
916         bytes_needed -= (unsigned int)bytes_read;
917         *data_offset += bytes_read;
918         ptr += bytes_read;
919     }
920     return TRUE;
921 }
922
923 static gboolean
924 load_cap_file(capture_file *cf)
925 {
926     int          err;
927     gchar       *err_info = NULL;
928     gint64       data_offset = 0;
929
930     guchar      *pd;
931     wtap_rec     rec;
932     epan_dissect_t edt;
933
934     wtap_rec_init(&rec);
935
936     epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
937
938     pd = (guchar*)g_malloc(WTAP_MAX_PACKET_SIZE_STANDARD);
939     while (raw_pipe_read(&rec, pd, &err, &err_info, &data_offset)) {
940         process_packet(cf, &edt, data_offset, &rec, pd);
941     }
942
943     epan_dissect_cleanup(&edt);
944
945     wtap_rec_cleanup(&rec);
946     g_free(pd);
947     if (err != 0) {
948         /* Print a message noting that the read failed somewhere along the line. */
949         cfile_read_failure_message("Rawshark", cf->filename, err, err_info);
950         return FALSE;
951     }
952
953     return TRUE;
954 }
955
956 static gboolean
957 process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
958                wtap_rec *rec, const guchar *pd)
959 {
960     frame_data fdata;
961     gboolean passed;
962     int i;
963
964     if(rec->rec_header.packet_header.len == 0)
965     {
966         /* The user sends an empty packet when he wants to get output from us even if we don't currently have
967            packets to process. We spit out a line with the timestamp and the text "void"
968         */
969         printf("%lu %lu %lu void -\n", (unsigned long int)cf->count,
970                (unsigned long int)rec->ts.secs,
971                (unsigned long int)rec->ts.nsecs);
972
973         fflush(stdout);
974
975         return FALSE;
976     }
977
978     /* Count this packet. */
979     cf->count++;
980
981     /* If we're going to print packet information, or we're going to
982        run a read filter, or we're going to process taps, set up to
983        do a dissection and do so. */
984     frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
985
986     passed = TRUE;
987
988     /* If we're running a read filter, prime the epan_dissect_t with that
989        filter. */
990     if (n_rfilters > 0) {
991         for(i = 0; i < n_rfcodes; i++) {
992             epan_dissect_prime_with_dfilter(edt, rfcodes[i]);
993         }
994     }
995
996     printf("%lu", (unsigned long int) cf->count);
997
998     frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
999                                   &cf->provider.ref, cf->provider.prev_dis);
1000
1001     if (cf->provider.ref == &fdata) {
1002        ref_frame = fdata;
1003        cf->provider.ref = &ref_frame;
1004     }
1005
1006     /* We only need the columns if we're printing packet info but we're
1007      *not* verbose; in verbose mode, we print the protocol tree, not
1008      the protocol summary. */
1009     epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1010                                frame_tvbuff_new(&cf->provider, &fdata, pd),
1011                                &fdata, &cf->cinfo);
1012
1013     frame_data_set_after_dissect(&fdata, &cum_bytes);
1014     prev_dis_frame = fdata;
1015     cf->provider.prev_dis = &prev_dis_frame;
1016
1017     prev_cap_frame = fdata;
1018     cf->provider.prev_cap = &prev_cap_frame;
1019
1020     for(i = 0; i < n_rfilters; i++) {
1021         /* Run the read filter if we have one. */
1022         if (rfcodes[i])
1023             passed = dfilter_apply_edt(rfcodes[i], edt);
1024         else
1025             passed = TRUE;
1026
1027         /* Print a one-line summary */
1028         printf(" %d", passed ? 1 : 0);
1029     }
1030
1031     printf(" -\n");
1032
1033     /* The ANSI C standard does not appear to *require* that a line-buffered
1034        stream be flushed to the host environment whenever a newline is
1035        written, it just says that, on such a stream, characters "are
1036        intended to be transmitted to or from the host environment as a
1037        block when a new-line character is encountered".
1038
1039        The Visual C++ 6.0 C implementation doesn't do what is intended;
1040        even if you set a stream to be line-buffered, it still doesn't
1041        flush the buffer at the end of every line.
1042
1043        So, if the "-l" flag was specified, we flush the standard output
1044        at the end of a packet.  This will do the right thing if we're
1045        printing packet summary lines, and, as we print the entire protocol
1046        tree for a single packet without waiting for anything to happen,
1047        it should be as good as line-buffered mode if we're printing
1048        protocol trees.  (The whole reason for the "-l" flag in either
1049        tcpdump or Rawshark is to allow the output of a live capture to
1050        be piped to a program or script and to have that script see the
1051        information for the packet as soon as it's printed, rather than
1052        having to wait until a standard I/O buffer fills up. */
1053     if (line_buffered)
1054         fflush(stdout);
1055
1056     if (ferror(stdout)) {
1057         show_print_file_io_error(errno);
1058         exit(2);
1059     }
1060
1061     epan_dissect_reset(edt);
1062     frame_data_destroy(&fdata);
1063
1064     return passed;
1065 }
1066
1067 /****************************************************************************************
1068  * FIELD EXTRACTION ROUTINES
1069  ****************************************************************************************/
1070 typedef struct _pci_t {
1071     char *filter;
1072     int hf_index;
1073     int cmd_line_index;
1074 } pci_t;
1075
1076 static const char* ftenum_to_string(header_field_info *hfi)
1077 {
1078     const char* str;
1079     if (!hfi) {
1080         return "n.a.";
1081     }
1082
1083     if (string_fmts->len > 0 && hfi->strings) {
1084         return "FT_STRING";
1085     }
1086
1087     str = ftype_name(hfi->type);
1088     if (str == NULL) {
1089         str = "n.a.";
1090     }
1091
1092     return str;
1093 }
1094
1095 static void field_display_to_string(header_field_info *hfi, char* buf, int size)
1096 {
1097     if (hfi->type != FT_BOOLEAN)
1098     {
1099         g_strlcpy(buf, proto_field_display_to_string(hfi->display), size);
1100     }
1101     else
1102     {
1103         g_snprintf(buf, size, "(Bit count: %d)", hfi->display);
1104     }
1105 }
1106
1107 /*
1108  * Copied from various parts of proto.c
1109  */
1110 #define FIELD_STR_INIT_LEN 256
1111 #define cVALS(x) (const value_string*)(x)
1112 static gboolean print_field_value(field_info *finfo, int cmd_line_index)
1113 {
1114     header_field_info   *hfinfo;
1115     char                *fs_buf = NULL;
1116     char                *fs_ptr = NULL;
1117     static GString     *label_s = NULL;
1118     int                 fs_len;
1119     guint              i;
1120     string_fmt_t       *sf;
1121     guint32            uvalue;
1122     gint32             svalue;
1123     guint64            uvalue64;
1124     gint64             svalue64;
1125     const true_false_string *tfstring = &tfs_true_false;
1126
1127     hfinfo = finfo->hfinfo;
1128
1129     if (!label_s) {
1130         label_s = g_string_new("");
1131     }
1132
1133     if(finfo->value.ftype->val_to_string_repr)
1134     {
1135         /*
1136          * this field has an associated value,
1137          * e.g: ip.hdr_len
1138          */
1139         fs_len = fvalue_string_repr_len(&finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
1140         fs_buf = fvalue_to_string_repr(NULL, &finfo->value,
1141                               FTREPR_DFILTER, finfo->hfinfo->display);
1142         fs_ptr = fs_buf;
1143
1144         /* String types are quoted. Remove them. */
1145         if (IS_FT_STRING(finfo->value.ftype->ftype) && fs_len > 2) {
1146             fs_buf[fs_len - 1] = '\0';
1147             fs_ptr++;
1148         }
1149     }
1150
1151     if (string_fmts->len > 0 && finfo->hfinfo->strings) {
1152         g_string_truncate(label_s, 0);
1153         for (i = 0; i < string_fmts->len; i++) {
1154             sf = (string_fmt_t *)g_ptr_array_index(string_fmts, i);
1155             if (sf->plain) {
1156                 g_string_append(label_s, sf->plain);
1157             } else {
1158                 switch (sf->format) {
1159                     case SF_NAME:
1160                         g_string_append(label_s, hfinfo->name);
1161                         break;
1162                     case SF_NUMVAL:
1163                         g_string_append(label_s, fs_ptr);
1164                         break;
1165                     case SF_STRVAL:
1166                         switch(hfinfo->type) {
1167                             case FT_BOOLEAN:
1168                                 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1169                                 tfstring = (const struct true_false_string*) hfinfo->strings;
1170                                 g_string_append(label_s, uvalue64 ? tfstring->true_string : tfstring->false_string);
1171                                 break;
1172                             case FT_INT8:
1173                             case FT_INT16:
1174                             case FT_INT24:
1175                             case FT_INT32:
1176                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1177                                 svalue = fvalue_get_sinteger(&finfo->value);
1178                                 if (hfinfo->display & BASE_RANGE_STRING) {
1179                                     g_string_append(label_s, rval_to_str_const(svalue, (const range_string *) hfinfo->strings, "Unknown"));
1180                                 } else if (hfinfo->display & BASE_EXT_STRING) {
1181                                     g_string_append(label_s, val_to_str_ext_const(svalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1182                                 } else {
1183                                     g_string_append(label_s, val_to_str_const(svalue, cVALS(hfinfo->strings), "Unknown"));
1184                                 }
1185                                 break;
1186                             case FT_INT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1187                             case FT_INT48:
1188                             case FT_INT56:
1189                             case FT_INT64:
1190                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1191                                 svalue64 = fvalue_get_sinteger64(&finfo->value);
1192                                 if (hfinfo->display & BASE_VAL64_STRING) {
1193                                     g_string_append(label_s, val64_to_str_const(svalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1194                                 }
1195                                 break;
1196                             case FT_UINT8:
1197                             case FT_UINT16:
1198                             case FT_UINT24:
1199                             case FT_UINT32:
1200                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1201                                 uvalue = fvalue_get_uinteger(&finfo->value);
1202                                 if (!hfinfo->bitmask && hfinfo->display & BASE_RANGE_STRING) {
1203                                     g_string_append(label_s, rval_to_str_const(uvalue, (const range_string *) hfinfo->strings, "Unknown"));
1204                                 } else if (hfinfo->display & BASE_EXT_STRING) {
1205                                     g_string_append(label_s, val_to_str_ext_const(uvalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1206                                 } else {
1207                                     g_string_append(label_s, val_to_str_const(uvalue, cVALS(hfinfo->strings), "Unknown"));
1208                                 }
1209                                 break;
1210                             case FT_UINT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1211                             case FT_UINT48:
1212                             case FT_UINT56:
1213                             case FT_UINT64:
1214                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1215                                 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1216                                 if (hfinfo->display & BASE_VAL64_STRING) {
1217                                     g_string_append(label_s, val64_to_str_const(uvalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1218                                 }
1219                                 break;
1220                             default:
1221                                 break;
1222                         }
1223                         break;
1224                     default:
1225                         break;
1226                 }
1227             }
1228         }
1229         printf(" %d=\"%s\"", cmd_line_index, label_s->str);
1230         wmem_free(NULL, fs_buf);
1231         return TRUE;
1232     }
1233
1234     if(finfo->value.ftype->val_to_string_repr)
1235     {
1236         printf(" %d=\"%s\"", cmd_line_index, fs_ptr);
1237         wmem_free(NULL, fs_buf);
1238         return TRUE;
1239     }
1240
1241     /*
1242      * This field doesn't have an associated value,
1243      * e.g. http
1244      * We return n.a.
1245      */
1246     printf(" %d=\"n.a.\"", cmd_line_index);
1247     return TRUE;
1248 }
1249
1250 static tap_packet_status
1251 protocolinfo_packet(void *prs, packet_info *pinfo _U_, epan_dissect_t *edt, const void *dummy _U_)
1252 {
1253     pci_t *rs=(pci_t *)prs;
1254     GPtrArray *gp;
1255     guint i;
1256
1257     gp=proto_get_finfo_ptr_array(edt->tree, rs->hf_index);
1258     if(!gp){
1259         printf(" n.a.");
1260         return TAP_PACKET_DONT_REDRAW;
1261     }
1262
1263     /*
1264      * Print each occurrence of the field
1265      */
1266     for (i = 0; i < gp->len; i++) {
1267         print_field_value((field_info *)gp->pdata[i], rs->cmd_line_index);
1268     }
1269
1270     return TAP_PACKET_DONT_REDRAW;
1271 }
1272
1273 int g_cmd_line_index = 0;
1274
1275 /*
1276  * field must be persistent - we don't g_strdup() it below
1277  */
1278 static void
1279 protocolinfo_init(char *field)
1280 {
1281     pci_t *rs;
1282     header_field_info *hfi;
1283     GString *error_string;
1284     char hfibuf[100];
1285
1286     hfi=proto_registrar_get_byname(field);
1287     if(!hfi){
1288         fprintf(stderr, "rawshark: Field \"%s\" doesn't exist.\n", field);
1289         exit(1);
1290     }
1291
1292     field_display_to_string(hfi, hfibuf, sizeof(hfibuf));
1293     printf("%d %s %s - ",
1294             g_cmd_line_index,
1295             ftenum_to_string(hfi),
1296             hfibuf);
1297
1298     rs=(pci_t *)g_malloc(sizeof(pci_t));
1299     rs->hf_index=hfi->id;
1300     rs->filter=field;
1301     rs->cmd_line_index = g_cmd_line_index++;
1302
1303     error_string=register_tap_listener("frame", rs, rs->filter, TL_REQUIRES_PROTO_TREE, NULL, protocolinfo_packet, NULL, NULL);
1304     if(error_string){
1305         /* error, we failed to attach to the tap. complain and clean up */
1306         fprintf(stderr, "rawshark: Couldn't register field extraction tap: %s\n",
1307                 error_string->str);
1308         g_string_free(error_string, TRUE);
1309         if(rs->filter){
1310             g_free(rs->filter);
1311         }
1312         g_free(rs);
1313
1314         exit(1);
1315     }
1316 }
1317
1318 /*
1319  * Given a format string, split it into a GPtrArray of string_fmt_t structs
1320  * and fill in string_fmt_parts.
1321  */
1322
1323 static void
1324 add_string_fmt(string_fmt_e format, gchar *plain) {
1325     string_fmt_t *sf = (string_fmt_t *)g_malloc(sizeof(string_fmt_t));
1326
1327     sf->format = format;
1328     sf->plain = g_strdup(plain);
1329
1330     g_ptr_array_add(string_fmts, sf);
1331 }
1332
1333 static gboolean
1334 parse_field_string_format(gchar *format) {
1335     GString *plain_s = g_string_new("");
1336     size_t len;
1337     size_t pos = 0;
1338
1339     if (!format) {
1340         return FALSE;
1341     }
1342
1343     len = strlen(format);
1344     g_ptr_array_set_size(string_fmts, 0);
1345
1346     while (pos < len) {
1347         if (format[pos] == '%') {
1348             if (pos >= len) { /* There should always be a following character */
1349                 return FALSE;
1350             }
1351             pos++;
1352             if (plain_s->len > 0) {
1353                 add_string_fmt(SF_NONE, plain_s->str);
1354                 g_string_truncate(plain_s, 0);
1355             }
1356             switch (format[pos]) {
1357                 case 'D':
1358                     add_string_fmt(SF_NAME, NULL);
1359                     break;
1360                 case 'N':
1361                     add_string_fmt(SF_NUMVAL, NULL);
1362                     break;
1363                 case 'S':
1364                     add_string_fmt(SF_STRVAL, NULL);
1365                     break;
1366                 case '%':
1367                     g_string_append_c(plain_s, '%');
1368                     break;
1369                 default: /* Invalid format */
1370                     return FALSE;
1371             }
1372         } else {
1373             g_string_append_c(plain_s, format[pos]);
1374         }
1375         pos++;
1376     }
1377
1378     if (plain_s->len > 0) {
1379         add_string_fmt(SF_NONE, plain_s->str);
1380     }
1381     g_string_free(plain_s, TRUE);
1382
1383     return TRUE;
1384 }
1385 /****************************************************************************************
1386  * END OF FIELD EXTRACTION ROUTINES
1387  ****************************************************************************************/
1388
1389 static void
1390 show_print_file_io_error(int err)
1391 {
1392     switch (err) {
1393
1394         case ENOSPC:
1395             cmdarg_err("Not all the packets could be printed because there is "
1396                        "no space left on the file system.");
1397             break;
1398
1399 #ifdef EDQUOT
1400         case EDQUOT:
1401             cmdarg_err("Not all the packets could be printed because you are "
1402                        "too close to, or over your disk quota.");
1403             break;
1404 #endif
1405
1406         default:
1407             cmdarg_err("An error occurred while printing packets: %s.",
1408                        g_strerror(err));
1409             break;
1410     }
1411 }
1412
1413 /*
1414  * General errors and warnings are reported with an console message
1415  * in Rawshark.
1416  */
1417 static void
1418 failure_warning_message(const char *msg_format, va_list ap)
1419 {
1420     fprintf(stderr, "rawshark: ");
1421     vfprintf(stderr, msg_format, ap);
1422     fprintf(stderr, "\n");
1423 }
1424
1425 /*
1426  * Open/create errors are reported with an console message in Rawshark.
1427  */
1428 static void
1429 open_failure_message(const char *filename, int err, gboolean for_writing)
1430 {
1431     fprintf(stderr, "rawshark: ");
1432     fprintf(stderr, file_open_error_message(err, for_writing), filename);
1433     fprintf(stderr, "\n");
1434 }
1435
1436 static const nstime_t *
1437 raw_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
1438 {
1439     if (prov->ref && prov->ref->num == frame_num)
1440         return &prov->ref->abs_ts;
1441
1442     if (prov->prev_dis && prov->prev_dis->num == frame_num)
1443         return &prov->prev_dis->abs_ts;
1444
1445     if (prov->prev_cap && prov->prev_cap->num == frame_num)
1446         return &prov->prev_cap->abs_ts;
1447
1448     return NULL;
1449 }
1450
1451 static epan_t *
1452 raw_epan_new(capture_file *cf)
1453 {
1454     static const struct packet_provider_funcs funcs = {
1455         raw_get_frame_ts,
1456         cap_file_provider_get_interface_name,
1457         cap_file_provider_get_interface_description,
1458         NULL,
1459     };
1460
1461     return epan_new(&cf->provider, &funcs);
1462 }
1463
1464 cf_status_t
1465 raw_cf_open(capture_file *cf, const char *fname)
1466 {
1467     if ((fd = raw_pipe_open(fname)) < 0)
1468         return CF_ERROR;
1469
1470     /* The open succeeded.  Fill in the information for this file. */
1471
1472     /* Create new epan session for dissection. */
1473     epan_free(cf->epan);
1474     cf->epan = raw_epan_new(cf);
1475
1476     cf->provider.wth = NULL;
1477     cf->f_datalen = 0; /* not used, but set it anyway */
1478
1479     /* Set the file name because we need it to set the follow stream filter.
1480        XXX - is that still true?  We need it for other reasons, though,
1481        in any case. */
1482     cf->filename = g_strdup(fname);
1483
1484     /* Indicate whether it's a permanent or temporary file. */
1485     cf->is_tempfile = FALSE;
1486
1487     /* No user changes yet. */
1488     cf->unsaved_changes = FALSE;
1489
1490     cf->cd_t      = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
1491     cf->open_type = WTAP_TYPE_AUTO;
1492     cf->count     = 0;
1493     cf->drops_known = FALSE;
1494     cf->drops     = 0;
1495     cf->snap      = 0;
1496     nstime_set_zero(&cf->elapsed_time);
1497     cf->provider.ref = NULL;
1498     cf->provider.prev_dis = NULL;
1499     cf->provider.prev_cap = NULL;
1500
1501     return CF_OK;
1502 }
1503
1504 /*
1505  * Read errors are reported with an console message in Rawshark.
1506  */
1507 static void
1508 read_failure_message(const char *filename, int err)
1509 {
1510     cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
1511                filename, g_strerror(err));
1512 }
1513
1514 /*
1515  * Write errors are reported with an console message in Rawshark.
1516  */
1517 static void
1518 write_failure_message(const char *filename, int err)
1519 {
1520     cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
1521                filename, g_strerror(err));
1522 }
1523
1524 /*
1525  * Report an error in command-line arguments.
1526  */
1527 static void
1528 rawshark_cmdarg_err(const char *fmt, va_list ap)
1529 {
1530     fprintf(stderr, "rawshark: ");
1531     vfprintf(stderr, fmt, ap);
1532     fprintf(stderr, "\n");
1533 }
1534
1535 /*
1536  * Report additional information for an error in command-line arguments.
1537  */
1538 static void
1539 rawshark_cmdarg_err_cont(const char *fmt, va_list ap)
1540 {
1541     vfprintf(stderr, fmt, ap);
1542     fprintf(stderr, "\n");
1543 }
1544
1545 /*
1546  * Editor modelines
1547  *
1548  * Local Variables:
1549  * c-basic-offset: 4
1550  * tab-width: 8
1551  * indent-tabs-mode: nil
1552  * End:
1553  *
1554  * ex: set shiftwidth=4 tabstop=8 expandtab:
1555  * :indentSize=4:tabSize=8:noTabs=true:
1556  */