* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config.h>
#include "ui/util.h"
#include "ui/decode_as_utils.h"
#include "ui/dissect_opts.h"
-#include "epan/register.h"
#include <epan/epan_dissect.h>
#include <epan/tap.h>
#include <epan/stat_tap_ui.h>
#endif
#define INVALID_OPTION 1
+#define NO_FILE_SPECIFIED 1
#define INIT_ERROR 2
#define INVALID_FILTER 2
#define OPEN_ERROR 2
static gboolean process_file(capture_file *, int, gint64);
static gboolean process_packet_single_pass(capture_file *cf,
- epan_dissect_t *edt, gint64 offset, struct wtap_pkthdr *whdr,
+ epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
const guchar *pd, guint tap_flags);
static void show_print_file_io_error(int err);
static gboolean write_preamble(capture_file *cf);
epan_get_runtime_version_info(str);
}
-int
-main(int argc, char *argv[])
+static int
+real_main(int argc, char *argv[])
{
GString *comp_info_str;
GString *runtime_info_str;
cmdarg_err_init(failure_warning_message, failure_message_cont);
#ifdef _WIN32
- arg_list_utf_16to8(argc, argv);
create_app_running_mutex();
-#if !GLIB_CHECK_VERSION(2,31,0)
- g_thread_init(NULL);
-#endif
#endif /* _WIN32 */
/*
* Attempt to get the pathname of the directory containing the
* executable file.
*/
- init_progfile_dir_error = init_progfile_dir(argv[0], main);
+ init_progfile_dir_error = init_progfile_dir(argv[0]);
if (init_progfile_dir_error != NULL) {
fprintf(stderr,
"tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
"-G" flag, as the "-G" flag dumps information registered by the
dissectors, and we must do it before we read the preferences, in
case any dissectors register preferences. */
- if (!epan_init(register_all_protocols, register_all_protocol_handoffs, NULL,
- NULL)) {
+ if (!epan_init(NULL, NULL, TRUE)) {
exit_status = INIT_ERROR;
goto clean_exit;
}
goto clean_exit;
}
- /* If no capture filter or display filter has been specified, and there are
- still command-line arguments, treat them as the tokens of a capture
- filter (if no "-r" flag was specified) or a display filter (if a "-r"
- flag was specified. */
+ /* We require a -r flag specifying a file to read. */
+ if (cf_name == NULL) {
+ cmdarg_err("A file to read must be specified with \"-r\".");
+ exit_status = NO_FILE_SPECIFIED;
+ goto clean_exit;
+ }
+
+ /* If no display filter has been specified, and there are still command-
+ line arguments, treat them as the tokens of a display filter. */
if (optind < argc) {
- if (cf_name != NULL) {
- if (dfilter != NULL) {
- cmdarg_err("Display filters were specified both with \"-d\" "
- "and with additional command-line arguments.");
- exit_status = INVALID_OPTION;
- goto clean_exit;
- }
- dfilter = get_args_as_string(argc, argv, optind);
+ if (dfilter != NULL) {
+ cmdarg_err("Display filters were specified both with \"-d\" "
+ "and with additional command-line arguments.");
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
+ dfilter = get_args_as_string(argc, argv, optind);
}
/* if "-q" wasn't specified, we should print packet information */
line that their preferences have changed. */
prefs_apply_all();
- /* At this point MATE will have registered its field array so we can
- have a tap filter with one of MATE's late-registered fields as part
- of the filter. We can now process all the "-z" arguments. */
- start_requested_stats();
-
/*
* Enabled and disabled protocols and heuristic dissectors as per
* command-line options.
we're using any taps that need dissection. */
do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
- if (cf_name) {
- /*
- * We're reading a capture file.
- */
+ /*
+ * Read the file.
+ */
- /* TODO: if tfshark is ever changed to give the user a choice of which
- open_routine reader to use, then the following needs to change. */
- if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
- exit_status = OPEN_ERROR;
- goto clean_exit;
- }
+ /* TODO: if tfshark is ever changed to give the user a choice of which
+ open_routine reader to use, then the following needs to change. */
+ if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
+ exit_status = OPEN_ERROR;
+ goto clean_exit;
+ }
- /* Process the packets in the file */
- TRY {
- /* XXX - for now there is only 1 packet */
- success = process_file(&cfile, 1, 0);
- }
- CATCH(OutOfMemoryError) {
- fprintf(stderr,
- "Out Of Memory.\n"
- "\n"
- "Sorry, but TFShark has to terminate now.\n"
- "\n"
- "Some infos / workarounds can be found at:\n"
- "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
- success = FALSE;
- }
- ENDTRY;
+ /* Start statistics taps; we do so after successfully opening the
+ capture file, so we know we have something to compute stats
+ on, and after registering all dissectors, so that MATE will
+ have registered its field array so we can have a tap filter
+ with one of MATE's late-registered fields as part of the
+ filter. */
+ start_requested_stats();
- if (!success) {
- /* We still dump out the results of taps, etc., as we might have
- read some packets; however, we exit with an error status. */
- exit_status = 2;
- }
+ /* Process the packets in the file */
+ TRY {
+ /* XXX - for now there is only 1 packet */
+ success = process_file(&cfile, 1, 0);
+ }
+ CATCH(OutOfMemoryError) {
+ fprintf(stderr,
+ "Out Of Memory.\n"
+ "\n"
+ "Sorry, but TFShark has to terminate now.\n"
+ "\n"
+ "Some infos / workarounds can be found at:\n"
+ "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+ success = FALSE;
+ }
+ ENDTRY;
+
+ if (!success) {
+ /* We still dump out the results of taps, etc., as we might have
+ read some packets; however, we exit with an error status. */
+ exit_status = 2;
}
g_free(cf_name);
return exit_status;
}
+#ifdef _WIN32
+int
+wmain(int argc, wchar_t *wc_argv[])
+{
+ char **argv;
+
+ argv = arg_list_utf_16to8(argc, wc_argv);
+ return real_main(argc, argv);
+}
+#else
+int
+main(int argc, char *argv[])
+{
+ return real_main(argc, argv);
+}
+#endif
+
static const nstime_t *
tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
{
static gboolean
process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
- gint64 offset, struct wtap_pkthdr *whdr,
+ gint64 offset, wtap_rec *rec,
const guchar *pd)
{
frame_data fdlocal;
that all packets can be marked as 'passed'. */
passed = TRUE;
- frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
+ frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
/* If we're going to print packet information, or we're going to
run a read filter, or display filter, or we're going to process taps, set up to
cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run(edt, whdr,
+ epan_dissect_file_run(edt, rec,
file_tvbuff_new(&cf->provider, &fdlocal, pd),
&fdlocal, NULL);
static gboolean
process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
- frame_data *fdata, struct wtap_pkthdr *phdr,
+ frame_data *fdata, wtap_rec *rec,
Buffer *buf, guint tap_flags)
{
column_info *cinfo;
cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run_with_taps(edt, phdr,
+ epan_dissect_file_run_with_taps(edt, rec,
file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
/* Run the read/display filter if we have one. */
}
static gboolean
-local_wtap_read(capture_file *cf, struct wtap_pkthdr* file_phdr _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
+local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
{
/* int bytes_read; */
gint64 packet_size = wtap_file_size(cf->provider.wth, err);
/* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
- file_phdr->caplen = (guint32)packet_size;
- file_phdr->len = (guint32)packet_size;
+ file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
+ file_rec->rec_header.packet_header.len = (guint32)packet_size;
/*
* Set the packet encapsulation to the file's encapsulation
* *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
* anyway.
*/
- wth->phdr.pkt_encap = wth->file_encap;
+ wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
if (!wth->subtype_read(wth, err, err_info, data_offset)) {
/*
* It makes no sense for the captured data length to be bigger
* than the actual data length.
*/
- if (wth->phdr.caplen > wth->phdr.len)
- wth->phdr.caplen = wth->phdr.len;
+ if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
+ wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
/*
* Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
* but the read routine didn't set this packet's
* encapsulation type.
*/
- g_assert(wth->phdr.pkt_encap != WTAP_ENCAP_PER_PACKET);
+ g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
#endif
return TRUE; /* success */
guint tap_flags;
Buffer buf;
epan_dissect_t *edt = NULL;
- struct wtap_pkthdr file_phdr;
+ wtap_rec file_rec;
guint8* raw_data;
if (print_packet_info) {
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- wtap_phdr_init(&file_phdr);
+ wtap_rec_init(&file_rec);
/* XXX - TEMPORARY HACK TO ELF DISSECTOR */
- file_phdr.pkt_encap = 1234;
+ file_rec.rec_header.packet_header.pkt_encap = 1234;
if (perform_two_pass_analysis) {
frame_data *fdata;
so it's not going to be "visible". */
edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
}
- while (local_wtap_read(cf, &file_phdr, &err, &err_info, &data_offset, &raw_data)) {
- if (process_packet_first_pass(cf, edt, data_offset, &file_phdr/*wtap_phdr(cf->provider.wth)*/,
- wtap_buf_ptr(cf->provider.wth))) {
+ while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
+ if (process_packet_first_pass(cf, edt, data_offset, &file_rec/*wtap_get_rec(cf->provider.wth)*/,
+ wtap_get_buf_ptr(cf->provider.wth))) {
/* Stop reading if we have the maximum number of packets;
* When the -c option has not been used, max_packet_count
#if 0
if (wtap_seek_read(cf->provider.wth, fdata->file_off,
&buf, fdata->cap_len, &err, &err_info)) {
- process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf, tap_flags);
+ process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
}
#else
- if (!process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf,
+ if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
tap_flags))
return FALSE;
#endif
edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
}
- while (local_wtap_read(cf, &file_phdr, &err, &err_info, &data_offset, &raw_data)) {
+ while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
framenum++;
if (!process_packet_single_pass(cf, edt, data_offset,
- &file_phdr/*wtap_phdr(cf->provider.wth)*/,
+ &file_rec/*wtap_get_rec(cf->provider.wth)*/,
raw_data, tap_flags))
return FALSE;
}
}
- wtap_phdr_cleanup(&file_phdr);
+ wtap_rec_cleanup(&file_rec);
if (err != 0) {
/*
static gboolean
process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
- struct wtap_pkthdr *whdr, const guchar *pd,
+ wtap_rec *rec, const guchar *pd,
guint tap_flags)
{
frame_data fdata;
that all packets can be marked as 'passed'. */
passed = TRUE;
- frame_data_init(&fdata, cf->count, whdr, offset, cum_bytes);
+ frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
/* If we're going to print packet information, or we're going to
run a read filter, or we're going to process taps, set up to
cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run_with_taps(edt, whdr,
+ epan_dissect_file_run_with_taps(edt, rec,
frame_tvbuff_new(&cf->provider, &fdata, pd),
&fdata, cinfo);