### Bug Summary

File: | builds/wireshark/wireshark/tshark.c
Warning: | line 3287, column 21 Value stored to 'ret' is never read

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tshark.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-02-13-100400-3624-1 -x c /builds/wireshark/wireshark/tshark.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

1 | /* tshark.c
2 | *
3 | * Text-mode variant of Wireshark, along the lines of tcpdump and snoop,
4 | * by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris <guy@alum.mit.edu>.
5 | *
6 | * Wireshark - Network traffic analyzer
7 | * By Gerald Combs <gerald@wireshark.org>
8 | * Copyright 1998 Gerald Combs
9 | *
10 | * SPDX-License-Identifier: GPL-2.0-or-later
11 | */
12 |
13 | #include <config.h>
14 |
15 | #define WS_LOG_DOMAIN"Main" LOG_DOMAIN_MAIN"Main"
16 |
17 | #include <stdlib.h>
18 | #include <stdio.h>
19 | #include <string.h>
20 | #include <locale.h>
21 | #include <limits.h>
22 |
23 | #include <wsutil/ws_getopt.h>
24 |
25 | #include <errno(*__errno_location ()).h>
26 |
27 | #ifdef _WIN32
28 | # include <winsock2.h>
29 | #endif
30 |
31 | #ifndef _WIN32
32 | #include <signal.h>
33 | #endif
34 |
35 | #include <glib.h>
36 |
37 | #include <epan/exceptions.h>
38 | #include <epan/epan.h>
39 |
40 | #include <ws_exit_codes.h>
41 | #include <wsutil/clopts_common.h>
42 | #include <wsutil/cmdarg_err.h>
43 | #include <ui/urls.h>
44 | #include <wsutil/filesystem.h>
45 | #include <wsutil/file_util.h>
46 | #include <wsutil/time_util.h>
47 | #include <wsutil/socket.h>
48 | #include <wsutil/privileges.h>
49 | #include <wsutil/please_report_bug.h>
50 | #include <wsutil/wslog.h>
51 | #include <wsutil/ws_assert.h>
52 | #include <wsutil/strtoi.h>
53 | #include <wsutil/report_message.h>
54 | #include <app/application_flavor.h>
55 | #include <wsutil/path_config.h>
56 | #include <cli_main.h>
57 | #include <wsutil/version_info.h>
58 | #include <wiretap/wtap_opttypes.h>
59 |
60 | #include "globals.h"
61 | #include <epan/timestamp.h>
62 | #include <epan/packet.h>
63 | #ifdef HAVE_LUA1
64 | #include <epan/wslua/init_wslua.h>
65 | #endif
66 | #include <epan/disabled_protos.h>
67 | #include <epan/prefs.h>
68 | #include <epan/column.h>
69 | #include <epan/decode_as.h>
70 | #include <epan/print.h>
71 | #include <epan/addr_resolv.h>
72 | #include <epan/iana-info.h>
73 | #include <epan/manuf.h>
74 | #include <epan/secrets.h>
75 | #ifdef HAVE_LIBPCAP1
76 | #include "ui/capture_ui_utils.h"
77 | #endif
78 | #include "ui/taps.h"
79 | #include "ui/util.h"
80 | #include "ui/ws_ui_util.h"
81 | #include "ui/decode_as_utils.h"
82 | #include "wsutil/filter_files.h"
83 | #include "ui/cli/tshark-tap.h"
84 | #include "ui/cli/tap-exportobject.h"
85 | #include "ui/tap_export_pdu.h"
86 | #include "ui/dissect_opts.h"
87 | #include "ui/failure_message.h"
88 | #include "ui/capture_opts.h"
89 | #if defined(HAVE_LIBSMI1)
90 | #include "epan/oids.h"
91 | #endif
92 | #include "epan/maxmind_db.h"
93 | #include <epan/epan_dissect.h>
94 | #include <epan/tap.h>
95 | #include <epan/stat_tap_ui.h>
96 | #include <epan/conversation_table.h>
97 | #include <epan/srt_table.h>
98 | #include <epan/rtd_table.h>
99 | #include <epan/ex-opt.h>
100 | #include <epan/exported_pdu.h>
101 | #include <epan/secrets.h>
102 |
103 | #include "capture/capture-pcap-util.h"
104 |
105 | #ifdef HAVE_LIBPCAP1
106 | #include "capture/capture_ifinfo.h"
107 | #ifdef _WIN32
108 | #include "capture/capture-wpcap.h"
109 | #endif /* _WIN32 */
110 | #include <capture/capture_session.h>
111 | #include <capture/capture_sync.h>
112 | #include <ui/capture_info.h>
113 | #endif /* HAVE_LIBPCAP */
114 | #include <epan/funnel.h>
115 |
116 | #include <wsutil/str_util.h>
117 | #include <wsutil/utf8_entities.h>
118 | #include <wsutil/json_dumper.h>
119 | #include <wsutil/wslog.h>
120 | #ifdef _WIN32
121 | #include <wsutil/win32-utils.h>
122 | #endif
123 |
124 | #include "extcap.h"
125 |
126 | #ifdef HAVE_PLUGINS1
127 | #include <wsutil/codecs.h>
128 | #include <wsutil/plugins.h>
129 | #endif
130 |
131 | /* Additional exit codes */
132 | #define INVALID_EXPORT2 2
133 | #define INVALID_TAP2 2
134 | #define INVALID_CAPTURE2 2
135 |
136 | #define LONGOPT_EXPORT_OBJECTS3000 +1 LONGOPT_BASE_APPLICATION3000+1
137 | #define LONGOPT_COLOR3000 +2 LONGOPT_BASE_APPLICATION3000+2
138 | #define LONGOPT_NO_DUPLICATE_KEYS3000 +3 LONGOPT_BASE_APPLICATION3000+3
139 | #define LONGOPT_ELASTIC_MAPPING_FILTER3000 +4 LONGOPT_BASE_APPLICATION3000+4
140 | #define LONGOPT_EXPORT_TLS_SESSION_KEYS3000 +5 LONGOPT_BASE_APPLICATION3000+5
141 | #define LONGOPT_CAPTURE_COMMENT3000 +6 LONGOPT_BASE_APPLICATION3000+6
142 | #define LONGOPT_HEXDUMP3000 +7 LONGOPT_BASE_APPLICATION3000+7
143 | #define LONGOPT_SELECTED_FRAME3000 +8 LONGOPT_BASE_APPLICATION3000+8
144 | #define LONGOPT_PRINT_TIMERS3000 +9 LONGOPT_BASE_APPLICATION3000+9
145 | #define LONGOPT_GLOBAL_PROFILE3000 +10 LONGOPT_BASE_APPLICATION3000+10
146 | #define LONGOPT_COMPRESS3000 +11 LONGOPT_BASE_APPLICATION3000+11
147 |
148 | capture_file cfile;
149 |
150 | static uint32_t cum_bytes;
151 | static frame_data ref_frame;
152 | static frame_data prev_dis_frame;
153 | static frame_data prev_cap_frame;
154 |
155 | static bool_Bool perform_two_pass_analysis;
156 | static uint32_t epan_auto_reset_count;
157 | static bool_Bool epan_auto_reset;
158 |
159 | static uint32_t selected_frame_number;
160 |
161 | /*
162 | * The way the packet decode is to be written.
163 | */
164 | typedef enum {
165 | WRITE_NONE, /* dummy initial state */
166 | WRITE_TEXT, /* summary or detail text */
167 | WRITE_XML, /* PDML or PSML */
168 | WRITE_FIELDS, /* User defined list of fields */
169 | WRITE_JSON, /* JSON */
170 | WRITE_JSON_RAW, /* JSON only raw hex */
171 | WRITE_EK /* JSON bulk insert to Elasticsearch */
172 | /* Add CSV and the like here */
173 | } output_action_e;
174 |
175 | static output_action_e output_action;
176 | static bool_Bool do_dissection; /* true if we have to dissect each packet */
177 | static bool_Bool print_packet_info; /* true if we're to print packet information */
178 | static bool_Bool print_summary; /* true if we're to print packet summary information */
179 | static bool_Bool print_details; /* true if we're to print packet details information */
180 | static bool_Bool print_hex; /* true if we're to print hex/ascii information */
181 | static bool_Bool line_buffered;
182 | static bool_Bool quiet;
183 | static bool_Bool really_quiet;
184 | static char* delimiter_char = " ";
185 | static bool_Bool dissect_color;
186 | static unsigned hexdump_source_option = HEXDUMP_SOURCE_MULTI(0x0000U); /* Default - Enable legacy multi-source mode */
187 | static unsigned hexdump_ascii_option = HEXDUMP_ASCII_INCLUDE(0x0000U); /* Default - Enable legacy undelimited ASCII dump */
188 | static unsigned hexdump_timestamp_option = HEXDUMP_TIMESTAMP_NONE(0x0000U); /* Default - no timestamp preamble */
189 |
190 | static print_format_e print_format = PR_FMT_TEXT;
191 | static print_stream_t *print_stream;
192 |
193 | static char *output_file_name;
194 |
195 | static output_fields_t* output_fields;
196 |
197 | static bool_Bool no_duplicate_keys;
198 | static proto_node_children_grouper_func node_children_grouper = proto_node_group_children_by_unique;
199 |
200 | static json_dumper jdumper;
201 |
202 | /* The line separator used between packets, changeable via the -S option */
203 | static const char *separator = "";
204 |
205 | /* Per-file comments to be added to the output file. */
206 | static GPtrArray *capture_comments;
207 |
208 | static bool_Bool prefs_loaded;
209 |
210 | #ifdef HAVE_LIBPCAP1
211 | /*
212 | * true if we're to print packet counts to keep track of captured packets.
213 | */
214 | static bool_Bool print_packet_counts;
215 |
216 | static capture_options global_capture_opts;
217 | static capture_session global_capture_session;
218 | static info_data_t global_info_data;
219 |
220 | #ifdef SIGINFO
221 | static bool_Bool infodelay; /* if true, don't print capture info in SIGINFO handler */
222 | static bool_Bool infoprint; /* if true, print capture info after clearing infodelay */
223 | #endif /* SIGINFO */
224 |
225 | static bool_Bool capture(void);
226 | static bool_Bool capture_input_new_file(capture_session *cap_session,
227 | char *new_file);
228 | static void capture_input_new_packets(capture_session *cap_session,
229 | int to_read);
230 | static void capture_input_drops(capture_session *cap_session, uint32_t dropped,
231 | const char* interface_name);
232 | static void capture_input_error(capture_session *cap_session,
233 | char *error_msg, char *secondary_error_msg);
234 | static void capture_input_cfilter_error(capture_session *cap_session,
235 | unsigned i, const char *error_message);
236 | static void capture_input_closed(capture_session *cap_session, char *msg);
237 |
238 | static void report_counts(void);
239 | #ifdef _WIN32
240 | static BOOL WINAPI capture_cleanup(DWORD);
241 | #else /* _WIN32 */
242 | static void capture_cleanup(int);
243 | #ifdef SIGINFO
244 | static void report_counts_siginfo(int);
245 | #endif /* SIGINFO */
246 | #endif /* _WIN32 */
247 | #endif /* HAVE_LIBPCAP */
248 |
249 | static void reset_epan_mem(capture_file *cf, epan_dissect_t *edt, bool_Bool tree, bool_Bool visual);
250 |
251 | typedef enum {
252 | PROCESS_FILE_SUCCEEDED,
253 | PROCESS_FILE_NO_FILE_PROCESSED,
254 | PROCESS_FILE_ERROR,
255 | PROCESS_FILE_INTERRUPTED
256 | } process_file_status_t;
257 | static process_file_status_t process_cap_file(capture_file *, char *, int, bool_Bool, int, int64_t, int, ws_compression_type);
258 |
259 | typedef enum {
260 | PROCESS_PACKET_PASSED,
261 | PROCESS_PACKET_DIDNT_PASS,
262 | PROCESS_PACKET_PRINT_ERROR
263 | } process_packet_status_t;
264 | static process_packet_status_t process_packet_single_pass(capture_file *cf,
265 | epan_dissect_t *edt, int64_t offset, wtap_rec *rec, unsigned tap_flags);
266 | static void show_print_file_io_error(void);
267 | static bool_Bool write_preamble(capture_file *cf);
268 | static bool_Bool print_packet(capture_file *cf, epan_dissect_t *edt);
269 | static bool_Bool write_finale(void);
270 |
271 | static GHashTable *output_only_tables;
272 |
273 | static bool_Bool opt_print_timers;
274 | struct elapsed_pass_s {
275 | int64_t dissect;
276 | int64_t dfilter_read;
277 | int64_t dfilter_filter;
278 | };
279 | static struct {
280 | int64_t dfilter_expand;
281 | int64_t dfilter_compile;
282 | struct elapsed_pass_s first_pass;
283 | int64_t elapsed_first_pass;
284 | struct elapsed_pass_s second_pass;
285 | int64_t elapsed_second_pass;
286 | }
287 | tshark_elapsed;
288 |
289 | static void
290 | print_elapsed_json(const char *cf_name, const char *dfilter)
291 | {
292 | json_dumper dumper = {
293 | .output_file = stderrstderr,
294 | .flags = JSON_DUMPER_FLAGS_PRETTY_PRINT(1 << 0),
295 | };
296 |
297 | if (tshark_elapsed.elapsed_first_pass == 0) {
298 | // Should not happen
299 | ws_warning("Print timers requested but no timing info provided")do { if (1) { ws_log_full("Main", LOG_LEVEL_WARNING, "tshark.c" , 299, __func__, "Print timers requested but no timing info provided" ); } } while (0);
300 | return;
301 | }
302 |
303 | #define DUMP(name, val)json_dumper_set_member_name(&dumper, name); json_dumper_value_anyf (&dumper, "%""l" "d", val) \
304 | json_dumper_set_member_name(&dumper, name); \
305 | json_dumper_value_anyf(&dumper, "%"PRId64"l" "d", val)
306 |
307 | json_dumper_begin_object(&dumper);
308 | json_dumper_set_member_name(&dumper, "version");
309 | json_dumper_value_string(&dumper, application_get_vcs_version_info_short());
310 | if (cf_name) {
311 | json_dumper_set_member_name(&dumper, "path");
312 | json_dumper_value_string(&dumper, cf_name);
313 | }
314 | if (dfilter) {
315 | json_dumper_set_member_name(&dumper, "filter");
316 | json_dumper_value_string(&dumper, dfilter);
317 | }
318 | json_dumper_set_member_name(&dumper, "time_unit");
319 | json_dumper_value_string(&dumper, "microseconds");
320 | DUMP("elapsed", tshark_elapsed.elapsed_first_pass +json_dumper_set_member_name(&dumper, "elapsed"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.elapsed_first_pass + tshark_elapsed.elapsed_second_pass)
321 | tshark_elapsed.elapsed_second_pass)json_dumper_set_member_name(&dumper, "elapsed"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.elapsed_first_pass + tshark_elapsed.elapsed_second_pass);
322 | DUMP("dfilter_expand", tshark_elapsed.dfilter_expand)json_dumper_set_member_name(&dumper, "dfilter_expand"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.dfilter_expand);
323 | DUMP("dfilter_compile", tshark_elapsed.dfilter_compile)json_dumper_set_member_name(&dumper, "dfilter_compile"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.dfilter_compile);
324 | json_dumper_begin_array(&dumper);
325 | json_dumper_begin_object(&dumper);
326 | DUMP("elapsed", tshark_elapsed.elapsed_first_pass)json_dumper_set_member_name(&dumper, "elapsed"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.elapsed_first_pass);
327 | DUMP("dissect", tshark_elapsed.first_pass.dissect)json_dumper_set_member_name(&dumper, "dissect"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.first_pass.dissect);
328 | DUMP("display_filter", tshark_elapsed.first_pass.dfilter_filter)json_dumper_set_member_name(&dumper, "display_filter"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.first_pass.dfilter_filter );
329 | DUMP("read_filter", tshark_elapsed.first_pass.dfilter_read)json_dumper_set_member_name(&dumper, "read_filter"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.first_pass.dfilter_read );
330 | json_dumper_end_object(&dumper);
331 | if (tshark_elapsed.elapsed_second_pass) {
332 | json_dumper_begin_object(&dumper);
333 | DUMP("elapsed", tshark_elapsed.elapsed_second_pass)json_dumper_set_member_name(&dumper, "elapsed"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.elapsed_second_pass);
334 | DUMP("dissect", tshark_elapsed.second_pass.dissect)json_dumper_set_member_name(&dumper, "dissect"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.second_pass.dissect);
335 | DUMP("display_filter", tshark_elapsed.second_pass.dfilter_filter)json_dumper_set_member_name(&dumper, "display_filter"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.second_pass.dfilter_filter );
336 | DUMP("read_filter", tshark_elapsed.second_pass.dfilter_read)json_dumper_set_member_name(&dumper, "read_filter"); json_dumper_value_anyf (&dumper, "%""l" "d", tshark_elapsed.second_pass.dfilter_read );
337 | json_dumper_end_object(&dumper);
338 | }
339 | json_dumper_end_array(&dumper);
340 | json_dumper_end_object(&dumper);
341 | json_dumper_finish(&dumper);
342 | }
343 |
344 | static void
345 | list_capture_types(void)
346 | {
347 | GArray *writable_type_subtypes;
348 |
349 | fprintf(stderrstderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
350 | writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME);
351 | for (unsigned i = 0; i < writable_type_subtypes->len; i++) {
352 | int ft = g_array_index(writable_type_subtypes, int, i)(((int*) (void *) (writable_type_subtypes)->data) [(i)]);
353 | fprintf(stderrstderr, " %s - %s\n", wtap_file_type_subtype_name(ft),
354 | wtap_file_type_subtype_description(ft));
355 | }
356 | g_array_free(writable_type_subtypes, TRUE(!(0)));
357 | }
358 |
359 | static void
360 | list_output_compression_types(void) {
361 | GSList *output_compression_types;
362 |
363 | cmdarg_err("The available output compression type(s) are:");
364 | output_compression_types = ws_get_all_output_compression_type_names_list();
365 | for (GSList *compression_type = output_compression_types;
366 | compression_type != NULL((void*)0);
367 | compression_type = g_slist_next(compression_type)((compression_type) ? (((GSList *)(compression_type))->next ) : ((void*)0))) {
368 | cmdarg_err_cont(" %s", (const char *)compression_type->data);
369 | }
370 |
371 | g_slist_free(output_compression_types);
372 | }
373 |
374 | struct string_elem {
375 | const char *sstr; /* The short string */
376 | const char *lstr; /* The long string */
377 | };
378 |
379 | static int
380 | string_compare(const void *a, const void *b)
381 | {
382 | return strcmp(((const struct string_elem *)a)->sstr,
383 | ((const struct string_elem *)b)->sstr);
384 | }
385 |
386 | static void
387 | string_elem_print(void *data)
388 | {
389 | fprintf(stderrstderr, " %s - %s\n",
390 | ((struct string_elem *)data)->sstr,
391 | ((struct string_elem *)data)->lstr);
392 | }
393 |
394 | static void
395 | list_read_capture_types(void)
396 | {
397 | unsigned i;
398 | size_t num_file_types;
399 | struct string_elem *captypes;
400 | GSList *list = NULL((void*)0);
401 | const char *magic = "Magic-value-based";
402 | const char *heuristic = "Heuristics-based";
403 |
404 | /* How many readable file types are there? */
405 | num_file_types = 0;
406 | for (i = 0; open_routines[i].name != NULL((void*)0); i++)
407 | num_file_types++;
408 | captypes = g_new(struct string_elem, num_file_types)((struct string_elem *) g_malloc_n ((num_file_types), sizeof ( struct string_elem)));
409 |
410 | fprintf(stderrstderr, "tshark: The available read file types for the \"-X read_format:\" option are:\n");
411 | for (i = 0; i < num_file_types && open_routines[i].name != NULL((void*)0); i++) {
412 | captypes[i].sstr = open_routines[i].name;
413 | captypes[i].lstr = (open_routines[i].type == OPEN_INFO_MAGIC) ? magic : heuristic;
414 | list = g_slist_insert_sorted(list, &captypes[i], string_compare);
415 | }
416 | g_slist_free_full(list, string_elem_print);
417 | g_free(captypes);
418 | }
419 |
420 | static void
421 | list_export_pdu_taps(void)
422 | {
423 | fprintf(stderrstderr, "tshark: The available export tap names and the encapsulation types they produce for the \"-U tap_name\" option are:\n");
424 | for (GSList *export_pdu_tap_name_list = get_export_pdu_tap_list();
425 | export_pdu_tap_name_list != NULL((void*)0);
426 | export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)((export_pdu_tap_name_list) ? (((GSList *)(export_pdu_tap_name_list ))->next) : ((void*)0))) {
427 | fprintf(stderrstderr, " %s - %s\n", (const char*)(export_pdu_tap_name_list->data), wtap_encap_description(export_pdu_tap_get_encap((const char*)export_pdu_tap_name_list->data)));
428 | }
429 | }
430 |
431 | static void
432 | print_usage(FILE *output)
433 | {
434 | fprintf(output, "\n");
435 | fprintf(output, "Usage: tshark [options] ...\n");
436 | fprintf(output, "\n");
437 |
438 | #ifdef HAVE_LIBPCAP1
439 | fprintf(output, "Capture interface:\n");
440 | fprintf(output, " -i <interface>, --interface <interface>\n");
441 | fprintf(output, " name or idx of interface (def: first non-loopback)\n");
442 | fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
443 | fprintf(output, " -s <snaplen>, --snapshot-length <snaplen>\n");
444 | fprintf(output, " packet snapshot length (def: appropriate maximum)\n");
445 | fprintf(output, " -p, --no-promiscuous-mode\n");
446 | fprintf(output, " don't capture in promiscuous mode\n");
447 | fprintf(output, " -I, --monitor-mode capture in monitor mode, if available\n");
448 | fprintf(output, " -B <buffer size>, --buffer-size <buffer size>\n");
449 | fprintf(output, " size of kernel buffer in MiB (def: %dMiB)\n", DEFAULT_CAPTURE_BUFFER_SIZE2);
450 | fprintf(output, " -y <link type>, --linktype <link type>\n");
451 | fprintf(output, " link layer type (def: first appropriate)\n");
452 | fprintf(output, " --time-stamp-type <type> timestamp method for interface\n");
453 | fprintf(output, " -D, --list-interfaces print list of interfaces and exit\n");
454 | fprintf(output, " -L, --list-data-link-types\n");
455 | fprintf(output, " print list of link-layer types of iface and exit\n");
456 | fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
457 | fprintf(output, " --no-optimize do not optimize capture filter\n");
458 | fprintf(output, "\n");
459 | fprintf(output, "Capture display:\n");
460 | fprintf(output, " --update-interval interval between updates with new packets, in milliseconds (def: %dms)\n", DEFAULT_UPDATE_INTERVAL100);
461 | fprintf(output, "Capture stop conditions:\n");
462 | fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
463 | fprintf(output, " -a <autostop cond.> ..., --autostop <autostop cond.> ...\n");
464 | fprintf(output, " duration:NUM - stop after NUM seconds\n");
465 | fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
466 | fprintf(output, " files:NUM - stop after NUM files\n");
467 | fprintf(output, " packets:NUM - stop after NUM packets\n");
468 | /*fprintf(output, "\n");*/
469 | fprintf(output, "Capture output:\n");
470 | fprintf(output, " -b <ringbuffer opt.> ..., --ring-buffer <ringbuffer opt.>\n");
471 | fprintf(output, " duration:NUM - switch to next file after NUM secs\n");
472 | fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
473 | fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
474 | fprintf(output, " packets:NUM - switch to next file after NUM packets\n");
475 | fprintf(output, " interval:NUM - switch to next file when the time is\n");
476 | fprintf(output, " an exact multiple of NUM secs\n");
477 | fprintf(output, " printname:FILE - print filename to FILE when written\n");
478 | fprintf(output, " (can use 'stdout' or 'stderr')\n");
479 | #endif /* HAVE_LIBPCAP */
480 | #ifdef HAVE_PCAP_REMOTE
481 | fprintf(output, "RPCAP options:\n");
482 | fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
483 | #endif
484 | /*fprintf(output, "\n");*/
485 | fprintf(output, "Input file:\n");
486 | fprintf(output, " -r <infile>, --read-file <infile>\n");
487 | fprintf(output, " set the filename to read from (or '-' for stdin)\n");
488 |
489 | fprintf(output, "\n");
490 | fprintf(output, "Processing:\n");
491 | fprintf(output, " -2 perform a two-pass analysis\n");
492 | fprintf(output, " -M <packet count> perform session auto reset\n");
493 | fprintf(output, " -R <read filter>, --read-filter <read filter>\n");
494 | fprintf(output, " packet Read filter in Wireshark display filter syntax\n");
495 | fprintf(output, " (requires -2)\n");
496 | fprintf(output, " -Y <display filter>, --display-filter <display filter>\n");
497 | fprintf(output, " packet displaY filter in Wireshark display filter\n");
498 | fprintf(output, " syntax\n");
499 | fprintf(output, " -n disable all name resolutions (def: \"mNd\" enabled, or\n");
500 | fprintf(output, " as set in preferences)\n");
501 | // Note: the order of the flags here matches the options in the settings dialog e.g. "dsN" only have an effect if "n" is set
502 | fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mtndsNvg\"\n");
503 | fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE"<layer_type>==<selector>,<decode_as_protocol>");
504 | fprintf(output, " \"Decode As\", see the man page for details\n");
505 | fprintf(output, " Example: tcp.port==8888,http\n");
506 | fprintf(output, " -H <hosts file> read a list of entries from a hosts file, which will\n");
507 | fprintf(output, " then be written to a capture file. (Implies -W n)\n");
508 | fprintf(output, " --enable-protocol <proto_name>\n");
509 | fprintf(output, " enable dissection of proto_name\n");
510 | fprintf(output, " --disable-protocol <proto_name>\n");
511 | fprintf(output, " disable dissection of proto_name\n");
512 | fprintf(output, " --only-protocols <protocols>\n");
513 | fprintf(output, " Only enable dissection of these protocols, comma\n");
514 | fprintf(output, " separated. Disable everything else\n");
515 | fprintf(output, " --disable-all-protocols\n");
516 | fprintf(output, " Disable dissection of all protocols\n");
517 | fprintf(output, " --enable-heuristic <short_name>\n");
518 | fprintf(output, " enable dissection of heuristic protocol\n");
519 | fprintf(output, " --disable-heuristic <short_name>\n");
520 | fprintf(output, " disable dissection of heuristic protocol\n");
521 |
522 | /*fprintf(output, "\n");*/
523 | fprintf(output, "Output:\n");
524 | fprintf(output, " -w <outfile|-> write packets to a pcapng-format file named \"outfile\"\n");
525 | fprintf(output, " (or '-' for stdout). If the output filename has the\n");
526 | fprintf(output, " .gz extension, it will be compressed to a gzip archive\n");
527 | fprintf(output, " --capture-comment <comment>\n");
528 | fprintf(output, " add a capture file comment, if supported\n");
529 | fprintf(output, " -C <config profile> start with specified configuration profile\n");
530 | fprintf(output, " --global-profile use the global profile instead of personal profile\n");
531 | fprintf(output, " -F <output file type> set the output file type; default is pcapng.\n");
532 | fprintf(output, " an empty \"-F\" option will list the file types\n");
533 | fprintf(output, " -V add output of packet tree (Packet Details)\n");
534 | fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
535 | fprintf(output, " separated\n");
536 | fprintf(output, " -P, --print print packet summary even when writing to a file\n");
537 | fprintf(output, " -S <separator> the line separator to print between packets\n");
538 | fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
539 | fprintf(output, " --hexdump <hexoption> add hexdump, set options for data source and ASCII dump\n");
540 | fprintf(output, " all dump all data sources (-x default)\n");
541 | fprintf(output, " frames dump only frame data source\n");
542 | fprintf(output, " ascii include ASCII dump text (-x default)\n");
543 | fprintf(output, " delimit delimit ASCII dump text with '|' characters\n");
544 | fprintf(output, " noascii exclude ASCII dump text\n");
545 | fprintf(output, " time include frame timestamp preamble\n");
546 | fprintf(output, " notime do not include frame timestamp preamble (-x default)\n");
547 | fprintf(output, " help display help for --hexdump and exit\n");
548 | fprintf(output, " -T pdml|ps|psml|json|jsonraw|ek|tabs|text|fields|?\n");
549 | fprintf(output, " format of text output (def: text)\n");
550 | fprintf(output, " -j <protocolfilter> protocols layers filter if -T ek|pdml|json selected\n");
551 | fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n");
552 | fprintf(output, " nodes, unless child is specified also in the filter)\n");
553 | fprintf(output, " -J <protocolfilter> top level protocol filter if -T ek|pdml|json selected\n");
554 | fprintf(output, " (e.g. \"http tcp\", filter which expands all child nodes)\n");
555 | fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
556 | fprintf(output, " _ws.col.info)\n");
557 | fprintf(output, " this option can be repeated to print multiple fields\n");
558 | fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
559 | fprintf(output, " bom=y|n print a UTF-8 BOM\n");
560 | fprintf(output, " header=y|n switch headers on and off\n");
561 | fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
562 | fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
563 | fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
564 | fprintf(output, " aggregator\n");
565 | fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
566 | fprintf(output, " -t (a|ad|adoy|d|dd|e|r|rc|u|ud|udoy)[.[N]]|.[N]\n");
567 | fprintf(output, " output format of time stamps (def: r: rel. to first)\n");
568 | fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
569 | fprintf(output, " -l flush standard output after each packet\n");
570 | fprintf(output, " (implies --update-interval 0)\n");
571 | fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
572 | fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
573 | fprintf(output, " -g enable group read access on the output file(s)\n");
574 | fprintf(output, " -W n Save extra information in the file, if supported.\n");
575 | fprintf(output, " n = write network address resolution information\n");
576 | fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
577 | fprintf(output, " -U tap_name PDUs export mode, see the man page for details\n");
578 | fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
579 | fprintf(output, " --export-objects <protocol>,<destdir>\n");
580 | fprintf(output, " save exported objects for a protocol to a directory\n");
581 | fprintf(output, " named \"destdir\"\n");
582 | fprintf(output, " --export-tls-session-keys <keyfile>\n");
583 | fprintf(output, " export TLS Session Keys to a file named \"keyfile\"\n");
584 | fprintf(output, " --color color output text similarly to the Wireshark GUI,\n");
585 | fprintf(output, " requires a terminal with 24-bit color support\n");
586 | fprintf(output, " Also supplies color attributes to pdml and psml formats\n");
587 | fprintf(output, " (Note that attributes are nonstandard)\n");
588 | fprintf(output, " --no-duplicate-keys If -T json is specified, merge duplicate keys in an object\n");
589 | fprintf(output, " into a single key with as value a json array containing all\n");
590 | fprintf(output, " values\n");
591 | fprintf(output, " --elastic-mapping-filter <protocols> If -G elastic-mapping is specified, put only the\n");
592 | fprintf(output, " specified protocols within the mapping file\n");
593 | fprintf(output, " --temp-dir <directory> write temporary files to this directory\n");
594 | fprintf(output, " (default: %s)\n", g_get_tmp_dir());
595 | fprintf(output, " --compress <type> compress the output file using the type compression format\n");
596 | fprintf(output, "\n");
597 |
598 | ws_log_print_usage(output);
599 | fprintf(output, "\n");
600 |
601 | fprintf(output, "Miscellaneous:\n");
602 | fprintf(output, " -h, --help display this help and exit\n");
603 | fprintf(output, " -v, --version display version info and exit\n");
604 | fprintf(output, " -o <name>:<value> ... override preference setting\n");
605 | fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
606 | fprintf(output, " -G [report] dump one of several available reports and exit\n");
607 | fprintf(output, " default report=\"fields\"\n");
608 | fprintf(output, " use \"-G help\" for more help\n");
609 | #ifdef __linux__1
610 | fprintf(output, "\n");
611 | fprintf(output, "Dumpcap can benefit from an enabled BPF JIT compiler if available.\n");
612 | fprintf(output, "You might want to enable it by executing:\n");
613 | fprintf(output, " \"echo 1 > /proc/sys/net/core/bpf_jit_enable\"\n");
614 | fprintf(output, "Note that this can make your system less secure!\n");
615 | #endif
616 |
617 | }
618 |
619 | static void
620 | glossary_option_help(void)
621 | {
622 | FILE *output;
623 |
624 | output = stdoutstdout;
625 |
626 | fprintf(output, "%s\n", get_appname_and_version());
627 |
628 | fprintf(output, "\n");
629 | fprintf(output, "Usage: tshark -G <report>\n");
630 | fprintf(output, "\n");
631 | fprintf(output, "Glossary table reports:\n");
632 | fprintf(output, " -G column-formats dump column format codes and exit\n");
633 | fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
634 | fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
635 | fprintf(output, " -G dissectors dump registered dissector names\n");
636 | fprintf(output, " -G elastic-mapping dump ElasticSearch mapping file\n");
637 | fprintf(output, " -G enterprises dump IANA Private Enterprise Number (PEN) table\n");
638 | fprintf(output, " -G fieldcount dump count of header fields and exit\n");
639 | fprintf(output, " -G fields,[prefix] dump fields glossary and exit\n");
640 | fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
641 | fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
642 | fprintf(output, " -G manuf dump ethernet manufacturer tables\n");
643 | fprintf(output, " -G plugins dump installed plugins and exit\n");
644 | fprintf(output, " -G protocols dump protocols in registration database and exit\n");
645 | fprintf(output, " -G services dump transport service (port) names\n");
646 | fprintf(output, " -G values dump value, range, true/false strings and exit\n");
647 | fprintf(output, "\n");
648 | fprintf(output, "Preference reports:\n");
649 | fprintf(output, " -G currentprefs dump current preferences and exit\n");
650 | fprintf(output, " -G defaultprefs dump default preferences and exit\n");
651 | fprintf(output, " -G folders dump about:folders\n");
652 | fprintf(output, "\n");
653 | }
654 |
655 | static void
656 | hexdump_option_help(FILE *output)
657 | {
658 | fprintf(output, "%s\n", get_appname_and_version());
659 | fprintf(output, "\n");
660 | fprintf(output, "tshark: Valid --hexdump <hexoption> values include:\n");
661 | fprintf(output, "\n");
662 | fprintf(output, "Data source options:\n");
663 | fprintf(output, " all add hexdump, dump all data sources (-x default)\n");
664 | fprintf(output, " frames add hexdump, dump only frame data source\n");
665 | fprintf(output, "\n");
666 | fprintf(output, "ASCII options:\n");
667 | fprintf(output, " ascii add hexdump, include ASCII dump text (-x default)\n");
668 | fprintf(output, " delimit add hexdump, delimit ASCII dump text with '|' characters\n");
669 | fprintf(output, " noascii add hexdump, exclude ASCII dump text\n");
670 | fprintf(output, "\n");
671 | fprintf(output, "Timestamp options:\n");
672 | fprintf(output, " time add hexdump, include frame timestamp preamble (uses the format from -t)\n");
673 | fprintf(output, " notime add hexdump, do not include frame timestamp preamble (-x default)\n");
674 | fprintf(output, "Miscellaneous:\n");
675 | fprintf(output, " help display this help and exit\n");
676 | fprintf(output, "\n");
677 | fprintf(output, "Example:\n");
678 | fprintf(output, "\n");
679 | fprintf(output, " $ tshark ... --hexdump frames --hexdump delimit ...\n");
680 | fprintf(output, "\n");
681 | }
682 |
683 | static void
684 | print_current_user(void)
685 | {
686 | char *cur_user, *cur_group;
687 |
688 | if (started_with_special_privs()) {
689 | cur_user = get_cur_username();
690 | cur_group = get_cur_groupname();
691 | fprintf(stderrstderr, "Running as user \"%s\" and group \"%s\".",
692 | cur_user, cur_group);
693 | g_free(cur_user);
694 | g_free(cur_group);
695 | if (running_with_special_privs()) {
696 | fprintf(stderrstderr, " This could be dangerous.");
697 | }
698 | fprintf(stderrstderr, "\n");
699 | }
700 | }
701 |
702 | static void
703 | gather_tshark_compile_info(feature_list l)
704 | {
705 | /* Capture libraries */
706 | gather_caplibs_compile_info(l);
707 | epan_gather_compile_info(l);
708 | }
709 |
710 | static void
711 | gather_tshark_runtime_info(feature_list l)
712 | {
713 | #ifdef HAVE_LIBPCAP1
714 | gather_caplibs_runtime_info(l);
715 | #endif
716 |
717 | /* stuff used by libwireshark */
718 | epan_gather_runtime_info(l);
719 | }
720 |
721 | static bool_Bool
722 | _compile_dfilter(const char *text, dfilter_t **dfp, const char *caller)
723 | {
724 | bool_Bool ok;
725 | df_error_t *df_err;
726 | char *err_off;
727 | char *expanded;
728 | int64_t elapsed_start;
729 |
730 | elapsed_start = g_get_monotonic_time();
731 | expanded = dfilter_expand(text, &df_err);
732 | if (expanded == NULL((void*)0)) {
733 | cmdarg_err("%s", df_err->msg);
734 | df_error_free(&df_err);
735 | return false0;
736 | }
737 | tshark_elapsed.dfilter_expand = g_get_monotonic_time() - elapsed_start;
738 |
739 | elapsed_start = g_get_monotonic_time();
740 | ok = dfilter_compile_full(expanded, dfp, &df_err, DF_OPTIMIZE(1U << 2), caller);
741 | if (!ok ) {
742 | cmdarg_err("%s", df_err->msg);
743 |
744 | if (df_err->loc.col_start >= 0) {
745 | err_off = ws_strdup_underline(NULL((void*)0), df_err->loc.col_start, df_err->loc.col_len);
746 | cmdarg_err_cont(" %s", expanded);
747 | cmdarg_err_cont(" %s", err_off);
748 | g_free(err_off);
749 | }
750 | df_error_free(&df_err);
751 | }
752 | tshark_elapsed.dfilter_compile = g_get_monotonic_time() - elapsed_start;
753 |
754 | g_free(expanded);
755 | return ok;
756 | }
757 |
758 | #define compile_dfilter(text, dfp)_compile_dfilter(text, dfp, __func__) _compile_dfilter(text, dfp, __func__)
759 |
760 | static bool_Bool
761 | protocolfilter_add_opt(const char* arg, pf_flags filter_flags)
762 | {
763 | char **newfilter = NULL((void*)0);
764 | for (newfilter = wmem_strsplit(wmem_epan_scope(), arg, " ", -1); *newfilter; newfilter++) {
765 | if (strcmp(*newfilter, "") == 0) {
766 | /* Don't treat the empty string as an intended field abbreviation
767 | * to output, consecutive spaces on the command line probably
768 | * aren't intentional.
769 | */
770 | continue;
771 | }
772 | if (!output_fields_add_protocolfilter(output_fields, *newfilter, filter_flags)) {
773 | cmdarg_err("%s was already specified with different filter flags. Overwriting previous protocol filter.", *newfilter);
774 | }
775 | }
776 | return true1;
777 | }
778 |
779 | static void
780 | about_folders(void)
781 | {
782 | const char *constpath;
783 | char *path;
784 | int i;
785 | char **resultArray;
786 | const char *env_prefix = application_configuration_environment_prefix();
787 |
788 | /* "file open" */
789 |
790 | /*
791 | * Fetching the "File" dialogs folder not implemented.
792 | * This is arguably just a pwd for a ui/cli .
793 | */
794 |
795 | /* temp */
796 | constpath = g_get_tmp_dir();
797 | #ifdef HAVE_LIBPCAP1
798 | /* global_capture_opts only exists in this case */
799 | if (global_capture_opts.temp_dir)
800 | constpath = global_capture_opts.temp_dir;
801 | #endif
802 | printf("%-21s\t%s\n", "Temp:", constpath);
803 |
804 | /* pers conf */
805 | path = get_persconffile_path("", false0, env_prefix);
806 | printf("%-21s\t%s\n", "Personal configuration:", path);
807 | g_free(path);
808 |
809 | /* global conf */
810 | constpath = get_datafile_dir(env_prefix);
811 | if (constpath != NULL((void*)0)) {
812 | printf("%-21s\t%s\n", "Global configuration:", constpath);
813 | }
814 |
815 | /* system */
816 | constpath = get_systemfile_dir(env_prefix);
817 | printf("%-21s\t%s\n", "System:", constpath);
818 |
819 | /* program */
820 | constpath = get_progfile_dir();
821 | printf("%-21s\t%s\n", "Program:", constpath);
822 |
823 | #ifdef HAVE_PLUGINS1
824 | /* pers plugins */
825 | printf("%-21s\t%s\n", "Personal Plugins:", get_plugins_pers_dir_with_version(env_prefix));
826 |
827 | /* global plugins */
828 | printf("%-21s\t%s\n", "Global Plugins:", get_plugins_dir_with_version(env_prefix));
829 | #endif
830 |
831 | #ifdef HAVE_LUA1
832 | /* pers lua plugins */
833 | printf("%-21s\t%s\n", "Personal Lua Plugins:", get_plugins_pers_dir(env_prefix));
834 |
835 | /* global lua plugins */
836 | printf("%-21s\t%s\n", "Global Lua Plugins:", get_plugins_dir(env_prefix));
837 | #endif
838 |
839 | /* Personal Extcap */
840 | constpath = get_extcap_pers_dir(env_prefix);
841 |
842 | resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S":", 10);
843 | for(i = 0; resultArray[i]; i++)
844 | printf("%-21s\t%s\n", "Personal Extcap path:", g_strstrip(resultArray[i])g_strchomp (g_strchug (resultArray[i])));
845 |
846 | g_strfreev(resultArray);
847 |
848 | /* Global Extcap */
849 | constpath = get_extcap_dir(env_prefix, application_extcap_dir());
850 |
851 | resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S":", 10);
852 | for(i = 0; resultArray[i]; i++)
853 | printf("%-21s\t%s\n", "Global Extcap path:", g_strstrip(resultArray[i])g_strchomp (g_strchug (resultArray[i])));
854 |
855 | g_strfreev(resultArray);
856 |
857 | /* MaxMindDB */
858 | path = maxmind_db_get_paths();
859 |
860 | resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S":", 10);
861 |
862 | for(i = 0; resultArray[i]; i++)
863 | printf("%-21s\t%s\n", "MaxMind database path:", g_strstrip(resultArray[i])g_strchomp (g_strchug (resultArray[i])));
864 |
865 | g_strfreev(resultArray);
866 | g_free(path);
867 |
868 | #ifdef HAVE_LIBSMI1
869 | /* SMI MIBs/PIBs */
870 | path = oid_get_default_mib_path(application_configuration_environment_prefix());
871 |
872 | resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S":", 20);
873 |
874 | for(i = 0; resultArray[i]; i++)
875 | printf("%-21s\t%s\n", "MIB/PIB path:", g_strstrip(resultArray[i])g_strchomp (g_strchug (resultArray[i])));
876 |
877 | g_strfreev(resultArray);
878 | g_free(path);
879 | #endif
880 |
881 | }
882 |
883 | static int
884 | dump_glossary(const char* glossary, const char* elastic_mapping_filter)
885 | {
886 | int exit_status = EXIT_SUCCESS0;
887 | /* If invoked with the "-G" flag, we dump out information based on
888 | the argument to the "-G" flag.
889 | */
890 |
891 | /* This is now called after the preferences are loaded and all
892 | * the command line options are handled, including -o, -d,
893 | * --[enable|disable]-[protocol|heuristic].
894 | * Some UATs can register new fields (e.g. HTTP/2), so for most
895 | * cases load everything.
896 | *
897 | * prefs_reset() is used for defaultprefs to get the default values.
898 | * Note that makes it difficult to use defaultprefs in concert with
899 | * any other glossary (we could do it last.)
900 | */
901 | proto_initialize_all_prefixes();
902 |
903 | if (strcmp(glossary, "column-formats") == 0)
904 | column_dump_column_formats();
905 | else if (strcmp(glossary, "currentprefs") == 0) {
906 | write_prefs(application_configuration_environment_prefix(), NULL((void*)0));
907 | }
908 | else if (strcmp(glossary, "decodes") == 0) {
909 | dissector_dump_decodes();
910 | } else if (strcmp(glossary, "defaultprefs") == 0) {
911 | prefs_reset(application_configuration_environment_prefix(), application_columns(), application_num_columns());
912 | write_prefs(application_configuration_environment_prefix(), NULL((void*)0));
913 | } else if (strcmp(glossary, "dissector-tables") == 0)
914 | dissector_dump_dissector_tables();
915 | else if (strcmp(glossary, "dissectors") == 0)
916 | dissector_dump_dissectors();
917 | else if (strcmp(glossary, "elastic-mapping") == 0)
918 | proto_registrar_dump_elastic(elastic_mapping_filter);
919 | else if (strncmp(glossary, "elastic-mapping,", strlen("elastic-mapping,")) == 0) {
920 | elastic_mapping_filter = glossary + strlen("elastic-mapping,");
921 | proto_registrar_dump_elastic(elastic_mapping_filter);
922 | }
923 | else if (strcmp(glossary, "fieldcount") == 0) {
924 | /* return value for the test suite */
925 | exit_status = proto_registrar_dump_fieldcount();
926 | }
927 | else if (strcmp(glossary, "fields") == 0) {
928 | proto_registrar_dump_fields();
929 | }
930 | else if (strncmp(glossary, "fields,", strlen("fields,")) == 0) {
931 | const char* prefix = glossary + strlen("fields,");
932 | bool_Bool matched = proto_registrar_dump_field_completions(prefix);
933 | if (!matched) {
934 | cmdarg_err("No field or protocol begins with \"%s\"", prefix);
935 | exit_status = EXIT_FAILURE1;
936 | }
937 | }
938 | else if (strcmp(glossary, "folders") == 0) {
939 | about_folders();
940 | } else if (strcmp(glossary, "ftypes") == 0)
941 | proto_registrar_dump_ftypes();
942 | else if (strcmp(glossary, "heuristic-decodes") == 0) {
943 | dissector_dump_heur_decodes();
944 | } else if (strcmp(glossary, "manuf") == 0)
945 | ws_manuf_dump(stdoutstdout);
946 | else if (strcmp(glossary, "enterprises") == 0)
947 | global_enterprises_dump(stdoutstdout);
948 | else if (strcmp(glossary, "services") == 0)
949 | global_services_dump(stdoutstdout);
950 | else if (strcmp(glossary, "plugins") == 0) {
951 | #ifdef HAVE_PLUGINS1
952 | codecs_init(application_configuration_environment_prefix());
953 | plugins_dump_all();
954 | #endif
955 | #ifdef HAVE_LUA1
956 | wslua_plugins_dump_all();
957 | #endif
958 | extcap_dump_all();
959 | }
960 | else if (strcmp(glossary, "protocols") == 0) {
961 | proto_registrar_dump_protocols();
962 | } else if (strcmp(glossary, "values") == 0)
963 | proto_registrar_dump_values();
964 | else if (strcmp(glossary, "help") == 0)
965 | glossary_option_help();
966 | /* These are supported only for backwards compatibility and may or may not work
967 | * for a given user in a given directory on a given operating system with a given
968 | * command-line interpreter.
969 | */
970 | else if (strcmp(glossary, "?") == 0)
971 | glossary_option_help();
972 | else if (strcmp(glossary, "-?") == 0)
973 | glossary_option_help();
974 | else {
975 | cmdarg_err("Invalid \"%s\" option for -G flag, enter -G help for more help.", glossary);
976 | exit_status = WS_EXIT_INVALID_OPTION1;
977 | }
978 |
979 | return exit_status;
980 | }
981 |
982 | static bool_Bool
983 | must_do_dissection(dfilter_t *rfcode, dfilter_t *dfcode,
984 | char *volatile pdu_export_arg)
985 | {
986 | /* We have to dissect each packet if:
987 |
988 | we're printing information about each packet;
989 |
990 | we're using a read filter on the packets;
991 |
992 | we're using a display filter on the packets;
993 |
994 | we're exporting PDUs;
995 |
996 | we're using any taps that need dissection. */
997 | return print_packet_info || rfcode || dfcode || pdu_export_arg ||
998 | tap_listeners_require_dissection();
999 | }
1000 |
1001 | #ifdef HAVE_LIBPCAP1
1002 | /*
1003 | * Check whether a purported *shark packet-matching expression (display
1004 | * or read filter) looks like a capture filter and, if so, print a
1005 | * warning.
1006 | *
1007 | * Used, for example, if the string in question isn't a valid packet-
1008 | * matching expression.
1009 | */
1010 | static void
1011 | warn_about_capture_filter(const char *rfilter)
1012 | {
1013 | struct bpf_program fcode;
1014 | pcap_t *pc;
1015 |
1016 | pc = pcap_open_dead(DLT_EN10MB1, MIN_PACKET_SIZE1);
1017 | if (pc != NULL((void*)0)) {
1018 | if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) {
1019 | pcap_freecode(&fcode);
1020 | cmdarg_err_cont(
1021 | " Note: That read filter code looks like a valid capture filter;\n"
1022 | " maybe you mixed them up?");
1023 | }
1024 | pcap_close(pc);
1025 | }
1026 | }
1027 | #endif
1028 |
1029 | #ifdef HAVE_LIBPCAP1
1030 | static GList *cached_if_list;
1031 |
1032 | static GList *
1033 | capture_opts_get_interface_list(int *err, char **err_str)
1034 | {
1035 | if (cached_if_list == NULL((void*)0)) {
1036 | /*
1037 | * This isn't a GUI tool, so no need for a callback.
1038 | */
1039 | cached_if_list = capture_interface_list(global_capture_opts.app_name, err, err_str, NULL((void*)0));
1040 | }
1041 | /*
1042 | * Routines expect to free the returned interface list, so return
1043 | * a deep copy.
1044 | */
1045 | return interface_list_copy(cached_if_list);
1046 | }
1047 | #endif
1048 |
1049 | int
1050 | main(int argc, char *argv[])
1051 | {
1052 | char *err_msg;
1053 | int opt;
1054 | static const struct ws_option long_options[] = {
1055 | {"help", ws_no_argument0, NULL((void*)0), 'h'},
1056 | {"version", ws_no_argument0, NULL((void*)0), 'v'},
1057 | LONGOPT_CAPTURE_COMMON{"autostop", 1, ((void*)0), 'a'}, {"ring-buffer", 1, ((void*) 0), 'b'}, {"buffer-size", 1, ((void*)0), 'B'}, {"list-interfaces" , 0, ((void*)0), 'D'}, {"list-sources", 0, ((void*)0), 'D'}, { "interface", 1, ((void*)0), 'i'}, {"source", 1, ((void*)0), 'i' }, {"monitor-mode", 0, ((void*)0), 'I'}, {"list-data-link-types" , 0, ((void*)0), 'L'}, {"no-promiscuous-mode", 0, ((void*)0), 'p'}, {"snapshot-length", 1, ((void*)0), 's'}, {"linktype", 1 , ((void*)0), 'y'}, {"list-time-stamp-types", 0, ((void*)0), 1000 +1}, {"no-optimize", 0, ((void*)0), 1000 +6}, {"time-stamp-type" , 1, ((void*)0), 1000 +2}, {"compress-type", 1, ((void*)0), 1000 +3}, {"temp-dir", 1, ((void*)0), 1000 +4}, {"update-interval" , 1, ((void*)0), 1000 +5},
1058 | LONGOPT_DISSECT_COMMON{"disable-protocol", 1, ((void*)0), 2000 +1 }, {"enable-heuristic" , 1, ((void*)0), 2000 +2 }, {"disable-heuristic", 1, ((void*) 0), 2000 +3 }, {"enable-protocol", 1, ((void*)0), 2000 +4 }, { "only-protocols", 1, ((void*)0), 2000 +5 }, {"disable-all-protocols" , 0, ((void*)0), 2000 +6 }, {"read-filter", 1, ((void*)0), 'R' }, {"display-filter", 1, ((void*)0), 'Y' },
1059 | LONGOPT_READ_CAPTURE_COMMON{"read-file", 1, ((void*)0), 'r' },
1060 | LONGOPT_WSLOG{"log-level", 1, ((void*)0), 5000 +1}, {"log-domain", 1, ((void *)0), 5000 +2}, {"log-domains", 1, ((void*)0), 5000 +2}, {"log-file" , 1, ((void*)0), 5000 +3}, {"log-fatal", 1, ((void*)0), 5000 + 4}, {"log-fatal-domain", 1, ((void*)0), 5000 +5}, {"log-fatal-domains" , 1, ((void*)0), 5000 +5}, {"log-debug", 1, ((void*)0), 5000 + 6}, {"log-noisy", 1, ((void*)0), 5000 +7},
1061 | {"print", ws_no_argument0, NULL((void*)0), 'P'},
1062 | {"export-objects", ws_required_argument1, NULL((void*)0), LONGOPT_EXPORT_OBJECTS3000 +1},
1063 | {"export-tls-session-keys", ws_required_argument1, NULL((void*)0), LONGOPT_EXPORT_TLS_SESSION_KEYS3000 +5},
1064 | {"color", ws_no_argument0, NULL((void*)0), LONGOPT_COLOR3000 +2},
1065 | {"no-duplicate-keys", ws_no_argument0, NULL((void*)0), LONGOPT_NO_DUPLICATE_KEYS3000 +3},
1066 | {"elastic-mapping-filter", ws_required_argument1, NULL((void*)0), LONGOPT_ELASTIC_MAPPING_FILTER3000 +4},
1067 | {"capture-comment", ws_required_argument1, NULL((void*)0), LONGOPT_CAPTURE_COMMENT3000 +6},
1068 | {"hexdump", ws_required_argument1, NULL((void*)0), LONGOPT_HEXDUMP3000 +7},
1069 | {"selected-frame", ws_required_argument1, NULL((void*)0), LONGOPT_SELECTED_FRAME3000 +8},
1070 | {"print-timers", ws_no_argument0, NULL((void*)0), LONGOPT_PRINT_TIMERS3000 +9},
1071 | {"global-profile", ws_no_argument0, NULL((void*)0), LONGOPT_GLOBAL_PROFILE3000 +10},
1072 | {"compress", ws_required_argument1, NULL((void*)0), LONGOPT_COMPRESS3000 +11},
1073 | {0, 0, 0, 0}
1074 | };
1075 | bool_Bool arg_error = false0;
1076 | bool_Bool has_extcap_options = false0;
1077 | volatile bool_Bool is_capturing = true1;
1078 |
1079 | int err;
1080 | char *err_info;
1081 | bool_Bool exp_pdu_status;
1082 | volatile process_file_status_t status;
1083 | volatile bool_Bool draw_taps = false0;
1084 | volatile int exit_status = EXIT_SUCCESS0;
1085 | #ifdef HAVE_LIBPCAP1
1086 | int caps_queries = 0;
1087 | GList *if_list;
1088 | char *err_str, *err_str_secondary;
1089 | #else
1090 | bool_Bool capture_option_specified = false0;
1091 | int max_packet_count = 0;
1092 | #endif
1093 | volatile int out_file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN-1;
1094 | volatile bool_Bool out_file_name_res = false0;
1095 | volatile int in_file_type = WTAP_TYPE_AUTO0;
1096 | char *volatile cf_name = NULL((void*)0);
1097 | char *rfilter = NULL((void*)0);
1098 | char *volatile dfilter = NULL((void*)0);
1099 | dfilter_t *rfcode = NULL((void*)0);
1100 | dfilter_t *dfcode = NULL((void*)0);
1101 | e_prefs *prefs_p;
1102 | char *output_only = NULL((void*)0);
1103 | char *volatile pdu_export_arg = NULL((void*)0);
1104 | char *volatile exp_pdu_filename = NULL((void*)0);
1105 | const char *volatile tls_session_keys_file = NULL((void*)0);
1106 | exp_pdu_t exp_pdu_tap_data;
1107 | const char* glossary = NULL((void*)0);
1108 | const char* elastic_mapping_filter = NULL((void*)0);
1109 | ws_compression_type volatile compression_type = WS_FILE_UNKNOWN_COMPRESSION;
1110 | const struct file_extension_info* file_extensions;
1111 | unsigned num_extensions;
1112 | epan_app_data_t app_data;
1113 |
1114 | /*
1115 | * The leading + ensures that getopt_long() does not permute the argv[]
1116 | * entries.
1117 | *
1118 | * We have to make sure that the first getopt_long() preserves the content
1119 | * of argv[] for the subsequent getopt_long() call.
1120 | *
1121 | * We use getopt_long() in both cases to ensure that we're using a routine
1122 | * whose permutation behavior we can control in the same fashion on all
1123 | * platforms, and so that, if we ever need to process a long argument before
1124 | * doing further initialization, we can do so.
1125 | *
1126 | * Glibc and Solaris libc document that a leading + disables permutation
1127 | * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
1128 | * and macOS don't document it, but do so anyway.
1129 | *
1130 | * We do *not* use a leading - because the behavior of a leading - is
1131 | * platform-dependent.
1132 | */
1133 | #define OPTSTRING"+2" "a:" "b:" "B:" "c:Df:F:i:" "I" "Lps:y:" "d:K:nN:R:t:u:Y:" "r:" "M:C:e:E:F:gG:hH:j:J:lo:O:PqQS:T:U:vVw:W:xX:z:" "+2" OPTSTRING_CAPTURE_COMMON"a:" "b:" "B:" "c:Df:F:i:" "I" "Lps:y:" OPTSTRING_DISSECT_COMMON"d:K:nN:R:t:u:Y:" OPTSTRING_READ_CAPTURE_COMMON"r:" "M:C:e:E:F:gG:hH:j:J:lo:O:PqQS:T:U:vVw:W:xX:z:"
1134 |
1135 | static const char optstring[] = OPTSTRING"+2" "a:" "b:" "B:" "c:Df:F:i:" "I" "Lps:y:" "d:K:nN:R:t:u:Y:" "r:" "M:C:e:E:F:gG:hH:j:J:lo:O:PqQS:T:U:vVw:W:xX:z:";
1136 |
1137 | /* Future proof by zeroing out all data */
1138 | memset(&app_data, 0, sizeof(app_data));
1139 |
1140 | /* Set the program name. */
1141 | g_set_prgname("tshark");
1142 |
1143 | /*
1144 | * Set the C-language locale to the native environment and set the
1145 | * code page to UTF-8 on Windows.
1146 | */
1147 | #ifdef _WIN32
1148 | setlocale(LC_ALL6, ".UTF-8");
1149 | #else
1150 | setlocale(LC_ALL6, "");
1151 | #endif
1152 |
1153 | ws_tzset();
1154 |
1155 | cmdarg_err_init(stderr_cmdarg_err, stderr_cmdarg_err_cont);
1156 |
1157 | /* Initialize log handler early so we can have proper logging during startup. */
1158 | ws_log_init(vcmdarg_err, "TShark Debug Console");
1159 |
1160 | /* Early logging command-line initialization. */
1161 | ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION1);
1162 |
1163 | ws_noisy("Finished log init and parsing command line log arguments")do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "tshark.c" , 1163, __func__, "Finished log init and parsing command line log arguments" ); } } while (0);
1164 | ws_debug("tshark started with %d args", argc)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 1164, __func__, "tshark started with %d args", argc); } } while (0);
1165 |
1166 | #ifdef _WIN32
1167 | create_app_running_mutex();
1168 | #endif /* _WIN32 */
1169 |
1170 | /*
1171 | * Get credential information for later use, and drop privileges
1172 | * before doing anything else.
1173 | * Let the user know if anything happened.
1174 | */
1175 | init_process_policies();
1176 | relinquish_special_privs_perm();
1177 | print_current_user();
1178 |
1179 | /*
1180 | * Attempt to get the pathname of the directory containing the
1181 | * executable file.
1182 | */
1183 | err_msg = configuration_init(argv[0], "wireshark");
1184 | if (err_msg != NULL((void*)0)) {
1185 | fprintf(stderrstderr,
1186 | "tshark: Can't get pathname of directory containing the tshark program: %s.\n"
1187 | "It won't be possible to capture traffic.\n"
1188 | "Report this to the Wireshark developers.",
1189 | err_msg);
1190 | g_free(err_msg);
1191 | }
1192 |
1193 | initialize_funnel_ops();
1194 |
1195 | #ifdef _WIN32
1196 | ws_init_dll_search_path();
1197 | #ifdef HAVE_LIBPCAP1
1198 | /* Load wpcap if possible. Do this before collecting the run-time version information */
1199 | load_wpcap();
1200 | #endif /* HAVE_LIBPCAP */
1201 | #endif /* _WIN32 */
1202 |
1203 | /* Initialize the version information. */
1204 | ws_init_version_info("TShark", application_flavor_name_proper(), application_get_vcs_version_info,
1205 | gather_tshark_compile_info, gather_tshark_runtime_info);
1206 |
1207 | /* Fail sometimes. Useful for testing fuzz scripts. */
1208 | /* if (g_random_int_range(0, 100) < 5) abort(); */
1209 |
1210 | /*
1211 | * In order to have the -X opts assigned before the wslua machine starts
1212 | * we need to call getopt_long before epan_init() gets called.
1213 | *
1214 | * In order to handle, for example, -o options, we also need to call it
1215 | * *after* epan_init() gets called, so that the dissectors have had a
1216 | * chance to register their preferences.
1217 | *
1218 | * Spawning a bunch of extcap processes can delay program startup,
1219 | * particularly on Windows. Check to see if we have any options that
1220 | * might require extcap and set has_extcap_options = true if that's
1221 | * the case.
1222 | *
1223 | * XXX - can we do this all with one getopt_long() call, saving the
1224 | * arguments we can't handle until after initializing libwireshark,
1225 | * and then process them after initializing libwireshark?
1226 | *
1227 | * We set ws_opterr to 0 so that ws_getopt_long doesn't print error
1228 | * messages for bad long options. We'll do that once, in the final
1229 | * call where all the error handling happens.
1230 | */
1231 | ws_opterr = 0;
1232 |
1233 | /* We should check at first if we should use a global profile before
1234 | parsing the profile name
1235 | XXX - We could check this in the next ws_getopt_long, and save the
1236 | profile name and only apply it after finishing the loop. */
1237 | while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL((void*)0))) != -1) {
1238 | switch (opt) {
1239 | case LONGOPT_GLOBAL_PROFILE3000 +10:
1240 | set_persconffile_dir(get_datafile_dir(application_configuration_environment_prefix()));
1241 | break;
1242 | default:
1243 | break;
1244 | }
1245 | }
1246 |
1247 | /*
1248 | * Reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
1249 | * We still don't want to print error messages, though.
1250 | */
1251 | ws_optreset = 1;
1252 | ws_optind = 1;
1253 |
1254 | while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL((void*)0))) != -1) {
1255 | switch (opt) {
1256 | case 'C': /* Configuration Profile */
1257 | if (profile_exists(application_configuration_environment_prefix(), ws_optarg, false0)) {
1258 | set_profile_name (ws_optarg);
1259 | } else if (profile_exists(application_configuration_environment_prefix(), ws_optarg, true1)) {
1260 | char *pf_dir_path, *pf_dir_path2, *pf_filename;
1261 | /* Copy from global profile */
1262 | if (create_persconffile_profile(application_configuration_environment_prefix(), ws_optarg, &pf_dir_path) == -1) {
1263 | cmdarg_err("Can't create directory\n\"%s\":\n%s.",
1264 | pf_dir_path, g_strerror(errno(*__errno_location ())));
1265 |
1266 | g_free(pf_dir_path);
1267 | exit_status = WS_EXIT_INVALID_FILE3;
1268 | goto clean_exit;
1269 | }
1270 | if (copy_persconffile_profile(application_configuration_environment_prefix(), ws_optarg, ws_optarg, true1, &pf_filename,
1271 | &pf_dir_path, &pf_dir_path2) == -1) {
1272 | cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
1273 | pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno(*__errno_location ())));
1274 |
1275 | g_free(pf_filename);
1276 | g_free(pf_dir_path);
1277 | g_free(pf_dir_path2);
1278 | exit_status = WS_EXIT_INVALID_FILE3;
1279 | goto clean_exit;
1280 | }
1281 | set_profile_name (ws_optarg);
1282 | } else {
1283 | cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg);
1284 | exit_status = WS_EXIT_INVALID_OPTION1;
1285 | goto clean_exit;
1286 | }
1287 | break;
1288 | case 'G':
1289 | if (glossary != NULL((void*)0)) {
1290 | /* Multiple glossaries are difficult especially due to defaultprefs */
1291 | cmdarg_err("Multiple glossary reports (-G) are unsupported");
1292 | exit_status = WS_EXIT_INVALID_OPTION1;
1293 | goto clean_exit;
1294 | } else {
1295 | glossary = ws_optarg;
1296 | }
1297 | if (g_str_has_suffix(ws_optarg, "prefs")(__builtin_constant_p ("prefs")? __extension__ ({ const char * const __str = (ws_optarg); const char * const __suffix = ("prefs" ); gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix ))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(__suffix)), __suffix_len ) == 0; } __result; }) : (g_str_has_suffix) (ws_optarg, "prefs" ) )) {
1298 | has_extcap_options = true1;
1299 | }
1300 | is_capturing = false0;
1301 | break;
1302 | case 'i':
1303 | has_extcap_options = true1;
1304 | break;
1305 | case 'o':
1306 | if (g_str_has_prefix(ws_optarg, "extcap.")(__builtin_constant_p ("extcap.")? __extension__ ({ const char * const __str = (ws_optarg); const char * const __prefix = ( "extcap."); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str , __prefix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix ) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (ws_optarg, "extcap." ) )) {
1307 | has_extcap_options = true1;
1308 | }
1309 | break;
1310 | case 'P': /* Print packet summary info even when writing to a file */
1311 | print_packet_info = true1;
1312 | print_summary = true1;
1313 | break;
1314 | case 'r': /* Read capture file x */
1315 | cf_name = g_strdup(ws_optarg)g_strdup_inline (ws_optarg);
1316 | is_capturing = false0;
1317 | break;
1318 | case 'O': /* Only output these protocols */
1319 | output_only = g_strdup(ws_optarg)g_strdup_inline (ws_optarg);
1320 | /* FALLTHROUGH */
1321 | case 'V': /* Verbose */
1322 | print_details = true1;
1323 | print_packet_info = true1;
1324 | break;
1325 | case 'x': /* Print packet data in hex (and ASCII) */
1326 | print_hex = true1;
1327 | /* The user asked for hex output, so let's ensure they get it,
1328 | * even if they're writing to a file.
1329 | */
1330 | print_packet_info = true1;
1331 | break;
1332 | case 'X':
1333 | ex_opt_add(ws_optarg);
1334 | break;
1335 | case 'h':
1336 | case 'v':
1337 | is_capturing = false0;
1338 | break;
1339 | default:
1340 | break;
1341 | }
1342 | }
1343 |
1344 | #ifndef HAVE_LUA1
1345 | if (ex_opt_count("lua_script") > 0) {
1346 | cmdarg_err("This version of TShark was not built with support for Lua scripting.");
1347 | exit_status = WS_EXIT_INIT_FAILED8;
1348 | goto clean_exit;
1349 | }
1350 | #endif /* HAVE_LUA */
1351 |
1352 | init_report_failure_message("TShark");
1353 |
1354 | #ifdef HAVE_LIBPCAP1
1355 | capture_opts_init(&global_capture_opts, application_flavor_name_lower(), capture_opts_get_interface_list);
1356 | capture_session_init(&global_capture_session, &cfile,
1357 | capture_input_new_file, capture_input_new_packets,
1358 | capture_input_drops, capture_input_error,
1359 | capture_input_cfilter_error, capture_input_closed);
1360 | #endif
1361 |
1362 | timestamp_set_type(TS_RELATIVE);
1363 | timestamp_set_precision(TS_PREC_AUTO);
1364 | timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
1365 |
1366 | /*
1367 | * Libwiretap must be initialized before libwireshark is, so that
1368 | * dissection-time handlers for file-type-dependent blocks can
1369 | * register using the file type/subtype value for the file type.
1370 | */
1371 | application_file_extensions(&file_extensions, &num_extensions);
1372 | wtap_init(true1, application_configuration_environment_prefix(), file_extensions, num_extensions);
1373 |
1374 | /* Register all dissectors; we must do this before checking for the
1375 | "-G" flag, as the "-G" flag dumps information registered by the
1376 | dissectors, and we must do it before we read the preferences, in
1377 | case any dissectors register preferences. */
1378 | app_data.env_var_prefix = application_configuration_environment_prefix();
1379 | app_data.col_fmt = application_columns();
1380 | app_data.num_cols = application_num_columns();
1381 | app_data.register_func = register_all_protocols;
1382 | app_data.handoff_func = register_all_protocol_handoffs;
1383 | app_data.tap_reg_listeners = tap_reg_listener;
1384 | if (!epan_init(NULL((void*)0), NULL((void*)0), true1, &app_data)) {
1385 | exit_status = WS_EXIT_INIT_FAILED8;
1386 | goto clean_exit;
1387 | }
1388 |
1389 | /* Register extcap preferences only when needed. */
1390 | if (has_extcap_options || is_capturing) {
1391 | /*
1392 | * XXX - We don't properly handle the capture_no_extcap preference.
1393 | * To make it work, before registering the extcap preferences we'd
1394 | * have to read at least that preference for the chosen profile, and
1395 | * also check to make sure an "-o" option didn't override it.
1396 | * Then, after registering the extcap preferences, we'd have to
1397 | * set the extcap preferences from the preferences file and "-o"
1398 | * options on the command line.
1399 | */
1400 | extcap_register_preferences();
1401 | }
1402 |
1403 | conversation_table_set_gui_info(init_iousers);
1404 | endpoint_table_set_gui_info(init_endpoints);
1405 | srt_table_iterate_tables(register_srt_tables, NULL((void*)0));
1406 | rtd_table_iterate_tables(register_rtd_tables, NULL((void*)0));
1407 | stat_tap_iterate_tables(register_simple_stat_tables, NULL((void*)0));
1408 |
1409 | ws_debug("tshark reading settings")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 1409, __func__, "tshark reading settings"); } } while (0);
1410 |
1411 | /* Load libwireshark settings from the current profile. */
1412 | prefs_p = epan_load_settings();
1413 | prefs_loaded = true1;
1414 |
1415 | cap_file_init(&cfile);
1416 |
1417 | /* Print format defaults to this. */
1418 | print_format = PR_FMT_TEXT;
1419 | delimiter_char = " ";
1420 |
1421 | output_fields = output_fields_new();
1422 |
1423 | /*
1424 | * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
1425 | *
1426 | * Also reset ws_opterr to 1, so that error messages are printed by
1427 | * getopt_long().
1428 | */
1429 | ws_optreset = 1;
1430 | ws_optind = 1;
1431 | ws_opterr = 1;
1432 |
1433 | /* Now get our args */
1434 | while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL((void*)0))) != -1) {
1435 | switch (opt) {
1436 | case '2': /* Perform two-pass analysis */
1437 | if(epan_auto_reset){
1438 | cmdarg_err("-2 does not support auto session reset.");
1439 | arg_error=true1;
1440 | }
1441 | perform_two_pass_analysis = true1;
1442 | break;
1443 | case 'M':
1444 | if(perform_two_pass_analysis){
1445 | cmdarg_err("-M does not support two-pass analysis.");
1446 | arg_error=true1;
1447 | }
1448 | if (!get_uint32(ws_optarg, "epan reset count", &epan_auto_reset_count))
1449 | arg_error = true1;
1450 |
1451 | epan_auto_reset = true1;
1452 | break;
1453 | case 'a': /* autostop criteria */
1454 | case 'b': /* Ringbuffer option */
1455 | case 'f': /* capture filter */
1456 | case 'g': /* enable group read access on file(s) */
1457 | case 'i': /* Use interface x */
1458 | case LONGOPT_SET_TSTAMP_TYPE1000 +2: /* Set capture timestamp type */
1459 | case 'p': /* Don't capture in promiscuous mode */
1460 | #ifdef HAVE_PCAP_REMOTE
1461 | case 'A': /* Authentication */
1462 | #endif
1463 | case 'I': /* Capture in monitor mode, if available */
1464 | case 's': /* Set the snapshot (capture) length */
1465 | case 'y': /* Set the pcap data link type */
1466 | case 'B': /* Buffer size */
1467 | case LONGOPT_NO_OPTIMIZE1000 +6: /* Don't optimize capture filter */
1468 | case LONGOPT_COMPRESS_TYPE1000 +3: /* compress type */
1469 | case LONGOPT_CAPTURE_TMPDIR1000 +4: /* capture temp directory */
1470 | case LONGOPT_UPDATE_INTERVAL1000 +5: /* sync pipe update interval */
1471 | /* These are options only for packet capture. */
1472 | #ifdef HAVE_LIBPCAP1
1473 | exit_status = capture_opts_add_opt(application_configuration_environment_prefix(), &global_capture_opts, opt, ws_optarg);
1474 | if (exit_status != 0) {
1475 | goto clean_exit;
1476 | }
1477 | #else
1478 | capture_option_specified = true1;
1479 | arg_error = true1;
1480 | #endif
1481 | break;
1482 | case 'c': /* Stop after x packets */
1483 | #ifdef HAVE_LIBPCAP1
1484 | exit_status = capture_opts_add_opt(application_configuration_environment_prefix(), &global_capture_opts, opt, ws_optarg);
1485 | if (exit_status != 0) {
1486 | goto clean_exit;
1487 | }
1488 | #else
1489 | if (!get_positive_int(ws_optarg, "packet count", &max_packet_count)) {
1490 | exit_status = WS_EXIT_INVALID_OPTION1;
1491 | goto clean_exit;
1492 | }
1493 | #endif
1494 | break;
1495 | case 'w': /* Write to file x */
1496 | output_file_name = g_strdup(ws_optarg)g_strdup_inline (ws_optarg);
1497 | #ifdef HAVE_LIBPCAP1
1498 | exit_status = capture_opts_add_opt(application_configuration_environment_prefix(), &global_capture_opts, opt, ws_optarg);
1499 | if (exit_status != 0) {
1500 | goto clean_exit;
1501 | }
1502 | #endif
1503 | break;
1504 | case 'C':
1505 | /* already processed; just ignore it now */
1506 | break;
1507 | case 'D': /* Print a list of capture devices and exit */
1508 | #ifdef HAVE_LIBPCAP1
1509 | exit_status = EXIT_SUCCESS0;
1510 | if_list = capture_interface_list(global_capture_opts.app_name, &err, &err_str,NULL((void*)0));
1511 | if (err != 0) {
1512 | /*
1513 | * An error occurred when fetching the local
1514 | * interfaces. Report it.
1515 | */
1516 | cmdarg_err("%s", err_str);
1517 | g_free(err_str);
1518 | exit_status = WS_EXIT_PCAP_ERROR13;
1519 | }
1520 | if (if_list == NULL((void*)0)) {
1521 | /*
1522 | * No interfaces were found. If that's not the
1523 | * result of an error when fetching the local
1524 | * interfaces, let the user know.
1525 | */
1526 | if (err == 0) {
1527 | cmdarg_err("There are no interfaces on which a capture can be done");
1528 | exit_status = WS_EXIT_NO_INTERFACES12;
1529 | }
1530 | goto clean_exit;
1531 | }
1532 | capture_opts_print_interfaces(if_list);
1533 | free_interface_list(if_list);
1534 | goto clean_exit;
1535 | #else
1536 | capture_option_specified = true1;
1537 | arg_error = true1;
1538 | #endif
1539 | break;
1540 | case 'e':
1541 | /* Field entry */
1542 | {
1543 | const char* col_field = try_convert_to_column_field(ws_optarg);
1544 | if (col_field) {
1545 | output_fields_add(output_fields, col_field);
1546 | } else {
1547 | header_field_info *hfi = proto_registrar_get_byalias(ws_optarg);
1548 | if (hfi)
1549 | output_fields_add(output_fields, hfi->abbrev);
1550 | else
1551 | output_fields_add(output_fields, ws_optarg);
1552 | }
1553 | }
1554 | break;
1555 | case 'E':
1556 | /* Field option */
1557 | if (!output_fields_set_option(output_fields, ws_optarg)) {
1558 | cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg);
1559 | output_fields_list_options(stderrstderr);
1560 | exit_status = WS_EXIT_INVALID_OPTION1;
1561 | goto clean_exit;
1562 | }
1563 | break;
1564 | case 'F':
1565 | out_file_type = wtap_name_to_file_type_subtype(ws_optarg);
1566 | if (out_file_type < 0) {
1567 | cmdarg_err("\"%s\" isn't a valid capture file type", ws_optarg);
1568 | list_capture_types();
1569 | exit_status = WS_EXIT_INVALID_OPTION1;
1570 | goto clean_exit;
1571 | }
1572 | break;
1573 | case 'G':
1574 | /* already processed; just ignore it now */
1575 | break;
1576 | case 'j':
1577 | if (!protocolfilter_add_opt(ws_optarg, PF_NONE)) {
1578 | exit_status = WS_EXIT_INVALID_OPTION1;
1579 | goto clean_exit;
1580 | }
1581 | break;
1582 | case 'J':
1583 | if (!protocolfilter_add_opt(ws_optarg, PF_INCLUDE_CHILDREN)) {
1584 | exit_status = WS_EXIT_INVALID_OPTION1;
1585 | goto clean_exit;
1586 | }
1587 | break;
1588 | case 'W': /* Select extra information to save in our capture file */
1589 | /* This is patterned after the -N flag which may not be the best idea. */
1590 | if (strchr(ws_optarg, 'n')) {
1591 | out_file_name_res = true1;
1592 | } else {
1593 | cmdarg_err("Invalid -W argument \"%s\"; it must be one of:", ws_optarg);
1594 | cmdarg_err_cont("\t'n' write network address resolution information (pcapng only)");
1595 | exit_status = WS_EXIT_INVALID_OPTION1;
1596 | goto clean_exit;
1597 | }
1598 | break;
1599 | case 'H': /* Read address to name mappings from a hosts file */
1600 | if (! add_hosts_file(ws_optarg))
1601 | {
1602 | cmdarg_err("Can't read host entries from \"%s\"", ws_optarg);
1603 | exit_status = WS_EXIT_INVALID_OPTION1;
1604 | goto clean_exit;
1605 | }
1606 | out_file_name_res = true1;
1607 | break;
1608 |
1609 | case 'h': /* Print help and exit */
1610 | show_help_header("Dump and analyze network traffic.");
1611 | print_usage(stdoutstdout);
1612 | exit_status = EXIT_SUCCESS0;
1613 | goto clean_exit;
1614 | break;
1615 | case 'l': /* "Line-buffer" standard output */
1616 | /* The ANSI C standard does not appear to *require* that a line-buffered
1617 | stream be flushed to the host environment whenever a newline is
1618 | written, it just says that, on such a stream, characters "are
1619 | intended to be transmitted to or from the host environment as a
1620 | block when a new-line character is encountered".
1621 |
1622 | The Visual C++ 6.0 C implementation doesn't do what is intended;
1623 | even if you set a stream to be line-buffered, it still doesn't
1624 | flush the buffer at the end of every line.
1625 |
1626 | The whole reason for the "-l" flag in either tcpdump or TShark
1627 | is to allow the output of a live capture to be piped to a program
1628 | or script and to have that script see the information for the
1629 | packet as soon as it's printed, rather than having to wait until
1630 | a standard I/O buffer fills up.
1631 |
1632 | So, if the "-l" flag is specified, we flush the standard output
1633 | at the end of a packet. This will do the right thing if we're
1634 | printing packet summary lines, and, as we print the entire protocol
1635 | tree for a single packet without waiting for anything to happen,
1636 | it should be as good as line-buffered mode if we're printing
1637 | protocol trees - arguably even better, as it may do fewer
1638 | writes. */
1639 | line_buffered = true1;
1640 | #ifdef HAVE_LIBPCAP1
1641 | /* Set the update-interval to 0 so that dumpcap reports packets
1642 | * as soon as available instead of buffering them.
1643 | */
1644 | exit_status = capture_opts_add_opt(application_configuration_environment_prefix(), &global_capture_opts, opt, ws_optarg);
1645 | if (exit_status != 0) {
1646 | goto clean_exit;
1647 | }
1648 | #endif
1649 | break;
1650 | case 'L': /* Print list of link-layer types and exit */
1651 | #ifdef HAVE_LIBPCAP1
1652 | caps_queries |= CAPS_QUERY_LINK_TYPES;
1653 | #else
1654 | capture_option_specified = true1;
1655 | arg_error = true1;
1656 | #endif
1657 | break;
1658 | case LONGOPT_LIST_TSTAMP_TYPES1000 +1: /* List possible timestamp types */
1659 | #ifdef HAVE_LIBPCAP1
1660 | caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
1661 | #else
1662 | capture_option_specified = true1;
1663 | arg_error = true1;
1664 | #endif
1665 | break;
1666 | case 'o': /* Override preference from command line */
1667 | {
1668 | char *errmsg = NULL((void*)0);
1669 |
1670 | switch (prefs_set_pref(ws_optarg, &errmsg)) {
1671 |
1672 | case PREFS_SET_OK:
1673 | break;
1674 |
1675 | case PREFS_SET_SYNTAX_ERR:
1676 | cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
1677 | errmsg ? ": " : "", errmsg ? errmsg : "");
1678 | g_free(errmsg);
1679 | exit_status = WS_EXIT_INVALID_OPTION1;
1680 | goto clean_exit;
1681 | break;
1682 |
1683 | case PREFS_SET_NO_SUCH_PREF:
1684 | cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
1685 | exit_status = WS_EXIT_INVALID_OPTION1;
1686 | goto clean_exit;
1687 | break;
1688 |
1689 | case PREFS_SET_OBSOLETE:
1690 | cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
1691 | exit_status = WS_EXIT_INVALID_OPTION1;
1692 | goto clean_exit;
1693 | break;
1694 | }
1695 | break;
1696 | }
1697 | case 'q': /* Quiet */
1698 | quiet = true1;
1699 | break;
1700 | case 'Q': /* Really quiet */
1701 | quiet = true1;
1702 | really_quiet = true1;
1703 | break;
1704 | case 'r':
1705 | /* already processed; just ignore it now */
1706 | break;
1707 | case 'R': /* Read file filter */
1708 | rfilter = ws_optarg;
1709 | break;
1710 | case 'P':
1711 | /* already processed; just ignore it now */
1712 | break;
1713 | case 'S': /* Set the line Separator to be printed between packets */
1714 | separator = ws_optarg;
1715 | break;
1716 | case 'T': /* printing Type */
1717 | /* output_action has been already set. It means multiple -T. */
1718 | if (output_action > WRITE_NONE) {
1719 | cmdarg_err("Multiple -T parameters are unsupported");
1720 | exit_status = WS_EXIT_INVALID_OPTION1;
1721 | goto clean_exit;
1722 | }
1723 | print_packet_info = true1;
1724 | if (strcmp(ws_optarg, "text") == 0) {
1725 | output_action = WRITE_TEXT;
1726 | print_format = PR_FMT_TEXT;
1727 | } else if (strcmp(ws_optarg, "tabs") == 0) {
1728 | output_action = WRITE_TEXT;
1729 | print_format = PR_FMT_TEXT;
1730 | delimiter_char = "\t";
1731 | } else if (strcmp(ws_optarg, "ps") == 0) {
1732 | output_action = WRITE_TEXT;
1733 | print_format = PR_FMT_PS;
1734 | } else if (strcmp(ws_optarg, "pdml") == 0) {
1735 | output_action = WRITE_XML;
1736 | print_details = true1; /* Need details */
1737 | print_summary = false0; /* Don't allow summary */
1738 | } else if (strcmp(ws_optarg, "psml") == 0) {
1739 | output_action = WRITE_XML;
1740 | print_details = false0; /* Don't allow details */
1741 | print_summary = true1; /* Need summary */
1742 | } else if (strcmp(ws_optarg, "fields") == 0) {
1743 | output_action = WRITE_FIELDS;
1744 | print_details = true1; /* Need full tree info */
1745 | print_summary = false0; /* Don't allow summary */
1746 | } else if (strcmp(ws_optarg, "json") == 0) {
1747 | output_action = WRITE_JSON;
1748 | print_details = true1; /* Need details */
1749 | print_summary = false0; /* Don't allow summary */
1750 | } else if (strcmp(ws_optarg, "ek") == 0) {
1751 | output_action = WRITE_EK;
1752 | if (!print_summary)
1753 | print_details = true1;
1754 | } else if (strcmp(ws_optarg, "jsonraw") == 0) {
1755 | output_action = WRITE_JSON_RAW;
1756 | print_details = true1; /* Need details */
1757 | print_summary = false0; /* Don't allow summary */
1758 | }
1759 | else {
1760 | cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */
1761 | cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
1762 | "\t specified by the -E option.\n"
1763 | "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
1764 | "\t details of a decoded packet. This information is equivalent to\n"
1765 | "\t the packet details printed with the -V flag.\n"
1766 | "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
1767 | "\t the packets, or a multi-line view of the details of each of\n"
1768 | "\t the packets, depending on whether the -V flag was specified.\n"
1769 | "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
1770 | "\t summary information of a decoded packet. This information is\n"
1771 | "\t equivalent to the information shown in the one-line summary\n"
1772 | "\t printed by default.\n"
1773 | "\t\"json\" Packet Summary, an JSON-based format for the details\n"
1774 | "\t summary information of a decoded packet. This information is \n"
1775 | "\t equivalent to the packet details printed with the -V flag.\n"
1776 | "\t\"jsonraw\" Packet Details, a JSON-based format for machine parsing\n"
1777 | "\t including only raw hex decoded fields (same as -T json -x but\n"
1778 | "\t without text decoding, only raw fields included). \n"
1779 | "\t\"ek\" Packet Details, an EK JSON-based format for the bulk insert \n"
1780 | "\t into elastic search cluster. This information is \n"
1781 | "\t equivalent to the packet details printed with the -V flag.\n"
1782 | "\t\"text\" Text of a human-readable one-line summary of each of the\n"
1783 | "\t packets, or a multi-line view of the details of each of the\n"
1784 | "\t packets, depending on whether the -V flag was specified.\n"
1785 | "\t This is the default.\n"
1786 | "\t\"tabs\" Similar to the text report except that each column of the\n"
1787 | "\t human-readable one-line summary is delimited with an ASCII\n"
1788 | "\t horizontal tab character.");
1789 | exit_status = WS_EXIT_INVALID_OPTION1;
1790 | goto clean_exit;
1791 | }
1792 | break;
1793 | case 'U': /* Export PDUs to file */
1794 | if (strcmp(ws_optarg, "") == 0 || strcmp(ws_optarg, "?") == 0) {
1795 | list_export_pdu_taps();
1796 | exit_status = WS_EXIT_INVALID_OPTION1;
1797 | goto clean_exit;
1798 | }
1799 | pdu_export_arg = g_strdup(ws_optarg)g_strdup_inline (ws_optarg);
1800 | break;
1801 | case 'v': /* Show version and exit */
1802 | #ifdef ENABLE_CHECK_FILTER
1803 | /* If we're testing start-up of the epan library, go ahead and
1804 | * load all the delayed initialization prefixes (e.g. Diameter)
1805 | * so that they are reported on.
1806 | */
1807 | proto_initialize_all_prefixes();
1808 | #endif
1809 | show_version();
1810 | /* We don't really have to cleanup here, but it's a convenient way to test
1811 | * start-up and shut-down of the epan library without any UI-specific
1812 | * cruft getting in the way. Makes the results of running
1813 | * $ ./tools/valgrind-wireshark -n
1814 | * much more useful. */
1815 | epan_cleanup();
1816 | extcap_cleanup();
1817 | exit_status = EXIT_SUCCESS0;
1818 | goto clean_exit;
1819 | case 'O': /* Only output these protocols */
1820 | /* already processed; just ignore it now */
1821 | break;
1822 | case 'V': /* Verbose */
1823 | /* already processed; just ignore it now */
1824 | break;
1825 | case 'x': /* Print packet data in hex (and ASCII) */
1826 | /* already processed; just ignore it now */
1827 | break;
1828 | case 'X':
1829 | /* already processed; just ignore it now */
1830 | break;
1831 | case 'Y':
1832 | dfilter = g_strdup(ws_optarg)g_strdup_inline (ws_optarg);
1833 | break;
1834 | case 'z':
1835 | /* We won't call the init function for the stat this soon
1836 | as it would disallow MATE's fields (which are registered
1837 | by the preferences set callback) from being used as
1838 | part of a tap filter. Instead, we just add the argument
1839 | to a list of stat arguments. */
1840 | if (strcmp("help", ws_optarg) == 0) {
1841 | fprintf(stderrstderr, "tshark: The available statistics for the \"-z\" option are:\n");
1842 | list_stat_cmd_args();
1843 | exit_status = EXIT_SUCCESS0;
1844 | goto clean_exit;
1845 | }
1846 | if (!process_stat_cmd_arg(ws_optarg)) {
1847 | cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg);
1848 | list_stat_cmd_args();
1849 | exit_status = WS_EXIT_INVALID_OPTION1;
1850 | goto clean_exit;
1851 | }
1852 | break;
1853 | case 'd': /* Decode as rule */
1854 | case 'K': /* Kerberos keytab file */
1855 | case 'n': /* No name resolution */
1856 | case 'N': /* Select what types of addresses/port #s to resolve */
1857 | case 't': /* Time stamp type */
1858 | case 'u': /* Seconds type */
1859 | case LONGOPT_DISABLE_PROTOCOL2000 +1: /* disable dissection of protocol */
1860 | case LONGOPT_ENABLE_HEURISTIC2000 +2: /* enable heuristic dissection of protocol */
1861 | case LONGOPT_DISABLE_HEURISTIC2000 +3: /* disable heuristic dissection of protocol */
1862 | case LONGOPT_ENABLE_PROTOCOL2000 +4: /* enable dissection of protocol (that is disabled by default) */
1863 | case LONGOPT_ONLY_PROTOCOLS2000 +5: /* enable dissection of only this comma separated list of protocols */
1864 | case LONGOPT_DISABLE_ALL_PROTOCOLS2000 +6: /* enable dissection of protocol (that is disabled by default) */
1865 | if (!dissect_opts_handle_opt(opt, ws_optarg)) {
1866 | exit_status = WS_EXIT_INVALID_OPTION1;
1867 | goto clean_exit;
1868 | }
1869 | break;
1870 | case LONGOPT_EXPORT_OBJECTS3000 +1: /* --export-objects */
1871 | if (strcmp("help", ws_optarg) == 0) {
1872 | fprintf(stderrstderr, "tshark: The available export object types for the \"--export-objects\" option are:\n");
1873 | eo_list_object_types();
1874 | exit_status = EXIT_SUCCESS0;
1875 | goto clean_exit;
1876 | }
1877 | if (!eo_tap_opt_add(ws_optarg)) {
1878 | exit_status = WS_EXIT_INVALID_OPTION1;
1879 | goto clean_exit;
1880 | }
1881 | break;
1882 | case LONGOPT_EXPORT_TLS_SESSION_KEYS3000 +5: /* --export-tls-session-keys */
1883 | tls_session_keys_file = ws_optarg;
1884 | break;
1885 | case LONGOPT_COLOR3000 +2: /* print in color where appropriate */
1886 | dissect_color = true1;
1887 | /* This has no effect if we don't print packet info or filter
1888 | (we can filter on the coloring rules). Should we warn or
1889 | error later if so, instead of silently ignoring it? */
1890 | break;
1891 | case LONGOPT_NO_DUPLICATE_KEYS3000 +3:
1892 | no_duplicate_keys = true1;
1893 | node_children_grouper = proto_node_group_children_by_json_key;
1894 | break;
1895 | case LONGOPT_ELASTIC_MAPPING_FILTER3000 +4:
1896 | /*
1897 | * XXX - A long option that exists to alter one other option
1898 | * (-G elastic-mapping) and for no other reason seems verbose.
1899 | * Deprecate in favor of -G elastic-mapping,<filter> ?
1900 | */
1901 | elastic_mapping_filter = ws_optarg;
1902 | break;
1903 | case LONGOPT_CAPTURE_COMMENT3000 +6: /* capture comment */
1904 | if (capture_comments == NULL((void*)0)) {
1905 | capture_comments = g_ptr_array_new_with_free_func(g_free);
1906 | }
1907 | g_ptr_array_add(capture_comments, g_strdup(ws_optarg)g_strdup_inline (ws_optarg));
1908 | break;
1909 | case LONGOPT_HEXDUMP3000 +7:
1910 | print_hex = true1;
1911 | print_packet_info = true1;
1912 | if (strcmp(ws_optarg, "all") == 0)
1913 | hexdump_source_option = HEXDUMP_SOURCE_MULTI(0x0000U);
1914 | else if (strcmp(ws_optarg, "frames") == 0)
1915 | hexdump_source_option = HEXDUMP_SOURCE_PRIMARY(0x0004U);
1916 | else if (strcmp(ws_optarg, "ascii") == 0)
1917 | hexdump_ascii_option = HEXDUMP_ASCII_INCLUDE(0x0000U);
1918 | else if (strcmp(ws_optarg, "delimit") == 0)
1919 | hexdump_ascii_option = HEXDUMP_ASCII_DELIMIT(0x0001U);
1920 | else if (strcmp(ws_optarg, "noascii") == 0)
1921 | hexdump_ascii_option = HEXDUMP_ASCII_EXCLUDE(0x0002U);
1922 | else if (strcmp(ws_optarg, "time") == 0)
1923 | hexdump_timestamp_option = HEXDUMP_TIMESTAMP(0x0008U);
1924 | else if (strcmp(ws_optarg, "notime") == 0)
1925 | hexdump_timestamp_option = HEXDUMP_TIMESTAMP_NONE(0x0000U);
1926 | else if (strcmp("help", ws_optarg) == 0) {
1927 | hexdump_option_help(stdoutstdout);
1928 | exit_status = EXIT_SUCCESS0;
1929 | goto clean_exit;
1930 | } else {
1931 | fprintf(stderrstderr, "tshark: \"%s\" is an invalid value for --hexdump <hexoption>\n", ws_optarg);
1932 | fprintf(stderrstderr, "For valid <hexoption> values enter: tshark --hexdump help\n");
1933 | exit_status = WS_EXIT_INVALID_OPTION1;
1934 | goto clean_exit;
1935 | }
1936 | break;
1937 | case LONGOPT_SELECTED_FRAME3000 +8:
1938 | /* Hidden option to mark a frame as "selected". Used for testing and debugging.
1939 | * Only active in two-pass mode. */
1940 | if (!ws_strtou32(ws_optarg, NULL((void*)0), &selected_frame_number)) {
1941 | fprintf(stderrstderr, "tshark: \"%s\" is not a valid frame number\n", ws_optarg);
1942 | exit_status = WS_EXIT_INVALID_OPTION1;
1943 | goto clean_exit;
1944 | }
1945 | break;
1946 | case LONGOPT_PRINT_TIMERS3000 +9:
1947 | opt_print_timers = true1;
1948 | break;
1949 | case LONGOPT_GLOBAL_PROFILE3000 +10:
1950 | /* already processed; just ignore it now */
1951 | break;
1952 | case LONGOPT_COMPRESS3000 +11: /* compress type */
1953 | compression_type = ws_name_to_compression_type(ws_optarg);
1954 | if (compression_type == WS_FILE_UNKNOWN_COMPRESSION) {
1955 | cmdarg_err("\"%s\" isn't a valid output compression mode",
1956 | ws_optarg);
1957 | list_output_compression_types();
1958 | goto clean_exit;
1959 | }
1960 | break;
1961 | case '?': /* Bad flag - print usage message */
1962 | default:
1963 | /* wslog arguments are okay */
1964 | if (ws_log_is_wslog_arg(opt))
1965 | break;
1966 |
1967 | switch(ws_optopt) {
1968 | case 'F':
1969 | list_capture_types();
1970 | break;
1971 | case 'G':
1972 | glossary_option_help();
1973 | break;
1974 | case LONGOPT_COMPRESS3000 +11:
1975 | case LONGOPT_COMPRESS_TYPE1000 +3:
1976 | list_output_compression_types();
1977 | break;
1978 | default:
1979 | print_usage(stderrstderr);
1980 | }
1981 | exit_status = WS_EXIT_INVALID_OPTION1;
1982 | goto clean_exit;
1983 | break;
1984 | }
1985 | }
1986 |
1987 | /* set the default output action to TEXT */
1988 | if (output_action == WRITE_NONE)
1989 | output_action = WRITE_TEXT;
1990 |
1991 | /* set the default file type to pcapng */
1992 | if (out_file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN-1)
1993 | out_file_type = wtap_pcapng_file_type_subtype();
1994 |
1995 | /*
1996 | * Print packet summary information is the default if neither -V or -x
1997 | * were specified. Note that this is new behavior, which allows for the
1998 | * possibility of printing only hex/ascii output without necessarily
1999 | * requiring that either the summary or details be printed too.
2000 | */
2001 | if (!print_summary && !print_details && !print_hex)
2002 | print_summary = true1;
2003 |
2004 | if (no_duplicate_keys && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW) {
2005 | cmdarg_err("--no-duplicate-keys can only be used with \"-T json\" and \"-T jsonraw\"");
2006 | exit_status = WS_EXIT_INVALID_OPTION1;
2007 | goto clean_exit;
2008 | }
2009 |
2010 | /* If we specified output fields, but not the output field type... */
2011 | /* XXX: If we specified both output fields with -e *and* protocol filters
2012 | * with -j/-J, only the former are used. Should we warn or abort?
2013 | * This also doesn't distinguish PDML from PSML, but shouldn't allow the
2014 | * latter.
2015 | */
2016 | if ((WRITE_FIELDS != output_action && WRITE_XML != output_action && WRITE_JSON != output_action && WRITE_EK != output_action) && 0 != output_fields_num_fields(output_fields)) {
2017 | cmdarg_err("Output fields were specified with \"-e\", "
2018 | "but \"-Tek, -Tfields, -Tjson or -Tpdml\" was not specified.");
2019 | exit_status = WS_EXIT_INVALID_OPTION1;
2020 | goto clean_exit;
2021 | } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
2022 | cmdarg_err("\"-Tfields\" was specified, but no fields were "
2023 | "specified with \"-e\".");
2024 |
2025 | exit_status = WS_EXIT_INVALID_OPTION1;
2026 | goto clean_exit;
2027 | }
2028 |
2029 | if (dissect_color) {
2030 | if (!color_filters_init(&err_msg, NULL((void*)0), application_configuration_environment_prefix())) {
2031 | fprintf(stderrstderr, "%s\n", err_msg);
2032 | g_free(err_msg);
2033 | }
2034 | }
2035 |
2036 | /* If no capture filter or display filter has been specified, and there are
2037 | still command-line arguments, treat them as the tokens of a capture
2038 | filter (if no "-r" flag was specified) or a display filter (if a "-r"
2039 | flag was specified. */
2040 | if (ws_optind < argc) {
2041 | if (cf_name != NULL((void*)0)) {
2042 | if (dfilter != NULL((void*)0)) {
2043 | cmdarg_err("Display filters were specified both with \"-Y\" "
2044 | "and with additional command-line arguments.");
2045 | exit_status = WS_EXIT_INVALID_OPTION1;
2046 | goto clean_exit;
2047 | }
2048 | dfilter = get_args_as_string(argc, argv, ws_optind);
2049 | } else {
2050 | #ifdef HAVE_LIBPCAP1
2051 | unsigned i;
2052 |
2053 | if (global_capture_opts.default_options.cfilter) {
2054 | cmdarg_err("A default capture filter was specified both with \"-f\""
2055 | " and with additional command-line arguments.");
2056 | exit_status = WS_EXIT_INVALID_OPTION1;
2057 | goto clean_exit;
2058 | }
2059 | for (i = 0; i < global_capture_opts.ifaces->len; i++) {
2060 | interface_options *interface_opts;
2061 | interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i)(((interface_options*) (void *) (global_capture_opts.ifaces)-> data) [(i)]);
2062 | if (interface_opts->cfilter == NULL((void*)0)) {
2063 | interface_opts->cfilter = get_args_as_string(argc, argv, ws_optind);
2064 | } else {
2065 | cmdarg_err("A capture filter was specified both with \"-f\""
2066 | " and with additional command-line arguments.");
2067 | exit_status = WS_EXIT_INVALID_OPTION1;
2068 | goto clean_exit;
2069 | }
2070 | }
2071 | global_capture_opts.default_options.cfilter = get_args_as_string(argc, argv, ws_optind);
2072 | #else
2073 | capture_option_specified = true1;
2074 | #endif
2075 | }
2076 | }
2077 |
2078 | if (!output_file_name) {
2079 | /* We're not saving the capture to a file; if "-q" wasn't specified,
2080 | we should print packet information */
2081 | if (!quiet)
2082 | print_packet_info = true1;
2083 | } else {
2084 | const char *save_file = output_file_name;
2085 | /* We're saving to a file; if we're writing to the standard output.
2086 | and we'll also be writing dissected packets to the standard
2087 | output, reject the request. At best, we could redirect that
2088 | to the standard error; we *can't* write both to the standard
2089 | output and have either of them be useful. */
2090 | if (strcmp(save_file, "-") == 0 && print_packet_info) {
2091 | cmdarg_err("You can't write both raw packet data and dissected packets"
2092 | " to the standard output.");
2093 | exit_status = WS_EXIT_INVALID_OPTION1;
2094 | goto clean_exit;
2095 | }
2096 | if (compression_type == WS_FILE_UNKNOWN_COMPRESSION) {
2097 | /* An explicitly specified compression type overrides filename
2098 | * magic. (Should we allow a way to specify "no" compression
2099 | * with, e.g. a ".gz" extension?) */
2100 | const char *sfx = strrchr(save_file, '.');
2101 | if (sfx) {
2102 | compression_type = ws_extension_to_compression_type(sfx + 1);
2103 | }
2104 | }
2105 | }
2106 |
2107 | if (compression_type == WS_FILE_UNKNOWN_COMPRESSION) {
2108 | compression_type = WS_FILE_UNCOMPRESSED;
2109 | }
2110 |
2111 | if (!ws_can_write_compression_type(compression_type)) {
2112 | cmdarg_err("Output files can't be written as %s",
2113 | ws_compression_type_description(compression_type));
2114 | exit_status = WS_EXIT_INVALID_OPTION1;
2115 | goto clean_exit;
2116 | }
2117 |
2118 | if (compression_type != WS_FILE_UNCOMPRESSED && !wtap_dump_can_compress(out_file_type)) {
2119 | cmdarg_err("The file format %s can't be written to output compressed format",
2120 | wtap_file_type_subtype_name(out_file_type));
2121 | exit_status = WS_EXIT_INVALID_OPTION1;
2122 | goto clean_exit;
2123 | }
2124 |
2125 | /* XXX - We have two different long options for compression type;
2126 | * one (undocumented) for live capturing and one for not. That is confusing.
2127 | * LONGOPT_COMPRESS doesn't set "capture_option_specified" because it can be
2128 | * used when capturing or when not capturing.
2129 | */
2130 | if (compression_type != WS_FILE_UNCOMPRESSED && is_capturing) {
2131 | #ifdef HAVE_LIBPCAP1
2132 | exit_status = capture_opts_add_opt(application_configuration_environment_prefix(), &global_capture_opts, LONGOPT_COMPRESS_TYPE1000 +3, ws_compression_type_name(compression_type));
2133 | if (exit_status != 0) {
2134 | goto clean_exit;
2135 | }
2136 | #else
2137 | capture_option_specified = true1;
2138 | arg_error = true1;
2139 | #endif
2140 | }
2141 |
2142 | #ifndef HAVE_LIBPCAP1
2143 | if (capture_option_specified)
2144 | cmdarg_err("This version of TShark was not built with support for capturing packets.");
2145 | #endif
2146 | if (arg_error) {
2147 | print_usage(stderrstderr);
2148 | exit_status = WS_EXIT_INVALID_OPTION1;
2149 | goto clean_exit;
2150 | }
2151 |
2152 | if (print_hex) {
2153 | if (output_action != WRITE_TEXT && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW && output_action != WRITE_EK) {
2154 | cmdarg_err("Raw packet hex data can only be printed as text, PostScript, JSON, JSONRAW or EK JSON");
2155 | exit_status = WS_EXIT_INVALID_OPTION1;
2156 | goto clean_exit;
2157 | }
2158 | }
2159 |
2160 | if (output_only != NULL((void*)0)) {
2161 | char *ps;
2162 |
2163 | if (!print_details) {
2164 | cmdarg_err("-O requires -V");
2165 | exit_status = WS_EXIT_INVALID_OPTION1;
2166 | goto clean_exit;
2167 | }
2168 |
2169 | output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
2170 | for (ps = strtok (output_only, ","); ps; ps = strtok (NULL((void*)0), ",")) {
2171 | const char *name = ps;
2172 | header_field_info *hfi = proto_registrar_get_byalias(name);
2173 | if (hfi) {
2174 | name = hfi->abbrev;
2175 | }
2176 | g_hash_table_insert(output_only_tables, (void *)name, (void *)name);
2177 | }
2178 | }
2179 |
2180 | if (rfilter != NULL((void*)0) && !perform_two_pass_analysis) {
2181 | cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
2182 | exit_status = WS_EXIT_INVALID_OPTION1;
2183 | goto clean_exit;
2184 | }
2185 |
2186 | #ifdef HAVE_LIBPCAP1
2187 | if (caps_queries) {
2188 | /* We're supposed to list the link-layer/timestamp types for an interface;
2189 | did the user also specify a capture file to be read? */
2190 | if (cf_name) {
2191 | /* Yes - that's bogus. */
2192 | cmdarg_err("You can't specify %s and a capture file to be read.",
2193 | caps_queries & CAPS_QUERY_LINK_TYPES ? "-L" : "--list-time-stamp-types");
2194 | exit_status = WS_EXIT_INVALID_OPTION1;
2195 | goto clean_exit;
2196 | }
2197 | /* No - did they specify a ring buffer option? */
2198 | if (global_capture_opts.multi_files_on) {
2199 | cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2200 | exit_status = WS_EXIT_INVALID_OPTION1;
2201 | goto clean_exit;
2202 | }
2203 | } else {
2204 | if (cf_name) {
2205 | /*
2206 | * "-r" was specified, so we're reading a capture file.
2207 | * Capture options don't apply here.
2208 | */
2209 |
2210 | /* We don't support capture filters when reading from a capture file
2211 | (the BPF compiler doesn't support all link-layer types that we
2212 | support in capture files we read). */
2213 | if (global_capture_opts.default_options.cfilter) {
2214 | cmdarg_err("Only read filters, not capture filters, "
2215 | "can be specified when reading a capture file.");
2216 | exit_status = WS_EXIT_INVALID_OPTION1;
2217 | goto clean_exit;
2218 | }
2219 | if (global_capture_opts.multi_files_on) {
2220 | cmdarg_err("Multiple capture files requested, but "
2221 | "a capture isn't being done.");
2222 | exit_status = WS_EXIT_INVALID_OPTION1;
2223 | goto clean_exit;
2224 | }
2225 | if (global_capture_opts.has_file_duration) {
2226 | cmdarg_err("Switching capture files after a time period was specified, but "
2227 | "a capture isn't being done.");
2228 | exit_status = WS_EXIT_INVALID_OPTION1;
2229 | goto clean_exit;
2230 | }
2231 | if (global_capture_opts.has_file_interval) {
2232 | cmdarg_err("Switching capture files after a time interval was specified, but "
2233 | "a capture isn't being done.");
2234 | exit_status = WS_EXIT_INVALID_OPTION1;
2235 | goto clean_exit;
2236 | }
2237 | if (global_capture_opts.has_ring_num_files) {
2238 | cmdarg_err("A ring buffer of capture files was specified, but "
2239 | "a capture isn't being done.");
2240 | exit_status = WS_EXIT_INVALID_OPTION1;
2241 | goto clean_exit;
2242 | }
2243 | if (global_capture_opts.has_autostop_files) {
2244 | cmdarg_err("A maximum number of capture files was specified, but "
2245 | "a capture isn't being done.");
2246 | exit_status = WS_EXIT_INVALID_OPTION1;
2247 | goto clean_exit;
2248 | }
2249 |
2250 | /* Note: TShark now allows the restriction of a _read_ file by packet count
2251 | * and byte count as well as a write file. Other autostop options remain valid
2252 | * only for a write file.
2253 | */
2254 | if (global_capture_opts.has_autostop_duration) {
2255 | cmdarg_err("A maximum capture time was specified, but "
2256 | "a capture isn't being done.");
2257 | exit_status = WS_EXIT_INVALID_OPTION1;
2258 | goto clean_exit;
2259 | }
2260 | } else {
2261 | /*
2262 | * "-r" wasn't specified, so we're doing a live capture.
2263 | */
2264 | bool_Bool use_pcapng = true1;
2265 |
2266 | if (perform_two_pass_analysis) {
2267 | /* Two-pass analysis doesn't work with live capture since it requires us
2268 | * to buffer packets until we've read all of them, but a live capture
2269 | * has no useful/meaningful definition of "all" */
2270 | cmdarg_err("Live captures do not support two-pass analysis.");
2271 | exit_status = WS_EXIT_INVALID_OPTION1;
2272 | goto clean_exit;
2273 | }
2274 |
2275 | if (global_capture_opts.saving_to_file) {
2276 | /* They specified a "-w" flag, so we'll be saving to a capture file. */
2277 |
2278 | /* When capturing, we only support writing pcap or pcapng format. */
2279 | if (out_file_type == wtap_pcapng_file_type_subtype()) {
2280 | use_pcapng = true1;
2281 | } else if (out_file_type == wtap_pcap_file_type_subtype()) {
2282 | use_pcapng = false0;
2283 | } else if (out_file_type == wtap_pcap_nsec_file_type_subtype()) {
2284 | /* XXX - We request nanosecond time resolution regardless.
2285 | * In the future wiretap might treat the two pcap subtypes
2286 | * the same.
2287 | */
2288 | use_pcapng = false0;
2289 | } else {
2290 | cmdarg_err("Live captures can only be saved in pcap or pcapng format.");
2291 | capture_opts_list_file_types();
2292 | exit_status = WS_EXIT_INVALID_OPTION1;
2293 | goto clean_exit;
2294 | }
2295 | if (capture_comments != NULL((void*)0) && !use_pcapng) {
2296 | cmdarg_err("Capture comments can only be written to a pcapng file.");
2297 | exit_status = WS_EXIT_INVALID_OPTION1;
2298 | goto clean_exit;
2299 | }
2300 | if (global_capture_opts.multi_files_on) {
2301 | /* Multiple-file mode doesn't work under certain conditions:
2302 | a) it doesn't work if you're writing to the standard output;
2303 | b) it doesn't work if you're writing to a pipe;
2304 | */
2305 | if (strcmp(global_capture_opts.save_file, "-") == 0) {
2306 | cmdarg_err("Multiple capture files requested, but "
2307 | "the capture is being written to the standard output.");
2308 | exit_status = WS_EXIT_INVALID_OPTION1;
2309 | goto clean_exit;
2310 | }
2311 | if (global_capture_opts.output_to_pipe) {
2312 | cmdarg_err("Multiple capture files requested, but "
2313 | "the capture file is a pipe.");
2314 | exit_status = WS_EXIT_INVALID_OPTION1;
2315 | goto clean_exit;
2316 | }
2317 | if (!global_capture_opts.has_autostop_filesize &&
2318 | !global_capture_opts.has_file_duration &&
2319 | !global_capture_opts.has_file_interval &&
2320 | !global_capture_opts.has_file_packets) {
2321 | cmdarg_err("Multiple capture files requested, but "
2322 | "no maximum capture file size, duration, interval or packets were specified.");
2323 | exit_status = WS_EXIT_INVALID_OPTION1;
2324 | goto clean_exit;
2325 | }
2326 | }
2327 | /* Currently, we don't support read or display filters when capturing
2328 | and saving the packets. */
2329 | if (rfilter != NULL((void*)0)) {
2330 | cmdarg_err("Read filters aren't supported when capturing and saving the captured packets.");
2331 | exit_status = WS_EXIT_INVALID_OPTION1;
2332 | goto clean_exit;
2333 | }
2334 | if (dfilter != NULL((void*)0)) {
2335 | cmdarg_err("Display filters aren't supported when capturing and saving the captured packets.");
2336 | exit_status = WS_EXIT_INVALID_OPTION1;
2337 | goto clean_exit;
2338 | }
2339 | global_capture_opts.use_pcapng = use_pcapng;
2340 | } else {
2341 | /* They didn't specify a "-w" flag, so we won't be saving to a
2342 | capture file. Check for options that only make sense if
2343 | we're saving to a file. */
2344 | if (global_capture_opts.has_autostop_filesize) {
2345 | cmdarg_err("Maximum capture file size specified, but "
2346 | "capture isn't being saved to a file.");
2347 | exit_status = WS_EXIT_INVALID_OPTION1;
2348 | goto clean_exit;
2349 | }
2350 | if (global_capture_opts.multi_files_on) {
2351 | cmdarg_err("Multiple capture files requested, but "
2352 | "the capture isn't being saved to a file.");
2353 | exit_status = WS_EXIT_INVALID_OPTION1;
2354 | goto clean_exit;
2355 | }
2356 | if (capture_comments != NULL((void*)0)) {
2357 | cmdarg_err("Capture comments were specified, but "
2358 | "the capture isn't being saved to a file.");
2359 | exit_status = WS_EXIT_INVALID_OPTION1;
2360 | goto clean_exit;
2361 | }
2362 | }
2363 | }
2364 | }
2365 | #endif
2366 |
2367 | /*
2368 | * If capture comments were specified, -w also has to have been specified.
2369 | */
2370 | if (capture_comments != NULL((void*)0)) {
2371 | if (output_file_name) {
2372 | /* They specified a "-w" flag, so we'll be saving to a capture file.
2373 | * This is fine if they're writing in a format that supports
2374 | * section block comments.
2375 | */
2376 | if (wtap_file_type_subtype_supports_option(out_file_type,
2377 | WTAP_BLOCK_SECTION,
2378 | OPT_COMMENT1) == OPTION_NOT_SUPPORTED) {
2379 | GArray *writable_type_subtypes;
2380 |
2381 | cmdarg_err("Capture comments can only be written to files of the following types:");
2382 | writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME);
2383 | for (unsigned i = 0; i < writable_type_subtypes->len; i++) {
2384 | int ft = g_array_index(writable_type_subtypes, int, i)(((int*) (void *) (writable_type_subtypes)->data) [(i)]);
2385 |
2386 | if (wtap_file_type_subtype_supports_option(ft, WTAP_BLOCK_SECTION,
2387 | OPT_COMMENT1) != OPTION_NOT_SUPPORTED)
2388 | cmdarg_err_cont(" %s - %s", wtap_file_type_subtype_name(ft),
2389 | wtap_file_type_subtype_description(ft));
2390 | }
2391 | exit_status = WS_EXIT_INVALID_OPTION1;
2392 | goto clean_exit;
2393 | }
2394 | }
2395 | else {
2396 | cmdarg_err("Capture comments were specified, but you aren't writing a capture file.");
2397 | exit_status = WS_EXIT_INVALID_OPTION1;
2398 | goto clean_exit;
2399 | }
2400 | }
2401 |
2402 | err_msg = ws_init_sockets();
2403 | if (err_msg != NULL((void*)0))
2404 | {
2405 | cmdarg_err("%s", err_msg);
2406 | g_free(err_msg);
2407 | cmdarg_err_cont("%s", please_report_bug());
2408 | exit_status = WS_EXIT_INIT_FAILED8;
2409 | goto clean_exit;
2410 | }
2411 |
2412 | /* Notify all registered modules that have had any of their preferences
2413 | changed either from one of the preferences file or from the command
2414 | line that their preferences have changed. */
2415 | prefs_apply_all();
2416 |
2417 | /* We can also enable specified taps for export object */
2418 | start_exportobjects();
2419 |
2420 | /* At this point MATE will have registered its field array so we can
2421 | check if the fields specified by the user are all good.
2422 | */
2423 | {
2424 | GSList* it = NULL((void*)0);
2425 | GSList *invalid_fields = output_fields_valid(output_fields);
2426 | if (invalid_fields != NULL((void*)0)) {
2427 |
2428 | cmdarg_err("Some fields aren't valid:");
2429 | for (it=invalid_fields; it != NULL((void*)0); it = g_slist_next(it)((it) ? (((GSList *)(it))->next) : ((void*)0))) {
2430 | cmdarg_err_cont("\t%s", (char *)it->data);
2431 | }
2432 | g_slist_free(invalid_fields);
2433 | exit_status = WS_EXIT_INVALID_OPTION1;
2434 | goto clean_exit;
2435 | }
2436 | }
2437 |
2438 | if (ex_opt_count("read_format") > 0) {
2439 | char* name = ex_opt_get_next("read_format");
2440 | in_file_type = open_info_name_to_type(name);
2441 | if (in_file_type == WTAP_TYPE_AUTO0) {
2442 | cmdarg_err("\"%s\" isn't a valid read file format type", name? name : "");
2443 | g_free(name);
2444 | list_read_capture_types();
2445 | exit_status = WS_EXIT_INVALID_OPTION1;
2446 | goto clean_exit;
2447 | }
2448 | g_free(name);
2449 | }
2450 |
2451 | if (global_dissect_options.time_format != TS_NOT_SET)
2452 | timestamp_set_type(global_dissect_options.time_format);
2453 | if (global_dissect_options.time_precision != TS_PREC_NOT_SET)
2454 | timestamp_set_precision(global_dissect_options.time_precision);
2455 |
2456 | /*
2457 | * Enabled and disabled protocols and heuristic dissectors as per
2458 | * command-line options.
2459 | */
2460 | if (!setup_enabled_and_disabled_protocols()) {
2461 | exit_status = WS_EXIT_INVALID_OPTION1;
2462 | goto clean_exit;
2463 | }
2464 |
2465 | /* Build the column format array */
2466 | build_column_format_array(&cfile.cinfo, prefs_p->num_cols, true1);
2467 |
2468 | /* Everything is setup, dump glossaries now if that's what we're doing.
2469 | * We want to do this after protocols and heuristic dissectors are
2470 | * enabled and disabled. Doing it after building the column format
2471 | * array might make it easier to add a report that describes the
2472 | * current list of columns and how to add a new one (#17332).
2473 | */
2474 | if (glossary != NULL((void*)0)) {
2475 | exit_status = dump_glossary(glossary, elastic_mapping_filter);
2476 | goto clean_exit;
2477 | }
2478 |
2479 | #ifdef HAVE_LIBPCAP1
2480 | capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE1);
2481 | capture_opts_trim_ring_num_files(&global_capture_opts);
2482 | #endif
2483 |
2484 | if (rfilter != NULL((void*)0)) {
2485 | ws_debug("Compiling read filter: '%s'", rfilter)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2485, __func__, "Compiling read filter: '%s'", rfilter); } } while (0);
2486 | if (!compile_dfilter(rfilter, &rfcode)_compile_dfilter(rfilter, &rfcode, __func__)) {
2487 | epan_cleanup();
2488 | extcap_cleanup();
2489 |
2490 | #ifdef HAVE_LIBPCAP1
2491 | warn_about_capture_filter(rfilter);
2492 | #endif
2493 |
2494 | exit_status = WS_EXIT_INVALID_INTERFACE2;
2495 | goto clean_exit;
2496 | }
2497 | }
2498 | cfile.rfcode = rfcode;
2499 |
2500 | if (dfilter != NULL((void*)0)) {
2501 | ws_debug("Compiling display filter: '%s'", dfilter)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2501, __func__, "Compiling display filter: '%s'", dfilter); } } while (0);
2502 | if (!compile_dfilter(dfilter, &dfcode)_compile_dfilter(dfilter, &dfcode, __func__)) {
2503 | epan_cleanup();
2504 | extcap_cleanup();
2505 |
2506 | #ifdef HAVE_LIBPCAP1
2507 | warn_about_capture_filter(dfilter);
2508 | #endif
2509 |
2510 | exit_status = WS_EXIT_INVALID_FILTER4;
2511 | goto clean_exit;
2512 | }
2513 | }
2514 | cfile.dfcode = dfcode;
2515 | tap_load_main_filter(dfcode);
2516 |
2517 | if (print_packet_info) {
2518 | /* If we're printing as text or PostScript, we have
2519 | to create a print stream. */
2520 | if (output_action == WRITE_TEXT) {
2521 | switch (print_format) {
2522 |
2523 | case PR_FMT_TEXT:
2524 | print_stream = print_stream_text_stdio_new(stdoutstdout);
2525 | break;
2526 |
2527 | case PR_FMT_PS:
2528 | print_stream = print_stream_ps_stdio_new(stdoutstdout);
2529 | break;
2530 |
2531 | default:
2532 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 2532, __func__ , "assertion \"not reached\" failed");
2533 | }
2534 | }
2535 | }
2536 |
2537 | /* PDU export requested. Take the ownership of the '-w' file, apply tap
2538 | * filters and start tapping. */
2539 | if (pdu_export_arg) {
2540 | const char *exp_pdu_tap_name = pdu_export_arg;
2541 | const char *exp_pdu_filter = dfilter; /* may be NULL to disable filter */
2542 | char *exp_pdu_error;
2543 | int exp_fd;
2544 | char *comment;
2545 |
2546 | if (!cf_name) {
2547 | cmdarg_err("PDUs export requires a capture file (specify with -r).");
2548 | exit_status = WS_EXIT_INVALID_OPTION1;
2549 | goto clean_exit;
2550 | }
2551 | /* Take ownership of the '-w' output file. */
2552 | exp_pdu_filename = output_file_name;
2553 | output_file_name = NULL((void*)0);
2554 | #ifdef HAVE_LIBPCAP1
2555 | global_capture_opts.save_file = NULL((void*)0);
2556 | #endif
2557 | if (exp_pdu_filename == NULL((void*)0)) {
2558 | cmdarg_err("PDUs export requires an output file (-w).");
2559 | exit_status = WS_EXIT_INVALID_OPTION1;
2560 | goto clean_exit;
2561 | }
2562 |
2563 | exp_pdu_error = exp_pdu_pre_open(exp_pdu_tap_name, exp_pdu_filter,
2564 | &exp_pdu_tap_data);
2565 | if (exp_pdu_error) {
2566 | cmdarg_err("Cannot register tap: %s", exp_pdu_error);
2567 | g_free(exp_pdu_error);
2568 | list_export_pdu_taps();
2569 | exit_status = INVALID_TAP2;
2570 | goto clean_exit;
2571 | }
2572 |
2573 | if (strcmp(exp_pdu_filename, "-") == 0) {
2574 | /* Write to the standard output. */
2575 | exp_fd = 1;
2576 | } else {
2577 | exp_fd = ws_openopen(exp_pdu_filename, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000 | O_BINARY0, 0644);
2578 | if (exp_fd == -1) {
2579 | cmdarg_err("%s: %s", exp_pdu_filename, file_open_error_message(errno(*__errno_location ()), true1));
2580 | exit_status = WS_EXIT_INVALID_FILE3;
2581 | goto clean_exit;
2582 | }
2583 | }
2584 |
2585 | /* Activate the export PDU tap */
2586 | /* Write to our output file with this comment (if the type supports it,
2587 | * otherwise exp_pdu_open() will ignore the comment) */
2588 | comment = ws_strdup_printf("Dump of PDUs from %s", cf_name)wmem_strdup_printf(((void*)0), "Dump of PDUs from %s", cf_name );
2589 | exp_pdu_status = exp_pdu_open(&exp_pdu_tap_data, exp_pdu_filename,
2590 | out_file_type, exp_fd, comment,
2591 | &err, &err_info);
2592 | g_free(comment);
2593 | if (!exp_pdu_status) {
2594 | report_cfile_dump_open_failure(exp_pdu_filename, err, err_info,
2595 | out_file_type);
2596 | exit_status = INVALID_EXPORT2;
2597 | goto clean_exit;
2598 | }
2599 | }
2600 |
2601 | if (cf_name) {
2602 | ws_debug("tshark: Opening capture file: %s", cf_name)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2602, __func__, "tshark: Opening capture file: %s", cf_name ); } } while (0);
2603 | /*
2604 | * We're reading a capture file.
2605 | */
2606 | if (cf_open(&cfile, cf_name, in_file_type, false0, &err) != CF_OK) {
2607 | epan_cleanup();
2608 | extcap_cleanup();
2609 | exit_status = WS_EXIT_INVALID_FILE3;
2610 | goto clean_exit;
2611 | }
2612 |
2613 | /* Start statistics taps; we do so after successfully opening the
2614 | capture file, so we know we have something to compute stats
2615 | on, and after registering all dissectors, so that MATE will
2616 | have registered its field array so we can have a tap filter
2617 | with one of MATE's late-registered fields as part of the
2618 | filter. */
2619 | if (!start_requested_stats()) {
2620 | exit_status = WS_EXIT_INVALID_OPTION1;
2621 | goto clean_exit;
2622 | }
2623 |
2624 | /* Do we need to do dissection of packets? That depends on, among
2625 | other things, what taps are listening, so determine that after
2626 | starting the statistics taps. */
2627 | do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg);
2628 | ws_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2628, __func__, "tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE"); } } while (0);
2629 |
2630 | /* Process the packets in the file */
2631 | ws_debug("tshark: invoking process_cap_file() to process the packets")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2631, __func__, "tshark: invoking process_cap_file() to process the packets" ); } } while (0);
2632 | TRY{ except_t *volatile exc; volatile int except_state = 0; static const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch except_ch; except_setup_try(& except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch .except_jmp)) *(&exc) = &except_ch.except_obj; else * (&exc) = 0; if(except_state & 1) except_state |= 2; except_state &= ~1; if (except_state == 0 && exc == 0) {
2633 | status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res,
2634 | #ifdef HAVE_LIBPCAP1
2635 | global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
2636 | global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0,
2637 | global_capture_opts.has_autostop_written_packets ? global_capture_opts.autostop_written_packets : 0,
2638 | compression_type);
2639 | #else
2640 | max_packet_count,
2641 | 0,
2642 | 0,
2643 | WS_FILE_UNCOMPRESSED);
2644 | #endif
2645 | }
2646 | CATCH(OutOfMemoryError)if (except_state == 0 && exc != 0 && exc-> except_id.except_code == (8) && (except_state |= 1)) {
2647 | fprintf(stderrstderr,
2648 | "Out Of Memory.\n"
2649 | "\n"
2650 | "Sorry, but TShark has to terminate now.\n"
2651 | "\n"
2652 | "More information and workarounds can be found at\n"
2653 | WS_WIKI_URL("KnownBugs/OutOfMemory")"https://wiki.wireshark.org" "/" "KnownBugs/OutOfMemory" "\n");
2654 | status = PROCESS_FILE_ERROR;
2655 | }
2656 | ENDTRYif(!(except_state&1) && exc != 0) except_rethrow( exc); except_free(except_ch.except_obj.except_dyndata); except_pop (); };};
2657 |
2658 | switch (status) {
2659 |
2660 | case PROCESS_FILE_SUCCEEDED:
2661 | /* Everything worked OK; draw the taps. */
2662 | draw_taps = true1;
2663 | break;
2664 |
2665 | case PROCESS_FILE_NO_FILE_PROCESSED:
2666 | /* We never got to try to read the file, so there are no tap
2667 | results to dump. Exit with an error status. */
2668 | exit_status = 2;
2669 | break;
2670 |
2671 | case PROCESS_FILE_ERROR:
2672 | /* We still dump out the results of taps, etc., as we might have
2673 | read some packets; however, we exit with an error status. */
2674 | draw_taps = true1;
2675 | exit_status = 2;
2676 | break;
2677 |
2678 | case PROCESS_FILE_INTERRUPTED:
2679 | /* The user interrupted the read process; Don't dump out the
2680 | result of taps, etc., and exit with an error status. */
2681 | exit_status = 2;
2682 | break;
2683 | }
2684 |
2685 | if (pdu_export_arg) {
2686 | if (!exp_pdu_close(&exp_pdu_tap_data, &err, &err_info)) {
2687 | report_cfile_close_failure(exp_pdu_filename, err, err_info);
2688 | exit_status = 2;
2689 | }
2690 | g_free(pdu_export_arg);
2691 | g_free(exp_pdu_filename);
2692 | }
2693 | } else {
2694 | ws_debug("tshark: no capture file specified")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2694, __func__, "tshark: no capture file specified"); } } while (0);
2695 | /* No capture file specified, so we're supposed to do a live capture
2696 | or get a list of link-layer types for a live capture device;
2697 | do we have support for live captures? */
2698 | #ifdef HAVE_LIBPCAP1
2699 | #ifdef _WIN32
2700 | /* Warn the user if npf.sys isn't loaded. */
2701 | if (!npf_sys_is_running()) {
2702 | fprintf(stderrstderr, "The NPF driver isn't running. You may have trouble "
2703 | "capturing or\nlisting interfaces.\n");
2704 | }
2705 | #endif /* _WIN32 */
2706 |
2707 | /* if no interface was specified, pick a default */
2708 | exit_status = capture_opts_default_iface_if_necessary(&global_capture_opts,
2709 | ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL((void*)0));
2710 | if (exit_status != 0) {
2711 | goto clean_exit;
2712 | }
2713 |
2714 | /*
2715 | * If requested, list the link layer types and/or time stamp types
2716 | * and exit.
2717 | */
2718 | if (caps_queries) {
2719 | unsigned i;
2720 |
2721 | /* Get the list of link-layer types for the capture devices. */
2722 | exit_status = EXIT_SUCCESS0;
2723 | GList *if_cap_queries = NULL((void*)0);
2724 | if_cap_query_t *if_cap_query;
2725 | GHashTable *capability_hash;
2726 | for (i = 0; i < global_capture_opts.ifaces->len; i++) {
2727 | interface_options *interface_opts;
2728 | interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i)(((interface_options*) (void *) (global_capture_opts.ifaces)-> data) [(i)]);
2729 | if_cap_query = g_new(if_cap_query_t, 1)((if_cap_query_t *) g_malloc_n ((1), sizeof (if_cap_query_t)) );
2730 | if_cap_query->name = interface_opts->name;
2731 | if_cap_query->monitor_mode = interface_opts->monitor_mode;
2732 | if_cap_query->auth_username = NULL((void*)0);
2733 | if_cap_query->auth_password = NULL((void*)0);
2734 | #ifdef HAVE_PCAP_REMOTE
2735 | if (interface_opts->auth_type == CAPTURE_AUTH_PWD) {
2736 | if_cap_query->auth_username = interface_opts->auth_username;
2737 | if_cap_query->auth_password = interface_opts->auth_password;
2738 | }
2739 | #endif
2740 | if_cap_queries = g_list_prepend(if_cap_queries, if_cap_query);
2741 | }
2742 | if_cap_queries = g_list_reverse(if_cap_queries);
2743 | capability_hash = capture_get_if_list_capabilities(global_capture_opts.app_name, if_cap_queries, &err_str, &err_str_secondary, NULL((void*)0));
2744 | g_list_free_full(if_cap_queries, g_free);
2745 | for (i = 0; i < global_capture_opts.ifaces->len; i++) {
2746 | interface_options *interface_opts;
2747 | interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i)(((interface_options*) (void *) (global_capture_opts.ifaces)-> data) [(i)]);
2748 | if_capabilities_t *caps;
2749 | caps = g_hash_table_lookup(capability_hash, interface_opts->name);
2750 | if (caps == NULL((void*)0)) {
2751 | cmdarg_err("%s%s%s", err_str, err_str_secondary ? "\n" : "", err_str_secondary ? err_str_secondary : "");
2752 | g_free(err_str);
2753 | g_free(err_str_secondary);
2754 | exit_status = WS_EXIT_INVALID_CAPABILITY5;
2755 | break;
2756 | }
2757 | exit_status = capture_opts_print_if_capabilities(caps, interface_opts,
2758 | caps_queries);
2759 | if (exit_status != EXIT_SUCCESS0) {
2760 | break;
2761 | }
2762 | }
2763 | g_hash_table_destroy(capability_hash);
2764 | goto clean_exit;
2765 | }
2766 |
2767 | /*
2768 | * If the standard error isn't a terminal, don't print packet counts,
2769 | * as they won't show up on the user's terminal and they'll get in
2770 | * the way of error messages in the file (to which we assume the
2771 | * standard error was redirected; if it's redirected to the null
2772 | * device, there's no point in printing packet counts anyway).
2773 | *
2774 | * Otherwise, if we're printing packet information and the standard
2775 | * output is a terminal (which we assume means the standard output and
2776 | * error are going to the same terminal), don't print packet counts,
2777 | * as they'll get in the way of the packet information.
2778 | *
2779 | * Otherwise, if the user specified -q, don't print packet counts.
2780 | *
2781 | * Otherwise, print packet counts.
2782 | *
2783 | * XXX - what if the user wants to do a live capture, doesn't want
2784 | * to save it to a file, doesn't want information printed for each
2785 | * packet, does want some "-z" statistic, and wants packet counts
2786 | * so they know whether they're seeing any packets? -q will
2787 | * suppress the information printed for each packet, but it'll
2788 | * also suppress the packet counts.
2789 | */
2790 | if (!ws_isattyisatty(ws_filenofileno(stderrstderr)))
2791 | print_packet_counts = false0;
2792 | else if (print_packet_info && ws_isattyisatty(ws_filenofileno(stdoutstdout)))
2793 | print_packet_counts = false0;
2794 | else if (quiet)
2795 | print_packet_counts = false0;
2796 | else
2797 | print_packet_counts = true1;
2798 |
2799 | ws_debug("tshark: performing live capture")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2799, __func__, "tshark: performing live capture"); } } while (0);
2800 |
2801 | /* Start statistics taps; we should only do so after the capture
2802 | started successfully, so we know we have something to compute
2803 | stats, but we currently don't check for that - see below.
2804 |
2805 | We do so after registering all dissectors, so that MATE will
2806 | have registered its field array so we can have a tap filter
2807 | with one of MATE's late-registered fields as part of the
2808 | filter. */
2809 | if (!start_requested_stats()) {
2810 | exit_status = WS_EXIT_INVALID_OPTION1;
2811 | goto clean_exit;
2812 | }
2813 |
2814 | /* Do we need to do dissection of packets? That depends on, among
2815 | other things, what taps are listening, so determine that after
2816 | starting the statistics taps. */
2817 | do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg);
2818 | ws_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 2818, __func__, "tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE"); } } while (0);
2819 |
2820 | /* We're doing live capture; if the capture child is writing to a pipe,
2821 | we can't do dissection, because that would mean two readers for
2822 | the pipe, tshark and whatever else. */
2823 | if (do_dissection && global_capture_opts.output_to_pipe) {
2824 | if (tap_listeners_require_dissection()) {
2825 | cmdarg_err("Taps aren't supported when capturing and saving to a pipe.");
2826 | exit_status = WS_EXIT_INVALID_OPTION1;
2827 | goto clean_exit;
2828 | }
2829 | if (print_packet_info) {
2830 | cmdarg_err("Printing dissected packets isn't supported when capturing and saving to a pipe.");
2831 | exit_status = WS_EXIT_INVALID_OPTION1;
2832 | goto clean_exit;
2833 | }
2834 | /* We already checked the next three reasons for supersets of
2835 | capturing and saving to a pipe, but this doesn't hurt. */
2836 | if (pdu_export_arg) {
2837 | cmdarg_err("PDUs export isn't supported when capturing and saving to a pipe.");
2838 | exit_status = WS_EXIT_INVALID_OPTION1;
2839 | goto clean_exit;
2840 | }
2841 | if (rfcode != NULL((void*)0)) {
2842 | cmdarg_err("Read filters aren't supported when capturing and saving to a pipe.");
2843 | exit_status = WS_EXIT_INVALID_OPTION1;
2844 | goto clean_exit;
2845 | }
2846 | if (dfcode != NULL((void*)0)) {
2847 | cmdarg_err("Display filters aren't supported when capturing and saving to a pipe.");
2848 | exit_status = WS_EXIT_INVALID_OPTION1;
2849 | goto clean_exit;
2850 | }
2851 | /* There's some other reason we're dissecting. */
2852 | cmdarg_err("Dissection isn't supported when capturing and saving to a pipe.");
2853 | exit_status = WS_EXIT_INVALID_OPTION1;
2854 | goto clean_exit;
2855 | }
2856 |
2857 | /* Write a preamble if we're printing one. Do this after all checking
2858 | * for invalid options, so we don't print just a preamble and quit. */
2859 | if (print_packet_info) {
2860 | if (!write_preamble(&cfile)) {
2861 | show_print_file_io_error();
2862 | exit_status = WS_EXIT_INVALID_FILE3;
2863 | goto clean_exit;
2864 | }
2865 | }
2866 |
2867 | /*
2868 | * XXX - this returns false if an error occurred, but it also
2869 | * returns false if the capture stops because a time limit
2870 | * was reached (and possibly other limits), so we can't assume
2871 | * it means an error.
2872 | *
2873 | * The capture code is a bit twisty, so it doesn't appear to
2874 | * be an easy fix. We just ignore the return value for now.
2875 | * Instead, pass on the exit status from the capture child.
2876 | */
2877 | capture();
2878 | exit_status = global_capture_session.fork_child_status;
2879 |
2880 | if (print_packet_info) {
2881 | if (!write_finale()) {
2882 | show_print_file_io_error();
2883 | }
2884 | }
2885 |
2886 | /*
2887 | * If we never got a capture file, don't draw the taps; we not only
2888 | * didn't capture any packets, we never even did any capturing.
2889 | */
2890 | if (cfile.filename != NULL((void*)0))
2891 | draw_taps = true1;
2892 | #else
2893 | /* No - complain. */
2894 | cmdarg_err("This version of TShark was not built with support for capturing packets.");
2895 | exit_status = INVALID_CAPTURE2;
2896 | goto clean_exit;
2897 | #endif
2898 | }
2899 |
2900 | if (cfile.provider.frames != NULL((void*)0)) {
2901 | free_frame_data_sequence(cfile.provider.frames);
2902 | cfile.provider.frames = NULL((void*)0);
2903 | }
2904 |
2905 | if (draw_taps)
2906 | draw_tap_listeners(true1);
2907 |
2908 | if (tls_session_keys_file) {
2909 | size_t keylist_length = 0;
2910 | unsigned num_keys = 0;
2911 | char* keylist = NULL((void*)0);
2912 | secrets_export_values ret = secrets_export("TLS", &keylist, &keylist_length, &num_keys);
2913 | if ((ret == SECRETS_EXPORT_SUCCESS) && (keylist_length > 0))
2914 | write_file_binary_mode(tls_session_keys_file, keylist, keylist_length);
2915 | g_free(keylist);
2916 | }
2917 |
2918 | if (opt_print_timers) {
2919 | if (cf_name == NULL((void*)0)) {
2920 | /* We're doing a live capture. That isn't currently supported
2921 | * with timers. */
2922 | ws_message("Ignoring option --print-timers because we are doing a live capture")do { if (1) { ws_log_full("Main", LOG_LEVEL_MESSAGE, ((void*) 0), -1, ((void*)0), "Ignoring option --print-timers because we are doing a live capture" ); } } while (0);
2923 | }
2924 | else {
2925 | print_elapsed_json(cf_name, dfilter);
2926 | }
2927 | }
2928 |
2929 | /* Memory cleanup */
2930 | reset_tap_listeners();
2931 | funnel_dump_all_text_windows();
2932 | epan_free(cfile.epan);
2933 | epan_cleanup();
2934 | extcap_cleanup();
2935 |
2936 | output_fields_free(output_fields);
2937 | output_fields = NULL((void*)0);
2938 |
2939 | clean_exit:
2940 | cf_close(&cfile);
2941 | g_free(cf_name);
2942 | destroy_print_stream(print_stream);
2943 | g_free(output_file_name);
2944 | #ifdef HAVE_LIBPCAP1
2945 | capture_opts_cleanup(&global_capture_opts);
2946 | if (cached_if_list) {
2947 | free_interface_list(cached_if_list);
2948 | }
2949 | #endif
2950 | col_cleanup(&cfile.cinfo);
2951 | wtap_cleanup();
2952 | free_progdirs();
2953 | dfilter_free(dfcode);
2954 | g_free(dfilter);
2955 | return exit_status;
2956 | }
2957 |
2958 | bool_Bool loop_running;
2959 | uint32_t packet_count;
2960 |
2961 | static epan_t *
2962 | tshark_epan_new(capture_file *cf)
2963 | {
2964 | static const struct packet_provider_funcs funcs = {
2965 | cap_file_provider_get_frame_ts,
2966 | cap_file_provider_get_start_ts,
2967 | cap_file_provider_get_end_ts,
2968 | cap_file_provider_get_interface_name,
2969 | cap_file_provider_get_interface_description,
2970 | NULL((void*)0),
2971 | cap_file_provider_get_process_id,
2972 | cap_file_provider_get_process_name,
2973 | cap_file_provider_get_process_uuid,
2974 | };
2975 |
2976 | return epan_new(&cf->provider, &funcs);
2977 | }
2978 |
2979 | #ifdef HAVE_LIBPCAP1
2980 | static bool_Bool
2981 | capture(void)
2982 | {
2983 | GString *str;
2984 | GMainContext *ctx;
2985 | #ifndef _WIN32
2986 | struct sigaction action, oldaction;
2987 | #endif
2988 |
2989 | /* Create new dissection section. */
2990 | epan_free(cfile.epan);
2991 | cfile.epan = tshark_epan_new(&cfile);
2992 |
2993 | #ifdef _WIN32
2994 | /* Catch a CTRL+C event and, if we get it, clean up and exit. */
2995 | SetConsoleCtrlHandler(capture_cleanup, true1);
2996 | #else /* _WIN32 */
2997 | /* Catch SIGINT and SIGTERM and, if we get either of them,
2998 | clean up and exit. If SIGHUP isn't being ignored, catch
2999 | it too and, if we get it, clean up and exit.
3000 |
3001 | We restart any read that was in progress, so that it doesn't
3002 | disrupt reading from the sync pipe. The signal handler tells
3003 | the capture child to finish; it will report that it finished,
3004 | or will exit abnormally, so we'll stop reading from the sync
3005 | pipe, pick up the exit status, and quit. */
3006 | memset(&action, 0, sizeof(action));
3007 | action.sa_handler__sigaction_handler.sa_handler = capture_cleanup;
3008 | action.sa_flags = SA_RESTART0x10000000;
3009 | sigemptyset(&action.sa_mask);
3010 | sigaction(SIGTERM15, &action, NULL((void*)0));
3011 | sigaction(SIGINT2, &action, NULL((void*)0));
3012 | sigaction(SIGHUP1, NULL((void*)0), &oldaction);
3013 | if (oldaction.sa_handler__sigaction_handler.sa_handler == SIG_DFL((__sighandler_t) 0))
3014 | sigaction(SIGHUP1, &action, NULL((void*)0));
3015 |
3016 | #ifdef SIGINFO
3017 | /* Catch SIGINFO and, if we get it and we're capturing to a file in
3018 | quiet mode, report the number of packets we've captured.
3019 |
3020 | Again, restart any read that was in progress, so that it doesn't
3021 | disrupt reading from the sync pipe. */
3022 | action.sa_handler__sigaction_handler.sa_handler = report_counts_siginfo;
3023 | action.sa_flags = SA_RESTART0x10000000;
3024 | sigemptyset(&action.sa_mask);
3025 | sigaction(SIGINFO, &action, NULL((void*)0));
3026 | #endif /* SIGINFO */
3027 | #endif /* _WIN32 */
3028 |
3029 | global_capture_session.state = CAPTURE_PREPARING;
3030 |
3031 | /* Let the user know which interfaces were chosen. */
3032 | str = get_iface_list_string(&global_capture_opts, IFLIST_QUOTE_IF_DESCRIPTION0x00000001);
3033 | if (really_quiet == false0)
3034 | fprintf(stderrstderr, "Capturing on %s\n", str->str);
3035 | fflush(stderrstderr);
3036 | g_string_free(str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free ) ((str), ((!(0)))));
3037 |
3038 | if (!sync_pipe_start(&global_capture_opts, capture_comments,
3039 | &global_capture_session, &global_info_data, NULL((void*)0)))
3040 | return false0;
3041 |
3042 | /*
3043 | * Force synchronous resolution of IP addresses; we're doing only
3044 | * one pass, so we can't do it in the background and fix up past
3045 | * dissections.
3046 | */
3047 | set_resolution_synchrony(true1);
3048 |
3049 | /* the actual capture loop */
3050 | ctx = g_main_context_default();
3051 | loop_running = true1;
3052 |
3053 | TRY{ except_t *volatile exc; volatile int except_state = 0; static const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch except_ch; except_setup_try(& except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch .except_jmp)) *(&exc) = &except_ch.except_obj; else * (&exc) = 0; if(except_state & 1) except_state |= 2; except_state &= ~1; if (except_state == 0 && exc == 0)
3054 | {
3055 | while (loop_running)
3056 | {
3057 | g_main_context_iteration(ctx, true1);
3058 | }
3059 | }
3060 | CATCH(OutOfMemoryError)if (except_state == 0 && exc != 0 && exc-> except_id.except_code == (8) && (except_state |= 1)) {
3061 | fprintf(stderrstderr,
3062 | "Out Of Memory.\n"
3063 | "\n"
3064 | "Sorry, but TShark has to terminate now.\n"
3065 | "\n"
3066 | "More information and workarounds can be found at\n"
3067 | WS_WIKI_URL("KnownBugs/OutOfMemory")"https://wiki.wireshark.org" "/" "KnownBugs/OutOfMemory" "\n");
3068 | abort();
3069 | }
3070 | ENDTRYif(!(except_state&1) && exc != 0) except_rethrow( exc); except_free(except_ch.except_obj.except_dyndata); except_pop (); };};
3071 | return true1;
3072 | }
3073 |
3074 | /* capture child detected an error */
3075 | static void
3076 | capture_input_error(capture_session *cap_session _U___attribute__((unused)), char *error_msg, char *secondary_error_msg)
3077 | {
3078 | /* The primary message might be an empty string, e.g. when the error was
3079 | * from extcap. (The extcap stderr is gathered when the session closes
3080 | * and printed in capture_input_closed below.) */
3081 | if (*error_msg != '\0') {
3082 | cmdarg_err("%s", error_msg);
3083 | if (secondary_error_msg != NULL((void*)0) && *secondary_error_msg != '\0') {
3084 | /* We have both primary and secondary messages. */
3085 | cmdarg_err_cont("%s", secondary_error_msg);
3086 | }
3087 | }
3088 | }
3089 |
3090 |
3091 | /* capture child detected an capture filter related error */
3092 | static void
3093 | capture_input_cfilter_error(capture_session *cap_session, unsigned i, const char *error_message)
3094 | {
3095 | capture_options *capture_opts = cap_session->capture_opts;
3096 | dfilter_t *rfcode = NULL((void*)0);
3097 | interface_options *interface_opts;
3098 |
3099 | ws_assert(i < capture_opts->ifaces->len)do { if ((1) && !(i < capture_opts->ifaces-> len)) ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 3099 , __func__, "assertion failed: %s", "i < capture_opts->ifaces->len" ); } while (0);
3100 | interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i)(((interface_options*) (void *) (capture_opts->ifaces)-> data) [(i)]);
3101 |
3102 | if (dfilter_compile(interface_opts->cfilter, &rfcode, NULL)dfilter_compile_full(interface_opts->cfilter, &rfcode, ((void*)0), (1U << 1)|(1U << 2), __func__) && rfcode != NULL((void*)0)) {
3103 | cmdarg_err(
3104 | "Invalid capture filter \"%s\" for interface '%s'.\n"
3105 | "\n"
3106 | "That string looks like a valid display filter; however, it isn't a valid\n"
3107 | "capture filter (%s).\n"
3108 | "\n"
3109 | "Note that display filters and capture filters don't have the same syntax,\n"
3110 | "so you can't use most display filter expressions as capture filters.\n"
3111 | "\n"
3112 | "See the User's Guide for a description of the capture filter syntax.",
3113 | interface_opts->cfilter, interface_opts->descr, error_message);
3114 | dfilter_free(rfcode);
3115 | } else {
3116 | cmdarg_err(
3117 | "Invalid capture filter \"%s\" for interface '%s'.\n"
3118 | "\n"
3119 | "That string isn't a valid capture filter (%s).\n"
3120 | "See the User's Guide for a description of the capture filter syntax.",
3121 | interface_opts->cfilter, interface_opts->descr, error_message);
3122 | }
3123 | }
3124 |
3125 |
3126 | /* capture child tells us we have a new (or the first) capture file */
3127 | static bool_Bool
3128 | capture_input_new_file(capture_session *cap_session, char *new_file)
3129 | {
3130 | capture_options *capture_opts = cap_session->capture_opts;
3131 | capture_file *cf = cap_session->cf;
3132 | bool_Bool is_tempfile;
3133 | int err;
3134 |
3135 | if (really_quiet == false0) {
3136 | if (cap_session->state == CAPTURE_PREPARING) {
3137 | ws_info("Capture started.")do { if (1) { ws_log_full("Main", LOG_LEVEL_INFO, ((void*)0), -1, ((void*)0), "Capture started."); } } while (0);
3138 | }
3139 | ws_info("File: \"%s\"", new_file)do { if (1) { ws_log_full("Main", LOG_LEVEL_INFO, ((void*)0), -1, ((void*)0), "File: \"%s\"", new_file); } } while (0);
3140 | }
3141 |
3142 | ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING)do { if ((1) && !(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING)) ws_log_fatal_full ("Main", LOG_LEVEL_ERROR, "tshark.c", 3142, __func__, "assertion failed: %s" , "cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING" ); } while (0);
3143 |
3144 | /* free the old filename */
3145 | if (capture_opts->save_file != NULL((void*)0)) {
3146 |
3147 | /* we start a new capture file, close the old one (if we had one before) */
3148 | if (cf->state != FILE_CLOSED) {
3149 | cf_close(cf);
3150 | }
3151 |
3152 | g_free(capture_opts->save_file);
3153 | is_tempfile = false0;
3154 |
3155 | epan_free(cf->epan);
3156 | cf->epan = tshark_epan_new(cf);
3157 | } else {
3158 | /* we didn't had a save_file before, must be a tempfile */
3159 | is_tempfile = true1;
3160 | }
3161 |
3162 | /* save the new filename */
3163 | capture_opts->save_file = g_strdup(new_file)g_strdup_inline (new_file);
3164 |
3165 | /* if we are in real-time mode, open the new file now */
3166 | if (do_dissection) {
3167 | /* this is probably unnecessary, but better safe than sorry */
3168 | cap_session->cf->open_type = WTAP_TYPE_AUTO0;
3169 | /* Attempt to open the capture file and set up to read from it. */
3170 | switch(cf_open(cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO0, is_tempfile, &err)) {
3171 | case CF_OK:
3172 | break;
3173 | case CF_ERROR:
3174 | /* Don't unlink (delete) the save file - leave it around,
3175 | for debugging purposes. */
3176 | g_free(capture_opts->save_file);
3177 | capture_opts->save_file = NULL((void*)0);
3178 | return false0;
3179 | }
3180 | } else if (quiet && is_tempfile) {
3181 | cf->state = FILE_READ_ABORTED;
3182 | cf->filename = g_strdup(new_file)g_strdup_inline (new_file);
3183 | cf->is_tempfile = is_tempfile;
3184 | }
3185 |
3186 | cap_session->state = CAPTURE_RUNNING;
3187 |
3188 | return true1;
3189 | }
3190 |
3191 |
3192 | /* capture child tells us we have new packets to read */
3193 | static void
3194 | capture_input_new_packets(capture_session *cap_session, int to_read)
3195 | {
3196 | bool_Bool ret;
3197 | int err;
3198 | char *err_info;
3199 | int64_t data_offset;
3200 | capture_file *cf = cap_session->cf;
3201 | bool_Bool filtering_tap_listeners;
3202 | unsigned tap_flags;
3203 |
3204 | #ifdef SIGINFO
3205 | /*
3206 | * Prevent a SIGINFO handler from writing to the standard error while
3207 | * we're doing so or writing to the standard output; instead, have it
3208 | * just set a flag telling us to print that information when we're done.
3209 | */
3210 | infodelay = true1;
3211 | #endif /* SIGINFO */
3212 |
3213 | /* Do we have any tap listeners with filters? */
3214 | filtering_tap_listeners = have_filtering_tap_listeners();
3215 |
3216 | /* Get the union of the flags for all tap listeners. */
3217 | tap_flags = union_of_tap_listener_flags();
3218 |
3219 | if (do_dissection) {
3220 | bool_Bool create_proto_tree;
3221 | epan_dissect_t *edt;
3222 | wtap_rec rec;
3223 |
3224 | /*
3225 | * Determine whether we need to create a protocol tree.
3226 | * We do if:
3227 | *
3228 | * we're going to apply a read filter;
3229 | *
3230 | * we're going to apply a display filter;
3231 | *
3232 | * we're going to print the protocol tree;
3233 | *
3234 | * one of the tap listeners is going to apply a filter;
3235 | *
3236 | * one of the tap listeners requires a protocol tree;
3237 | *
3238 | * a postdissector wants field values or protocols
3239 | * on the first pass;
3240 | *
3241 | * we have custom columns (which require field values, which
3242 | * currently requires that we build a protocol tree).
3243 | */
3244 | create_proto_tree =
3245 | (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
3246 | (tap_flags & TL_REQUIRES_PROTO_TREE0x00000001) || postdissectors_want_hfids() ||
3247 | have_custom_cols(&cf->cinfo) || dissect_color);
3248 |
3249 | /* The protocol tree will be "visible", i.e., nothing faked, only if
3250 | we're printing packet details, which is true if we're printing stuff
3251 | ("print_packet_info" is true) and we're in verbose mode
3252 | ("packet_details" is true). But if we specified certain fields with
3253 | "-e", we'll prime those directly later. */
3254 | bool_Bool visible = print_packet_info && print_details && output_fields_num_fields(output_fields) == 0;
3255 | edt = epan_dissect_new(cf->epan, create_proto_tree, visible);
3256 |
3257 | wtap_rec_init(&rec, DEFAULT_INIT_BUFFER_SIZE_2048(2 * 1024));
3258 |
3259 | while (to_read-- && cf->provider.wth) {
3260 | wtap_cleareof(cf->provider.wth);
3261 | ret = wtap_read(cf->provider.wth, &rec, &err, &err_info, &data_offset);
3262 | reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details);
3263 | if (ret == false0) {
3264 | /* Read from file failed; tell the capture child to stop.
3265 | XXX - report this error? */
3266 | sync_pipe_stop(cap_session);
3267 | wtap_close(cf->provider.wth);
3268 | cf->provider.wth = NULL((void*)0);
3269 | } else {
3270 | /*
3271 | * The packet was successfully read; process it.
3272 | */
3273 | switch (process_packet_single_pass(cf, edt, data_offset, &rec,
3274 | tap_flags)) {
3275 |
3276 | case PROCESS_PACKET_PASSED:
3277 | /* Either there's no read filtering or this packet
3278 | passed the filter, and, if we were supposed to
3279 | print dissection information, we did so successfully. */
3280 | packet_count++;
3281 | ret = true1;
3282 | break;
3283 |
3284 | case PROCESS_PACKET_DIDNT_PASS:
3285 | /* There is read filtering and this packet didn't pass
3286 | the filter. */
3287 | ret = false0;
| Value stored to 'ret' is never read
3288 | break;
3289 |
3290 | case PROCESS_PACKET_PRINT_ERROR:
3291 | /* Either here's no read filtering or this packet passed
3292 | the read filter, and we tried to print dissection
3293 | informaion, but that failed. We've already reported
3294 | the error, unless it was EPIPE, in which case we just
3295 | silently quit; tell the capture child to stop. */
3296 | sync_pipe_stop(cap_session);
3297 | wtap_close(cf->provider.wth);
3298 | cf->provider.wth = NULL((void*)0);
3299 | }
3300 | }
3301 | wtap_rec_reset(&rec);
3302 | }
3303 |
3304 | epan_dissect_free(edt);
3305 |
3306 | wtap_rec_cleanup(&rec);
3307 |
3308 | } else {
3309 | /*
3310 | * Dumpcap's doing all the work; we're not doing any dissection.
3311 | * Count all the packets it wrote.
3312 | */
3313 | packet_count += to_read;
3314 | }
3315 |
3316 | if (print_packet_counts) {
3317 | /* We're printing packet counts. */
3318 | if (packet_count != 0) {
3319 | fprintf(stderrstderr, "\r%u ", packet_count);
3320 | /* stderr could be line buffered */
3321 | fflush(stderrstderr);
3322 | }
3323 | }
3324 |
3325 | #ifdef SIGINFO
3326 | /*
3327 | * Allow SIGINFO handlers to write.
3328 | */
3329 | infodelay = false0;
3330 |
3331 | /*
3332 | * If a SIGINFO handler asked us to write out capture counts, do so.
3333 | */
3334 | if (infoprint)
3335 | report_counts();
3336 | #endif /* SIGINFO */
3337 | }
3338 |
3339 | static void
3340 | report_counts(void)
3341 | {
3342 | if ((print_packet_counts == false0) && (really_quiet == false0)) {
3343 | /* Report the count only if we aren't printing a packet count
3344 | as packets arrive. */
3345 | fprintf(stderrstderr, "%u packet%s captured\n", packet_count,
3346 | plurality(packet_count, "", "s")((packet_count) == 1 ? ("") : ("s")));
3347 | }
3348 | #ifdef SIGINFO
3349 | infoprint = false0; /* we just reported it */
3350 | #endif /* SIGINFO */
3351 | }
3352 |
3353 | #ifdef SIGINFO
3354 | static void
3355 | report_counts_siginfo(int signum _U___attribute__((unused)))
3356 | {
3357 | int sav_errno = errno(*__errno_location ());
3358 | /* If we've been told to delay printing, just set a flag asking
3359 | that we print counts (if we're supposed to), otherwise print
3360 | the count of packets captured (if we're supposed to). */
3361 | if (infodelay)
3362 | infoprint = true1;
3363 | else
3364 | report_counts();
3365 | errno(*__errno_location ()) = sav_errno;
3366 | }
3367 | #endif /* SIGINFO */
3368 |
3369 |
3370 | /* capture child detected any packet drops? */
3371 | static void
3372 | capture_input_drops(capture_session *cap_session _U___attribute__((unused)), uint32_t dropped, const char* interface_name)
3373 | {
3374 | if (print_packet_counts) {
3375 | /* We're printing packet counts to stderr.
3376 | Send a newline so that we move to the line after the packet count. */
3377 | fprintf(stderrstderr, "\n");
3378 | }
3379 |
3380 | if (dropped != 0) {
3381 | /* We're printing packet counts to stderr.
3382 | Send a newline so that we move to the line after the packet count. */
3383 | if (interface_name != NULL((void*)0)) {
3384 | fprintf(stderrstderr, "%u packet%s dropped from %s\n", dropped, plurality(dropped, "", "s")((dropped) == 1 ? ("") : ("s")), interface_name);
3385 | } else {
3386 | fprintf(stderrstderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s")((dropped) == 1 ? ("") : ("s")));
3387 | }
3388 | }
3389 | }
3390 |
3391 |
3392 | /*
3393 | * Capture child closed its side of the pipe, report any error and
3394 | * do the required cleanup.
3395 | */
3396 | static void
3397 | capture_input_closed(capture_session *cap_session _U___attribute__((unused)), char *msg)
3398 | {
3399 | if (msg != NULL((void*)0) && *msg != '\0')
3400 | fprintf(stderrstderr, "tshark: %s\n", msg);
3401 |
3402 | report_counts();
3403 |
3404 | loop_running = false0;
3405 | }
3406 |
3407 | #ifdef _WIN32
3408 | static BOOL WINAPI
3409 | capture_cleanup(DWORD ctrltype _U___attribute__((unused)))
3410 | {
3411 | /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to
3412 | Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT
3413 | is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of
3414 | like SIGTERM at least when the machine's shutting down.
3415 |
3416 | For now, we handle them all as indications that we should clean up
3417 | and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that
3418 | way on UNIX.
3419 |
3420 | We must return true so that no other handler - such as one that would
3421 | terminate the process - gets called.
3422 |
3423 | XXX - for some reason, typing ^C to TShark, if you run this in
3424 | a Cygwin console window in at least some versions of Cygwin,
3425 | causes TShark to terminate immediately; this routine gets
3426 | called, but the main loop doesn't get a chance to run and
3427 | exit cleanly, at least if this is compiled with Microsoft Visual
3428 | C++ (i.e., it's a property of the Cygwin console window or Bash;
3429 | it happens if TShark is not built with Cygwin - for all I know,
3430 | building it with Cygwin may make the problem go away). */
3431 |
3432 | /* tell the capture child to stop */
3433 | sync_pipe_stop(&global_capture_session);
3434 |
3435 | /* don't stop our own loop already here, otherwise status messages and
3436 | * cleanup wouldn't be done properly. The child will indicate the stop of
3437 | * everything by calling capture_input_closed() later */
3438 |
3439 | return true1;
3440 | }
3441 | #else
3442 | static void
3443 | capture_cleanup(int signum _U___attribute__((unused)))
3444 | {
3445 | /* tell the capture child to stop */
3446 | sync_pipe_stop(&global_capture_session);
3447 |
3448 | /* don't stop our own loop already here, otherwise status messages and
3449 | * cleanup wouldn't be done properly. The child will indicate the stop of
3450 | * everything by calling capture_input_closed() later */
3451 | }
3452 | #endif /* _WIN32 */
3453 | #endif /* HAVE_LIBPCAP */
3454 |
3455 | static bool_Bool
3456 | process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
3457 | int64_t offset, wtap_rec *rec)
3458 | {
3459 | frame_data fdlocal;
3460 | uint32_t framenum;
3461 | bool_Bool passed;
3462 | int64_t elapsed_start;
3463 |
3464 | /* The frame number of this packet is one more than the count of
3465 | frames in this packet. */
3466 | framenum = cf->count + 1;
3467 |
3468 | /* If we're not running a display filter and we're not printing any
3469 | packet information, we don't need to do a dissection. This means
3470 | that all packets can be marked as 'passed'. */
3471 | passed = true1;
3472 |
3473 | frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
3474 |
3475 | /* If we're going to run a read filter or a display filter, set up to
3476 | do a dissection and do so. (This is the first pass of two passes
3477 | over the packets, so we will not be printing any information
3478 | from the dissection or running taps on the packet; if we're doing
3479 | any of that, we'll do it in the second pass.) */
3480 | if (edt) {
3481 | if (gbl_resolv_flags.network_name || gbl_resolv_flags.maxmind_geoip) {
3482 | /* If we're doing async lookups, send any that are queued and
3483 | * retrieve results.
3484 | *
3485 | * Ideally we'd force any lookups that need to happen on the second pass
3486 | * to be sent asynchronously on this pass so the results would be ready.
3487 | * That will happen if they're involved in a filter (because we prime the
3488 | * tree below), but not currently for taps, if we're printing packet
3489 | * summaries or details, etc.
3490 | *
3491 | * XXX - If we're running a read filter that depends on a resolved
3492 | * name, we should be doing synchronous lookups in that case. Also
3493 | * marking the dependent frames below might not work with a display
3494 | * filter that depends on a resolved name.
3495 | */
3496 | host_name_lookup_process();
3497 | }
3498 |
3499 | column_info *cinfo = NULL((void*)0);
3500 |
3501 | /* If we're running a read filter, prime the epan_dissect_t with that
3502 | filter. */
3503 | if (cf->rfcode)
3504 | epan_dissect_prime_with_dfilter(edt, cf->rfcode);
3505 |
3506 | if (cf->dfcode)
3507 | epan_dissect_prime_with_dfilter(edt, cf->dfcode);
3508 |
3509 | frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
3510 | &cf->provider.ref, cf->provider.prev_dis);
3511 | if (cf->provider.ref == &fdlocal) {
3512 | ref_frame = fdlocal;
3513 | cf->provider.ref = &ref_frame;
3514 | }
3515 |
3516 | /* If we're applying a filter that needs the columns, construct them. */
3517 | if (dfilter_requires_columns(cf->rfcode) || dfilter_requires_columns(cf->dfcode)) {
3518 | cinfo = &cf->cinfo;
3519 | }
3520 |
3521 | elapsed_start = g_get_monotonic_time();
3522 | epan_dissect_run(edt, cf->cd_t, rec, &fdlocal, cinfo);
3523 | tshark_elapsed.first_pass.dissect += g_get_monotonic_time() - elapsed_start;
3524 |
3525 | /* Run the read filter if we have one. */
3526 | if (cf->rfcode) {
3527 | elapsed_start = g_get_monotonic_time();
3528 | passed = dfilter_apply_edt(cf->rfcode, edt);
3529 | tshark_elapsed.first_pass.dfilter_read += g_get_monotonic_time() - elapsed_start;
3530 | }
3531 | }
3532 |
3533 | if (passed) {
3534 | frame_data_set_after_dissect(&fdlocal, &cum_bytes);
3535 | cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
3536 |
3537 | /* If we're not doing dissection then there won't be any dependent frames.
3538 | * More importantly, edt.pi.fd.dependent_frames won't be initialized because
3539 | * epan hasn't been initialized.
3540 | * if we *are* doing dissection, then mark the dependent frames, but only
3541 | * if a display filter was given and it matches this packet.
3542 | */
3543 | if (edt && cf->dfcode) {
3544 | elapsed_start = g_get_monotonic_time();
3545 | if (dfilter_apply_edt(cf->dfcode, edt) && edt->pi.fd->dependent_frames) {
3546 | g_hash_table_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
3547 | }
3548 |
3549 | if (selected_frame_number != 0 && selected_frame_number == cf->count + 1) {
3550 | /* If we are doing dissection and we have a "selected frame"
3551 | * then load that frame's references (if any) onto the compiled
3552 | * display filter. Selected frame number is ordinal, count is cardinal. */
3553 | dfilter_load_field_references(cf->dfcode, edt->tree);
3554 | }
3555 | tshark_elapsed.first_pass.dfilter_filter += g_get_monotonic_time() - elapsed_start;
3556 | }
3557 |
3558 | cf->count++;
3559 | } else {
3560 | /* if we don't add it to the frame_data_sequence, clean it up right now
3561 | * to avoid leaks */
3562 | frame_data_destroy(&fdlocal);
3563 | }
3564 |
3565 | if (edt)
3566 | epan_dissect_reset(edt);
3567 |
3568 | return passed;
3569 | }
3570 |
3571 | /*
3572 | * Set if reading a file was interrupted by a CTRL_ event on Windows or
3573 | * a signal on UN*X.
3574 | */
3575 | static bool_Bool read_interrupted;
3576 |
3577 | #ifdef _WIN32
3578 | static BOOL WINAPI
3579 | read_cleanup(DWORD ctrltype _U___attribute__((unused)))
3580 | {
3581 | /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to
3582 | Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT
3583 | is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of
3584 | like SIGTERM at least when the machine's shutting down.
3585 |
3586 | For now, we handle them all as indications that we should clean up
3587 | and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that
3588 | way on UNIX.
3589 |
3590 | We must return true so that no other handler - such as one that would
3591 | terminate the process - gets called.
3592 |
3593 | XXX - for some reason, typing ^C to TShark, if you run this in
3594 | a Cygwin console window in at least some versions of Cygwin,
3595 | causes TShark to terminate immediately; this routine gets
3596 | called, but the main loop doesn't get a chance to run and
3597 | exit cleanly, at least if this is compiled with Microsoft Visual
3598 | C++ (i.e., it's a property of the Cygwin console window or Bash;
3599 | it happens if TShark is not built with Cygwin - for all I know,
3600 | building it with Cygwin may make the problem go away). */
3601 |
3602 | /* tell the read to stop */
3603 | read_interrupted = true1;
3604 |
3605 | return true1;
3606 | }
3607 | #else
3608 | static void
3609 | read_cleanup(int signum _U___attribute__((unused)))
3610 | {
3611 | /* tell the read to stop */
3612 | read_interrupted = true1;
3613 | }
3614 | #endif /* _WIN32 */
3615 |
3616 | typedef enum {
3617 | PASS_SUCCEEDED,
3618 | PASS_READ_ERROR,
3619 | PASS_WRITE_ERROR,
3620 | PASS_PRINT_ERROR,
3621 | PASS_INTERRUPTED
3622 | } pass_status_t;
3623 |
3624 | static pass_status_t
3625 | process_cap_file_first_pass(capture_file *cf, int max_packet_count,
3626 | int64_t max_byte_count, int *err, char **err_info)
3627 | {
3628 | wtap_rec rec;
3629 | epan_dissect_t *edt = NULL((void*)0);
3630 | int64_t data_offset;
3631 | pass_status_t status = PASS_SUCCEEDED;
3632 | int framenum = 0;
3633 |
3634 | wtap_rec_init(&rec, DEFAULT_INIT_BUFFER_SIZE_2048(2 * 1024));
3635 |
3636 | /* Allocate a frame_data_sequence for all the frames. */
3637 | cf->provider.frames = new_frame_data_sequence();
3638 |
3639 | if (do_dissection) {
3640 | bool_Bool create_proto_tree;
3641 |
3642 | /*
3643 | * Determine whether we need to create a protocol tree.
3644 | * We do if:
3645 | *
3646 | * we're going to apply a read filter;
3647 | *
3648 | * we're going to apply a display filter;
3649 | *
3650 | * a postdissector wants field values or protocols
3651 | * on the first pass.
3652 | */
3653 | create_proto_tree =
3654 | (cf->rfcode != NULL((void*)0) || cf->dfcode != NULL((void*)0) || postdissectors_want_hfids() || dissect_color);
3655 |
3656 | ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3656, __func__, "tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); } } while (0);
3657 |
3658 | /* We're not going to display the protocol tree on this pass,
3659 | so it's not going to be "visible". */
3660 | edt = epan_dissect_new(cf->epan, create_proto_tree, false0);
3661 | }
3662 |
3663 | ws_debug("tshark: reading records for first pass")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3663, __func__, "tshark: reading records for first pass"); } } while (0);
3664 | *err = 0;
3665 | while (wtap_read(cf->provider.wth, &rec, err, err_info, &data_offset)) {
3666 | if (read_interrupted) {
3667 | status = PASS_INTERRUPTED;
3668 | break;
3669 | }
3670 | framenum++;
3671 |
3672 | if (process_packet_first_pass(cf, edt, data_offset, &rec)) {
3673 | /* Stop reading if we hit a stop condition */
3674 | if (max_packet_count > 0 && framenum >= max_packet_count) {
3675 | ws_debug("tshark: max_packet_count (%d) reached", max_packet_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3675, __func__, "tshark: max_packet_count (%d) reached", max_packet_count ); } } while (0);
3676 | *err = 0; /* This is not an error */
3677 | break;
3678 | }
3679 | if (max_byte_count != 0 && data_offset >= max_byte_count) {
3680 | ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached",do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3681, __func__, "tshark: max_byte_count (%" "l" "d" "/%" "l" "d" ") reached", data_offset, max_byte_count); } } while (0)
3681 | data_offset, max_byte_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3681, __func__, "tshark: max_byte_count (%" "l" "d" "/%" "l" "d" ") reached", data_offset, max_byte_count); } } while (0);
3682 | *err = 0; /* This is not an error */
3683 | break;
3684 | }
3685 | }
3686 | wtap_rec_reset(&rec);
3687 | }
3688 | if (*err != 0)
3689 | status = PASS_READ_ERROR;
3690 |
3691 | if (edt)
3692 | epan_dissect_free(edt);
3693 |
3694 | /* Close the sequential I/O side, to free up memory it requires. */
3695 | wtap_sequential_close(cf->provider.wth);
3696 |
3697 | /* Allow the protocol dissectors to free up memory that they
3698 | * don't need after the sequential run-through of the packets. */
3699 | postseq_cleanup_all_protocols();
3700 |
3701 | cf->provider.prev_dis = NULL((void*)0);
3702 | cf->provider.prev_cap = NULL((void*)0);
3703 |
3704 | wtap_rec_cleanup(&rec);
3705 |
3706 | return status;
3707 | }
3708 |
3709 | static process_packet_status_t
3710 | process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
3711 | frame_data *fdata, wtap_rec *rec, unsigned tap_flags _U___attribute__((unused)))
3712 | {
3713 | column_info *cinfo;
3714 | bool_Bool passed;
3715 | wtap_block_t block = NULL((void*)0);
3716 | int64_t elapsed_start;
3717 |
3718 | /* If we're not running a display filter and we're not printing any
3719 | packet information, we don't need to do a dissection. This means
3720 | that all packets can be marked as 'passed'. */
3721 | passed = true1;
3722 |
3723 | /* If we're going to print packet information, or we're going to
3724 | run a read filter, or we're going to process taps, set up to
3725 | do a dissection and do so. (This is the second pass of two
3726 | passes over the packets; that's the pass where we print
3727 | packet information or run taps.) */
3728 | if (edt) {
3729 | /* If we're running a display filter, prime the epan_dissect_t with that
3730 | filter. */
3731 | if (cf->dfcode)
3732 | epan_dissect_prime_with_dfilter(edt, cf->dfcode);
3733 |
3734 | col_custom_prime_edt(edt, &cf->cinfo);
3735 |
3736 | output_fields_prime_edt(edt, output_fields);
3737 | /* The PDML spec requires a 'geninfo' pseudo-protocol that needs
3738 | * information from our 'frame' protocol.
3739 | */
3740 | if (output_fields_num_fields(output_fields) != 0 &&
3741 | output_action == WRITE_XML) {
3742 | epan_dissect_prime_with_hfid(edt, proto_registrar_get_id_byname("frame"));
3743 | }
3744 |
3745 | /* We only need the columns if either
3746 | 1) some tap or filter needs the columns
3747 | or
3748 | 2) we're printing packet info but we're *not* verbose; in verbose
3749 | mode, we print the protocol tree, not the protocol summary.
3750 | or
3751 | 3) there is a column mapped to an individual field
3752 | */
3753 | if ((tap_listeners_require_columns()) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields) || dfilter_requires_columns(cf->dfcode))
3754 | cinfo = &cf->cinfo;
3755 | else
3756 | cinfo = NULL((void*)0);
3757 |
3758 | frame_data_set_before_dissect(fdata, &cf->elapsed_time,
3759 | &cf->provider.ref, cf->provider.prev_dis);
3760 | if (cf->provider.ref == fdata) {
3761 | ref_frame = *fdata;
3762 | cf->provider.ref = &ref_frame;
3763 | }
3764 |
3765 | if (dissect_color) {
3766 | color_filters_prime_edt(edt);
3767 | fdata->need_colorize = 1;
3768 | }
3769 |
3770 | /* epan_dissect_run (and epan_dissect_reset) unref the block.
3771 | * We need it later, e.g. in order to copy the options. */
3772 | block = wtap_block_ref(rec->block);
3773 | elapsed_start = g_get_monotonic_time();
3774 | epan_dissect_run_with_taps(edt, cf->cd_t, rec, fdata, cinfo);
3775 | tshark_elapsed.second_pass.dissect += g_get_monotonic_time() - elapsed_start;
3776 |
3777 | /* Run the display filter if we have one. */
3778 | if (cf->dfcode) {
3779 | elapsed_start = g_get_monotonic_time();
3780 | passed = dfilter_apply_edt(cf->dfcode, edt);
3781 | tshark_elapsed.second_pass.dfilter_filter += g_get_monotonic_time() - elapsed_start;
3782 | }
3783 | }
3784 |
3785 | if (passed) {
3786 | frame_data_set_after_dissect(fdata, &cum_bytes);
3787 | /* Process this packet. */
3788 | if (print_packet_info) {
3789 | /* We're printing packet information; print the information for
3790 | this packet. */
3791 | if (!print_packet(cf, edt)) {
3792 | show_print_file_io_error();
3793 | return PROCESS_PACKET_PRINT_ERROR;
3794 | }
3795 |
3796 | /* If we're doing "line-buffering", flush the standard output
3797 | after every packet. See the comment above, for the "-l"
3798 | option, for an explanation of why we do that. */
3799 | if (line_buffered) {
3800 | if (fflush(stdoutstdout) == EOF(-1)) {
3801 | /* Report a write error; see above */
3802 | show_print_file_io_error();
3803 | return PROCESS_PACKET_PRINT_ERROR;
3804 | }
3805 | }
3806 | }
3807 | cf->provider.prev_dis = fdata;
3808 | }
3809 | cf->provider.prev_cap = fdata;
3810 |
3811 | if (edt) {
3812 | epan_dissect_reset(edt);
3813 | rec->block = block;
3814 | }
3815 | return (passed || fdata->dependent_of_displayed) ? PROCESS_PACKET_PASSED : PROCESS_PACKET_DIDNT_PASS;
3816 | }
3817 |
3818 | static bool_Bool
3819 | process_new_idbs(wtap *wth, wtap_dumper *pdh, int *err, char **err_info)
3820 | {
3821 | wtap_block_t if_data;
3822 |
3823 | while ((if_data = wtap_get_next_interface_description(wth)) != NULL((void*)0)) {
3824 | /*
3825 | * Only add interface blocks if the output file supports (meaning
3826 | * *requires*) them.
3827 | *
3828 | * That mean that the abstract interface provided by libwiretap
3829 | * involves WTAP_BLOCK_IF_ID_AND_INFO blocks.
3830 | */
3831 | if (pdh != NULL((void*)0)) {
3832 | if (wtap_file_type_subtype_supports_block(wtap_dump_file_type_subtype(pdh), WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) {
3833 | if (!wtap_dump_add_idb(pdh, if_data, err, err_info))
3834 | return false0;
3835 | }
3836 | }
3837 | }
3838 | return true1;
3839 | }
3840 |
3841 | static pass_status_t
3842 | process_cap_file_second_pass(capture_file *cf, wtap_dumper *pdh,
3843 | int *err, char **err_info,
3844 | volatile uint32_t *err_framenum,
3845 | int max_write_packet_count)
3846 | {
3847 | wtap_rec rec;
3848 | int framenum;
3849 | bool_Bool got_printing_error;
3850 | int write_framenum = 0;
3851 | frame_data *fdata;
3852 | bool_Bool filtering_tap_listeners;
3853 | unsigned tap_flags;
3854 | epan_dissect_t *edt = NULL((void*)0);
3855 | pass_status_t status = PASS_SUCCEEDED;
3856 |
3857 | /*
3858 | * Process whatever IDBs we haven't seen yet. This will be all
3859 | * the IDBs in the file, as we've finished reading it; they'll
3860 | * all be at the beginning of the output file.
3861 | */
3862 | if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) {
3863 | *err_framenum = 0;
3864 | return PASS_WRITE_ERROR;
3865 | }
3866 |
3867 | wtap_rec_init(&rec, DEFAULT_INIT_BUFFER_SIZE_2048(2 * 1024));
3868 |
3869 | /* Do we have any tap listeners with filters? */
3870 | filtering_tap_listeners = have_filtering_tap_listeners();
3871 |
3872 | /* Get the union of the flags for all tap listeners. */
3873 | tap_flags = union_of_tap_listener_flags();
3874 |
3875 | if (do_dissection) {
3876 | bool_Bool create_proto_tree;
3877 |
3878 | /*
3879 | * Determine whether we need to create a protocol tree.
3880 | * We do if:
3881 | *
3882 | * we're going to apply a display filter;
3883 | *
3884 | * we're going to print the protocol tree;
3885 | *
3886 | * one of the tap listeners requires a protocol tree;
3887 | *
3888 | * we have custom columns (which require field values, which
3889 | * currently requires that we build a protocol tree).
3890 | */
3891 | create_proto_tree =
3892 | (cf->dfcode || print_details || filtering_tap_listeners ||
3893 | (tap_flags & TL_REQUIRES_PROTO_TREE0x00000001) || have_custom_cols(&cf->cinfo) || dissect_color);
3894 |
3895 | ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3895, __func__, "tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); } } while (0);
3896 |
3897 | /* The protocol tree will be "visible", i.e., nothing faked, only if
3898 | we're printing packet details, which is true if we're printing stuff
3899 | ("print_packet_info" is true) and we're in verbose mode
3900 | ("packet_details" is true). But if we specified certain fields with
3901 | "-e", we'll prime those directly later. */
3902 | bool_Bool visible = print_packet_info && print_details && output_fields_num_fields(output_fields) == 0;
3903 | edt = epan_dissect_new(cf->epan, create_proto_tree, visible);
3904 | }
3905 |
3906 | /*
3907 | * Force synchronous resolution of IP addresses; in this pass, we
3908 | * can't do it in the background and fix up past dissections.
3909 | */
3910 | set_resolution_synchrony(true1);
3911 |
3912 | for (framenum = 1, got_printing_error = false0;
3913 | framenum <= (int)cf->count && !got_printing_error;
3914 | framenum++) {
3915 | if (read_interrupted) {
3916 | status = PASS_INTERRUPTED;
3917 | break;
3918 | }
3919 | fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3920 | if (!wtap_seek_read(cf->provider.wth, fdata->file_off, &rec, err,
3921 | err_info)) {
3922 | /* Error reading from the input file. */
3923 | status = PASS_READ_ERROR;
3924 | break;
3925 | }
3926 | ws_debug("tshark: invoking process_packet_second_pass() for frame #%d", framenum)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3926, __func__, "tshark: invoking process_packet_second_pass() for frame #%d" , framenum); } } while (0);
3927 | switch (process_packet_second_pass(cf, edt, fdata, &rec, tap_flags)) {
3928 |
3929 | case PROCESS_PACKET_PASSED:
3930 | /* Either there's no read filtering or this packet passed the
3931 | filter, so, if we're writing to a capture file, write
3932 | this packet out. */
3933 | /* XXX - With certain file types, time stamps are only available
3934 | * from a sequential wtap_read but not wtap_seek_read, in which
3935 | * case we could copy them from fdata when saving. */
3936 | write_framenum++;
3937 | if (pdh != NULL((void*)0)) {
3938 | ws_debug("tshark: writing packet #%d to outfile packet #%d", framenum, write_framenum)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3938, __func__, "tshark: writing packet #%d to outfile packet #%d" , framenum, write_framenum); } } while (0);
3939 | if (!wtap_dump(pdh, &rec, err, err_info)) {
3940 | /* Error writing to the output file. */
3941 | ws_debug("tshark: error writing to a capture file (%d)", *err)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3941, __func__, "tshark: error writing to a capture file (%d)" , *err); } } while (0);
3942 | *err_framenum = framenum;
3943 | status = PASS_WRITE_ERROR;
3944 | break;
3945 | }
3946 | /* Stop reading if we hit a stop condition */
3947 | if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) {
3948 | ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 3948, __func__, "tshark: max_write_packet_count (%d) reached" , max_write_packet_count); } } while (0);
3949 | *err = 0; /* This is not an error */
3950 | break;
3951 | }
3952 | }
3953 | break;
3954 |
3955 | case PROCESS_PACKET_DIDNT_PASS:
3956 | /* There is read filtering and this packet didn't pass the filter. */
3957 | break;
3958 |
3959 | case PROCESS_PACKET_PRINT_ERROR:
3960 | /* Either here's no read filtering or this packet passed
3961 | the read filter, and we tried to print dissection
3962 | informaion, but that failed. We've already reported
3963 | the error, unless it was EPIPE, in which case we just
3964 | silently quit; stop processing packes. */
3965 | got_printing_error = true1;
3966 | status = PASS_PRINT_ERROR;
3967 | break;
3968 | }
3969 | wtap_rec_reset(&rec);
3970 | }
3971 |
3972 | if (edt)
3973 | epan_dissect_free(edt);
3974 |
3975 | wtap_rec_cleanup(&rec);
3976 |
3977 | return status;
3978 | }
3979 |
3980 | static pass_status_t
3981 | process_cap_file_single_pass(capture_file *cf, wtap_dumper *pdh,
3982 | int max_packet_count, int64_t max_byte_count,
3983 | int max_write_packet_count,
3984 | int *err, char **err_info,
3985 | volatile uint32_t *err_framenum)
3986 | {
3987 | wtap_rec rec;
3988 | bool_Bool create_proto_tree = false0;
3989 | bool_Bool filtering_tap_listeners;
3990 | unsigned tap_flags;
3991 | int framenum = 0;
3992 | bool_Bool got_printing_error;
3993 | int write_framenum = 0;
3994 | epan_dissect_t *edt = NULL((void*)0);
3995 | int64_t data_offset;
3996 | pass_status_t status = PASS_SUCCEEDED;
3997 | bool_Bool visible = false0;
3998 |
3999 | wtap_rec_init(&rec, DEFAULT_INIT_BUFFER_SIZE_2048(2 * 1024));
4000 |
4001 | /* Do we have any tap listeners with filters? */
4002 | filtering_tap_listeners = have_filtering_tap_listeners();
4003 |
4004 | /* Get the union of the flags for all tap listeners. */
4005 | tap_flags = union_of_tap_listener_flags();
4006 |
4007 | if (do_dissection) {
4008 | /*
4009 | * Determine whether we need to create a protocol tree.
4010 | * We do if:
4011 | *
4012 | * we're going to apply a read filter;
4013 | *
4014 | * we're going to apply a display filter;
4015 | *
4016 | * we're going to print the protocol tree;
4017 | *
4018 | * one of the tap listeners is going to apply a filter;
4019 | *
4020 | * one of the tap listeners requires a protocol tree;
4021 | *
4022 | * a postdissector wants field values or protocols
4023 | * on the first pass;
4024 | *
4025 | * we have custom columns (which require field values, which
4026 | * currently requires that we build a protocol tree).
4027 | */
4028 | create_proto_tree =
4029 | (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
4030 | (tap_flags & TL_REQUIRES_PROTO_TREE0x00000001) || postdissectors_want_hfids() ||
4031 | have_custom_cols(&cf->cinfo) || dissect_color);
4032 |
4033 | ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4033, __func__, "tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); } } while (0);
4034 |
4035 | /* The protocol tree will be "visible", i.e., nothing faked, only if
4036 | we're printing packet details, which is true if we're printing stuff
4037 | ("print_packet_info" is true) and we're in verbose mode
4038 | ("packet_details" is true). But if we specified certain fields with
4039 | "-e", we'll prime those directly later. */
4040 | visible = print_packet_info && print_details && output_fields_num_fields(output_fields) == 0;
4041 | edt = epan_dissect_new(cf->epan, create_proto_tree, visible);
4042 | }
4043 |
4044 | /*
4045 | * Force synchronous resolution of IP addresses; we're doing only
4046 | * one pass, so we can't do it in the background and fix up past
4047 | * dissections.
4048 | */
4049 | set_resolution_synchrony(true1);
4050 |
4051 | *err = 0;
4052 | got_printing_error = false0;
4053 | while (wtap_read(cf->provider.wth, &rec, err, err_info, &data_offset) &&
4054 | !got_printing_error) {
4055 | if (read_interrupted) {
4056 | status = PASS_INTERRUPTED;
4057 | break;
4058 | }
4059 | framenum++;
4060 |
4061 | /*
4062 | * Process whatever IDBs we haven't seen yet.
4063 | */
4064 | if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) {
4065 | *err_framenum = framenum;
4066 | status = PASS_WRITE_ERROR;
4067 | break;
4068 | }
4069 |
4070 | ws_debug("tshark: processing packet #%d", framenum)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4070, __func__, "tshark: processing packet #%d", framenum); } } while (0);
4071 |
4072 | reset_epan_mem(cf, edt, create_proto_tree, visible);
4073 |
4074 | switch (process_packet_single_pass(cf, edt, data_offset, &rec,
4075 | tap_flags)) {
4076 | case PROCESS_PACKET_PASSED:
4077 | /* Either there's no read filtering or this packet passed the
4078 | filter, so, if we're writing to a capture file, write
4079 | this packet out. */
4080 | write_framenum++;
4081 | if (pdh != NULL((void*)0)) {
4082 | ws_debug("tshark: writing packet #%d to outfile as #%d",do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4083, __func__, "tshark: writing packet #%d to outfile as #%d" , framenum, write_framenum); } } while (0)
4083 | framenum, write_framenum)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4083, __func__, "tshark: writing packet #%d to outfile as #%d" , framenum, write_framenum); } } while (0);
4084 | if (!wtap_dump(pdh, &rec, err, err_info)) {
4085 | /* Error writing to the output file. */
4086 | ws_debug("tshark: error writing to a capture file (%d)", *err)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4086, __func__, "tshark: error writing to a capture file (%d)" , *err); } } while (0);
4087 | *err_framenum = framenum;
4088 | status = PASS_WRITE_ERROR;
4089 | break;
4090 | }
4091 | }
4092 | break;
4093 |
4094 | case PROCESS_PACKET_DIDNT_PASS:
4095 | /* There is read filtering and this packet didn't pass the filter. */
4096 | break;
4097 |
4098 | case PROCESS_PACKET_PRINT_ERROR:
4099 | /* Either here's no read filtering or this packet passed
4100 | the read filter, and we tried to print dissection
4101 | informaion, but that failed. We've already reported
4102 | the error, unless it was EPIPE, in which case we just
4103 | silently quit; tell the capture child to stop. */
4104 | got_printing_error = true1;
4105 | break;
4106 | }
4107 | /* Stop reading if we hit a stop condition */
4108 | if (max_packet_count > 0 && framenum >= max_packet_count) {
4109 | ws_debug("tshark: max_packet_count (%d) reached", max_packet_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4109, __func__, "tshark: max_packet_count (%d) reached", max_packet_count ); } } while (0);
4110 | *err = 0; /* This is not a read error */
4111 | break;
4112 | }
4113 | if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) {
4114 | ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4114, __func__, "tshark: max_write_packet_count (%d) reached" , max_write_packet_count); } } while (0);
4115 | *err = 0; /* This is not a read error */
4116 | break;
4117 | }
4118 | if (max_byte_count != 0 && data_offset >= max_byte_count) {
4119 | ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached",do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4120, __func__, "tshark: max_byte_count (%" "l" "d" "/%" "l" "d" ") reached", data_offset, max_byte_count); } } while (0)
4120 | data_offset, max_byte_count)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4120, __func__, "tshark: max_byte_count (%" "l" "d" "/%" "l" "d" ") reached", data_offset, max_byte_count); } } while (0);
4121 | *err = 0; /* This is not a read error */
4122 | break;
4123 | }
4124 | /* Stop reading if we got an error processing the packet. */
4125 | if (got_printing_error) {
4126 | *err = 0; /* This is not a read error */
4127 | break;
4128 | }
4129 | wtap_rec_reset(&rec);
4130 | }
4131 | if (status == PASS_SUCCEEDED) {
4132 | if (*err != 0) {
4133 | /* Error reading from the input file. */
4134 | status = PASS_READ_ERROR;
4135 | } else {
4136 | /*
4137 | * Process whatever IDBs we haven't seen yet.
4138 | */
4139 | if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) {
4140 | *err_framenum = framenum;
4141 | status = PASS_WRITE_ERROR;
4142 | }
4143 |
4144 | /*
4145 | * Did we get a printing error?
4146 | */
4147 | if (got_printing_error) {
4148 | status = PASS_PRINT_ERROR;
4149 | }
4150 | }
4151 | }
4152 |
4153 | if (edt)
4154 | epan_dissect_free(edt);
4155 |
4156 | wtap_rec_cleanup(&rec);
4157 |
4158 | return status;
4159 | }
4160 |
4161 | static process_file_status_t
4162 | process_cap_file(capture_file *cf, char *save_file, int out_file_type,
4163 | bool_Bool out_file_name_res, int max_packet_count, int64_t max_byte_count,
4164 | int max_write_packet_count, ws_compression_type compression_type)
4165 | {
4166 | process_file_status_t status = PROCESS_FILE_SUCCEEDED;
4167 | wtap_dumper *pdh;
4168 | #ifndef _WIN32
4169 | struct sigaction action, oldaction;
4170 | #endif
4171 | int err = 0, err_pass1 = 0;
4172 | char *err_info = NULL((void*)0), *err_info_pass1 = NULL((void*)0);
4173 | volatile uint32_t err_framenum;
4174 | wtap_dump_params params = WTAP_DUMP_PARAMS_INIT{.snaplen=0};
4175 | char *shb_user_appl;
4176 | pass_status_t first_pass_status, second_pass_status;
4177 | int64_t elapsed_start;
4178 |
4179 | if (save_file != NULL((void*)0)) {
4180 | /* Set up to write to the capture file. */
4181 | wtap_dump_params_init_no_idbs(&params, cf->provider.wth);
4182 |
4183 | /* If we don't have an application name add TShark */
4184 | if (wtap_block_get_string_option_value(g_array_index(params.shb_hdrs, wtap_block_t, 0)(((wtap_block_t*) (void *) (params.shb_hdrs)->data) [(0)]), OPT_SHB_USERAPPL4, &shb_user_appl) != WTAP_OPTTYPE_SUCCESS) {
4185 | /* this is free'd by wtap_block_unref() later */
4186 | wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0)(((wtap_block_t*) (void *) (params.shb_hdrs)->data) [(0)]), OPT_SHB_USERAPPL4, "%s", get_appname_and_version());
4187 | }
4188 | if (capture_comments != NULL((void*)0)) {
4189 | for (unsigned i = 0; i < capture_comments->len; i++) {
4190 | wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0)(((wtap_block_t*) (void *) (params.shb_hdrs)->data) [(0)]),
4191 | OPT_COMMENT1, "%s",
4192 | (char *)g_ptr_array_index(capture_comments, i)((capture_comments)->pdata)[i]);
4193 | }
4194 | }
4195 |
4196 | ws_debug("tshark: writing format type %d, to %s", out_file_type, save_file)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4196, __func__, "tshark: writing format type %d, to %s", out_file_type , save_file); } } while (0);
4197 | if (strcmp(save_file, "-") == 0) {
4198 | /* Write to the standard output. */
4199 | pdh = wtap_dump_open_stdout(out_file_type, compression_type, &params,
4200 | &err, &err_info);
4201 | } else {
4202 | pdh = wtap_dump_open(save_file, out_file_type, compression_type, &params,
4203 | &err, &err_info);
4204 | }
4205 |
4206 | g_free(params.idb_inf);
4207 | params.idb_inf = NULL((void*)0);
4208 |
4209 | if (pdh == NULL((void*)0)) {
4210 | /* We couldn't set up to write to the capture file. */
4211 | report_cfile_dump_open_failure(save_file, err, err_info,
4212 | out_file_type);
4213 | status = PROCESS_FILE_NO_FILE_PROCESSED;
4214 | goto out;
4215 | }
4216 | } else {
4217 | /* Set up to print packet information. */
4218 | if (print_packet_info) {
4219 | if (!write_preamble(cf)) {
4220 | show_print_file_io_error();
4221 | status = PROCESS_FILE_NO_FILE_PROCESSED;
4222 | goto out;
4223 | }
4224 | }
4225 | pdh = NULL((void*)0);
4226 | }
4227 |
4228 | #ifdef _WIN32
4229 | /* Catch a CTRL+C event and, if we get it, clean up and exit. */
4230 | SetConsoleCtrlHandler(read_cleanup, true1);
4231 | #else /* _WIN32 */
4232 | /* Catch SIGINT and SIGTERM and, if we get either of them,
4233 | clean up and exit. If SIGHUP isn't being ignored, catch
4234 | it too and, if we get it, clean up and exit.
4235 |
4236 | We restart any read that was in progress, so that it doesn't
4237 | disrupt reading from the sync pipe. The signal handler tells
4238 | the capture child to finish; it will report that it finished,
4239 | or will exit abnormally, so we'll stop reading from the sync
4240 | pipe, pick up the exit status, and quit. */
4241 | memset(&action, 0, sizeof(action));
4242 | action.sa_handler__sigaction_handler.sa_handler = read_cleanup;
4243 | action.sa_flags = SA_RESTART0x10000000;
4244 | sigemptyset(&action.sa_mask);
4245 | sigaction(SIGTERM15, &action, NULL((void*)0));
4246 | sigaction(SIGINT2, &action, NULL((void*)0));
4247 | sigaction(SIGHUP1, NULL((void*)0), &oldaction);
4248 | if (oldaction.sa_handler__sigaction_handler.sa_handler == SIG_DFL((__sighandler_t) 0))
4249 | sigaction(SIGHUP1, &action, NULL((void*)0));
4250 | #endif /* _WIN32 */
4251 |
4252 | if (perform_two_pass_analysis) {
4253 | ws_debug("tshark: perform_two_pass_analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4253, __func__, "tshark: perform_two_pass_analysis, do_dissection=%s" , do_dissection ? "TRUE" : "FALSE"); } } while (0);
4254 |
4255 | elapsed_start = g_get_monotonic_time();
4256 | first_pass_status = process_cap_file_first_pass(cf, max_packet_count,
4257 | max_byte_count,
4258 | &err_pass1,
4259 | &err_info_pass1);
4260 | tshark_elapsed.elapsed_first_pass = g_get_monotonic_time() - elapsed_start;
4261 |
4262 | ws_debug("tshark: done with first pass")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4262, __func__, "tshark: done with first pass"); } } while ( 0);
4263 |
4264 | if (first_pass_status == PASS_INTERRUPTED) {
4265 | /* The first pass was interrupted; skip the second pass.
4266 | It won't be run, so it won't get an error. */
4267 | second_pass_status = PASS_SUCCEEDED;
4268 | } else {
4269 | /*
4270 | * If we got a read error on the first pass, we still do the second
4271 | * pass, so we can at least process the packets we read, and then
4272 | * report the first-pass error after the second pass (and before
4273 | * we report any second-pass errors), so all the errors show up
4274 | * at the end.
4275 | */
4276 | elapsed_start = g_get_monotonic_time();
4277 | second_pass_status = process_cap_file_second_pass(cf, pdh, &err, &err_info,
4278 | &err_framenum,
4279 | max_write_packet_count);
4280 | tshark_elapsed.elapsed_second_pass = g_get_monotonic_time() - elapsed_start;
4281 |
4282 | ws_debug("tshark: done with second pass")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4282, __func__, "tshark: done with second pass"); } } while (0);
4283 | }
4284 | }
4285 | else {
4286 | /* !perform_two_pass_analysis */
4287 | ws_debug("tshark: perform one pass analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4287, __func__, "tshark: perform one pass analysis, do_dissection=%s" , do_dissection ? "TRUE" : "FALSE"); } } while (0);
4288 |
4289 | first_pass_status = PASS_SUCCEEDED; /* There is no first pass */
4290 |
4291 | elapsed_start = g_get_monotonic_time();
4292 | second_pass_status = process_cap_file_single_pass(cf, pdh,
4293 | max_packet_count,
4294 | max_byte_count,
4295 | max_write_packet_count,
4296 | &err, &err_info,
4297 | &err_framenum);
4298 | tshark_elapsed.elapsed_first_pass = g_get_monotonic_time() - elapsed_start;
4299 |
4300 | ws_debug("tshark: done with single pass")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4300, __func__, "tshark: done with single pass"); } } while (0);
4301 | }
4302 |
4303 | if (first_pass_status != PASS_SUCCEEDED ||
4304 | second_pass_status != PASS_SUCCEEDED) {
4305 | /*
4306 | * At least one of the passes didn't succeed; either it got a failure
4307 | * or it was interrupted.
4308 | */
4309 | if (first_pass_status != PASS_INTERRUPTED ||
4310 | second_pass_status != PASS_INTERRUPTED) {
4311 | /* At least one of the passes got an error. */
4312 | ws_debug("tshark: something failed along the line (%d)", err)do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "tshark.c" , 4312, __func__, "tshark: something failed along the line (%d)" , err); } } while (0);
4313 | /*
4314 | * If we're printing packet data, and the standard output and error
4315 | * are going to the same place, flush the standard output, so everything
4316 | * buffered up is written, and then print a newline to the standard
4317 | * error before printing the error message, to separate it from the
4318 | * packet data. (Alas, that only works on UN*X; st_dev is meaningless,
4319 | * and the _fstat() documentation at Microsoft doesn't indicate whether
4320 | * st_ino is even supported.)
4321 | */
4322 | #ifndef _WIN32
4323 | if (print_packet_info) {
4324 | ws_statb64struct stat stat_stdout, stat_stderr;
4325 |
4326 | if (ws_fstat64fstat(1, &stat_stdout) == 0 && ws_fstat64fstat(2, &stat_stderr) == 0) {
4327 | if (stat_stdout.st_dev == stat_stderr.st_dev &&
4328 | stat_stdout.st_ino == stat_stderr.st_ino) {
4329 | fflush(stdoutstdout);
4330 | fprintf(stderrstderr, "\n");
4331 | }
4332 | }
4333 | }
4334 | #endif
4335 | }
4336 | /* Report status of pass 1 of two-pass processing. */
4337 | switch (first_pass_status) {
4338 |
4339 | case PASS_SUCCEEDED:
4340 | /* No problem. */
4341 | break;
4342 |
4343 | case PASS_READ_ERROR:
4344 | /* Read error. */
4345 | report_cfile_read_failure(cf->filename, err_pass1, err_info_pass1);
4346 | status = PROCESS_FILE_ERROR;
4347 | break;
4348 |
4349 | case PASS_WRITE_ERROR:
4350 | /* Won't happen on the first pass. */
4351 | break;
4352 |
4353 | case PASS_PRINT_ERROR:
4354 | /* Won't happen on the first pass. */
4355 | break;
4356 |
4357 | case PASS_INTERRUPTED:
4358 | /* Not an error, so nothing to report. */
4359 | status = PROCESS_FILE_INTERRUPTED;
4360 | break;
4361 | }
4362 |
4363 | /* Report status of pass 2 of two-pass processing or the only pass
4364 | of one-pass processing. */
4365 | switch (second_pass_status) {
4366 |
4367 | case PASS_SUCCEEDED:
4368 | /* No problem. */
4369 | break;
4370 |
4371 | case PASS_READ_ERROR:
4372 | /* Read error. */
4373 | report_cfile_read_failure(cf->filename, err, err_info);
4374 | status = PROCESS_FILE_ERROR;
4375 | break;
4376 |
4377 | case PASS_WRITE_ERROR:
4378 | /* Write error.
4379 | XXX - framenum is not necessarily the frame number in
4380 | the input file if there was a read filter. */
4381 | report_cfile_write_failure(cf->filename, save_file, err, err_info,
4382 | err_framenum, out_file_type);
4383 | status = PROCESS_FILE_ERROR;
4384 | break;
4385 |
4386 | case PASS_PRINT_ERROR:
4387 | /* The print error has already been reported. */
4388 | status = PROCESS_FILE_ERROR;
4389 | break;
4390 |
4391 | case PASS_INTERRUPTED:
4392 | /* Not an error, so nothing to report. */
4393 | status = PROCESS_FILE_INTERRUPTED;
4394 | break;
4395 | }
4396 | }
4397 | if (save_file != NULL((void*)0)) {
4398 | if (second_pass_status != PASS_WRITE_ERROR) {
4399 | if (pdh && out_file_name_res) {
4400 | /* XXX: This doesn't work as expected. First, it should be
4401 | * moved to between the first and second passes (if doing
4402 | * two-pass mode), so that the new NRB appears before packets,
4403 | * which is better for subsequent one-pass mode. It never works
4404 | * well in one-pass mode.
4405 | *
4406 | * Second, it only writes hosts that we've done lookups for,
4407 | * which means unless packet details are printed (or there's
4408 | * a display filter that matches something that will do a host
4409 | * lookup, e.g. -Y "ip") it doesn't actually have anything
4410 | * in the list to save. Notably, that includes the case of
4411 | * "tshark [-2] -H hosts.txt -r <infile> -w <outfile>",
4412 | * which a user would certainly expect to dissect packets,
4413 | * lookup hostnames, and add them to an NRB for later use.
4414 | * A workaround is if "-V > /dev/null" is added, but who
4415 | * expects that?
4416 | *
4417 | * A third issue is that name resolution blocks aren't
4418 | * written for live captures.
4419 | */
4420 | if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) {
4421 | cmdarg_err("The file format \"%s\" doesn't support name resolution information.",
4422 | wtap_file_type_subtype_name(out_file_type));
4423 | }
4424 | }
4425 | /* Now close the capture file. */
4426 | if (!wtap_dump_close(pdh, NULL((void*)0), &err, &err_info)) {
4427 | report_cfile_close_failure(save_file, err, err_info);
4428 | status = PROCESS_FILE_ERROR;
4429 | }
4430 | } else {
4431 | /* We got a write error; it was reported, so just close the dump file
4432 | without bothering to check for further errors. */
4433 | wtap_dump_close(pdh, NULL((void*)0), &err, &err_info);
4434 | g_free(err_info);
4435 | status = PROCESS_FILE_ERROR;
4436 | }
4437 | } else {
4438 | if (print_packet_info) {
4439 | if (!write_finale()) {
4440 | show_print_file_io_error();
4441 | status = PROCESS_FILE_ERROR;
4442 | }
4443 | }
4444 | }
4445 |
4446 | out:
4447 | wtap_close(cf->provider.wth);
4448 | cf->provider.wth = NULL((void*)0);
4449 |
4450 | wtap_dump_params_cleanup(&params);
4451 |
4452 | return status;
4453 | }
4454 |
4455 | static process_packet_status_t
4456 | process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, int64_t offset,
4457 | wtap_rec *rec, unsigned tap_flags _U___attribute__((unused)))
4458 | {
4459 | frame_data fdata;
4460 | column_info *cinfo;
4461 | bool_Bool passed;
4462 | wtap_block_t block = NULL((void*)0);
4463 | int64_t elapsed_start;
4464 |
4465 | /* Count this packet. */
4466 | cf->count++;
4467 |
4468 | /* If we're not running a display filter and we're not printing any
4469 | packet information, we don't need to do a dissection. This means
4470 | that all packets can be marked as 'passed'. */
4471 | passed = true1;
4472 |
4473 | frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
4474 |
4475 | /* If we're going to print packet information, or we're going to
4476 | run a read filter, or we're going to process taps, set up to
4477 | do a dissection and do so. (This is the one and only pass
4478 | over the packets, so, if we'll be printing packet information
4479 | or running taps, we'll be doing it here.) */
4480 | if (edt) {
4481 | /* If we're running a filter, prime the epan_dissect_t with that
4482 | filter. */
4483 | if (cf->dfcode)
4484 | epan_dissect_prime_with_dfilter(edt, cf->dfcode);
4485 |
4486 | col_custom_prime_edt(edt, &cf->cinfo);
4487 |
4488 | output_fields_prime_edt(edt, output_fields);
4489 | /* The PDML spec requires a 'geninfo' pseudo-protocol that needs
4490 | * information from our 'frame' protocol.
4491 | */
4492 | if (output_fields_num_fields(output_fields) != 0 &&
4493 | output_action == WRITE_XML) {
4494 | epan_dissect_prime_with_hfid(edt, proto_registrar_get_id_byname("frame"));
4495 | }
4496 |
4497 | /* We only need the columns if either
4498 | 1) some tap or filter needs the columns
4499 | or
4500 | 2) we're printing packet info but we're *not* verbose; in verbose
4501 | mode, we print the protocol tree, not the protocol summary.
4502 | or
4503 | 3) there is a column mapped as an individual field */
4504 | if ((tap_listeners_require_columns()) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields) || dfilter_requires_columns(cf->dfcode))
4505 | cinfo = &cf->cinfo;
4506 | else
4507 | cinfo = NULL((void*)0);
4508 |
4509 | frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
4510 | &cf->provider.ref, cf->provider.prev_dis);
4511 | if (cf->provider.ref == &fdata) {
4512 | ref_frame = fdata;
4513 | cf->provider.ref = &ref_frame;
4514 | }
4515 |
4516 | if (dissect_color) {
4517 | color_filters_prime_edt(edt);
4518 | fdata.need_colorize = 1;
4519 | }
4520 |
4521 | /* epan_dissect_run (and epan_dissect_reset) unref the block.
4522 | * We need it later, e.g. in order to copy the options. */
4523 | block = wtap_block_ref(rec->block);
4524 | elapsed_start = g_get_monotonic_time();
4525 | epan_dissect_run_with_taps(edt, cf->cd_t, rec, &fdata, cinfo);
4526 | tshark_elapsed.first_pass.dissect += g_get_monotonic_time() - elapsed_start;
4527 |
4528 | /* Run the filter if we have it. */
4529 | if (cf->dfcode) {
4530 | elapsed_start = g_get_monotonic_time();
4531 | passed = dfilter_apply_edt(cf->dfcode, edt);
4532 | tshark_elapsed.first_pass.dfilter_filter += g_get_monotonic_time() - elapsed_start;
4533 | }
4534 | }
4535 |
4536 | if (passed) {
4537 | frame_data_set_after_dissect(&fdata, &cum_bytes);
4538 |
4539 | /* Process this packet. */
4540 | if (print_packet_info) {
4541 | /* We're printing packet information; print the information for
4542 | this packet. */
4543 | ws_assert(edt)do { if ((1) && !(edt)) ws_log_fatal_full("Main", LOG_LEVEL_ERROR , "tshark.c", 4543, __func__, "assertion failed: %s", "edt"); } while (0);
4544 | if (!print_packet(cf, edt)) {
4545 | show_print_file_io_error();
4546 | return PROCESS_PACKET_PRINT_ERROR;
4547 | }
4548 |
4549 | /* If we're doing "line-buffering", flush the standard output
4550 | after every packet. See the comment above, for the "-l"
4551 | option, for an explanation of why we do that. */
4552 | if (line_buffered) {
4553 | if (fflush(stdoutstdout) == EOF(-1)) {
4554 | /* Report a write error; see above */
4555 | show_print_file_io_error();
4556 | return PROCESS_PACKET_PRINT_ERROR;
4557 | }
4558 | }
4559 | }
4560 |
4561 | /* this must be set after print_packet() [bug #8160] */
4562 | prev_dis_frame = fdata;
4563 | cf->provider.prev_dis = &prev_dis_frame;
4564 | }
4565 |
4566 | prev_cap_frame = fdata;
4567 | cf->provider.prev_cap = &prev_cap_frame;
4568 |
4569 | if (edt) {
4570 | epan_dissect_reset(edt);
4571 | frame_data_destroy(&fdata);
4572 | rec->block = block;
4573 | }
4574 | return passed ? PROCESS_PACKET_PASSED : PROCESS_PACKET_DIDNT_PASS;
4575 | }
4576 |
4577 | static bool_Bool
4578 | write_preamble(capture_file *cf)
4579 | {
4580 | switch (output_action) {
4581 |
4582 | case WRITE_TEXT:
4583 | return print_preamble(print_stream, cf->filename, application_get_vcs_version_info());
4584 |
4585 | case WRITE_XML:
4586 | if (print_details)
4587 | write_pdml_preamble(stdoutstdout, cf->filename, get_doc_dir(application_configuration_environment_prefix()));
4588 | else
4589 | write_psml_preamble(&cf->cinfo, stdoutstdout);
4590 | return !ferror(stdoutstdout);
4591 |
4592 | case WRITE_FIELDS:
4593 | write_fields_preamble(output_fields, stdoutstdout);
4594 | return !ferror(stdoutstdout);
4595 |
4596 | case WRITE_JSON:
4597 | case WRITE_JSON_RAW:
4598 | jdumper = write_json_preamble(stdoutstdout);
4599 | return !ferror(stdoutstdout);
4600 |
4601 | case WRITE_EK:
4602 | return true1;
4603 |
4604 | default:
4605 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 4605, __func__ , "assertion \"not reached\" failed");
4606 | return false0;
4607 | }
4608 | }
4609 |
4610 | static char *
4611 | get_line_buf(size_t len)
4612 | {
4613 | static char *line_bufp = NULL((void*)0);
4614 | static size_t line_buf_len = 256;
4615 | size_t new_line_buf_len;
4616 |
4617 | for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
4618 | new_line_buf_len *= 2)
4619 | ;
4620 | if (line_bufp == NULL((void*)0)) {
4621 | line_buf_len = new_line_buf_len;
4622 | line_bufp = (char *)g_malloc(line_buf_len + 1);
4623 | } else {
4624 | if (new_line_buf_len > line_buf_len) {
4625 | line_buf_len = new_line_buf_len;
4626 | line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
4627 | }
4628 | }
4629 | return line_bufp;
4630 | }
4631 |
4632 | static inline void
4633 | put_string(char *dest, const char *str, size_t str_len)
4634 | {
4635 | memcpy(dest, str, str_len);
4636 | dest[str_len] = '\0';
4637 | }
4638 |
4639 | static inline void
4640 | put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
4641 | {
4642 | size_t i;
4643 |
4644 | for (i = str_len; i < str_with_spaces; i++)
4645 | *dest++ = ' ';
4646 |
4647 | put_string(dest, str, str_len);
4648 | }
4649 |
4650 | static inline void
4651 | put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
4652 | {
4653 | size_t i;
4654 |
4655 | memcpy(dest, str, str_len);
4656 | for (i = str_len; i < str_with_spaces; i++)
4657 | dest[i] = ' ';
4658 |
4659 | dest[str_with_spaces] = '\0';
4660 | }
4661 |
4662 | static bool_Bool
4663 | print_columns(capture_file *cf, const epan_dissect_t *edt)
4664 | {
4665 | char *line_bufp;
4666 | unsigned i;
4667 | size_t buf_offset;
4668 | size_t column_len;
4669 | size_t col_len;
4670 | col_item_t* col_item;
4671 | char str_format[11];
4672 | const color_filter_t *color_filter = NULL((void*)0);
4673 |
4674 | line_bufp = get_line_buf(256);
4675 | buf_offset = 0;
4676 | *line_bufp = '\0';
4677 |
4678 | if (dissect_color)
4679 | color_filter = edt->pi.fd->color_filter;
4680 |
4681 | for (i = 0; i < cf->cinfo.num_cols; i++) {
4682 | col_item = &cf->cinfo.columns[i];
4683 | /* Skip columns not marked as visible. */
4684 | if (!get_column_visible(i))
4685 | continue;
4686 | const char* col_text = get_column_text(&cf->cinfo, i);
4687 | switch (col_item->col_fmt) {
4688 | case COL_NUMBER:
4689 | case COL_NUMBER_DIS:
4690 | column_len = col_len = strlen(col_text);
4691 | if (column_len < 5)
4692 | column_len = 5;
4693 | line_bufp = get_line_buf(buf_offset + column_len);
4694 | put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
4695 | break;
4696 |
4697 | case COL_CLS_TIME:
4698 | case COL_REL_TIME:
4699 | case COL_ABS_TIME:
4700 | case COL_ABS_YMD_TIME: /* XXX - wider */
4701 | case COL_ABS_YDOY_TIME: /* XXX - wider */
4702 | case COL_UTC_TIME:
4703 | case COL_UTC_YMD_TIME: /* XXX - wider */
4704 | case COL_UTC_YDOY_TIME: /* XXX - wider */
4705 | column_len = col_len = strlen(col_text);
4706 | if (column_len < 10)
4707 | column_len = 10;
4708 | line_bufp = get_line_buf(buf_offset + column_len);
4709 | put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
4710 | break;
4711 |
4712 | case COL_DEF_SRC:
4713 | case COL_RES_SRC:
4714 | case COL_UNRES_SRC:
4715 | case COL_DEF_DL_SRC:
4716 | case COL_RES_DL_SRC:
4717 | case COL_UNRES_DL_SRC:
4718 | case COL_DEF_NET_SRC:
4719 | case COL_RES_NET_SRC:
4720 | case COL_UNRES_NET_SRC:
4721 | column_len = col_len = strlen(col_text);
4722 | if (column_len < 12)
4723 | column_len = 12;
4724 | line_bufp = get_line_buf(buf_offset + column_len);
4725 | put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
4726 | break;
4727 |
4728 | case COL_DEF_DST:
4729 | case COL_RES_DST:
4730 | case COL_UNRES_DST:
4731 | case COL_DEF_DL_DST:
4732 | case COL_RES_DL_DST:
4733 | case COL_UNRES_DL_DST:
4734 | case COL_DEF_NET_DST:
4735 | case COL_RES_NET_DST:
4736 | case COL_UNRES_NET_DST:
4737 | column_len = col_len = strlen(col_text);
4738 | if (column_len < 12)
4739 | column_len = 12;
4740 | line_bufp = get_line_buf(buf_offset + column_len);
4741 | put_string_spaces(line_bufp + buf_offset, col_text, col_len, column_len);
4742 | break;
4743 |
4744 | default:
4745 | column_len = strlen(col_text);
4746 | line_bufp = get_line_buf(buf_offset + column_len);
4747 | put_string(line_bufp + buf_offset, col_text, column_len);
4748 | break;
4749 | }
4750 | buf_offset += column_len;
4751 | if (i != cf->cinfo.num_cols - 1) {
4752 | /*
4753 | * This isn't the last column, so we need to print a
4754 | * separator between this column and the next.
4755 | *
4756 | * If we printed a network source and are printing a
4757 | * network destination of the same type next, separate
4758 | * them with a UTF-8 right arrow; if we printed a network
4759 | * destination and are printing a network source of the same
4760 | * type next, separate them with a UTF-8 left arrow;
4761 | * otherwise separate them with a space.
4762 | *
4763 | * We add enough space to the buffer for " \xe2\x86\x90 "
4764 | * or " \xe2\x86\x92 ", even if we're only adding " ".
4765 | */
4766 | line_bufp = get_line_buf(buf_offset + 5);
4767 | switch (col_item->col_fmt) {
4768 |
4769 | case COL_DEF_SRC:
4770 | case COL_RES_SRC:
4771 | case COL_UNRES_SRC:
4772 | switch (cf->cinfo.columns[i+1].col_fmt) {
4773 |
4774 | case COL_DEF_DST:
4775 | case COL_RES_DST:
4776 | case COL_UNRES_DST:
4777 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW"\u2192", delimiter_char);
4778 | put_string(line_bufp + buf_offset, str_format, 5);
4779 | buf_offset += 5;
4780 | break;
4781 |
4782 | default:
4783 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4784 | buf_offset += 1;
4785 | break;
4786 | }
4787 | break;
4788 |
4789 | case COL_DEF_DL_SRC:
4790 | case COL_RES_DL_SRC:
4791 | case COL_UNRES_DL_SRC:
4792 | switch (cf->cinfo.columns[i+1].col_fmt) {
4793 |
4794 | case COL_DEF_DL_DST:
4795 | case COL_RES_DL_DST:
4796 | case COL_UNRES_DL_DST:
4797 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW"\u2192", delimiter_char);
4798 | put_string(line_bufp + buf_offset, str_format, 5);
4799 | buf_offset += 5;
4800 | break;
4801 |
4802 | default:
4803 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4804 | buf_offset += 1;
4805 | break;
4806 | }
4807 | break;
4808 |
4809 | case COL_DEF_NET_SRC:
4810 | case COL_RES_NET_SRC:
4811 | case COL_UNRES_NET_SRC:
4812 | switch (cf->cinfo.columns[i+1].col_fmt) {
4813 |
4814 | case COL_DEF_NET_DST:
4815 | case COL_RES_NET_DST:
4816 | case COL_UNRES_NET_DST:
4817 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW"\u2192", delimiter_char);
4818 | put_string(line_bufp + buf_offset, str_format, 5);
4819 | buf_offset += 5;
4820 | break;
4821 |
4822 | default:
4823 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4824 | buf_offset += 1;
4825 | break;
4826 | }
4827 | break;
4828 |
4829 | case COL_DEF_DST:
4830 | case COL_RES_DST:
4831 | case COL_UNRES_DST:
4832 | switch (cf->cinfo.columns[i+1].col_fmt) {
4833 |
4834 | case COL_DEF_SRC:
4835 | case COL_RES_SRC:
4836 | case COL_UNRES_SRC:
4837 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW"\u2190", delimiter_char);
4838 | put_string(line_bufp + buf_offset, str_format, 5);
4839 | buf_offset += 5;
4840 | break;
4841 |
4842 | default:
4843 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4844 | buf_offset += 1;
4845 | break;
4846 | }
4847 | break;
4848 |
4849 | case COL_DEF_DL_DST:
4850 | case COL_RES_DL_DST:
4851 | case COL_UNRES_DL_DST:
4852 | switch (cf->cinfo.columns[i+1].col_fmt) {
4853 |
4854 | case COL_DEF_DL_SRC:
4855 | case COL_RES_DL_SRC:
4856 | case COL_UNRES_DL_SRC:
4857 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW"\u2190", delimiter_char);
4858 | put_string(line_bufp + buf_offset, str_format, 5);
4859 | buf_offset += 5;
4860 | break;
4861 |
4862 | default:
4863 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4864 | buf_offset += 1;
4865 | break;
4866 | }
4867 | break;
4868 |
4869 | case COL_DEF_NET_DST:
4870 | case COL_RES_NET_DST:
4871 | case COL_UNRES_NET_DST:
4872 | switch (cf->cinfo.columns[i+1].col_fmt) {
4873 |
4874 | case COL_DEF_NET_SRC:
4875 | case COL_RES_NET_SRC:
4876 | case COL_UNRES_NET_SRC:
4877 | snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW"\u2190", delimiter_char);
4878 | put_string(line_bufp + buf_offset, str_format, 5);
4879 | buf_offset += 5;
4880 | break;
4881 |
4882 | default:
4883 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4884 | buf_offset += 1;
4885 | break;
4886 | }
4887 | break;
4888 |
4889 | default:
4890 | put_string(line_bufp + buf_offset, delimiter_char, 1);
4891 | buf_offset += 1;
4892 | break;
4893 | }
4894 | }
4895 | }
4896 |
4897 | if (dissect_color && color_filter != NULL((void*)0))
4898 | return print_line_color(print_stream, 0, line_bufp, &color_filter->fg_color, &color_filter->bg_color);
4899 | else
4900 | return print_line(print_stream, 0, line_bufp);
4901 | }
4902 |
4903 | static bool_Bool
4904 | print_packet(capture_file *cf, epan_dissect_t *edt)
4905 | {
4906 | if (print_summary || output_fields_has_cols(output_fields))
4907 | /* Just fill in the columns. */
4908 | epan_dissect_fill_in_columns(edt, false0, true1);
4909 |
4910 | /* Print summary columns and/or protocol tree */
4911 | switch (output_action) {
4912 |
4913 | case WRITE_TEXT:
4914 | if (print_summary && !print_columns(cf, edt))
4915 | return false0;
4916 | if (print_details) {
4917 | if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
4918 | print_hex, edt, output_only_tables, print_stream))
4919 | return false0;
4920 | if (!print_hex) {
4921 | if (!print_line(print_stream, 0, separator))
4922 | return false0;
4923 | }
4924 | }
4925 | break;
4926 |
4927 | case WRITE_XML:
4928 | if (print_summary) {
4929 | write_psml_columns(edt, stdoutstdout, dissect_color);
4930 | return !ferror(stdoutstdout);
4931 | }
4932 | if (print_details) {
4933 | write_pdml_proto_tree(output_fields, edt, &cf->cinfo, stdoutstdout, dissect_color);
4934 | printf("\n");
4935 | return !ferror(stdoutstdout);
4936 | }
4937 | break;
4938 |
4939 | case WRITE_FIELDS:
4940 | if (print_summary) {
4941 | /*No non-verbose "fields" format */
4942 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 4942, __func__ , "assertion \"not reached\" failed");
4943 | }
4944 | if (print_details) {
4945 | write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdoutstdout);
4946 | printf("\n");
4947 | return !ferror(stdoutstdout);
4948 | }
4949 | break;
4950 |
4951 | case WRITE_JSON:
4952 | if (print_summary)
4953 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 4953, __func__ , "assertion \"not reached\" failed");
4954 | if (print_details) {
4955 | write_json_proto_tree(output_fields, print_dissections_expanded,
4956 | print_hex, edt, &cf->cinfo, node_children_grouper, &jdumper);
4957 | return !ferror(stdoutstdout);
4958 | }
4959 | break;
4960 |
4961 | case WRITE_JSON_RAW:
4962 | if (print_summary)
4963 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 4963, __func__ , "assertion \"not reached\" failed");
4964 | if (print_details) {
4965 | write_json_proto_tree(output_fields, print_dissections_none,
4966 | true1, edt, &cf->cinfo, node_children_grouper, &jdumper);
4967 | return !ferror(stdoutstdout);
4968 | }
4969 | break;
4970 |
4971 | case WRITE_EK:
4972 | write_ek_proto_tree(output_fields, print_summary, print_hex,
4973 | edt, &cf->cinfo, stdoutstdout);
4974 | return !ferror(stdoutstdout);
4975 |
4976 | default:
4977 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 4977, __func__ , "assertion \"not reached\" failed");
4978 | }
4979 |
4980 | if (print_hex) {
4981 | if (print_summary || print_details) {
4982 | if (!print_line(print_stream, 0, ""))
4983 | return false0;
4984 | }
4985 | if (!print_hex_data(print_stream, edt, hexdump_source_option | hexdump_ascii_option | hexdump_timestamp_option))
4986 | return false0;
4987 | if (!print_line(print_stream, 0, separator))
4988 | return false0;
4989 | }
4990 | return true1;
4991 | }
4992 |
4993 | static bool_Bool
4994 | write_finale(void)
4995 | {
4996 | switch (output_action) {
4997 |
4998 | case WRITE_TEXT:
4999 | return print_finale(print_stream);
5000 |
5001 | case WRITE_XML:
5002 | if (print_details)
5003 | write_pdml_finale(stdoutstdout);
5004 | else
5005 | write_psml_finale(stdoutstdout);
5006 | return !ferror(stdoutstdout);
5007 |
5008 | case WRITE_FIELDS:
5009 | write_fields_finale(output_fields, stdoutstdout);
5010 | return !ferror(stdoutstdout);
5011 |
5012 | case WRITE_JSON:
5013 | case WRITE_JSON_RAW:
5014 | write_json_finale(&jdumper);
5015 | return !ferror(stdoutstdout);
5016 |
5017 | case WRITE_EK:
5018 | return true1;
5019 |
5020 | default:
5021 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "tshark.c", 5021, __func__ , "assertion \"not reached\" failed");
5022 | return false0;
5023 | }
5024 | }
5025 |
5026 | void
5027 | cf_close(capture_file *cf)
5028 | {
5029 | if (cf->state == FILE_CLOSED)
5030 | return; /* Nothing to do */
5031 |
5032 | if (cf->provider.wth != NULL((void*)0)) {
5033 | wtap_close(cf->provider.wth);
5034 | cf->provider.wth = NULL((void*)0);
5035 | }
5036 | /* We have no file open... */
5037 | if (cf->filename != NULL((void*)0)) {
5038 | /* If it's a temporary file, remove it. */
5039 | if (cf->is_tempfile)
5040 | ws_unlinkunlink(cf->filename);
5041 | g_free(cf->filename);
5042 | cf->filename = NULL((void*)0);
5043 | }
5044 |
5045 | /* We have no file open. */
5046 | cf->state = FILE_CLOSED;
5047 | }
5048 |
5049 | cf_status_t
5050 | cf_open(capture_file *cf, const char *fname, unsigned int type, bool_Bool is_tempfile, int *err)
5051 | {
5052 | wtap *wth;
5053 | char *err_info;
5054 |
5055 | wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis, application_configuration_environment_prefix());
5056 | if (wth == NULL((void*)0))
5057 | goto fail;
5058 |
5059 | /* The open succeeded. Fill in the information for this file. */
5060 |
5061 | cf->provider.wth = wth;
5062 | cf->f_datalen = 0; /* not used, but set it anyway */
5063 |
5064 | /* Set the file name because we need it to set the follow stream filter.
5065 | XXX - is that still true? We need it for other reasons, though,
5066 | in any case. */
5067 | cf->filename = g_strdup(fname)g_strdup_inline (fname);
5068 |
5069 | /* Indicate whether it's a permanent or temporary file. */
5070 | cf->is_tempfile = is_tempfile;
5071 |
5072 | /* No user changes yet. */
5073 | cf->unsaved_changes = false0;
5074 |
5075 | cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
5076 | cf->open_type = type;
5077 | cf->count = 0;
5078 | cf->drops_known = false0;
5079 | cf->drops = 0;
5080 | cf->snap = wtap_snapshot_length(cf->provider.wth);
5081 | nstime_set_zero(&cf->elapsed_time);
5082 | cf->provider.ref = NULL((void*)0);
5083 | cf->provider.prev_dis = NULL((void*)0);
5084 | cf->provider.prev_cap = NULL((void*)0);
5085 |
5086 | cf->state = FILE_READ_IN_PROGRESS;
5087 |
5088 | /* Create new epan session for dissection. */
5089 | epan_free(cf->epan);
5090 | cf->epan = tshark_epan_new(cf);
5091 |
5092 | wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
5093 | wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
5094 | wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
5095 |
5096 | return CF_OK;
5097 |
5098 | fail:
5099 | report_cfile_open_failure(fname, *err, err_info);
5100 | return CF_ERROR;
5101 | }
5102 |
5103 | static void
5104 | show_print_file_io_error(void)
5105 | {
5106 | switch (errno(*__errno_location ())) {
5107 |
5108 | case ENOSPC28:
5109 | cmdarg_err("Not all the packets could be printed because there is "
5110 | "no space left on the file system.");
5111 | break;
5112 |
5113 | #ifdef EDQUOT122
5114 | case EDQUOT122:
5115 | cmdarg_err("Not all the packets could be printed because you are "
5116 | "too close to, or over your disk quota.");
5117 | break;
5118 | #endif
5119 |
5120 | case EPIPE32:
5121 | /*
5122 | * This almost certainly means "the next program after us in
5123 | * the pipeline exited before we were finished writing", so
5124 | * this isn't a real error, it just means we're done. (We
5125 | * don't get SIGPIPE because libwireshark ignores SIGPIPE
5126 | * to avoid getting killed if writing to the MaxMind process
5127 | * gets SIGPIPE because that process died.)
5128 | *
5129 | * Presumably either that program exited deliberately (for
5130 | * example, "head -N" read N lines and printed them), in
5131 | * which case there's no error to report, or it terminated
5132 | * due to an error or a signal, in which case *that's* the
5133 | * error and that error has been reported.
5134 | */
5135 | break;
5136 |
5137 | default:
5138 | #ifdef _WIN32
5139 | if (errno(*__errno_location ()) == EINVAL22 && _doserrno == ERROR_NO_DATA) {
5140 | /*
5141 | * XXX - on Windows, a write to a pipe where the read side
5142 | * has been closed apparently may return the Windows error
5143 | * ERROR_BROKEN_PIPE, which the Visual Studio C library maps
5144 | * to EPIPE, or may return the Windows error ERROR_NO_DATA,
5145 | * which the Visual Studio C library maps to EINVAL.
5146 | *
5147 | * Either of those almost certainly means "the next program
5148 | * after us in the pipeline exited before we were finished
5149 | * writing", so, if _doserrno is ERROR_NO_DATA, this isn't
5150 | * a real error, it just means we're done. (Windows doesn't
5151 | * SIGPIPE.)
5152 | *
5153 | * Presumably either that program exited deliberately (for
5154 | * example, "head -N" read N lines and printed them), in
5155 | * which case there's no error to report, or it terminated
5156 | * due to an error or a signal, in which case *that's* the
5157 | * error and that error has been reported.
5158 | */
5159 | break;
5160 | }
5161 |
5162 | /*
5163 | * It's a different error; report it, but with the error
5164 | * message for _doserrno, which will give more detail
5165 | * than just "Invalid argument".
5166 | */
5167 | cmdarg_err("An error occurred while printing packets: %s.",
5168 | win32strerror(_doserrno));
5169 | #else
5170 | cmdarg_err("An error occurred while printing packets: %s.",
5171 | g_strerror(errno(*__errno_location ())));
5172 | #endif
5173 | break;
5174 | }
5175 | }
5176 |
5177 | static void
5178 | reset_epan_mem(capture_file *cf,epan_dissect_t *edt, bool_Bool tree, bool_Bool visual)
5179 | {
5180 | if (!epan_auto_reset || (cf->count < epan_auto_reset_count) || !edt)
5181 | return;
5182 |
5183 | fprintf(stderrstderr, "resetting session.\n");
5184 |
5185 | epan_dissect_cleanup(edt);
5186 | epan_free(cf->epan);
5187 |
5188 | cf->epan = tshark_epan_new(cf);
5189 | epan_dissect_init(edt, cf->epan, tree, visual);
5190 | cf->count = 0;
5191 | }