diff options
-rw-r--r-- | tshark.c | 76 | ||||
-rw-r--r-- | ui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | ui/Makefile.common | 2 | ||||
-rw-r--r-- | ui/export_pdu_ui_utils.c | 112 | ||||
-rw-r--r-- | ui/export_pdu_ui_utils.h | 43 | ||||
-rw-r--r-- | ui/gtk/export_pdu_dlg.c | 1 | ||||
-rw-r--r-- | ui/qt/export_pdu_dialog.cpp | 1 | ||||
-rw-r--r-- | ui/tap_export_pdu.c | 87 | ||||
-rw-r--r-- | ui/tap_export_pdu.h | 24 |
9 files changed, 286 insertions, 61 deletions
@@ -84,6 +84,7 @@ #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> @@ -390,6 +391,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"); @@ -993,6 +995,8 @@ main(int argc, char *argv[]) GSList *disable_protocol_slist = NULL; GSList *enable_heur_slist = NULL; GSList *disable_heur_slist = NULL; + gchar **volatile pdu_export_args = NULL; + exp_pdu_t exp_pdu_tap_data; /* * The leading + ensures that getopt_long() does not permute the argv[] @@ -1013,7 +1017,7 @@ main(int argc, char *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; @@ -1665,6 +1669,13 @@ main(int argc, char *argv[]) return 1; } break; + 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 'v': /* Show version and exit */ comp_info_str = get_compiled_version_info(get_tshark_compiled_version_info, epan_get_compiled_version_info); @@ -2163,6 +2174,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; @@ -2171,8 +2231,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(); tshark_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE"); if (cf_name) { @@ -2212,6 +2275,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 { tshark_debug("tshark: no capture file specified"); /* No capture file specified, so we're supposed to do a live capture diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index f7842b8ce7..28d1ab00cf 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -31,6 +31,7 @@ set(COMMON_UI_SRC export_object_http.c export_object_smb.c export_object_tftp.c + export_pdu_ui_utils.c help_url.c iface_lists.c io_graph_item.c diff --git a/ui/Makefile.common b/ui/Makefile.common index 05f738f41b..0cd6da548b 100644 --- a/ui/Makefile.common +++ b/ui/Makefile.common @@ -52,6 +52,7 @@ WIRESHARK_UI_SRC = \ export_object_http.c \ export_object_smb.c \ export_object_tftp.c \ + export_pdu_ui_utils.c \ iface_lists.c \ io_graph_item.c \ language.c \ @@ -90,6 +91,7 @@ noinst_HEADERS = \ console.h \ decode_as_utils.h \ export_object.h \ + export_pdu_ui_utils.h \ last_open_dir.h \ file_dialog.h \ help_url.h \ diff --git a/ui/export_pdu_ui_utils.c b/ui/export_pdu_ui_utils.c new file mode 100644 index 0000000000..1a907ab8df --- /dev/null +++ b/ui/export_pdu_ui_utils.c @@ -0,0 +1,112 @@ +/* +* export_pdu_ui_utils.c +* Routines for exported_pdu dissection +* Copyright 2013, Anders Broman <anders-broman@ericsson.com> +* +* Wireshark - Network traffic analyzer +* By Gerald Combs <gerald@wireshark.org> +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "config.h" + +#include "globals.h" +#include "wiretap/pcap-encap.h" +#include "wsutil/os_version_info.h" +#include "wsutil/tempfile.h" +#include "ws_version_info.h" + +#include <epan/tap.h> +#include <epan/exported_pdu.h> +#include <epan/epan_dissect.h> +#include <wiretap/wtap.h> +#include <wiretap/wtap_opttypes.h> +#include <wiretap/pcapng.h> + +#include "ui/alert_box.h" +#include "ui/simple_dialog.h" +#include "tap_export_pdu.h" +#include "export_pdu_ui_utils.h" + +static void +exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data) +{ + int import_file_fd; + char *tmpname, *capfile_name; + int err; + + /* Choose a random name for the temporary import buffer */ + import_file_fd = create_tempfile(&tmpname, "Wireshark_PDU_"); + capfile_name = g_strdup(tmpname); + + err = exp_pdu_open(exp_pdu_tap_data, import_file_fd, + g_strdup_printf("Dump of PDUs from %s", cfile.filename)); + if (err != 0) { + open_failure_alert_box(capfile_name ? capfile_name : "temporary file", err, TRUE); + goto end; + } + + /* Run the tap */ + cf_retap_packets(&cfile); + + err = exp_pdu_close(exp_pdu_tap_data); + if (err!= 0) { + write_failure_alert_box(capfile_name, err); + } + + /* XXX: should this use the open_routine type in the cfile instead of WTAP_TYPE_AUTO? */ + if (cf_open(&cfile, capfile_name, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { + open_failure_alert_box(capfile_name, err, FALSE); + goto end; + } + + switch (cf_read(&cfile, FALSE)) { + case CF_READ_OK: + case CF_READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case CF_READ_ABORTED: + /* The user bailed out of re-reading the capture file; the + capture file has been closed - just free the capture file name + string and return (without changing the last containing + directory). */ + break; + } + +end: + g_free(capfile_name); +} + +gboolean +do_export_pdu(const char *filter, gchar *tap_name, exp_pdu_t *exp_pdu_tap_data) +{ + char *error; + error = exp_pdu_pre_open(tap_name, filter, exp_pdu_tap_data); + if (error) { + /* Error. We failed to attach to the tap. Clean up */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error); + g_free(error); + return FALSE; + } + + exp_pdu_file_open(exp_pdu_tap_data); + + return TRUE; +}
\ No newline at end of file diff --git a/ui/export_pdu_ui_utils.h b/ui/export_pdu_ui_utils.h new file mode 100644 index 0000000000..54cbd13063 --- /dev/null +++ b/ui/export_pdu_ui_utils.h @@ -0,0 +1,43 @@ +/* +* export_pdu_ui_utils.h +* Routines for exported_pdu dissection +* Copyright 2013, Anders Broman <anders-broman@ericsson.com> +* +* Wireshark - Network traffic analyzer +* By Gerald Combs <gerald@wireshark.org> +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef EXPORT_PDU_UI_UTILS_H +#define EXPORT_PDU_UI_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** +* Filters the current opened capture file into a temporary file. On success, +* TRUE is returned and the filtered file is opened into the UI. +*/ +gboolean do_export_pdu(const char *filter, gchar *tap_name, exp_pdu_t *data); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* EXPORT_PDU_UI_UTILS_H */ diff --git a/ui/gtk/export_pdu_dlg.c b/ui/gtk/export_pdu_dlg.c index 1bc5be7b32..929cce92d4 100644 --- a/ui/gtk/export_pdu_dlg.c +++ b/ui/gtk/export_pdu_dlg.c @@ -41,6 +41,7 @@ #include "ui/tap_export_pdu.h" +#include "ui/export_pdu_ui_utils.h" #include "ui/gtk/export_pdu_dlg.h" static GtkWidget *export_pdu_dlg = NULL; diff --git a/ui/qt/export_pdu_dialog.cpp b/ui/qt/export_pdu_dialog.cpp index d1f9c30120..7316c680a7 100644 --- a/ui/qt/export_pdu_dialog.cpp +++ b/ui/qt/export_pdu_dialog.cpp @@ -32,6 +32,7 @@ #include <epan/exported_pdu.h> #include "ui/tap_export_pdu.h" +#include "ui/export_pdu_ui_utils.h" ExportPDUDialog::ExportPDUDialog(QWidget *parent) : QDialog(parent), diff --git a/ui/tap_export_pdu.c b/ui/tap_export_pdu.c index 608e4a1acb..3131973ed2 100644 --- a/ui/tap_export_pdu.c +++ b/ui/tap_export_pdu.c @@ -25,18 +25,16 @@ #include "globals.h" #include "wiretap/pcap-encap.h" -#include "wsutil/tempfile.h" #include "wsutil/os_version_info.h" #include "ws_version_info.h" #include <epan/tap.h> #include <epan/exported_pdu.h> #include <epan/epan_dissect.h> +#include <wiretap/wtap.h> #include <wiretap/wtap_opttypes.h> #include <wiretap/pcapng.h> -#include "ui/alert_box.h" -#include "ui/simple_dialog.h" #include "tap_export_pdu.h" /* Main entry point to the tap */ @@ -97,10 +95,10 @@ export_pdu_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const return FALSE; /* Do not redraw */ } -static void -exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data) +int +exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, char *comment) { - char *tmpname, *capfile_name; + int err; /* pcapng defs */ @@ -118,7 +116,7 @@ exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data) shb_hdr = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION); /* options */ - opt_comment = g_strdup_printf("Dump of PDUs from %s", cfile.filename); + opt_comment = comment; wtap_optionblock_set_option_string(shb_hdr, OPT_COMMENT, opt_comment); g_free(opt_comment); @@ -153,79 +151,52 @@ exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data) g_array_append_val(idb_inf->interface_data, int_data); /* Use a random name for the temporary import buffer */ - exp_pdu_tap_data->wdh = wtap_dump_open_tempfile_ng(&tmpname, "Wireshark_PDU_", - WTAP_FILE_TYPE_SUBTYPE_PCAPNG, - WTAP_ENCAP_WIRESHARK_UPPER_PDU, WTAP_MAX_PACKET_SIZE, - FALSE, shb_hdr, idb_inf, NULL, &err); - capfile_name = g_strdup(tmpname); + exp_pdu_tap_data->wdh = wtap_dump_fdopen_ng(fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU, WTAP_MAX_PACKET_SIZE, FALSE, + shb_hdr, idb_inf, NULL, &err); if (exp_pdu_tap_data->wdh == NULL) { - open_failure_alert_box(capfile_name ? capfile_name : "temporary file", err, TRUE); - goto end; + g_assert(err != 0); + return err; } - /* Run the tap */ - cf_retap_packets(&cfile); - + return 0; +} - if (!wtap_dump_close(exp_pdu_tap_data->wdh, &err)) { - write_failure_alert_box(capfile_name, err); - } +int +exp_pdu_close(exp_pdu_t *exp_pdu_tap_data) +{ + int err = 0; + if (!wtap_dump_close(exp_pdu_tap_data->wdh, &err)) + g_assert(err != 0); remove_tap_listener(exp_pdu_tap_data); - - /* XXX: should this use the open_routine type in the cfile instead of WTAP_TYPE_AUTO? */ - if (cf_open(&cfile, capfile_name, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { - open_failure_alert_box(capfile_name, err, FALSE); - goto end; - } - - switch (cf_read(&cfile, FALSE)) { - case CF_READ_OK: - case CF_READ_ERROR: - /* Just because we got an error, that doesn't mean we were unable - to read any of the file; we handle what we could get from the - file. */ - break; - - case CF_READ_ABORTED: - /* The user bailed out of re-reading the capture file; the - capture file has been closed - just free the capture file name - string and return (without changing the last containing - directory). */ - break; - } - -end: - g_free(capfile_name); - wtap_optionblock_free(shb_hdr); - wtap_free_idb_info(idb_inf); + return err; } -gboolean -do_export_pdu(const char *filter, gchar *tap_name, exp_pdu_t *exp_pdu_tap_data) + +char * +exp_pdu_pre_open(const char *tap_name, const char *filter, exp_pdu_t *exp_pdu_tap_data) { GString *error_string; + /* XXX: can we always assume WTAP_ENCAP_WIRESHARK_UPPER_PDU? */ + exp_pdu_tap_data->pkt_encap = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU); + /* Register this tap listener now */ error_string = register_tap_listener(tap_name, /* The name of the tap we want to listen to */ exp_pdu_tap_data, /* instance identifier/pointer to a struct holding * all state variables */ filter, /* pointer to a filter string */ - TL_REQUIRES_NOTHING, /* flags for the tap listener */ + TL_REQUIRES_PROTO_TREE, /* flags for the tap listener */ NULL, export_pdu_packet, NULL); - if (error_string){ - /* Error. We failed to attach to the tap. Clean up */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str); - g_string_free(error_string, TRUE); - return FALSE; - } + if (error_string != NULL) + return g_string_free(error_string, FALSE); - exp_pdu_file_open(exp_pdu_tap_data); - return TRUE; + return NULL; } + /* * Editor modelines * diff --git a/ui/tap_export_pdu.h b/ui/tap_export_pdu.h index df6b5bad45..49e46ebeff 100644 --- a/ui/tap_export_pdu.h +++ b/ui/tap_export_pdu.h @@ -32,7 +32,29 @@ typedef struct _exp_pdu_t { wtap_dumper* wdh; } exp_pdu_t; -gboolean do_export_pdu(const char *filter, gchar *tap_name, exp_pdu_t *data); +/** +* Registers the tap listener which will add matching packets to the exported +* file. Must be called before exp_pdu_open. +* +* @param tap_name One of the names registered with register_export_pdu_tap(). +* @param filter An tap filter, may be NULL to disable filtering which +* improves performance if you do not need a filter. +* @return NULL on success or an error string on failure which must be freed +* with g_free(). Failure could occur when the filter or tap_name are invalid. +*/ +char *exp_pdu_pre_open(const char *tap_name, const char *filter, + exp_pdu_t *exp_pdu_tap_data); + +/** +* Use the given file descriptor for writing an output file. Can only be called +* once and exp_pdu_pre_open() must be called before. +* +* @return 0 on success or a wtap error code. +*/ +int exp_pdu_open(exp_pdu_t *data, int fd, char *comment); + +/* Stops the PDUs export. */ +int exp_pdu_close(exp_pdu_t *exp_pdu_tap_data); #ifdef __cplusplus } |