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 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15 /*
16 * Rawshark does the following:
17 * - Opens a specified file or named pipe
18 * - Applies a specfied DLT or "decode as" encapsulation
19 * - Reads frames prepended with a libpcap packet header.
20 * - Prints a status line, followed by fields from a specified list.
21 */
22
23 #include <config.h>
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <locale.h>
29 #include <limits.h>
30
31 #ifndef _WIN32
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #endif
35
36 #include <errno.h>
37
38 #include <wsutil/ws_getopt.h>
39
40 #include <glib.h>
41 #include <epan/epan.h>
42
43 #include <ui/cmdarg_err.h>
44 #include <ui/exit_codes.h>
45 #include <wsutil/filesystem.h>
46 #include <wsutil/file_util.h>
47 #include <wsutil/socket.h>
48 #include <wsutil/plugins.h>
49 #include <wsutil/privileges.h>
50 #include <wsutil/report_message.h>
51 #include <wsutil/please_report_bug.h>
52 #include <wsutil/wslog.h>
53 #include <ui/clopts_common.h>
54
55 #include "globals.h"
56 #include <epan/packet.h>
57 #include <epan/ftypes/ftypes-int.h>
58 #include "file.h"
59 #include "frame_tvbuff.h"
60 #include <epan/disabled_protos.h>
61 #include <epan/prefs.h>
62 #include <epan/column.h>
63 #include <epan/print.h>
64 #include <epan/addr_resolv.h>
65 #ifdef HAVE_LIBPCAP
66 #include "ui/capture_ui_utils.h"
67 #endif
68 #include "ui/util.h"
69 #include "ui/dissect_opts.h"
70 #include "ui/failure_message.h"
71 #include <epan/epan_dissect.h>
72 #include <epan/stat_tap_ui.h>
73 #include <epan/timestamp.h>
74 #include "epan/column-utils.h"
75 #include "epan/proto.h"
76 #include <epan/tap.h>
77
78 #include <wiretap/wtap.h>
79 #include <wiretap/libpcap.h>
80 #include <wiretap/pcap-encap.h>
81
82 #include <cli_main.h>
83 #include <ui/version_info.h>
84
85 #include "capture/capture-pcap-util.h"
86
87 #include "extcap.h"
88
89 #ifdef HAVE_LIBPCAP
90 #include <setjmp.h>
91 #ifdef _WIN32
92 #include "capture/capture-wpcap.h"
93 #endif /* _WIN32 */
94 #endif /* HAVE_LIBPCAP */
95
96 #if 0
97 /*
98 * This is the template for the decode as option; it is shared between the
99 * various functions that output the usage for this parameter.
100 */
101 static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
102 #endif
103
104 /* Additional exit codes */
105 #define INVALID_DFILTER 2
106 #define FORMAT_ERROR 2
107
108 capture_file cfile;
109
110 static guint32 cum_bytes;
111 static frame_data ref_frame;
112 static frame_data prev_dis_frame;
113 static frame_data prev_cap_frame;
114
115 /*
116 * The way the packet decode is to be written.
117 */
118 typedef enum {
119 WRITE_TEXT, /* summary or detail text */
120 WRITE_XML /* PDML or PSML */
121 /* Add CSV and the like here */
122 } output_action_e;
123
124 static gboolean line_buffered;
125 static print_format_e print_format = PR_FMT_TEXT;
126
127 static gboolean want_pcap_pkthdr;
128
129 cf_status_t raw_cf_open(capture_file *cf, const char *fname);
130 static gboolean load_cap_file(capture_file *cf);
131 static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
132 wtap_rec *rec, Buffer *buf);
133 static void show_print_file_io_error(int err);
134
135 static void rawshark_cmdarg_err(const char *fmt, va_list ap);
136 static void rawshark_cmdarg_err_cont(const char *fmt, va_list ap);
137 static void protocolinfo_init(char *field);
138 static gboolean parse_field_string_format(char *format);
139
140 typedef enum {
141 SF_NONE, /* No format (placeholder) */
142 SF_NAME, /* %D Field name / description */
143 SF_NUMVAL, /* %N Numeric value */
144 SF_STRVAL /* %S String value */
145 } string_fmt_e;
146
147 typedef struct string_fmt_s {
148 gchar *plain;
149 string_fmt_e format; /* Valid if plain is NULL */
150 } string_fmt_t;
151
152 int n_rfilters;
153 int n_rfcodes;
154 dfilter_t *rfcodes[64];
155 int n_rfieldfilters;
156 dfilter_t *rfieldfcodes[64];
157 int fd;
158 int encap;
159 GPtrArray *string_fmts;
160
161 static void
print_usage(FILE * output)162 print_usage(FILE *output)
163 {
164 fprintf(output, "\n");
165 fprintf(output, "Usage: rawshark [options] ...\n");
166 fprintf(output, "\n");
167
168 fprintf(output, "Input file:\n");
169 fprintf(output, " -r <infile> set the pipe or file name to read from\n");
170
171 fprintf(output, "\n");
172 fprintf(output, "Processing:\n");
173 fprintf(output, " -d <encap:linktype>|<proto:protoname>\n");
174 fprintf(output, " packet encapsulation or protocol\n");
175 fprintf(output, " -F <field> field to display\n");
176 #ifndef _WIN32
177 fprintf(output, " -m virtual memory limit, in bytes\n");
178 #endif
179 fprintf(output, " -n disable all name resolution (def: all enabled)\n");
180 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mnNtdv\"\n");
181 fprintf(output, " -p use the system's packet header format\n");
182 fprintf(output, " (which may have 64-bit timestamps)\n");
183 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
184 fprintf(output, " -s skip PCAP header on input\n");
185
186 fprintf(output, "\n");
187 fprintf(output, "Output:\n");
188 fprintf(output, " -l flush output after each packet\n");
189 fprintf(output, " -S format string for fields\n");
190 fprintf(output, " (%%D - name, %%S - stringval, %%N numval)\n");
191 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
192
193 ws_log_print_usage(output);
194
195 fprintf(output, "\n");
196 fprintf(output, "Miscellaneous:\n");
197 fprintf(output, " -h display this help and exit\n");
198 fprintf(output, " -o <name>:<value> ... override preference setting\n");
199 fprintf(output, " -v display version info and exit\n");
200 }
201
202 /**
203 * Open a pipe for raw input. This is a stripped-down version of
204 * pcap_loop.c:cap_pipe_open_live().
205 * We check if "pipe_name" is "-" (stdin) or a FIFO, and open it.
206 * @param pipe_name The name of the pipe or FIFO.
207 * @return A POSIX file descriptor on success, or -1 on failure.
208 */
209 static int
raw_pipe_open(const char * pipe_name)210 raw_pipe_open(const char *pipe_name)
211 {
212 #ifndef _WIN32
213 ws_statb64 pipe_stat;
214 #else
215 char *pncopy, *pos = NULL;
216 DWORD err;
217 wchar_t *err_str;
218 HANDLE hPipe = NULL;
219 #endif
220 int rfd;
221
222 ws_log(LOG_DOMAIN_CAPCHILD, LOG_LEVEL_DEBUG, "open_raw_pipe: %s", pipe_name);
223
224 /*
225 * XXX Rawshark blocks until we return
226 */
227 if (strcmp(pipe_name, "-") == 0) {
228 rfd = 0; /* read from stdin */
229 #ifdef _WIN32
230 /*
231 * This is needed to set the stdin pipe into binary mode, otherwise
232 * CR/LF are mangled...
233 */
234 _setmode(0, _O_BINARY);
235 #endif /* _WIN32 */
236 } else {
237 #ifndef _WIN32
238 if (ws_stat64(pipe_name, &pipe_stat) < 0) {
239 fprintf(stderr, "rawshark: The pipe %s could not be checked: %s\n",
240 pipe_name, g_strerror(errno));
241 return -1;
242 }
243 if (! S_ISFIFO(pipe_stat.st_mode)) {
244 if (S_ISCHR(pipe_stat.st_mode)) {
245 /*
246 * Assume the user specified an interface on a system where
247 * interfaces are in /dev. Pretend we haven't seen it.
248 */
249 } else
250 {
251 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
252 pipe_name);
253 }
254 return -1;
255 }
256 rfd = ws_open(pipe_name, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
257 if (rfd == -1) {
258 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
259 pipe_name, g_strerror(errno));
260 return -1;
261 }
262 #else /* _WIN32 */
263 #define PIPE_STR "\\pipe\\"
264 /* Under Windows, named pipes _must_ have the form
265 * "\\<server>\pipe\<pipe_name>". <server> may be "." for localhost.
266 */
267 pncopy = g_strdup(pipe_name);
268 if (strstr(pncopy, "\\\\") == pncopy) {
269 pos = strchr(pncopy + 3, '\\');
270 if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
271 pos = NULL;
272 }
273
274 g_free(pncopy);
275
276 if (!pos) {
277 fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
278 pipe_name);
279 return -1;
280 }
281
282 /* Wait for the pipe to appear */
283 while (1) {
284 hPipe = CreateFile(utf_8to16(pipe_name), GENERIC_READ, 0, NULL,
285 OPEN_EXISTING, 0, NULL);
286
287 if (hPipe != INVALID_HANDLE_VALUE)
288 break;
289
290 err = GetLastError();
291 if (err != ERROR_PIPE_BUSY) {
292 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
293 NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
294 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s (error %lu)\n",
295 pipe_name, utf_16to8(err_str), err);
296 LocalFree(err_str);
297 return -1;
298 }
299
300 if (!WaitNamedPipe(utf_8to16(pipe_name), 30 * 1000)) {
301 err = GetLastError();
302 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
303 NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
304 fprintf(stderr, "rawshark: \"%s\" could not be waited for: %s (error %lu)\n",
305 pipe_name, utf_16to8(err_str), err);
306 LocalFree(err_str);
307 return -1;
308 }
309 }
310
311 rfd = _open_osfhandle((intptr_t) hPipe, _O_RDONLY);
312 if (rfd == -1) {
313 fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
314 pipe_name, g_strerror(errno));
315 return -1;
316 }
317 #endif /* _WIN32 */
318 }
319
320 return rfd;
321 }
322
323 /**
324 * Parse a link-type argument of the form "encap:<pcap linktype>" or
325 * "proto:<proto name>". "Pcap linktype" must be a name conforming to
326 * pcap_datalink_name_to_val() or an integer; the integer should be
327 * a LINKTYPE_ value supported by Wiretap. "Proto name" must be
328 * a protocol name, e.g. "http".
329 */
330 static gboolean
set_link_type(const char * lt_arg)331 set_link_type(const char *lt_arg) {
332 char *spec_ptr = strchr(lt_arg, ':');
333 char *p;
334 int dlt_val;
335 long val;
336 dissector_handle_t dhandle;
337 GString *pref_str;
338 char *errmsg = NULL;
339
340 if (!spec_ptr)
341 return FALSE;
342
343 spec_ptr++;
344
345 if (strncmp(lt_arg, "encap:", strlen("encap:")) == 0) {
346 dlt_val = linktype_name_to_val(spec_ptr);
347 if (dlt_val == -1) {
348 errno = 0;
349 val = strtol(spec_ptr, &p, 10);
350 if (p == spec_ptr || *p != '\0' || errno != 0 || val > INT_MAX) {
351 return FALSE;
352 }
353 dlt_val = (int)val;
354 }
355 /*
356 * In those cases where a given link-layer header type
357 * has different LINKTYPE_ and DLT_ values, linktype_name_to_val()
358 * will return the OS's DLT_ value for that link-layer header
359 * type, not its OS-independent LINKTYPE_ value.
360 *
361 * On a given OS, wtap_pcap_encap_to_wtap_encap() should
362 * be able to map either LINKTYPE_ values or DLT_ values
363 * for the OS to the appropriate Wiretap encapsulation.
364 */
365 encap = wtap_pcap_encap_to_wtap_encap(dlt_val);
366 if (encap == WTAP_ENCAP_UNKNOWN) {
367 return FALSE;
368 }
369 return TRUE;
370 } else if (strncmp(lt_arg, "proto:", strlen("proto:")) == 0) {
371 dhandle = find_dissector(spec_ptr);
372 if (dhandle) {
373 encap = WTAP_ENCAP_USER0;
374 pref_str = g_string_new("uat:user_dlts:");
375 /* This must match the format used in the user_dlts file */
376 g_string_append_printf(pref_str,
377 "\"User 0 (DLT=147)\",\"%s\",\"0\",\"\",\"0\",\"\"",
378 spec_ptr);
379 if (prefs_set_pref(pref_str->str, &errmsg) != PREFS_SET_OK) {
380 g_string_free(pref_str, TRUE);
381 g_free(errmsg);
382 return FALSE;
383 }
384 g_string_free(pref_str, TRUE);
385 return TRUE;
386 }
387 }
388 return FALSE;
389 }
390
391 int
main(int argc,char * argv[])392 main(int argc, char *argv[])
393 {
394 char *err_msg;
395 int opt, i;
396
397 #ifndef _WIN32
398 struct rlimit limit;
399 #endif /* !_WIN32 */
400
401 gchar *pipe_name = NULL;
402 gchar *rfilters[64];
403 e_prefs *prefs_p;
404 char badopt;
405 GPtrArray *disp_fields = g_ptr_array_new();
406 guint fc;
407 gboolean skip_pcap_header = FALSE;
408 int ret = EXIT_SUCCESS;
409 static const struct ws_option long_options[] = {
410 {"help", ws_no_argument, NULL, 'h'},
411 {"version", ws_no_argument, NULL, 'v'},
412 {0, 0, 0, 0 }
413 };
414
415 #define OPTSTRING_INIT "d:F:hlm:nN:o:pr:R:sS:t:v"
416
417 static const char optstring[] = OPTSTRING_INIT;
418 static const struct report_message_routines rawshark_report_routines = {
419 failure_message,
420 failure_message,
421 open_failure_message,
422 read_failure_message,
423 write_failure_message,
424 cfile_open_failure_message,
425 cfile_dump_open_failure_message,
426 cfile_read_failure_message,
427 cfile_write_failure_message,
428 cfile_close_failure_message
429 };
430
431 /*
432 * Set the C-language locale to the native environment and set the
433 * code page to UTF-8 on Windows.
434 */
435 #ifdef _WIN32
436 setlocale(LC_ALL, ".UTF-8");
437 #else
438 setlocale(LC_ALL, "");
439 #endif
440
441 cmdarg_err_init(rawshark_cmdarg_err, rawshark_cmdarg_err_cont);
442
443 /* Initialize log handler early so we can have proper logging during startup. */
444 ws_log_init("rawshark", vcmdarg_err);
445
446 /* Early logging command-line initialization. */
447 ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
448
449 /* Initialize the version information. */
450 ws_init_version_info("Rawshark (Wireshark)", NULL,
451 epan_get_compiled_version_info,
452 NULL);
453
454 #ifdef _WIN32
455 create_app_running_mutex();
456 #endif /* _WIN32 */
457
458 /*
459 * Get credential information for later use.
460 */
461 init_process_policies();
462
463 /*
464 * Clear the filters arrays
465 */
466 memset(rfilters, 0, sizeof(rfilters));
467 memset(rfcodes, 0, sizeof(rfcodes));
468 n_rfilters = 0;
469 n_rfcodes = 0;
470
471 /*
472 * Initialize our string format
473 */
474 string_fmts = g_ptr_array_new();
475
476 /*
477 * Attempt to get the pathname of the directory containing the
478 * executable file.
479 */
480 err_msg = init_progfile_dir(argv[0]);
481 if (err_msg != NULL) {
482 fprintf(stderr, "rawshark: Can't get pathname of rawshark program: %s.\n",
483 err_msg);
484 }
485
486 init_report_message("rawshark", &rawshark_report_routines);
487
488 timestamp_set_type(TS_RELATIVE);
489 timestamp_set_precision(TS_PREC_AUTO);
490 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
491
492 /*
493 * XXX - is this necessary, given that we're not reading a
494 * regular capture file, we're reading rawshark's packet
495 * stream format?
496 *
497 * If it is, note that libwiretap must be initialized before
498 * libwireshark is, so that dissection-time handlers for
499 * file-type-dependent blocks can register using the file
500 * type/subtype value for the file type.
501 */
502 wtap_init(FALSE);
503
504 /* Register all dissectors; we must do this before checking for the
505 "-G" flag, as the "-G" flag dumps information registered by the
506 dissectors, and we must do it before we read the preferences, in
507 case any dissectors register preferences. */
508 if (!epan_init(NULL, NULL, TRUE)) {
509 ret = INIT_FAILED;
510 goto clean_exit;
511 }
512
513 /* Load libwireshark settings from the current profile. */
514 prefs_p = epan_load_settings();
515
516 #ifdef _WIN32
517 ws_init_dll_search_path();
518 /* Load Wpcap, if possible */
519 load_wpcap();
520 #endif
521
522 cap_file_init(&cfile);
523
524 /* Print format defaults to this. */
525 print_format = PR_FMT_TEXT;
526
527 /* Initialize our encapsulation type */
528 encap = WTAP_ENCAP_UNKNOWN;
529
530 /* Now get our args */
531 /* XXX - We should probably have an option to dump libpcap link types */
532 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
533 switch (opt) {
534 case 'd': /* Payload type */
535 if (!set_link_type(ws_optarg)) {
536 cmdarg_err("Invalid link type or protocol \"%s\"", ws_optarg);
537 ret = INVALID_OPTION;
538 goto clean_exit;
539 }
540 break;
541 case 'F': /* Read field to display */
542 g_ptr_array_add(disp_fields, g_strdup(ws_optarg));
543 break;
544 case 'h': /* Print help and exit */
545 show_help_header("Dump and analyze network traffic.");
546 print_usage(stdout);
547 goto clean_exit;
548 break;
549 case 'l': /* "Line-buffer" standard output */
550 /* This isn't line-buffering, strictly speaking, it's just
551 flushing the standard output after the information for
552 each packet is printed; however, that should be good
553 enough for all the purposes to which "-l" is put (and
554 is probably actually better for "-V", as it does fewer
555 writes).
556
557 See the comment in "process_packet()" for an explanation of
558 why we do that, and why we don't just use "setvbuf()" to
559 make the standard output line-buffered (short version: in
560 Windows, "line-buffered" is the same as "fully-buffered",
561 and the output buffer is only flushed when it fills up). */
562 line_buffered = TRUE;
563 break;
564 #ifndef _WIN32
565 case 'm':
566 limit.rlim_cur = get_positive_int(ws_optarg, "memory limit");
567 limit.rlim_max = get_positive_int(ws_optarg, "memory limit");
568
569 if(setrlimit(RLIMIT_AS, &limit) != 0) {
570 cmdarg_err("setrlimit() returned error");
571 ret = INVALID_OPTION;
572 goto clean_exit;
573 }
574 break;
575 #endif
576 case 'n': /* No name resolution */
577 disable_name_resolution();
578 break;
579 case 'N': /* Select what types of addresses/port #s to resolve */
580 badopt = string_to_name_resolve(ws_optarg, &gbl_resolv_flags);
581 if (badopt != '\0') {
582 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'd', m', 'n', 'N', and 't'",
583 badopt);
584 ret = INVALID_OPTION;
585 goto clean_exit;
586 }
587 break;
588 case 'o': /* Override preference from command line */
589 {
590 char *errmsg = NULL;
591
592 switch (prefs_set_pref(ws_optarg, &errmsg)) {
593
594 case PREFS_SET_OK:
595 break;
596
597 case PREFS_SET_SYNTAX_ERR:
598 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
599 errmsg ? ": " : "", errmsg ? errmsg : "");
600 g_free(errmsg);
601 ret = INVALID_OPTION;
602 goto clean_exit;
603 break;
604
605 case PREFS_SET_NO_SUCH_PREF:
606 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
607 ret = INVALID_OPTION;
608 goto clean_exit;
609 break;
610
611 case PREFS_SET_OBSOLETE:
612 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
613 ret = INVALID_OPTION;
614 goto clean_exit;
615 break;
616 }
617 break;
618 }
619 case 'p': /* Expect pcap_pkthdr packet headers, which may have 64-bit timestamps */
620 want_pcap_pkthdr = TRUE;
621 break;
622 case 'r': /* Read capture file xxx */
623 pipe_name = g_strdup(ws_optarg);
624 break;
625 case 'R': /* Read file filter */
626 if(n_rfilters < (int) sizeof(rfilters) / (int) sizeof(rfilters[0])) {
627 rfilters[n_rfilters++] = ws_optarg;
628 }
629 else {
630 cmdarg_err("Too many display filters");
631 ret = INVALID_OPTION;
632 goto clean_exit;
633 }
634 break;
635 case 's': /* Skip PCAP header */
636 skip_pcap_header = TRUE;
637 break;
638 case 'S': /* Print string representations */
639 if (!parse_field_string_format(ws_optarg)) {
640 cmdarg_err("Invalid field string format");
641 ret = INVALID_OPTION;
642 goto clean_exit;
643 }
644 break;
645 case 't': /* Time stamp type */
646 if (strcmp(ws_optarg, "r") == 0)
647 timestamp_set_type(TS_RELATIVE);
648 else if (strcmp(ws_optarg, "a") == 0)
649 timestamp_set_type(TS_ABSOLUTE);
650 else if (strcmp(ws_optarg, "ad") == 0)
651 timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
652 else if (strcmp(ws_optarg, "adoy") == 0)
653 timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
654 else if (strcmp(ws_optarg, "d") == 0)
655 timestamp_set_type(TS_DELTA);
656 else if (strcmp(ws_optarg, "dd") == 0)
657 timestamp_set_type(TS_DELTA_DIS);
658 else if (strcmp(ws_optarg, "e") == 0)
659 timestamp_set_type(TS_EPOCH);
660 else if (strcmp(ws_optarg, "u") == 0)
661 timestamp_set_type(TS_UTC);
662 else if (strcmp(ws_optarg, "ud") == 0)
663 timestamp_set_type(TS_UTC_WITH_YMD);
664 else if (strcmp(ws_optarg, "udoy") == 0)
665 timestamp_set_type(TS_UTC_WITH_YDOY);
666 else {
667 cmdarg_err("Invalid time stamp type \"%s\"",
668 ws_optarg);
669 cmdarg_err_cont(
670 "It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
671 cmdarg_err_cont(
672 "\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
673 cmdarg_err_cont(
674 "\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
675 cmdarg_err_cont(
676 "\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
677 cmdarg_err_cont(
678 "or \"udoy\" for absolute UTC with YYYY/DOY date.");
679 ret = INVALID_OPTION;
680 goto clean_exit;
681 }
682 break;
683 case 'v': /* Show version and exit */
684 {
685 show_version();
686 goto clean_exit;
687 }
688 default:
689 case '?': /* Bad flag - print usage message */
690 print_usage(stderr);
691 ret = INVALID_OPTION;
692 goto clean_exit;
693 }
694 }
695
696 /* Notify all registered modules that have had any of their preferences
697 changed either from one of the preferences file or from the command
698 line that their preferences have changed.
699 Initialize preferences before display filters, otherwise modules
700 like MATE won't work. */
701 prefs_apply_all();
702
703 /* Initialize our display fields */
704 for (fc = 0; fc < disp_fields->len; fc++) {
705 protocolinfo_init((char *)g_ptr_array_index(disp_fields, fc));
706 }
707 g_ptr_array_free(disp_fields, TRUE);
708 printf("\n");
709 fflush(stdout);
710
711 /* If no capture filter or read filter has been specified, and there are
712 still command-line arguments, treat them as the tokens of a capture
713 filter (if no "-r" flag was specified) or a read filter (if a "-r"
714 flag was specified. */
715 if (ws_optind < argc) {
716 if (pipe_name != NULL) {
717 if (n_rfilters != 0) {
718 cmdarg_err("Read filters were specified both with \"-R\" "
719 "and with additional command-line arguments");
720 ret = INVALID_OPTION;
721 goto clean_exit;
722 }
723 rfilters[n_rfilters] = get_args_as_string(argc, argv, ws_optind);
724 }
725 }
726
727 /* Make sure we got a dissector handle for our payload. */
728 if (encap == WTAP_ENCAP_UNKNOWN) {
729 cmdarg_err("No valid payload dissector specified.");
730 ret = INVALID_OPTION;
731 goto clean_exit;
732 }
733
734 err_msg = ws_init_sockets();
735 if (err_msg != NULL)
736 {
737 cmdarg_err("%s", err_msg);
738 g_free(err_msg);
739 cmdarg_err_cont("%s", please_report_bug());
740 ret = INIT_FAILED;
741 goto clean_exit;
742 }
743
744 /*
745 * Enabled and disabled protocols and heuristic dissectors as per
746 * command-line options.
747 */
748 setup_enabled_and_disabled_protocols();
749
750 /* Build the column format array */
751 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
752
753 if (n_rfilters != 0) {
754 for (i = 0; i < n_rfilters; i++) {
755 if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &err_msg)) {
756 cmdarg_err("%s", err_msg);
757 g_free(err_msg);
758 ret = INVALID_DFILTER;
759 goto clean_exit;
760 }
761 n_rfcodes++;
762 }
763 }
764
765 if (pipe_name) {
766 /*
767 * We're reading a pipe (or capture file).
768 */
769
770 /*
771 * Immediately relinquish any special privileges we have; we must not
772 * be allowed to read any capture files the user running Rawshark
773 * can't open.
774 */
775 relinquish_special_privs_perm();
776
777 if (raw_cf_open(&cfile, pipe_name) != CF_OK) {
778 ret = OPEN_ERROR;
779 goto clean_exit;
780 }
781
782 /* Do we need to PCAP header and magic? */
783 if (skip_pcap_header) {
784 unsigned int bytes_left = (unsigned int) sizeof(struct pcap_hdr) + sizeof(guint32);
785 gchar buf[sizeof(struct pcap_hdr) + sizeof(guint32)];
786 while (bytes_left != 0) {
787 ssize_t bytes = ws_read(fd, buf, bytes_left);
788 if (bytes <= 0) {
789 cmdarg_err("Not enough bytes for pcap header.");
790 ret = FORMAT_ERROR;
791 goto clean_exit;
792 }
793 bytes_left -= (unsigned int)bytes;
794 }
795 }
796
797 /* Process the packets in the file */
798 if (!load_cap_file(&cfile)) {
799 ret = OPEN_ERROR;
800 goto clean_exit;
801 }
802 } else {
803 /* If you want to capture live packets, use TShark. */
804 cmdarg_err("Input file or pipe name not specified.");
805 ret = OPEN_ERROR;
806 goto clean_exit;
807 }
808
809 clean_exit:
810 g_free(pipe_name);
811 epan_free(cfile.epan);
812 epan_cleanup();
813 extcap_cleanup();
814 wtap_cleanup();
815 return ret;
816 }
817
818 /**
819 * Read data from a raw pipe. The "raw" data consists of a libpcap
820 * packet header followed by the payload.
821 * @param buf [IN] A POSIX file descriptor. Because that's _exactly_ the sort
822 * of thing you want to use in Windows.
823 * @param err [OUT] Error indicator. Uses wiretap values.
824 * @param err_info [OUT] Error message.
825 * @param data_offset [OUT] data offset in the pipe.
826 * @return TRUE on success, FALSE on failure.
827 */
828 static gboolean
raw_pipe_read(wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info,gint64 * data_offset)829 raw_pipe_read(wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset) {
830 struct pcap_pkthdr mem_hdr;
831 struct pcaprec_hdr disk_hdr;
832 ssize_t bytes_read = 0;
833 unsigned int bytes_needed = (unsigned int) sizeof(disk_hdr);
834 guchar *ptr = (guchar*) &disk_hdr;
835
836 *err = 0;
837
838 if (want_pcap_pkthdr) {
839 bytes_needed = sizeof(mem_hdr);
840 ptr = (guchar*) &mem_hdr;
841 }
842
843 /*
844 * Newer versions of the VC runtime do parameter validation. If stdin
845 * has been closed, calls to _read, _get_osfhandle, et al will trigger
846 * the invalid parameter handler and crash.
847 * We could alternatively use ReadFile or set an invalid parameter
848 * handler.
849 * We could also tell callers not to close stdin prematurely.
850 */
851 #ifdef _WIN32
852 DWORD ghi_flags;
853 if (fd == 0 && GetHandleInformation(GetStdHandle(STD_INPUT_HANDLE), &ghi_flags) == 0) {
854 *err = 0;
855 *err_info = NULL;
856 return FALSE;
857 }
858 #endif
859
860 /* Copied from capture_loop.c */
861 while (bytes_needed > 0) {
862 bytes_read = ws_read(fd, ptr, bytes_needed);
863 if (bytes_read == 0) {
864 *err = 0;
865 *err_info = NULL;
866 return FALSE;
867 } else if (bytes_read < 0) {
868 *err = errno;
869 *err_info = NULL;
870 return FALSE;
871 }
872 bytes_needed -= (unsigned int)bytes_read;
873 *data_offset += bytes_read;
874 ptr += bytes_read;
875 }
876
877 rec->rec_type = REC_TYPE_PACKET;
878 rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
879 if (want_pcap_pkthdr) {
880 rec->ts.secs = mem_hdr.ts.tv_sec;
881 rec->ts.nsecs = (gint32)mem_hdr.ts.tv_usec * 1000;
882 rec->rec_header.packet_header.caplen = mem_hdr.caplen;
883 rec->rec_header.packet_header.len = mem_hdr.len;
884 } else {
885 rec->ts.secs = disk_hdr.ts_sec;
886 rec->ts.nsecs = disk_hdr.ts_usec * 1000;
887 rec->rec_header.packet_header.caplen = disk_hdr.incl_len;
888 rec->rec_header.packet_header.len = disk_hdr.orig_len;
889 }
890 bytes_needed = rec->rec_header.packet_header.caplen;
891
892 rec->rec_header.packet_header.pkt_encap = encap;
893
894 #if 0
895 printf("mem_hdr: %lu disk_hdr: %lu\n", sizeof(mem_hdr), sizeof(disk_hdr));
896 printf("tv_sec: %d (%04x)\n", (unsigned int) rec->ts.secs, (unsigned int) rec->ts.secs);
897 printf("tv_nsec: %d (%04x)\n", rec->ts.nsecs, rec->ts.nsecs);
898 printf("caplen: %d (%04x)\n", rec->rec_header.packet_header.caplen, rec->rec_header.packet_header.caplen);
899 printf("len: %d (%04x)\n", rec->rec_header.packet_header.len, rec->rec_header.packet_header.len);
900 #endif
901 if (bytes_needed > WTAP_MAX_PACKET_SIZE_STANDARD) {
902 *err = WTAP_ERR_BAD_FILE;
903 *err_info = g_strdup_printf("Bad packet length: %lu",
904 (unsigned long) bytes_needed);
905 return FALSE;
906 }
907
908 ws_buffer_assure_space(buf, bytes_needed);
909 ptr = ws_buffer_start_ptr(buf);
910 while (bytes_needed > 0) {
911 bytes_read = ws_read(fd, ptr, bytes_needed);
912 if (bytes_read == 0) {
913 *err = WTAP_ERR_SHORT_READ;
914 *err_info = NULL;
915 return FALSE;
916 } else if (bytes_read < 0) {
917 *err = errno;
918 *err_info = NULL;
919 return FALSE;
920 }
921 bytes_needed -= (unsigned int)bytes_read;
922 *data_offset += bytes_read;
923 ptr += bytes_read;
924 }
925 return TRUE;
926 }
927
928 static gboolean
load_cap_file(capture_file * cf)929 load_cap_file(capture_file *cf)
930 {
931 int err;
932 gchar *err_info = NULL;
933 gint64 data_offset = 0;
934
935 wtap_rec rec;
936 Buffer buf;
937 epan_dissect_t edt;
938
939 wtap_rec_init(&rec);
940 ws_buffer_init(&buf, 1514);
941
942 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
943
944 while (raw_pipe_read(&rec, &buf, &err, &err_info, &data_offset)) {
945 process_packet(cf, &edt, data_offset, &rec, &buf);
946 }
947
948 epan_dissect_cleanup(&edt);
949
950 wtap_rec_cleanup(&rec);
951 ws_buffer_free(&buf);
952 if (err != 0) {
953 /* Print a message noting that the read failed somewhere along the line. */
954 cfile_read_failure_message(cf->filename, err, err_info);
955 return FALSE;
956 }
957
958 return TRUE;
959 }
960
961 static gboolean
process_packet(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,Buffer * buf)962 process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
963 wtap_rec *rec, Buffer *buf)
964 {
965 frame_data fdata;
966 gboolean passed;
967 int i;
968
969 if(rec->rec_header.packet_header.len == 0)
970 {
971 /* The user sends an empty packet when he wants to get output from us even if we don't currently have
972 packets to process. We spit out a line with the timestamp and the text "void"
973 */
974 printf("%lu %" G_GUINT64_FORMAT " %d void -\n", (unsigned long int)cf->count,
975 (guint64)rec->ts.secs, rec->ts.nsecs);
976
977 fflush(stdout);
978
979 return FALSE;
980 }
981
982 /* Count this packet. */
983 cf->count++;
984
985 /* If we're going to print packet information, or we're going to
986 run a read filter, or we're going to process taps, set up to
987 do a dissection and do so. */
988 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
989
990 passed = TRUE;
991
992 /* If we're running a read filter, prime the epan_dissect_t with that
993 filter. */
994 if (n_rfilters > 0) {
995 for(i = 0; i < n_rfcodes; i++) {
996 epan_dissect_prime_with_dfilter(edt, rfcodes[i]);
997 }
998 }
999
1000 printf("%lu", (unsigned long int) cf->count);
1001
1002 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1003 &cf->provider.ref, cf->provider.prev_dis);
1004
1005 if (cf->provider.ref == &fdata) {
1006 ref_frame = fdata;
1007 cf->provider.ref = &ref_frame;
1008 }
1009
1010 /* We only need the columns if we're printing packet info but we're
1011 *not* verbose; in verbose mode, we print the protocol tree, not
1012 the protocol summary. */
1013 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1014 frame_tvbuff_new_buffer(&cf->provider, &fdata, buf),
1015 &fdata, &cf->cinfo);
1016
1017 frame_data_set_after_dissect(&fdata, &cum_bytes);
1018 prev_dis_frame = fdata;
1019 cf->provider.prev_dis = &prev_dis_frame;
1020
1021 prev_cap_frame = fdata;
1022 cf->provider.prev_cap = &prev_cap_frame;
1023
1024 for(i = 0; i < n_rfilters; i++) {
1025 /* Run the read filter if we have one. */
1026 if (rfcodes[i])
1027 passed = dfilter_apply_edt(rfcodes[i], edt);
1028 else
1029 passed = TRUE;
1030
1031 /* Print a one-line summary */
1032 printf(" %d", passed ? 1 : 0);
1033 }
1034
1035 printf(" -\n");
1036
1037 /* The ANSI C standard does not appear to *require* that a line-buffered
1038 stream be flushed to the host environment whenever a newline is
1039 written, it just says that, on such a stream, characters "are
1040 intended to be transmitted to or from the host environment as a
1041 block when a new-line character is encountered".
1042
1043 The Visual C++ 6.0 C implementation doesn't do what is intended;
1044 even if you set a stream to be line-buffered, it still doesn't
1045 flush the buffer at the end of every line.
1046
1047 So, if the "-l" flag was specified, we flush the standard output
1048 at the end of a packet. This will do the right thing if we're
1049 printing packet summary lines, and, as we print the entire protocol
1050 tree for a single packet without waiting for anything to happen,
1051 it should be as good as line-buffered mode if we're printing
1052 protocol trees. (The whole reason for the "-l" flag in either
1053 tcpdump or Rawshark is to allow the output of a live capture to
1054 be piped to a program or script and to have that script see the
1055 information for the packet as soon as it's printed, rather than
1056 having to wait until a standard I/O buffer fills up. */
1057 if (line_buffered)
1058 fflush(stdout);
1059
1060 if (ferror(stdout)) {
1061 show_print_file_io_error(errno);
1062 exit(2);
1063 }
1064
1065 epan_dissect_reset(edt);
1066 frame_data_destroy(&fdata);
1067
1068 return passed;
1069 }
1070
1071 /****************************************************************************************
1072 * FIELD EXTRACTION ROUTINES
1073 ****************************************************************************************/
1074 typedef struct _pci_t {
1075 char *filter;
1076 int hf_index;
1077 int cmd_line_index;
1078 } pci_t;
1079
ftenum_to_string(header_field_info * hfi)1080 static const char* ftenum_to_string(header_field_info *hfi)
1081 {
1082 const char* str;
1083 if (!hfi) {
1084 return "n.a.";
1085 }
1086
1087 if (string_fmts->len > 0 && hfi->strings) {
1088 return "FT_STRING";
1089 }
1090
1091 str = ftype_name(hfi->type);
1092 if (str == NULL) {
1093 str = "n.a.";
1094 }
1095
1096 return str;
1097 }
1098
field_display_to_string(header_field_info * hfi,char * buf,int size)1099 static void field_display_to_string(header_field_info *hfi, char* buf, int size)
1100 {
1101 if (hfi->type != FT_BOOLEAN)
1102 {
1103 (void) g_strlcpy(buf, proto_field_display_to_string(hfi->display), size);
1104 }
1105 else
1106 {
1107 g_snprintf(buf, size, "(Bit count: %d)", hfi->display);
1108 }
1109 }
1110
1111 /*
1112 * Copied from various parts of proto.c
1113 */
1114 #define FIELD_STR_INIT_LEN 256
1115 #define cVALS(x) (const value_string*)(x)
print_field_value(field_info * finfo,int cmd_line_index)1116 static gboolean print_field_value(field_info *finfo, int cmd_line_index)
1117 {
1118 header_field_info *hfinfo;
1119 char *fs_buf = NULL;
1120 char *fs_ptr = NULL;
1121 static GString *label_s = NULL;
1122 int fs_len;
1123 guint i;
1124 string_fmt_t *sf;
1125 guint32 uvalue;
1126 gint32 svalue;
1127 guint64 uvalue64;
1128 gint64 svalue64;
1129 const true_false_string *tfstring = &tfs_true_false;
1130
1131 hfinfo = finfo->hfinfo;
1132
1133 if (!label_s) {
1134 label_s = g_string_new("");
1135 }
1136
1137 if(finfo->value.ftype->val_to_string_repr)
1138 {
1139 /*
1140 * this field has an associated value,
1141 * e.g: ip.hdr_len
1142 */
1143 fs_len = fvalue_string_repr_len(&finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
1144 fs_buf = fvalue_to_string_repr(NULL, &finfo->value,
1145 FTREPR_DFILTER, finfo->hfinfo->display);
1146 fs_ptr = fs_buf;
1147
1148 /* String types are quoted. Remove them. */
1149 if (IS_FT_STRING(finfo->value.ftype->ftype) && fs_len > 2) {
1150 fs_buf[fs_len - 1] = '\0';
1151 fs_ptr++;
1152 }
1153 }
1154
1155 if (string_fmts->len > 0 && finfo->hfinfo->strings) {
1156 g_string_truncate(label_s, 0);
1157 for (i = 0; i < string_fmts->len; i++) {
1158 sf = (string_fmt_t *)g_ptr_array_index(string_fmts, i);
1159 if (sf->plain) {
1160 g_string_append(label_s, sf->plain);
1161 } else {
1162 switch (sf->format) {
1163 case SF_NAME:
1164 g_string_append(label_s, hfinfo->name);
1165 break;
1166 case SF_NUMVAL:
1167 g_string_append(label_s, fs_ptr);
1168 break;
1169 case SF_STRVAL:
1170 switch(hfinfo->type) {
1171 case FT_BOOLEAN:
1172 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1173 tfstring = (const true_false_string*) hfinfo->strings;
1174 g_string_append(label_s, tfs_get_string(!!uvalue64, tfstring));
1175 break;
1176 case FT_INT8:
1177 case FT_INT16:
1178 case FT_INT24:
1179 case FT_INT32:
1180 DISSECTOR_ASSERT(!hfinfo->bitmask);
1181 svalue = fvalue_get_sinteger(&finfo->value);
1182 if (hfinfo->display & BASE_RANGE_STRING) {
1183 g_string_append(label_s, rval_to_str_const(svalue, (const range_string *) hfinfo->strings, "Unknown"));
1184 } else if (hfinfo->display & BASE_EXT_STRING) {
1185 g_string_append(label_s, val_to_str_ext_const(svalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1186 } else {
1187 g_string_append(label_s, val_to_str_const(svalue, cVALS(hfinfo->strings), "Unknown"));
1188 }
1189 break;
1190 case FT_INT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1191 case FT_INT48:
1192 case FT_INT56:
1193 case FT_INT64:
1194 DISSECTOR_ASSERT(!hfinfo->bitmask);
1195 svalue64 = fvalue_get_sinteger64(&finfo->value);
1196 if (hfinfo->display & BASE_VAL64_STRING) {
1197 g_string_append(label_s, val64_to_str_const(svalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1198 }
1199 break;
1200 case FT_UINT8:
1201 case FT_UINT16:
1202 case FT_UINT24:
1203 case FT_UINT32:
1204 DISSECTOR_ASSERT(!hfinfo->bitmask);
1205 uvalue = fvalue_get_uinteger(&finfo->value);
1206 if (!hfinfo->bitmask && hfinfo->display & BASE_RANGE_STRING) {
1207 g_string_append(label_s, rval_to_str_const(uvalue, (const range_string *) hfinfo->strings, "Unknown"));
1208 } else if (hfinfo->display & BASE_EXT_STRING) {
1209 g_string_append(label_s, val_to_str_ext_const(uvalue, (value_string_ext *) hfinfo->strings, "Unknown"));
1210 } else {
1211 g_string_append(label_s, val_to_str_const(uvalue, cVALS(hfinfo->strings), "Unknown"));
1212 }
1213 break;
1214 case FT_UINT40: /* XXX: Shouldn't these be as smart as FT_INT{8,16,24,32}? */
1215 case FT_UINT48:
1216 case FT_UINT56:
1217 case FT_UINT64:
1218 DISSECTOR_ASSERT(!hfinfo->bitmask);
1219 uvalue64 = fvalue_get_uinteger64(&finfo->value);
1220 if (hfinfo->display & BASE_VAL64_STRING) {
1221 g_string_append(label_s, val64_to_str_const(uvalue64, (const val64_string *)(hfinfo->strings), "Unknown"));
1222 }
1223 break;
1224 default:
1225 break;
1226 }
1227 break;
1228 default:
1229 break;
1230 }
1231 }
1232 }
1233 printf(" %d=\"%s\"", cmd_line_index, label_s->str);
1234 wmem_free(NULL, fs_buf);
1235 return TRUE;
1236 }
1237
1238 if(finfo->value.ftype->val_to_string_repr)
1239 {
1240 printf(" %d=\"%s\"", cmd_line_index, fs_ptr);
1241 wmem_free(NULL, fs_buf);
1242 return TRUE;
1243 }
1244
1245 /*
1246 * This field doesn't have an associated value,
1247 * e.g. http
1248 * We return n.a.
1249 */
1250 printf(" %d=\"n.a.\"", cmd_line_index);
1251 return TRUE;
1252 }
1253
1254 static tap_packet_status
protocolinfo_packet(void * prs,packet_info * pinfo _U_,epan_dissect_t * edt,const void * dummy _U_)1255 protocolinfo_packet(void *prs, packet_info *pinfo _U_, epan_dissect_t *edt, const void *dummy _U_)
1256 {
1257 pci_t *rs=(pci_t *)prs;
1258 GPtrArray *gp;
1259 guint i;
1260
1261 gp=proto_get_finfo_ptr_array(edt->tree, rs->hf_index);
1262 if(!gp){
1263 printf(" n.a.");
1264 return TAP_PACKET_DONT_REDRAW;
1265 }
1266
1267 /*
1268 * Print each occurrence of the field
1269 */
1270 for (i = 0; i < gp->len; i++) {
1271 print_field_value((field_info *)gp->pdata[i], rs->cmd_line_index);
1272 }
1273
1274 return TAP_PACKET_DONT_REDRAW;
1275 }
1276
1277 int g_cmd_line_index = 0;
1278
1279 /*
1280 * field must be persistent - we don't g_strdup() it below
1281 */
1282 static void
protocolinfo_init(char * field)1283 protocolinfo_init(char *field)
1284 {
1285 pci_t *rs;
1286 header_field_info *hfi;
1287 GString *error_string;
1288 char hfibuf[100];
1289
1290 hfi=proto_registrar_get_byname(field);
1291 if(!hfi){
1292 fprintf(stderr, "rawshark: Field \"%s\" doesn't exist.\n", field);
1293 exit(1);
1294 }
1295
1296 field_display_to_string(hfi, hfibuf, sizeof(hfibuf));
1297 printf("%d %s %s - ",
1298 g_cmd_line_index,
1299 ftenum_to_string(hfi),
1300 hfibuf);
1301
1302 rs=g_new(pci_t, 1);
1303 rs->hf_index=hfi->id;
1304 rs->filter=field;
1305 rs->cmd_line_index = g_cmd_line_index++;
1306
1307 error_string=register_tap_listener("frame", rs, rs->filter, TL_REQUIRES_PROTO_TREE, NULL, protocolinfo_packet, NULL, NULL);
1308 if(error_string){
1309 /* error, we failed to attach to the tap. complain and clean up */
1310 fprintf(stderr, "rawshark: Couldn't register field extraction tap: %s\n",
1311 error_string->str);
1312 g_string_free(error_string, TRUE);
1313 if(rs->filter){
1314 g_free(rs->filter);
1315 }
1316 g_free(rs);
1317
1318 exit(1);
1319 }
1320 }
1321
1322 /*
1323 * Given a format string, split it into a GPtrArray of string_fmt_t structs
1324 * and fill in string_fmt_parts.
1325 */
1326
1327 static void
add_string_fmt(string_fmt_e format,gchar * plain)1328 add_string_fmt(string_fmt_e format, gchar *plain) {
1329 string_fmt_t *sf = g_new(string_fmt_t, 1);
1330
1331 sf->format = format;
1332 sf->plain = g_strdup(plain);
1333
1334 g_ptr_array_add(string_fmts, sf);
1335 }
1336
1337 static gboolean
parse_field_string_format(gchar * format)1338 parse_field_string_format(gchar *format) {
1339 size_t len;
1340 size_t pos = 0;
1341
1342 if (!format) {
1343 return FALSE;
1344 }
1345
1346 GString *plain_s = g_string_new("");
1347
1348 len = strlen(format);
1349 g_ptr_array_set_size(string_fmts, 0);
1350
1351 while (pos < len) {
1352 if (format[pos] == '%') {
1353 if (pos >= (len-1)) { /* There should always be a following specifier character */
1354 return FALSE;
1355 }
1356 pos++;
1357 if (plain_s->len > 0) {
1358 add_string_fmt(SF_NONE, plain_s->str);
1359 g_string_truncate(plain_s, 0);
1360 }
1361 switch (format[pos]) {
1362 case 'D':
1363 add_string_fmt(SF_NAME, NULL);
1364 break;
1365 case 'N':
1366 add_string_fmt(SF_NUMVAL, NULL);
1367 break;
1368 case 'S':
1369 add_string_fmt(SF_STRVAL, NULL);
1370 break;
1371 case '%':
1372 g_string_append_c(plain_s, '%');
1373 break;
1374 default: /* Invalid format */
1375 return FALSE;
1376 }
1377 } else {
1378 g_string_append_c(plain_s, format[pos]);
1379 }
1380 pos++;
1381 }
1382
1383 if (plain_s->len > 0) {
1384 add_string_fmt(SF_NONE, plain_s->str);
1385 }
1386 g_string_free(plain_s, TRUE);
1387
1388 return TRUE;
1389 }
1390 /****************************************************************************************
1391 * END OF FIELD EXTRACTION ROUTINES
1392 ****************************************************************************************/
1393
1394 static void
show_print_file_io_error(int err)1395 show_print_file_io_error(int err)
1396 {
1397 switch (err) {
1398
1399 case ENOSPC:
1400 cmdarg_err("Not all the packets could be printed because there is "
1401 "no space left on the file system.");
1402 break;
1403
1404 #ifdef EDQUOT
1405 case EDQUOT:
1406 cmdarg_err("Not all the packets could be printed because you are "
1407 "too close to, or over your disk quota.");
1408 break;
1409 #endif
1410
1411 default:
1412 cmdarg_err("An error occurred while printing packets: %s.",
1413 g_strerror(err));
1414 break;
1415 }
1416 }
1417
1418 static const nstime_t *
raw_get_frame_ts(struct packet_provider_data * prov,guint32 frame_num)1419 raw_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
1420 {
1421 if (prov->ref && prov->ref->num == frame_num)
1422 return &prov->ref->abs_ts;
1423
1424 if (prov->prev_dis && prov->prev_dis->num == frame_num)
1425 return &prov->prev_dis->abs_ts;
1426
1427 if (prov->prev_cap && prov->prev_cap->num == frame_num)
1428 return &prov->prev_cap->abs_ts;
1429
1430 return NULL;
1431 }
1432
1433 static epan_t *
raw_epan_new(capture_file * cf)1434 raw_epan_new(capture_file *cf)
1435 {
1436 static const struct packet_provider_funcs funcs = {
1437 raw_get_frame_ts,
1438 cap_file_provider_get_interface_name,
1439 cap_file_provider_get_interface_description,
1440 NULL,
1441 };
1442
1443 return epan_new(&cf->provider, &funcs);
1444 }
1445
1446 cf_status_t
raw_cf_open(capture_file * cf,const char * fname)1447 raw_cf_open(capture_file *cf, const char *fname)
1448 {
1449 if ((fd = raw_pipe_open(fname)) < 0)
1450 return CF_ERROR;
1451
1452 /* The open succeeded. Fill in the information for this file. */
1453
1454 /* Create new epan session for dissection. */
1455 epan_free(cf->epan);
1456 cf->epan = raw_epan_new(cf);
1457
1458 cf->provider.wth = NULL;
1459 cf->f_datalen = 0; /* not used, but set it anyway */
1460
1461 /* Set the file name because we need it to set the follow stream filter.
1462 XXX - is that still true? We need it for other reasons, though,
1463 in any case. */
1464 cf->filename = g_strdup(fname);
1465
1466 /* Indicate whether it's a permanent or temporary file. */
1467 cf->is_tempfile = FALSE;
1468
1469 /* No user changes yet. */
1470 cf->unsaved_changes = FALSE;
1471
1472 cf->cd_t = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
1473 cf->open_type = WTAP_TYPE_AUTO;
1474 cf->count = 0;
1475 cf->drops_known = FALSE;
1476 cf->drops = 0;
1477 cf->snap = 0;
1478 nstime_set_zero(&cf->elapsed_time);
1479 cf->provider.ref = NULL;
1480 cf->provider.prev_dis = NULL;
1481 cf->provider.prev_cap = NULL;
1482
1483 return CF_OK;
1484 }
1485
1486 /*
1487 * Report an error in command-line arguments.
1488 */
1489 static void
rawshark_cmdarg_err(const char * fmt,va_list ap)1490 rawshark_cmdarg_err(const char *fmt, va_list ap)
1491 {
1492 fprintf(stderr, "rawshark: ");
1493 vfprintf(stderr, fmt, ap);
1494 fprintf(stderr, "\n");
1495 }
1496
1497 /*
1498 * Report additional information for an error in command-line arguments.
1499 */
1500 static void
rawshark_cmdarg_err_cont(const char * fmt,va_list ap)1501 rawshark_cmdarg_err_cont(const char *fmt, va_list ap)
1502 {
1503 vfprintf(stderr, fmt, ap);
1504 fprintf(stderr, "\n");
1505 }
1506
1507 /*
1508 * Editor modelines
1509 *
1510 * Local Variables:
1511 * c-basic-offset: 4
1512 * tab-width: 8
1513 * indent-tabs-mode: nil
1514 * End:
1515 *
1516 * ex: set shiftwidth=4 tabstop=8 expandtab:
1517 * :indentSize=4:tabSize=8:noTabs=true:
1518 */
1519