aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorJaap Keuter <jaap.keuter@xs4all.nl>2018-01-27 00:46:32 +0100
committerAnders Broman <a.broman58@gmail.com>2018-01-30 05:44:38 +0000
commit27ae22bd2538ff7391a5e56723715932ecf80b0e (patch)
treefc514b88cad18d40506f8430c651ce65f91fdef8 /plugins
parent94d7500a7d2589548f210ef0e9cb6d9eba796239 (diff)
usbdump: Add usbdump wiretap plugin as functional example
This wiretap plugin serves a dual purpose. One is to add usbdump file reading capability to wiretap and therefore Wireshark and Tshark. Second it is an illustration of a basic wiretap plugin module. Change-Id: Iefbb156ea1bc5d90dabc1753942cdb9e393714ad Signed-off-by: Jaap Keuter <jaap.keuter@xs4all.nl> Reviewed-on: https://code.wireshark.org/review/25487 Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am3
-rw-r--r--plugins/wiretap/usbdump/AUTHORS2
-rw-r--r--plugins/wiretap/usbdump/CMakeLists.txt70
-rw-r--r--plugins/wiretap/usbdump/Makefile.am48
-rw-r--r--plugins/wiretap/usbdump/README3
-rw-r--r--plugins/wiretap/usbdump/usbdump.c351
6 files changed, 476 insertions, 1 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 267e8873ae..3db6a690ad 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -35,7 +35,8 @@ SUBDIRS = \
epan/unistim \
epan/wimax \
epan/wimaxasncp \
- epan/wimaxmacphy
+ epan/wimaxmacphy \
+ wiretap/usbdump
EXTRA_DIST = \
$(_CUSTOM_EXTRA_DIST_) \
diff --git a/plugins/wiretap/usbdump/AUTHORS b/plugins/wiretap/usbdump/AUTHORS
new file mode 100644
index 0000000000..f00e0146b8
--- /dev/null
+++ b/plugins/wiretap/usbdump/AUTHORS
@@ -0,0 +1,2 @@
+Author :
+Jaap Keuter <jaap.keuter@xs4all.nl>
diff --git a/plugins/wiretap/usbdump/CMakeLists.txt b/plugins/wiretap/usbdump/CMakeLists.txt
new file mode 100644
index 0000000000..daa98b4840
--- /dev/null
+++ b/plugins/wiretap/usbdump/CMakeLists.txt
@@ -0,0 +1,70 @@
+# CMakeLists.txt
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 1998 Gerald Combs
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+include(WiresharkPlugin)
+
+# Plugin name and version info (major minor micro extra)
+set_module_info(usbdump 0 0 1 0)
+
+set(WIRETAP_SRC
+ usbdump.c
+)
+
+set(PLUGIN_FILES
+ plugin.c
+ ${WIRETAP_SRC}
+)
+
+set(CLEAN_FILES
+ ${PLUGIN_FILES}
+)
+
+set_source_files_properties(
+ ${CLEAN_FILES}
+ PROPERTIES
+ COMPILE_FLAGS "${WERROR_COMMON_FLAGS}"
+)
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/wiretap
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+register_plugin_files(plugin.c
+ plugin_wtap
+ ${WIRETAP_SRC}
+)
+
+add_plugin_library(usbdump wiretap)
+
+install_plugin(usbdump wiretap)
+
+file(GLOB WIRETAP_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h")
+CHECKAPI(
+ NAME
+ usbdump
+ SWITCHES
+ -g abort -g termoutput -build
+ SOURCES
+ ${WIRETAP_SRC}
+ ${WIRETAP_HEADERS}
+)
+
+#
+# Editor modelines - http://www.wireshark.org/tools/modelines.html
+#
+# Local variables:
+# c-basic-offset: 8
+# tab-width: 8
+# indent-tabs-mode: t
+# End:
+#
+# vi: set shiftwidth=8 tabstop=8 noexpandtab:
+# :indentSize=8:tabSize=8:noTabs=false:
+#
diff --git a/plugins/wiretap/usbdump/Makefile.am b/plugins/wiretap/usbdump/Makefile.am
new file mode 100644
index 0000000000..b090b19e27
--- /dev/null
+++ b/plugins/wiretap/usbdump/Makefile.am
@@ -0,0 +1,48 @@
+# Makefile.am
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 1998 Gerald Combs
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+include $(top_srcdir)/Makefile.am.inc
+include $(top_srcdir)/plugins/wiretap/Makefile.am.inc
+
+# the name of the plugin
+PLUGIN_NAME = usbdump
+
+PLUGIN_VERSION = 0.0.1
+
+BUILT_SOURCES = \
+ plugin.c
+
+# Non-generated sources to be scanned for registration routines
+NONGENERATED_REGISTER_C_FILES = \
+ usbdump.c
+
+# Non-generated sources
+NONGENERATED_C_FILES = \
+ $(NONGENERATED_REGISTER_C_FILES)
+
+wiretap_plugin_LTLIBRARIES = usbdump.la
+
+usbdump_la_SOURCES = \
+ $(SRC_FILES) \
+ $(HEADER_FILES)
+
+nodist_usbdump_la_SOURCES = \
+ plugin.c
+
+usbdump_la_CPPFLAGS = $(AM_CPPFLAGS) $(PLUGIN_CPPFLAGS) -I$(abs_top_srcdir)/wiretap
+
+usbdump_la_CFLAGS = $(AM_CFLAGS) $(PLUGIN_CFLAGS) -I$(abs_top_srcdir)/wiretap
+
+usbdump_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+
+DISTCLEANFILES = \
+ plugin.c
+
+EXTRA_DIST = \
+ CMakeLists.txt
diff --git a/plugins/wiretap/usbdump/README b/plugins/wiretap/usbdump/README
new file mode 100644
index 0000000000..65a9b989dd
--- /dev/null
+++ b/plugins/wiretap/usbdump/README
@@ -0,0 +1,3 @@
+This wiretap plugin serves a dual purpose. One is to add usbdump file
+reading capability to wiretap and therefore Wireshark and Tshark.
+Second it is an illustration of a basic wiretap plugin module.
diff --git a/plugins/wiretap/usbdump/usbdump.c b/plugins/wiretap/usbdump/usbdump.c
new file mode 100644
index 0000000000..b52c94be09
--- /dev/null
+++ b/plugins/wiretap/usbdump/usbdump.c
@@ -0,0 +1,351 @@
+/* usbdump.c
+ *
+ * Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * File format support for usbdump file format
+ * Copyright (c) 2017 by Jaap Keuter <jaap.keuter@xs4all.nl>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * This wiretap is for an usbdump file format reader. The format is
+ * reverse engineered from FreeBSD source code.
+ *
+ * File format is little endian!
+ *
+ * Header
+ * ---------------------------------
+ * 0E 00 90 9A header magic
+ * 00 version major
+ * 03 version minor
+ * 00 00 00 00 00 00 00 00 reserved
+ * 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00
+ * 00 00
+ *
+ * Frames
+ * ---------------------------------
+ * F0 26 00 00 length of multiframe read from bpf (9968 octets)
+ *
+ * Frame, bpf header (little endian)
+ * ---------------------------------
+ * DE 3F 0E 59 ts sec
+ * 6A 77 01 00 ts usec
+ * 98 00 00 00 capture length (152)
+ * 98 00 00 00 data length (152)
+ * 1C header length (28)
+ * 04 bpf word alignment size
+ * 00 00 00 00 00 00 00 00 padding
+ * 00 00
+ *
+ * Frame, captured data
+ * ---------------------------------
+ * 98 00 00 00 00 00 00 00 length, ....
+ *
+ */
+
+#include "config.h"
+#include "wtap-int.h"
+#include "file_wrappers.h"
+#include "string.h"
+
+void wtap_register_usbdump(void);
+
+#define USBDUMP_MAGIC 0x9a90000e
+
+/* Private data needed to read the file initially. */
+typedef struct {
+ guint16 version;
+ guint32 multiframe_size;
+ gboolean multiframe_overrun;
+} usbdump_info_t;
+
+
+static gboolean usbdump_read(wtap *wth, int *err, gchar **err_info,
+ gint64 *data_offset);
+static gboolean usbdump_seek_read(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr, Buffer *buf,
+ int *err, gchar **err_info);
+static gboolean usbdump_read_packet(wtap *wth, FILE_T fh,
+ struct wtap_pkthdr *phdr, Buffer *buf,
+ int *err, gchar **err_info);
+
+static int usbdump_file_type_subtype;
+
+/*
+ * Try to interpret a file as a usbdump formatted file.
+ * Read relevant parts of the given file and collect information needed to
+ * read the individual frames. Return value indicates whether or not this is
+ * recognized as an usbdump file.
+ */
+static wtap_open_return_val
+usbdump_open(wtap *wth, int *err, char **err_info)
+{
+ guint32 magic;
+ guint16 version;
+ guint32 multiframe_size;
+ usbdump_info_t *usbdump_info;
+
+ /* Read in the number that should be at the start of a "usbdump" file */
+ if (!wtap_read_bytes(wth->fh, &magic, sizeof magic, err, err_info)) {
+ if (*err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Check the file magic */
+ if (GUINT32_FROM_LE(magic) != USBDUMP_MAGIC)
+ {
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Read the version of the header */
+ if (!wtap_read_bytes(wth->fh, &version, sizeof version, err, err_info)) {
+ if (*err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Check for the supported version number */
+ if (GUINT16_FROM_BE(version) != 3) {
+ /* We only support version 0.3 */
+ *err = WTAP_ERR_UNSUPPORTED;
+ *err_info = g_strdup_printf("usbdump: version %u.%u unsupported",
+ version >> 8, version & 0xff);
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Read the reserved field of the header */
+ if (!wtap_read_bytes(wth->fh, NULL, 26, err, err_info)) {
+ if (*err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Read the initial multiframe size field */
+ if (!wtap_read_bytes(wth->fh, &multiframe_size, sizeof multiframe_size,
+ err, err_info)) {
+ if (*err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ /* Create a private structure to track the multiframe */
+ usbdump_info = (usbdump_info_t *)g_malloc(sizeof(usbdump_info_t));
+ usbdump_info->version = GUINT16_FROM_BE(version);
+ usbdump_info->multiframe_size = GUINT32_FROM_LE(multiframe_size);
+ usbdump_info->multiframe_overrun = FALSE;
+
+ /*
+ * We are convinced this is a usbdump format file.
+ * Setup the wiretap structure and fill it with info of this format.
+ */
+ wth->priv = (void *)usbdump_info;
+ wth->subtype_read = usbdump_read;
+ wth->subtype_seek_read = usbdump_seek_read;
+ wth->file_type_subtype = usbdump_file_type_subtype;
+ wth->file_encap = WTAP_ENCAP_USB_FREEBSD;
+ wth->file_tsprec = WTAP_TSPREC_USEC;
+
+ return WTAP_OPEN_MINE;
+}
+
+/*
+ * Sequential read with offset reporting.
+ * Read the next frame in the file and adjust for the multiframe size
+ * indication. Report back where reading of this frame started to
+ * support subsequent random access read.
+ */
+static gboolean
+usbdump_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
+{
+ usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv;
+
+ /* Report the current file location */
+ *data_offset = file_tell(wth->fh);
+
+ /* Try to read a packet worth of data */
+ if (!usbdump_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
+ err, err_info))
+ return FALSE;
+
+ /* Check if we overrun the multiframe during the last read */
+ if (usbdump_info->multiframe_overrun)
+ {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = "Multiframe overrun";
+ return FALSE;
+ }
+
+ /* See if we reached the end of the multiframe */
+ if (usbdump_info->multiframe_size == 0)
+ {
+ /*
+ * Try to read the subsequent multiframe size field.
+ * This will fail at end of file, but that is accepted.
+ */
+ wtap_read_bytes_or_eof(wth->fh, &usbdump_info->multiframe_size,
+ sizeof usbdump_info->multiframe_size,
+ err, err_info);
+ }
+
+ return TRUE;
+}
+
+/*
+ * Random access read.
+ * Read the frame at the given offset in the file. Store the frame data
+ * in a buffer and fill in the packet header info.
+ */
+static gboolean
+usbdump_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err, gchar **err_info)
+{
+ /* Seek to the desired file position at the start of the frame */
+ if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+ return FALSE;
+
+ /* Try to read a packet worth of data */
+ if (!usbdump_read_packet(wth, wth->random_fh, phdr, buf, err, err_info)) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Read the actual frame data from the file.
+ * This requires reading the header, determine the size, read frame size worth
+ * of data into the buffer and setting the packet header fields to the values
+ * of the frame header.
+ *
+ * Also, for the sequential read, keep track of the position in the multiframe
+ * so that we can find the next multiframe size field.
+ */
+static gboolean
+usbdump_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+ int *err, gchar **err_info)
+{
+ usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv;
+
+ guint8 bpf_hdr[18];
+ guint8 bpf_hdr_len, alignment;
+
+ /* Read the packet header */
+ if (!wtap_read_bytes_or_eof(fh, bpf_hdr, 18, err, err_info))
+ return FALSE;
+
+ /* Get sizes */
+ bpf_hdr_len = bpf_hdr[16];
+ alignment = bpf_hdr[17];
+
+ /* Check header length */
+ if (bpf_hdr_len > 18)
+ {
+ /* Read packet header padding */
+ if (!wtap_read_bytes_or_eof(fh, NULL, bpf_hdr_len - 18, err, err_info))
+ return FALSE;
+ }
+
+ /* Keep track of multiframe_size and detect overrun */
+ if (usbdump_info->multiframe_size < bpf_hdr_len) {
+ usbdump_info->multiframe_overrun = TRUE;
+ } else {
+ usbdump_info->multiframe_size -= bpf_hdr_len;
+ }
+
+ /* Setup the per packet structure and fill it with info from this frame */
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN;
+ phdr->ts.secs = (guint32)bpf_hdr[3] << 24 | (guint32)bpf_hdr[2] << 16 |
+ (guint32)bpf_hdr[1] << 8 | (guint32)bpf_hdr[0];
+ phdr->ts.nsecs = ((guint32)bpf_hdr[7] << 24 | (guint32)bpf_hdr[6] << 16 |
+ (guint32)bpf_hdr[5] << 8 | (guint32)bpf_hdr[4]) * 1000;
+ phdr->caplen = (guint32)bpf_hdr[11] << 24 | (guint32)bpf_hdr[10] << 16 |
+ (guint32)bpf_hdr[9] << 8 | (guint32)bpf_hdr[8];
+ phdr->len = (guint32)bpf_hdr[15] << 24 | (guint32)bpf_hdr[14] << 16 |
+ (guint32)bpf_hdr[13] << 8 | (guint32)bpf_hdr[12];
+
+ /* Read the packet data */
+ if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
+ return FALSE;
+
+ /* Keep track of multiframe_size and detect overrun */
+ if (usbdump_info->multiframe_size < phdr->caplen) {
+ usbdump_info->multiframe_overrun = TRUE;
+ } else {
+ usbdump_info->multiframe_size -= phdr->caplen;
+ }
+
+ /* Check for and apply alignment as defined in the frame header */
+ guint8 pad_len = (guint32)alignment -
+ (((guint32)bpf_hdr_len + phdr->caplen) &
+ ((guint32)alignment - 1));
+ if (pad_len < alignment) {
+ /* Read alignment from the file */
+ if (!wtap_read_bytes(fh, NULL, pad_len, err, err_info))
+ return FALSE;
+
+ /* Keep track of multiframe_size and detect overrun */
+ if (usbdump_info->multiframe_size < pad_len) {
+ usbdump_info->multiframe_overrun = TRUE;
+ } else {
+ usbdump_info->multiframe_size -= pad_len;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * Register with wiretap.
+ * Register how we can handle an unknown file to see if this is a valid
+ * usbdump file and register information about this file format.
+ */
+void
+wtap_register_usbdump(void)
+{
+ struct open_info oi = {
+ "FreeBSD usbdump",
+ OPEN_INFO_MAGIC,
+ usbdump_open,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ wtap_register_open_info(&oi, FALSE);
+
+ struct file_type_subtype_info fi = {
+ "FreeBSD USBDUMP",
+ "usbdump",
+ NULL,
+ NULL,
+ FALSE,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ usbdump_file_type_subtype =
+ wtap_register_file_type_subtypes(&fi, WTAP_FILE_TYPE_SUBTYPE_UNKNOWN);
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */