#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");
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;
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
char *save_file_string = NULL;
gboolean filtering_tap_listeners;
guint tap_flags;
- wtap_optionblock_t shb_hdr = NULL;
+ GArray *shb_hdrs = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
- wtap_optionblock_t nrb_hdr = NULL;
+ GArray *nrb_hdrs = NULL;
struct wtap_pkthdr phdr;
Buffer buf;
epan_dissect_t *edt = NULL;
}
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 */
- wtap_optionblock_get_option_string(shb_hdr, OPT_SHB_USERAPPL, &shb_user_appl);
+ 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 */
- shb_user_appl = g_strdup_printf("TShark (Wireshark) %s", get_ws_vcs_version_info());
- wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_USERAPPL, shb_user_appl);
- g_free(shb_user_appl);
+ 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_optionblock_free(shb_hdr);
- wtap_optionblock_free(nrb_hdr);
+ wtap_optionblock_array_free(shb_hdrs);
+ wtap_optionblock_array_free(nrb_hdrs);
exit(2);
}
}
break;
}
wtap_dump_close(pdh, &err);
- wtap_optionblock_free(shb_hdr);
- wtap_optionblock_free(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_optionblock_free(shb_hdr);
- wtap_optionblock_free(nrb_hdr);
+ wtap_optionblock_array_free(shb_hdrs);
+ wtap_optionblock_array_free(nrb_hdrs);
return err;
}
*
* 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: