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