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