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