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