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