#include <signal.h>
#endif
-#ifdef HAVE_LIBZ
-#include <zlib.h> /* to get the libz version number */
-#endif
-
#ifdef HAVE_LIBCAP
# include <sys/capability.h>
#endif
#include <wsutil/file_util.h>
#include <wsutil/privileges.h>
#include <wsutil/report_err.h>
-#include <wsutil/ws_diag_control.h>
-#include <wsutil/ws_version_info.h>
+#include <ws_version_info.h>
+#include <wiretap/wtap_opttypes.h>
+#include <wiretap/pcapng.h>
#include "globals.h"
#include <epan/timestamp.h>
#include "ui/ui_util.h"
#include "ui/decode_as_utils.h"
#include "ui/cli/tshark-tap.h"
+#include "ui/tap_export_pdu.h"
#include "register.h"
#include "filter_files.h"
#include <epan/epan_dissect.h>
#include <epan/srt_table.h>
#include <epan/rtd_table.h>
#include <epan/ex-opt.h>
+#include <epan/exported_pdu.h>
#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
#include <epan/asn1.h>
#include <epan/funnel.h>
#include <wsutil/str_util.h>
+#include <wsutil/utf8_entities.h>
#ifdef HAVE_PLUGINS
#include <wsutil/plugins.h>
fprintf(output, " _ws.col.Info)\n");
fprintf(output, " this option can be repeated to print multiple fields\n");
fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
+ fprintf(output, " bom=y|n print a UTF-8 BOM\n");
fprintf(output, " header=y|n switch headers on and off\n");
fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
fprintf(output, " -W n Save extra information in the file, if supported.\n");
fprintf(output, " n = write network address resolution information\n");
fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
+ fprintf(output, " -U tap_name PDUs export mode, see the man page for details\n");
fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
fprintf(output, " --capture-comment <comment>\n");
fprintf(output, " add a capture comment to the newly created\n");
{
/* Capture libraries */
get_compiled_caplibs_version(str);
-
- /* LIBZ */
- g_string_append(str, ", ");
-#ifdef HAVE_LIBZ
- g_string_append(str, "with libz ");
-#ifdef ZLIB_VERSION
- g_string_append(str, ZLIB_VERSION);
-#else /* ZLIB_VERSION */
- g_string_append(str, "(version unknown)");
-#endif /* ZLIB_VERSION */
-#else /* HAVE_LIBZ */
- g_string_append(str, "without libz");
-#endif /* HAVE_LIBZ */
}
static void
get_runtime_caplibs_version(str);
#endif
- /* zlib */
-#if defined(HAVE_LIBZ) && !defined(_WIN32)
- g_string_append_printf(str, ", with libz %s", zlibVersion());
-#endif
-
/* stuff used by libwireshark */
epan_get_runtime_version_info(str);
}
GSList *disable_protocol_slist = NULL;
GSList *enable_heur_slist = NULL;
GSList *disable_heur_slist = NULL;
+ gchar *volatile pdu_export_arg = NULL;
+ exp_pdu_t exp_pdu_tap_data;
/*
* The leading + ensures that getopt_long() does not permute the argv[]
* We do *not* use a leading - because the behavior of a leading - is
* platform-dependent.
*/
-#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON "C:d:e:E:F:gG:hH:" "K:lnN:o:O:PqQr:R:S:t:T:u:vVw:W:xX:Y:z:"
+#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON "C:d:e:E:F:gG:hH:" "K:lnN:o:O:PqQr:R:S:t:T:u:U:vVw:W:xX:Y:z:"
static const char optstring[] = OPTSTRING;
g_string_free(comp_info_str, TRUE);
g_string_free(runtime_info_str, TRUE);
+ /* Fail sometimes. Useful for testing fuzz scripts. */
+ /* if (g_random_int_range(0, 100) < 5) abort(); */
+
/*
* In order to have the -X opts assigned before the wslua machine starts
* we need to call getopt_long before epan_init() gets called.
if (badopt != '\0') {
cmdarg_err("-N specifies unknown resolving option '%c'; valid options are:",
badopt);
- cmdarg_err_cont("\t'C' to enable concurrent (asynchronous) DNS lookups\n"
- "\t'd' to enable address resolution from captured DNS packets\n"
+ cmdarg_err_cont("\t'd' to enable address resolution from captured DNS packets\n"
"\t'm' to enable MAC address resolution\n"
"\t'n' to enable network address resolution\n"
"\t'N' to enable using external resolvers (e.g., DNS)\n"
return 1;
}
break;
+ case 'U': /* Export PDUs to file */
+ {
+ GSList *export_pdu_tap_name_list = NULL;
+
+ if (!*optarg) {
+ cmdarg_err("Tap name is required! Valid names are:");
+ for (export_pdu_tap_name_list = get_export_pdu_tap_list(); export_pdu_tap_name_list; export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)) {
+ cmdarg_err("%s\n", (const char*)(export_pdu_tap_name_list->data));
+ }
+ return 1;
+ }
+ pdu_export_arg = g_strdup(optarg);
+ break;
+ }
case 'v': /* Show version and exit */
comp_info_str = get_compiled_version_info(get_tshark_compiled_version_info,
epan_get_compiled_version_info);
}
}
+ /* PDU export requested. Take the ownership of the '-w' file, apply tap
+ * filters and start tapping. */
+ if (pdu_export_arg) {
+ const char *exp_pdu_filename;
+ const char *exp_pdu_tap_name = pdu_export_arg;
+ const char *exp_pdu_filter = dfilter; /* may be NULL to disable filter */
+ char *exp_pdu_error;
+ int exp_fd;
+
+ if (!cf_name) {
+ cmdarg_err("PDUs export requires a capture file (specify with -r).");
+ return 1;
+ }
+ /* Take ownership of the '-w' output file. */
+#ifdef HAVE_LIBPCAP
+ exp_pdu_filename = global_capture_opts.save_file;
+ global_capture_opts.save_file = NULL;
+#else
+ exp_pdu_filename = output_file_name;
+ output_file_name = NULL;
+#endif
+ if (exp_pdu_filename == NULL) {
+ cmdarg_err("PDUs export requires an output file (-w).");
+ return 1;
+ }
+
+ exp_pdu_error = exp_pdu_pre_open(exp_pdu_tap_name, exp_pdu_filter,
+ &exp_pdu_tap_data);
+ if (exp_pdu_error) {
+ cmdarg_err("Cannot register tap: %s", exp_pdu_error);
+ g_free(exp_pdu_error);
+ return 2;
+ }
+
+ exp_fd = ws_open(exp_pdu_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (exp_fd == -1) {
+ cmdarg_err("%s: %s", exp_pdu_filename, file_open_error_message(errno, TRUE));
+ return 2;
+ }
+
+ /* Activate the export PDU tap */
+ err = exp_pdu_open(&exp_pdu_tap_data, exp_fd,
+ g_strdup_printf("Dump of PDUs from %s", cf_name));
+ if (err != 0) {
+ cmdarg_err("Failed to start the PDU export: %s", g_strerror(err));
+ return 2;
+ }
+ }
+
/* We have to dissect each packet if:
we're printing information about each packet;
we're using a display filter on the packets;
+ we're exporting PDUs;
+
we're using any taps that need dissection. */
- do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
+ do_dissection = print_packet_info || rfcode || dfcode || pdu_export_arg ||
+ tap_listeners_require_dissection();
tshark_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE");
if (cf_name) {
read some packets; however, we exit with an error status. */
exit_status = 2;
}
+
+ if (pdu_export_arg) {
+ err = exp_pdu_close(&exp_pdu_tap_data);
+ if (err) {
+ cmdarg_err("%s", wtap_strerror(err));
+ exit_status = 2;
+ }
+ g_free(pdu_export_arg);
+ }
} else {
tshark_debug("tshark: no capture file specified");
/* No capture file specified, so we're supposed to do a live capture
* suppress the information printed for each packet, but it'll
* also suppress the packet counts.
*/
- if (!isatty(fileno(stderr)))
+ if (!ws_isatty(ws_fileno(stderr)))
print_packet_counts = FALSE;
- else if (print_packet_info && isatty(fileno(stdout)))
+ else if (print_packet_info && ws_isatty(ws_fileno(stdout)))
print_packet_counts = FALSE;
else if (quiet)
print_packet_counts = FALSE;
do a dissection and do so. */
if (edt) {
if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
- gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
+ gbl_resolv_flags.transport_name)
/* Grab any resolved addresses */
host_name_lookup_process();
do a dissection and do so. */
if (edt) {
if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
- gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
+ gbl_resolv_flags.transport_name)
/* Grab any resolved addresses */
host_name_lookup_process();
char *save_file_string = NULL;
gboolean filtering_tap_listeners;
guint tap_flags;
- wtapng_section_t *shb_hdr = NULL;
+ GArray *shb_hdrs = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
- wtapng_name_res_t *nrb_hdr = NULL;
+ GArray *nrb_hdrs = NULL;
struct wtap_pkthdr phdr;
Buffer buf;
epan_dissect_t *edt = NULL;
+ char *shb_user_appl;
wtap_phdr_init(&phdr);
}
tshark_debug("tshark: snapshot_length = %d", snapshot_length);
- shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
- nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
+ shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
+ nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
/* If we don't have an application name add Tshark */
- if (shb_hdr->shb_user_appl == NULL) {
- /* this is free'd by wtap_free_shb() later */
- shb_hdr->shb_user_appl = g_strdup_printf("TShark (Wireshark) %s", get_ws_vcs_version_info());
+ wtap_optionblock_get_option_string(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, &shb_user_appl);
+ if (shb_user_appl == NULL) {
+ /* this is free'd by wtap_optionblock_free() later */
+ wtap_optionblock_set_option_string_format(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, "TShark (Wireshark) %s", get_ws_vcs_version_info());
}
if (linktype != WTAP_ENCAP_PER_PACKET &&
if (strcmp(save_file, "-") == 0) {
/* Write to the standard output. */
pdh = wtap_dump_open_stdout_ng(out_file_type, linktype,
- snapshot_length, FALSE /* compressed */, shb_hdr, idb_inf, nrb_hdr, &err);
+ snapshot_length, FALSE /* compressed */, shb_hdrs, idb_inf, nrb_hdrs, &err);
} else {
pdh = wtap_dump_open_ng(save_file, out_file_type, linktype,
- snapshot_length, FALSE /* compressed */, shb_hdr, idb_inf, nrb_hdr, &err);
+ snapshot_length, FALSE /* compressed */, shb_hdrs, idb_inf, nrb_hdrs, &err);
}
}
break;
}
wtap_dump_close(pdh, &err);
- wtap_free_shb(shb_hdr);
- wtap_free_nrb(nrb_hdr);
+ wtap_optionblock_array_free(shb_hdrs);
+ wtap_optionblock_array_free(nrb_hdrs);
exit(2);
}
}
break;
}
wtap_dump_close(pdh, &err);
- wtap_free_shb(shb_hdr);
- wtap_free_nrb(nrb_hdr);
+ wtap_optionblock_array_free(shb_hdrs);
+ wtap_optionblock_array_free(nrb_hdrs);
exit(2);
}
}
cf->wth = NULL;
g_free(save_file_string);
- wtap_free_shb(shb_hdr);
- wtap_free_nrb(nrb_hdr);
+ wtap_optionblock_array_free(shb_hdrs);
+ wtap_optionblock_array_free(nrb_hdrs);
return err;
}
do a dissection and do so. */
if (edt) {
if (print_packet_info && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
- gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns))
+ gbl_resolv_flags.transport_name))
/* Grab any resolved addresses */
host_name_lookup_process();
*
* If we printed a network source and are printing a
* network destination of the same type next, separate
- * them with " -> "; if we printed a network destination
- * and are printing a network source of the same type
- * next, separate them with " <- "; otherwise separate them
- * with a space.
+ * them with a UTF-8 right arrow; if we printed a network
+ * destination and are printing a network source of the same
+ * type next, separate them with a UTF-8 left arrow;
+ * otherwise separate them with a space.
*
- * We add enough space to the buffer for " <- " or " -> ",
- * even if we're only adding " ".
+ * We add enough space to the buffer for " \xe2\x86\x90 "
+ * or " \xe2\x86\x92 ", even if we're only adding " ".
*/
- line_bufp = get_line_buf(buf_offset + 4);
+ line_bufp = get_line_buf(buf_offset + 5);
switch (col_item->col_fmt) {
case COL_DEF_SRC:
case COL_DEF_DST:
case COL_RES_DST:
case COL_UNRES_DST:
- put_string(line_bufp + buf_offset, " -> ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_RIGHTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default:
case COL_DEF_DL_DST:
case COL_RES_DL_DST:
case COL_UNRES_DL_DST:
- put_string(line_bufp + buf_offset, " -> ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_RIGHTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default:
case COL_DEF_NET_DST:
case COL_RES_NET_DST:
case COL_UNRES_NET_DST:
- put_string(line_bufp + buf_offset, " -> ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_RIGHTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default:
case COL_DEF_SRC:
case COL_RES_SRC:
case COL_UNRES_SRC:
- put_string(line_bufp + buf_offset, " <- ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_LEFTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default:
case COL_DEF_DL_SRC:
case COL_RES_DL_SRC:
case COL_UNRES_DL_SRC:
- put_string(line_bufp + buf_offset, " <- ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_LEFTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default:
case COL_DEF_NET_SRC:
case COL_RES_NET_SRC:
case COL_UNRES_NET_SRC:
- put_string(line_bufp + buf_offset, " <- ", 4);
- buf_offset += 4;
+ put_string(line_bufp + buf_offset, " " UTF8_LEFTWARDS_ARROW " ", 5);
+ buf_offset += 5;
break;
default: