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