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