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