1 /* rawshark.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * Rawshark - Raw field extractor by Gerald Combs <gerald@wireshark.org>
8  * and Loris Degioanni <loris.degioanni@cacetech.com>
9  * Based on TShark, by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris
10  * <guy@alum.mit.edu>.
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14 
15 /*
16  * Rawshark does the following:
17  * - Opens a specified file or named pipe
18  * - Applies a specfied DLT or "decode as" encapsulation
19  * - Reads frames prepended with a libpcap packet header.
20  * - Prints a status line, followed by fields from a specified list.
21  */
22 
23 #include <config.h>
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <locale.h>
29 #include <limits.h>
30 
31 #ifndef _WIN32
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #endif
35 
36 #include <errno.h>
37 
38 #include <wsutil/ws_getopt.h>
39 
40 #include <glib.h>
41 #include <epan/epan.h>
42 
43 #include <ui/cmdarg_err.h>
44 #include <ui/exit_codes.h>
45 #include <wsutil/filesystem.h>
46 #include <wsutil/file_util.h>
47 #include <wsutil/socket.h>
48 #include <wsutil/plugins.h>
49 #include <wsutil/privileges.h>
50 #include <wsutil/report_message.h>
51 #include <wsutil/please_report_bug.h>
52 #include <wsutil/wslog.h>
53 #include <ui/clopts_common.h>
54 
55 #include "globals.h"
56 #include <epan/packet.h>
57 #include <epan/ftypes/ftypes-int.h>
58 #include "file.h"
59 #include "frame_tvbuff.h"
60 #include <epan/disabled_protos.h>
61 #include <epan/prefs.h>
62 #include <epan/column.h>
63 #include <epan/print.h>
64 #include <epan/addr_resolv.h>
65 #ifdef HAVE_LIBPCAP
66 #include "ui/capture_ui_utils.h"
67 #endif
68 #include "ui/util.h"
69 #include "ui/dissect_opts.h"
70 #include "ui/failure_message.h"
71 #include <epan/epan_dissect.h>
72 #include <epan/stat_tap_ui.h>
73 #include <epan/timestamp.h>
74 #include "epan/column-utils.h"
75 #include "epan/proto.h"
76 #include <epan/tap.h>
77 
78 #include <wiretap/wtap.h>
79 #include <wiretap/libpcap.h>
80 #include <wiretap/pcap-encap.h>
81 
82 #include <cli_main.h>
83 #include <ui/version_info.h>
84 
85 #include "capture/capture-pcap-util.h"
86 
87 #include "extcap.h"
88 
89 #ifdef HAVE_LIBPCAP
90 #include <setjmp.h>
91 #ifdef _WIN32
92 #include "capture/capture-wpcap.h"
93 #endif /* _WIN32 */
94 #endif /* HAVE_LIBPCAP */
95 
96 #if 0
97 /*
98  * This is the template for the decode as option; it is shared between the
99  * various functions that output the usage for this parameter.
100  */
101 static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
102 #endif
103 
104 /* Additional exit codes */
105 #define INVALID_DFILTER 2
106 #define FORMAT_ERROR    2
107 
108 capture_file cfile;
109 
110 static guint32 cum_bytes;
111 static frame_data ref_frame;
112 static frame_data prev_dis_frame;
113 static frame_data prev_cap_frame;
114 
115 /*
116  * The way the packet decode is to be written.
117  */
118 typedef enum {
119     WRITE_TEXT, /* summary or detail text */
120     WRITE_XML   /* PDML or PSML */
121     /* Add CSV and the like here */
122 } output_action_e;
123 
124 static gboolean line_buffered;
125 static print_format_e print_format = PR_FMT_TEXT;
126 
127 static gboolean want_pcap_pkthdr;
128 
129 cf_status_t raw_cf_open(capture_file *cf, const char *fname);
130 static gboolean load_cap_file(capture_file *cf);
131 static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
132                                wtap_rec *rec, Buffer *buf);
133 static void show_print_file_io_error(int err);
134 
135 static void rawshark_cmdarg_err(const char *fmt, va_list ap);
136 static void rawshark_cmdarg_err_cont(const char *fmt, va_list ap);
137 static void protocolinfo_init(char *field);
138 static gboolean parse_field_string_format(char *format);
139 
140 typedef enum {
141     SF_NONE,    /* No format (placeholder) */
142     SF_NAME,    /* %D Field name / description */
143     SF_NUMVAL,  /* %N Numeric value */
144     SF_STRVAL   /* %S String value */
145 } string_fmt_e;
146 
147 typedef struct string_fmt_s {
148     gchar *plain;
149     string_fmt_e format;    /* Valid if plain is NULL */
150 } string_fmt_t;
151 
152 int n_rfilters;
153 int n_rfcodes;
154 dfilter_t *rfcodes[64];
155 int n_rfieldfilters;
156 dfilter_t *rfieldfcodes[64];
157 int fd;
158 int encap;
159 GPtrArray *string_fmts;
160 
161 static void
print_usage(FILE * output)162 print_usage(FILE *output)
163 {
164     fprintf(output, "\n");
165     fprintf(output, "Usage: rawshark [options] ...\n");
166     fprintf(output, "\n");
167 
168     fprintf(output, "Input file:\n");
169     fprintf(output, "  -r <infile>              set the pipe or file name to read from\n");
170 
171     fprintf(output, "\n");
172     fprintf(output, "Processing:\n");
173     fprintf(output, "  -d <encap:linktype>|<proto:protoname>\n");
174     fprintf(output, "                           packet encapsulation or protocol\n");
175     fprintf(output, "  -F <field>               field to display\n");
176 #ifndef _WIN32
177     fprintf(output, "  -m                       virtual memory limit, in bytes\n");
178 #endif
179     fprintf(output, "  -n                       disable all name resolution (def: all enabled)\n");
180     fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mnNtdv\"\n");
181     fprintf(output, "  -p                       use the system's packet header format\n");
182     fprintf(output, "                           (which may have 64-bit timestamps)\n");
183     fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
184     fprintf(output, "  -s                       skip PCAP header on input\n");
185 
186     fprintf(output, "\n");
187     fprintf(output, "Output:\n");
188     fprintf(output, "  -l                       flush output after each packet\n");
189     fprintf(output, "  -S                       format string for fields\n");
190     fprintf(output, "                           (%%D - name, %%S - stringval, %%N numval)\n");
191     fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
192 
193     ws_log_print_usage(output);
194 
195     fprintf(output, "\n");
196     fprintf(output, "Miscellaneous:\n");
197     fprintf(output, "  -h                       display this help and exit\n");
198     fprintf(output, "  -o <name>:<value> ...    override preference setting\n");
199     fprintf(output, "  -v                       display version info and exit\n");
200 }
201 
202 /**
203  * Open a pipe for raw input.  This is a stripped-down version of
204  * pcap_loop.c:cap_pipe_open_live().
205  * We check if "pipe_name" is "-" (stdin) or a FIFO, and open it.
206  * @param pipe_name The name of the pipe or FIFO.
207  * @return A POSIX file descriptor on success, or -1 on failure.
208  */
209 static int
raw_pipe_open(const char * pipe_name)210 raw_pipe_open(const char *pipe_name)
211 {
212 #ifndef _WIN32
213     ws_statb64 pipe_stat;
214 #else
215     char *pncopy, *pos = NULL;
216     DWORD err;
217     wchar_t *err_str;
218     HANDLE hPipe = NULL;
219 #endif
220     int          rfd;
221 
222     ws_log(LOG_DOMAIN_CAPCHILD, LOG_LEVEL_DEBUG, "open_raw_pipe: %s", pipe_name);
223 
224     /*
225      * XXX Rawshark blocks until we return
226      */
227     if (strcmp(pipe_name, "-") == 0) {
228         rfd = 0; /* read from stdin */
229 #ifdef _WIN32
230         /*
231          * This is needed to set the stdin pipe into binary mode, otherwise
232          * CR/LF are mangled...
233          */
234         _setmode(0, _O_BINARY);
235 #endif  /* _WIN32 */
236     } else {
237 #ifndef _WIN32
238         if (ws_stat64(pipe_name, &pipe_stat) < 0) {
239             fprintf(stderr, "rawshark: The pipe %s could not be checked: %s\n",
240                     pipe_name, g_strerror(errno));
241             return -1;
242         }
243         if (! S_ISFIFO(pipe_stat.st_mode)) {
244             if (S_ISCHR(pipe_stat.st_mode)) {
245                 /*
246                  * Assume the user specified an interface on a system where
247                  * interfaces are in /dev.  Pretend we haven't seen it.
248                  */
249             } else
250             {
251                 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
252                         pipe_name);
253             }
254             return -1;
255         }
256         rfd = ws_open(pipe_name, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
257         if (rfd == -1) {
258             fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
259                     pipe_name, g_strerror(errno));
260             return -1;
261         }
262 #else /* _WIN32 */
263 #define PIPE_STR "\\pipe\\"
264         /* Under Windows, named pipes _must_ have the form
265          * "\\<server>\pipe\<pipe_name>".  <server> may be "." for localhost.
266          */
267         pncopy = g_strdup(pipe_name);
268         if (strstr(pncopy, "\\\\") == pncopy) {
269             pos = strchr(pncopy + 3, '\\');
270             if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
271                 pos = NULL;
272         }
273 
274         g_free(pncopy);
275 
276         if (!pos) {
277             fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
278                     pipe_name);
279             return -1;
280         }
281 
282         /* Wait for the pipe to appear */
283         while (1) {
284             hPipe = CreateFile(utf_8to16(pipe_name), GENERIC_READ, 0, NULL,
285                                OPEN_EXISTING, 0, NULL);
286 
287             if (hPipe != INVALID_HANDLE_VALUE)
288                 break;
289 
290             err = GetLastError();
291             if (err != ERROR_PIPE_BUSY) {
292                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
293                               NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
294                 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s (error %lu)\n",
295                         pipe_name, utf_16to8(err_str), err);
296                 LocalFree(err_str);
297                 return -1;
298             }
299 
300             if (!WaitNamedPipe(utf_8to16(pipe_name), 30 * 1000)) {
301                 err = GetLastError();
302                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
303                               NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
304                 fprintf(stderr, "rawshark: \"%s\" could not be waited for: %s (error %lu)\n",
305                         pipe_name, utf_16to8(err_str), err);
306                 LocalFree(err_str);
307                 return -1;
308             }
309         }
310 
311         rfd = _open_osfhandle((intptr_t) hPipe, _O_RDONLY);
312         if (rfd == -1) {
313             fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
314                     pipe_name, g_strerror(errno));
315             return -1;
316         }
317 #endif /* _WIN32 */
318     }
319 
320     return rfd;
321 }
322 
323 /**
324  * Parse a link-type argument of the form "encap:<pcap linktype>" or
325  * "proto:<proto name>".  "Pcap linktype" must be a name conforming to
326  * pcap_datalink_name_to_val() or an integer; the integer should be
327  * a LINKTYPE_ value supported by Wiretap.  "Proto name" must be
328  * a protocol name, e.g. "http".
329  */
330 static gboolean
set_link_type(const char * lt_arg)331 set_link_type(const char *lt_arg) {
332     char *spec_ptr = strchr(lt_arg, ':');
333     char *p;
334     int dlt_val;
335     long val;
336     dissector_handle_t dhandle;
337     GString *pref_str;
338     char *errmsg = NULL;
339 
340     if (!spec_ptr)
341         return FALSE;
342 
343     spec_ptr++;
344 
345     if (strncmp(lt_arg, "encap:", strlen("encap:")) == 0) {
346         dlt_val = linktype_name_to_val(spec_ptr);
347         if (dlt_val == -1) {
348             errno = 0;
349             val = strtol(spec_ptr, &p, 10);
350             if (p == spec_ptr || *p != '\0' || errno != 0 || val > INT_MAX) {
351                 return FALSE;
352             }
353             dlt_val = (int)val;
354         }
355         /*
356          * In those cases where a given link-layer header type
357          * has different LINKTYPE_ and DLT_ values, linktype_name_to_val()
358          * will return the OS's DLT_ value for that link-layer header
359          * type, not its OS-independent LINKTYPE_ value.
360          *
361          * On a given OS, wtap_pcap_encap_to_wtap_encap() should
362          * be able to map either LINKTYPE_ values or DLT_ values
363          * for the OS to the appropriate Wiretap encapsulation.
364          */
365         encap = wtap_pcap_encap_to_wtap_encap(dlt_val);
366         if (encap == WTAP_ENCAP_UNKNOWN) {
367             return FALSE;
368         }
369         return TRUE;
370     } else if (strncmp(lt_arg, "proto:", strlen("proto:")) == 0) {
371         dhandle = find_dissector(spec_ptr);
372         if (dhandle) {
373             encap = WTAP_ENCAP_USER0;
374             pref_str = g_string_new("uat:user_dlts:");
375             /* This must match the format used in the user_dlts file */
376             g_string_append_printf(pref_str,
377                                    "\"User 0 (DLT=147)\",\"%s\",\"0\",\"\",\"0\",\"\"",
378                                    spec_ptr);
379             if (prefs_set_pref(pref_str->str, &errmsg) != PREFS_SET_OK) {
380                 g_string_free(pref_str, TRUE);
381                 g_free(errmsg);
382                 return FALSE;
383             }
384             g_string_free(pref_str, TRUE);
385             return TRUE;
386         }
387     }
388     return FALSE;
389 }
390 
391 int
main(int argc,char * argv[])392 main(int argc, char *argv[])
393 {
394     char                *err_msg;
395     int                  opt, i;
396 
397 #ifndef _WIN32
398     struct rlimit limit;
399 #endif  /* !_WIN32 */
400 
401     gchar               *pipe_name = NULL;
402     gchar               *rfilters[64];
403     e_prefs             *prefs_p;
404     char                 badopt;
405     GPtrArray           *disp_fields = g_ptr_array_new();
406     guint                fc;
407     gboolean             skip_pcap_header = FALSE;
408     int                  ret = EXIT_SUCCESS;
409     static const struct ws_option long_options[] = {
410       {"help", ws_no_argument, NULL, 'h'},
411       {"version", ws_no_argument, NULL, 'v'},
412       {0, 0, 0, 0 }
413     };
414 
415 #define OPTSTRING_INIT "d:F:hlm:nN:o:pr:R:sS:t:v"
416 
417     static const char    optstring[] = OPTSTRING_INIT;
418     static const struct report_message_routines rawshark_report_routines = {
419       failure_message,
420       failure_message,
421       open_failure_message,
422       read_failure_message,
423       write_failure_message,
424       cfile_open_failure_message,
425       cfile_dump_open_failure_message,
426       cfile_read_failure_message,
427       cfile_write_failure_message,
428       cfile_close_failure_message
429     };
430 
431     /*
432      * Set the C-language locale to the native environment and set the
433      * code page to UTF-8 on Windows.
434      */
435 #ifdef _WIN32
436     setlocale(LC_ALL, ".UTF-8");
437 #else
438     setlocale(LC_ALL, "");
439 #endif
440 
441     cmdarg_err_init(rawshark_cmdarg_err, rawshark_cmdarg_err_cont);
442 
443     /* Initialize log handler early so we can have proper logging during startup. */
444     ws_log_init("rawshark", vcmdarg_err);
445 
446     /* Early logging command-line initialization. */
447     ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
448 
449     /* Initialize the version information. */
450     ws_init_version_info("Rawshark (Wireshark)", NULL,
451                          epan_get_compiled_version_info,
452                          NULL);
453 
454 #ifdef _WIN32
455     create_app_running_mutex();
456 #endif /* _WIN32 */
457 
458     /*
459      * Get credential information for later use.
460      */
461     init_process_policies();
462 
463     /*
464      * Clear the filters arrays
465      */
466     memset(rfilters, 0, sizeof(rfilters));
467     memset(rfcodes, 0, sizeof(rfcodes));
468     n_rfilters = 0;
469     n_rfcodes = 0;
470 
471     /*
472      * Initialize our string format
473      */
474     string_fmts = g_ptr_array_new();
475 
476     /*
477      * Attempt to get the pathname of the directory containing the
478      * executable file.
479      */
480     err_msg = init_progfile_dir(argv[0]);
481     if (err_msg != NULL) {
482         fprintf(stderr, "rawshark: Can't get pathname of rawshark program: %s.\n",
483                 err_msg);
484     }
485 
486     init_report_message("rawshark", &rawshark_report_routines);
487 
488     timestamp_set_type(TS_RELATIVE);
489     timestamp_set_precision(TS_PREC_AUTO);
490     timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
491 
492     /*
493      * XXX - is this necessary, given that we're not reading a
494      * regular capture file, we're reading rawshark's packet
495      * stream format?
496      *
497      * If it is, note that libwiretap must be initialized before
498      * libwireshark is, so that dissection-time handlers for
499      * file-type-dependent blocks can register using the file
500      * type/subtype value for the file type.
501      */
502     wtap_init(FALSE);
503 
504     /* Register all dissectors; we must do this before checking for the
505        "-G" flag, as the "-G" flag dumps information registered by the
506        dissectors, and we must do it before we read the preferences, in
507        case any dissectors register preferences. */
508     if (!epan_init(NULL, NULL, TRUE)) {
509         ret = INIT_FAILED;
510         goto clean_exit;
511     }
512 
513     /* Load libwireshark settings from the current profile. */
514     prefs_p = epan_load_settings();
515 
516 #ifdef _WIN32
517     ws_init_dll_search_path();
518     /* Load Wpcap, if possible */
519     load_wpcap();
520 #endif
521 
522     cap_file_init(&cfile);
523 
524     /* Print format defaults to this. */
525     print_format = PR_FMT_TEXT;
526 
527     /* Initialize our encapsulation type */
528     encap = WTAP_ENCAP_UNKNOWN;
529 
530     /* Now get our args */
531     /* XXX - We should probably have an option to dump libpcap link types */
532     while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
533         switch (opt) {
534             case 'd':        /* Payload type */
535                 if (!set_link_type(ws_optarg)) {
536                     cmdarg_err("Invalid link type or protocol \"%s\"", ws_optarg);
537                     ret = INVALID_OPTION;
538                     goto clean_exit;
539                 }
540                 break;
541             case 'F':        /* Read field to display */
542                 g_ptr_array_add(disp_fields, g_strdup(ws_optarg));
543                 break;
544             case 'h':        /* Print help and exit */
545                 show_help_header("Dump and analyze network traffic.");
546                 print_usage(stdout);
547                 goto clean_exit;
548                 break;
549             case 'l':        /* "Line-buffer" standard output */
550                 /* This isn't line-buffering, strictly speaking, it's just
551                    flushing the standard output after the information for
552                    each packet is printed; however, that should be good
553                    enough for all the purposes to which "-l" is put (and
554                    is probably actually better for "-V", as it does fewer
555                    writes).
556 
557                    See the comment in "process_packet()" for an explanation of
558                    why we do that, and why we don't just use "setvbuf()" to
559                    make the standard output line-buffered (short version: in
560                    Windows, "line-buffered" is the same as "fully-buffered",
561                    and the output buffer is only flushed when it fills up). */
562                 line_buffered = TRUE;
563                 break;
564 #ifndef _WIN32
565             case 'm':
566                 limit.rlim_cur = get_positive_int(ws_optarg, "memory limit");
567                 limit.rlim_max = get_positive_int(ws_optarg, "memory limit");
568 
569                 if(setrlimit(RLIMIT_AS, &limit) != 0) {
570                     cmdarg_err("setrlimit() returned error");
571                     ret = INVALID_OPTION;
572                     goto clean_exit;
573                 }
574                 break;
575 #endif
576             case 'n':        /* No name resolution */
577                 disable_name_resolution();
578                 break;
579             case 'N':        /* Select what types of addresses/port #s to resolve */
580                 badopt = string_to_name_resolve(ws_optarg, &gbl_resolv_flags);
581                 if (badopt != '\0') {
582                     cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'd', m', 'n', 'N', and 't'",
583                                badopt);
584                     ret = INVALID_OPTION;
585                     goto clean_exit;
586                 }
587                 break;
588             case 'o':        /* Override preference from command line */
589             {
590                 char *errmsg = NULL;
591 
592                 switch (prefs_set_pref(ws_optarg, &errmsg)) {
593 
594                     case PREFS_SET_OK:
595                         break;
596 
597                     case PREFS_SET_SYNTAX_ERR:
598                         cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
599                                 errmsg ? ": " : "", errmsg ? errmsg : "");
600                         g_free(errmsg);
601                         ret = INVALID_OPTION;
602                         goto clean_exit;
603                         break;
604 
605                     case PREFS_SET_NO_SUCH_PREF:
606                         cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
607                         ret = INVALID_OPTION;
608                         goto clean_exit;
609                         break;
610 
611                     case PREFS_SET_OBSOLETE:
612                         cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
613                         ret = INVALID_OPTION;
614                         goto clean_exit;
615                         break;
616                 }
617                 break;
618             }
619             case 'p':        /* Expect pcap_pkthdr packet headers, which may have 64-bit timestamps */
620                 want_pcap_pkthdr = TRUE;
621                 break;
622             case 'r':        /* Read capture file xxx */
623                 pipe_name = g_strdup(ws_optarg);
624                 break;
625             case 'R':        /* Read file filter */
626                 if(n_rfilters < (int) sizeof(rfilters) / (int) sizeof(rfilters[0])) {
627                     rfilters[n_rfilters++] = ws_optarg;
628                 }
629                 else {
630                     cmdarg_err("Too many display filters");
631                     ret = INVALID_OPTION;
632                     goto clean_exit;
633                 }
634                 break;
635             case 's':        /* Skip PCAP header */
636                 skip_pcap_header = TRUE;
637                 break;
638             case 'S':        /* Print string representations */
639                 if (!parse_field_string_format(ws_optarg)) {
640                     cmdarg_err("Invalid field string format");
641                     ret = INVALID_OPTION;
642                     goto clean_exit;
643                 }
644                 break;
645             case 't':        /* Time stamp type */
646                 if (strcmp(ws_optarg, "r") == 0)
647                     timestamp_set_type(TS_RELATIVE);
648                 else if (strcmp(ws_optarg, "a") == 0)
649                     timestamp_set_type(TS_ABSOLUTE);
650                 else if (strcmp(ws_optarg, "ad") == 0)
651                     timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
652                 else if (strcmp(ws_optarg, "adoy") == 0)
653                     timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
654                 else if (strcmp(ws_optarg, "d") == 0)
655                     timestamp_set_type(TS_DELTA);
656                 else if (strcmp(ws_optarg, "dd") == 0)
657                     timestamp_set_type(TS_DELTA_DIS);
658                 else if (strcmp(ws_optarg, "e") == 0)
659                     timestamp_set_type(TS_EPOCH);
660                 else if (strcmp(ws_optarg, "u") == 0)
661                     timestamp_set_type(TS_UTC);
662                 else if (strcmp(ws_optarg, "ud") == 0)
663                     timestamp_set_type(TS_UTC_WITH_YMD);
664                 else if (strcmp(ws_optarg, "udoy") == 0)
665                     timestamp_set_type(TS_UTC_WITH_YDOY);
666                 else {
667                     cmdarg_err("Invalid time stamp type \"%s\"",
668                                ws_optarg);
669                     cmdarg_err_cont(
670 "It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
671                     cmdarg_err_cont(
672 "\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
673                     cmdarg_err_cont(
674 "\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
675                     cmdarg_err_cont(
676 "\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
677                     cmdarg_err_cont(
678 "or \"udoy\" for absolute UTC with YYYY/DOY date.");
679                     ret = INVALID_OPTION;
680                     goto clean_exit;
681                 }
682                 break;
683             case 'v':        /* Show version and exit */
684             {
685                 show_version();
686                 goto clean_exit;
687             }
688             default:
689             case '?':        /* Bad flag - print usage message */
690                 print_usage(stderr);
691                 ret = INVALID_OPTION;
692                 goto clean_exit;
693         }
694     }
695 
696     /* Notify all registered modules that have had any of their preferences
697        changed either from one of the preferences file or from the command
698        line that their preferences have changed.
699        Initialize preferences before display filters, otherwise modules
700        like MATE won't work. */
701     prefs_apply_all();
702 
703     /* Initialize our display fields */
704     for (fc = 0; fc < disp_fields->len; fc++) {
705         protocolinfo_init((char *)g_ptr_array_index(disp_fields, fc));
706     }
707     g_ptr_array_free(disp_fields, TRUE);
708     printf("\n");
709     fflush(stdout);
710 
711     /* If no capture filter or read filter has been specified, and there are
712        still command-line arguments, treat them as the tokens of a capture
713        filter (if no "-r" flag was specified) or a read filter (if a "-r"
714        flag was specified. */
715     if (ws_optind < argc) {
716         if (pipe_name != NULL) {
717             if (n_rfilters != 0) {
718                 cmdarg_err("Read filters were specified both with \"-R\" "
719                            "and with additional command-line arguments");
720                 ret = INVALID_OPTION;
721                 goto clean_exit;
722             }
723             rfilters[n_rfilters] = get_args_as_string(argc, argv, ws_optind);
724         }
725     }
726 
727     /* Make sure we got a dissector handle for our payload. */
728     if (encap == WTAP_ENCAP_UNKNOWN) {
729         cmdarg_err("No valid payload dissector specified.");
730         ret = INVALID_OPTION;
731         goto clean_exit;
732     }
733 
734     err_msg = ws_init_sockets();
735     if (err_msg != NULL)
736     {
737         cmdarg_err("%s", err_msg);
738         g_free(err_msg);
739         cmdarg_err_cont("%s", please_report_bug());
740         ret = INIT_FAILED;
741         goto clean_exit;
742     }
743 
744     /*
745      * Enabled and disabled protocols and heuristic dissectors as per
746      * command-line options.
747      */
748     setup_enabled_and_disabled_protocols();
749 
750     /* Build the column format array */
751     build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
752 
753     if (n_rfilters != 0) {
754         for (i = 0; i < n_rfilters; i++) {
755             if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &err_msg)) {
756                 cmdarg_err("%s", err_msg);
757                 g_free(err_msg);
758                 ret = INVALID_DFILTER;
759                 goto clean_exit;
760             }
761             n_rfcodes++;
762         }
763     }
764 
765     if (pipe_name) {
766         /*
767          * We're reading a pipe (or capture file).
768          */
769 
770         /*
771          * Immediately relinquish any special privileges we have; we must not
772          * be allowed to read any capture files the user running Rawshark
773          * can't open.
774          */
775         relinquish_special_privs_perm();
776 
777         if (raw_cf_open(&cfile, pipe_name) != CF_OK) {
778             ret = OPEN_ERROR;
779             goto clean_exit;
780         }
781 
782         /* Do we need to PCAP header and magic? */
783         if (skip_pcap_header) {
784             unsigned int bytes_left = (unsigned int) sizeof(struct pcap_hdr) + sizeof(guint32);
785             gchar buf[sizeof(struct pcap_hdr) + sizeof(guint32)];
786             while (bytes_left != 0) {
787                 ssize_t bytes = ws_read(fd, buf, bytes_left);
788                 if (bytes <= 0) {
789                     cmdarg_err("Not enough bytes for pcap header.");
790                     ret =  FORMAT_ERROR;
791                     goto clean_exit;
792                 }
793                 bytes_left -= (unsigned int)bytes;
794             }
795         }
796 
797         /* Process the packets in the file */
798         if (!load_cap_file(&cfile)) {
799             ret = OPEN_ERROR;
800             goto clean_exit;
801         }
802     } else {
803         /* If you want to capture live packets, use TShark. */
804         cmdarg_err("Input file or pipe name not specified.");
805         ret = OPEN_ERROR;
806         goto clean_exit;
807     }
808 
809 clean_exit:
810     g_free(pipe_name);
811     epan_free(cfile.epan);
812     epan_cleanup();
813     extcap_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
raw_pipe_read(wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info,gint64 * data_offset)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 = g_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
load_cap_file(capture_file * cf)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
process_packet(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,Buffer * buf)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 %" G_GUINT64_FORMAT " %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 
ftenum_to_string(header_field_info * hfi)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 
field_display_to_string(header_field_info * hfi,char * buf,int size)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         g_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)
print_field_value(field_info * finfo,int cmd_line_index)1116 static gboolean print_field_value(field_info *finfo, int cmd_line_index)
1117 {
1118     header_field_info   *hfinfo;
1119     char                *fs_buf = NULL;
1120     char                *fs_ptr = NULL;
1121     static GString     *label_s = NULL;
1122     int                 fs_len;
1123     guint              i;
1124     string_fmt_t       *sf;
1125     guint32            uvalue;
1126     gint32             svalue;
1127     guint64            uvalue64;
1128     gint64             svalue64;
1129     const true_false_string *tfstring = &tfs_true_false;
1130 
1131     hfinfo = finfo->hfinfo;
1132 
1133     if (!label_s) {
1134         label_s = g_string_new("");
1135     }
1136 
1137     if(finfo->value.ftype->val_to_string_repr)
1138     {
1139         /*
1140          * this field has an associated value,
1141          * e.g: ip.hdr_len
1142          */
1143         fs_len = fvalue_string_repr_len(&finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
1144         fs_buf = fvalue_to_string_repr(NULL, &finfo->value,
1145                               FTREPR_DFILTER, finfo->hfinfo->display);
1146         fs_ptr = fs_buf;
1147 
1148         /* String types are quoted. Remove them. */
1149         if (IS_FT_STRING(finfo->value.ftype->ftype) && fs_len > 2) {
1150             fs_buf[fs_len - 1] = '\0';
1151             fs_ptr++;
1152         }
1153     }
1154 
1155     if (string_fmts->len > 0 && finfo->hfinfo->strings) {
1156         g_string_truncate(label_s, 0);
1157         for (i = 0; i < string_fmts->len; i++) {
1158             sf = (string_fmt_t *)g_ptr_array_index(string_fmts, i);
1159             if (sf->plain) {
1160                 g_string_append(label_s, sf->plain);
1161             } else {
1162                 switch (sf->format) {
1163                     case SF_NAME:
1164                         g_string_append(label_s, hfinfo->name);
1165                         break;
1166                     case SF_NUMVAL:
1167                         g_string_append(label_s, fs_ptr);
1168                         break;
1169                     case SF_STRVAL:
1170                         switch(hfinfo->type) {
1171                             case FT_BOOLEAN:
1172                                 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1173                                 tfstring = (const true_false_string*) hfinfo->strings;
1174                                 g_string_append(label_s, tfs_get_string(!!uvalue64, tfstring));
1175                                 break;
1176                             case FT_INT8:
1177                             case FT_INT16:
1178                             case FT_INT24:
1179                             case FT_INT32:
1180                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1181                                 svalue = fvalue_get_sinteger(&finfo->value);
1182                                 if (hfinfo->display & BASE_RANGE_STRING) {
1183                                     g_string_append(label_s, rval_to_str_const(svalue, (const range_string *) hfinfo->strings, "Unknown"));
1184                                 } else if (hfinfo->display & BASE_EXT_STRING) {
1185                                     g_string_append(label_s, val_to_str_ext_const(svalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1186                                 } else {
1187                                     g_string_append(label_s, val_to_str_const(svalue, cVALS(hfinfo->strings), "Unknown"));
1188                                 }
1189                                 break;
1190                             case FT_INT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1191                             case FT_INT48:
1192                             case FT_INT56:
1193                             case FT_INT64:
1194                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1195                                 svalue64 = fvalue_get_sinteger64(&finfo->value);
1196                                 if (hfinfo->display & BASE_VAL64_STRING) {
1197                                     g_string_append(label_s, val64_to_str_const(svalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1198                                 }
1199                                 break;
1200                             case FT_UINT8:
1201                             case FT_UINT16:
1202                             case FT_UINT24:
1203                             case FT_UINT32:
1204                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1205                                 uvalue = fvalue_get_uinteger(&finfo->value);
1206                                 if (!hfinfo->bitmask && hfinfo->display & BASE_RANGE_STRING) {
1207                                     g_string_append(label_s, rval_to_str_const(uvalue, (const range_string *) hfinfo->strings, "Unknown"));
1208                                 } else if (hfinfo->display & BASE_EXT_STRING) {
1209                                     g_string_append(label_s, val_to_str_ext_const(uvalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1210                                 } else {
1211                                     g_string_append(label_s, val_to_str_const(uvalue, cVALS(hfinfo->strings), "Unknown"));
1212                                 }
1213                                 break;
1214                             case FT_UINT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1215                             case FT_UINT48:
1216                             case FT_UINT56:
1217                             case FT_UINT64:
1218                                 DISSECTOR_ASSERT(!hfinfo->bitmask);
1219                                 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1220                                 if (hfinfo->display & BASE_VAL64_STRING) {
1221                                     g_string_append(label_s, val64_to_str_const(uvalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1222                                 }
1223                                 break;
1224                             default:
1225                                 break;
1226                         }
1227                         break;
1228                     default:
1229                         break;
1230                 }
1231             }
1232         }
1233         printf(" %d=\"%s\"", cmd_line_index, label_s->str);
1234         wmem_free(NULL, fs_buf);
1235         return TRUE;
1236     }
1237 
1238     if(finfo->value.ftype->val_to_string_repr)
1239     {
1240         printf(" %d=\"%s\"", cmd_line_index, fs_ptr);
1241         wmem_free(NULL, fs_buf);
1242         return TRUE;
1243     }
1244 
1245     /*
1246      * This field doesn't have an associated value,
1247      * e.g. http
1248      * We return n.a.
1249      */
1250     printf(" %d=\"n.a.\"", cmd_line_index);
1251     return TRUE;
1252 }
1253 
1254 static tap_packet_status
protocolinfo_packet(void * prs,packet_info * pinfo _U_,epan_dissect_t * edt,const void * dummy _U_)1255 protocolinfo_packet(void *prs, packet_info *pinfo _U_, epan_dissect_t *edt, const void *dummy _U_)
1256 {
1257     pci_t *rs=(pci_t *)prs;
1258     GPtrArray *gp;
1259     guint i;
1260 
1261     gp=proto_get_finfo_ptr_array(edt->tree, rs->hf_index);
1262     if(!gp){
1263         printf(" n.a.");
1264         return TAP_PACKET_DONT_REDRAW;
1265     }
1266 
1267     /*
1268      * Print each occurrence of the field
1269      */
1270     for (i = 0; i < gp->len; i++) {
1271         print_field_value((field_info *)gp->pdata[i], rs->cmd_line_index);
1272     }
1273 
1274     return TAP_PACKET_DONT_REDRAW;
1275 }
1276 
1277 int g_cmd_line_index = 0;
1278 
1279 /*
1280  * field must be persistent - we don't g_strdup() it below
1281  */
1282 static void
protocolinfo_init(char * field)1283 protocolinfo_init(char *field)
1284 {
1285     pci_t *rs;
1286     header_field_info *hfi;
1287     GString *error_string;
1288     char hfibuf[100];
1289 
1290     hfi=proto_registrar_get_byname(field);
1291     if(!hfi){
1292         fprintf(stderr, "rawshark: Field \"%s\" doesn't exist.\n", field);
1293         exit(1);
1294     }
1295 
1296     field_display_to_string(hfi, hfibuf, sizeof(hfibuf));
1297     printf("%d %s %s - ",
1298             g_cmd_line_index,
1299             ftenum_to_string(hfi),
1300             hfibuf);
1301 
1302     rs=g_new(pci_t, 1);
1303     rs->hf_index=hfi->id;
1304     rs->filter=field;
1305     rs->cmd_line_index = g_cmd_line_index++;
1306 
1307     error_string=register_tap_listener("frame", rs, rs->filter, TL_REQUIRES_PROTO_TREE, NULL, protocolinfo_packet, NULL, NULL);
1308     if(error_string){
1309         /* error, we failed to attach to the tap. complain and clean up */
1310         fprintf(stderr, "rawshark: Couldn't register field extraction tap: %s\n",
1311                 error_string->str);
1312         g_string_free(error_string, TRUE);
1313         if(rs->filter){
1314             g_free(rs->filter);
1315         }
1316         g_free(rs);
1317 
1318         exit(1);
1319     }
1320 }
1321 
1322 /*
1323  * Given a format string, split it into a GPtrArray of string_fmt_t structs
1324  * and fill in string_fmt_parts.
1325  */
1326 
1327 static void
add_string_fmt(string_fmt_e format,gchar * plain)1328 add_string_fmt(string_fmt_e format, gchar *plain) {
1329     string_fmt_t *sf = g_new(string_fmt_t, 1);
1330 
1331     sf->format = format;
1332     sf->plain = g_strdup(plain);
1333 
1334     g_ptr_array_add(string_fmts, sf);
1335 }
1336 
1337 static gboolean
parse_field_string_format(gchar * format)1338 parse_field_string_format(gchar *format) {
1339     size_t len;
1340     size_t pos = 0;
1341 
1342     if (!format) {
1343         return FALSE;
1344     }
1345 
1346     GString *plain_s = g_string_new("");
1347 
1348     len = strlen(format);
1349     g_ptr_array_set_size(string_fmts, 0);
1350 
1351     while (pos < len) {
1352         if (format[pos] == '%') {
1353             if (pos >= (len-1)) { /* There should always be a following specifier character */
1354                 return FALSE;
1355             }
1356             pos++;
1357             if (plain_s->len > 0) {
1358                 add_string_fmt(SF_NONE, plain_s->str);
1359                 g_string_truncate(plain_s, 0);
1360             }
1361             switch (format[pos]) {
1362                 case 'D':
1363                     add_string_fmt(SF_NAME, NULL);
1364                     break;
1365                 case 'N':
1366                     add_string_fmt(SF_NUMVAL, NULL);
1367                     break;
1368                 case 'S':
1369                     add_string_fmt(SF_STRVAL, NULL);
1370                     break;
1371                 case '%':
1372                     g_string_append_c(plain_s, '%');
1373                     break;
1374                 default: /* Invalid format */
1375                     return FALSE;
1376             }
1377         } else {
1378             g_string_append_c(plain_s, format[pos]);
1379         }
1380         pos++;
1381     }
1382 
1383     if (plain_s->len > 0) {
1384         add_string_fmt(SF_NONE, plain_s->str);
1385     }
1386     g_string_free(plain_s, TRUE);
1387 
1388     return TRUE;
1389 }
1390 /****************************************************************************************
1391  * END OF FIELD EXTRACTION ROUTINES
1392  ****************************************************************************************/
1393 
1394 static void
show_print_file_io_error(int err)1395 show_print_file_io_error(int err)
1396 {
1397     switch (err) {
1398 
1399         case ENOSPC:
1400             cmdarg_err("Not all the packets could be printed because there is "
1401                        "no space left on the file system.");
1402             break;
1403 
1404 #ifdef EDQUOT
1405         case EDQUOT:
1406             cmdarg_err("Not all the packets could be printed because you are "
1407                        "too close to, or over your disk quota.");
1408             break;
1409 #endif
1410 
1411         default:
1412             cmdarg_err("An error occurred while printing packets: %s.",
1413                        g_strerror(err));
1414             break;
1415     }
1416 }
1417 
1418 static const nstime_t *
raw_get_frame_ts(struct packet_provider_data * prov,guint32 frame_num)1419 raw_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
1420 {
1421     if (prov->ref && prov->ref->num == frame_num)
1422         return &prov->ref->abs_ts;
1423 
1424     if (prov->prev_dis && prov->prev_dis->num == frame_num)
1425         return &prov->prev_dis->abs_ts;
1426 
1427     if (prov->prev_cap && prov->prev_cap->num == frame_num)
1428         return &prov->prev_cap->abs_ts;
1429 
1430     return NULL;
1431 }
1432 
1433 static epan_t *
raw_epan_new(capture_file * cf)1434 raw_epan_new(capture_file *cf)
1435 {
1436     static const struct packet_provider_funcs funcs = {
1437         raw_get_frame_ts,
1438         cap_file_provider_get_interface_name,
1439         cap_file_provider_get_interface_description,
1440         NULL,
1441     };
1442 
1443     return epan_new(&cf->provider, &funcs);
1444 }
1445 
1446 cf_status_t
raw_cf_open(capture_file * cf,const char * fname)1447 raw_cf_open(capture_file *cf, const char *fname)
1448 {
1449     if ((fd = raw_pipe_open(fname)) < 0)
1450         return CF_ERROR;
1451 
1452     /* The open succeeded.  Fill in the information for this file. */
1453 
1454     /* Create new epan session for dissection. */
1455     epan_free(cf->epan);
1456     cf->epan = raw_epan_new(cf);
1457 
1458     cf->provider.wth = NULL;
1459     cf->f_datalen = 0; /* not used, but set it anyway */
1460 
1461     /* Set the file name because we need it to set the follow stream filter.
1462        XXX - is that still true?  We need it for other reasons, though,
1463        in any case. */
1464     cf->filename = g_strdup(fname);
1465 
1466     /* Indicate whether it's a permanent or temporary file. */
1467     cf->is_tempfile = FALSE;
1468 
1469     /* No user changes yet. */
1470     cf->unsaved_changes = FALSE;
1471 
1472     cf->cd_t      = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
1473     cf->open_type = WTAP_TYPE_AUTO;
1474     cf->count     = 0;
1475     cf->drops_known = FALSE;
1476     cf->drops     = 0;
1477     cf->snap      = 0;
1478     nstime_set_zero(&cf->elapsed_time);
1479     cf->provider.ref = NULL;
1480     cf->provider.prev_dis = NULL;
1481     cf->provider.prev_cap = NULL;
1482 
1483     return CF_OK;
1484 }
1485 
1486 /*
1487  * Report an error in command-line arguments.
1488  */
1489 static void
rawshark_cmdarg_err(const char * fmt,va_list ap)1490 rawshark_cmdarg_err(const char *fmt, va_list ap)
1491 {
1492     fprintf(stderr, "rawshark: ");
1493     vfprintf(stderr, fmt, ap);
1494     fprintf(stderr, "\n");
1495 }
1496 
1497 /*
1498  * Report additional information for an error in command-line arguments.
1499  */
1500 static void
rawshark_cmdarg_err_cont(const char * fmt,va_list ap)1501 rawshark_cmdarg_err_cont(const char *fmt, va_list ap)
1502 {
1503     vfprintf(stderr, fmt, ap);
1504     fprintf(stderr, "\n");
1505 }
1506 
1507 /*
1508  * Editor modelines
1509  *
1510  * Local Variables:
1511  * c-basic-offset: 4
1512  * tab-width: 8
1513  * indent-tabs-mode: nil
1514  * End:
1515  *
1516  * ex: set shiftwidth=4 tabstop=8 expandtab:
1517  * :indentSize=4:tabSize=8:noTabs=true:
1518  */
1519