summaryrefslogtreecommitdiff
path: root/tshark.c
diff options
context:
space:
mode:
Diffstat (limited to 'tshark.c')
-rw-r--r--tshark.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/tshark.c b/tshark.c
index f96f49b930..738a631a89 100644
--- a/tshark.c
+++ b/tshark.c
@@ -98,6 +98,7 @@
#include "ui/util.h"
#include "ui/ui_util.h"
#include "ui/cli/tshark-tap.h"
+#include "ui/tap_export_pdu.h"
#include "version_info.h"
#include "register.h"
#include <epan/epan_dissect.h>
@@ -380,6 +381,7 @@ print_usage(FILE *output)
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[,filter] 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");
@@ -1009,11 +1011,13 @@ main(int argc, char *argv[])
int log_flags;
int optind_initial;
gchar *output_only = NULL;
+ gchar **pdu_export_args = NULL;
+ exp_pdu_t exp_pdu_tap_data;
/* the leading - ensures that getopt() does not permute the argv[] entries
we have to make sure that the first getopt() preserves the content of argv[]
for the subsequent getopt_long() call */
-#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;
@@ -1630,6 +1634,13 @@ main(int argc, char *argv[])
epan_cleanup();
return 0;
}
+ case 'U': /* Export PDUs to file */
+ if (!*optarg) {
+ cmdarg_err("Tap name is required!");
+ return 1;
+ }
+ pdu_export_args = g_strsplit(optarg, ",", 2);
+ break;
case 'O': /* Only output these protocols */
/* already processed; just ignore it now */
break;
@@ -2066,6 +2077,55 @@ main(int argc, char *argv[])
}
}
+ /* PDU export requested. Take the ownership of the '-w' file, apply tap
+ * filters and start tapping. */
+ if (pdu_export_args) {
+ const char *exp_pdu_filename;
+ const char *exp_pdu_tap_name = pdu_export_args[0];
+ const char *exp_pdu_filter = pdu_export_args[1]; /* 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;
@@ -2074,8 +2134,11 @@ main(int argc, char *argv[])
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_args ||
+ tap_listeners_require_dissection();
if (cf_name) {
/*
@@ -2112,6 +2175,15 @@ main(int argc, char *argv[])
read some packets; however, we exit with an error status. */
exit_status = 2;
}
+
+ if (pdu_export_args) {
+ err = exp_pdu_close(&exp_pdu_tap_data);
+ if (err) {
+ cmdarg_err("%s", wtap_strerror(err));
+ exit_status = 2;
+ }
+ g_strfreev(pdu_export_args);
+ }
} else {
/* No capture file specified, so we're supposed to do a live capture
or get a list of link-layer types for a live capture device;