summaryrefslogtreecommitdiff
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2014-05-24 13:57:11 -0700
committerGuy Harris <guy@alum.mit.edu>2014-05-24 20:57:57 +0000
commit1b6cc6320ee8d07293b3741738ee601bc86ba068 (patch)
treef35044e157310e4207ddbd0fca6c090b8770268a /wiretap
parent6db77b000fe58173eeed23b91b32c92c681feda2 (diff)
downloadwireshark-1b6cc6320ee8d07293b3741738ee601bc86ba068.tar.gz
Add support for plugins to handle pcap-ng block types.
We rename "file format" plugins to "libwiretap" plugins, as they can register as read handlers for a new file type, read/write handlers for a pcap-ng block type (or both). To register as a pcap-ng block type handler, in the register_wtap_module() routine of your plugin, call register_pcapng_block_type_handler() with the pcap-ng block type and pointers to your routines to read and write those blocks. Those routines should read and write REC_TYPE_FILE_TYPE_SPECIFIC records, with the block type in the pseudo-header for the record in the struct wtap_pkthdr structure, with time stamps stored in that structure, and with a blob of data for the rest of the record. This is for bug 8590. Change-Id: I71847d834854a29ceb85894fd094c2ae91a04273 Reviewed-on: https://code.wireshark.org/review/1775 Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/Makefile.common1
-rw-r--r--wiretap/pcapng.c118
-rw-r--r--wiretap/pcapng_module.h40
-rw-r--r--wiretap/wtap.c2
-rw-r--r--wiretap/wtap.h6
5 files changed, 153 insertions, 14 deletions
diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common
index 1929ecf330..e7ddddcea3 100644
--- a/wiretap/Makefile.common
+++ b/wiretap/Makefile.common
@@ -128,6 +128,7 @@ NONGENERATED_HEADER_FILES = \
pcap-common.h \
pcap-encap.h \
pcapng.h \
+ pcapng_module.h \
peekclassic.h \
peektagged.h \
pppdump.h \
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index 6fd0a881e2..5f5dbc322f 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -42,6 +42,7 @@
#include "pcap-common.h"
#include "pcap-encap.h"
#include "pcapng.h"
+#include "pcapng_module.h"
#if 0
#define pcapng_debug0(str) g_warning(str)
@@ -375,6 +376,52 @@ typedef struct {
wtap_new_ipv6_callback_t add_new_ipv6;
} pcapng_t;
+#ifdef HAVE_PLUGINS
+/*
+ * Table for plugins to handle particular block types.
+ *
+ * A handler has a "read" routine and a "write" routine.
+ *
+ * A "read" routine returns a block as a libwiretap record, filling
+ * in the wtap_pkthdr structure with the appropriate record type and
+ * other information, and filling in the supplied Buffer with
+ * data for which there's no place in the wtap_pkthdr structure.
+ *
+ * A "write" routine takes a libwiretap record and Buffer and writes
+ * out a block.
+ */
+typedef struct {
+ block_reader read;
+ block_writer write;
+} block_handler;
+
+static GHashTable *block_handlers;
+
+void
+register_pcapng_block_type_handler(guint block_type, block_reader read,
+ block_writer write)
+{
+ block_handler *handler;
+
+ if (block_handlers == NULL) {
+ /*
+ * Create the table of block handlers.
+ *
+ * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
+ * so we use "g_direct_hash()" and "g_direct_equal()".
+ */
+ block_handlers = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal,
+ NULL, g_free);
+ }
+ handler = g_malloc(sizeof *handler);
+ handler->read = read;
+ handler->write = write;
+ (void)g_hash_table_insert(block_handlers, GUINT_TO_POINTER(block_type),
+ handler);
+}
+#endif /* HAVE_PLUGINS */
+
static int
pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
char *content, guint len, guint to_read,
@@ -1962,8 +2009,10 @@ static int
pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_, int *err, gchar **err_info)
{
int block_read;
- guint64 file_offset64;
guint32 block_total_length;
+#ifdef HAVE_PLUGINS
+ block_handler *handler;
+#endif
if (bh->block_total_length < MIN_BLOCK_SIZE) {
*err = WTAP_ERR_BAD_FILE;
@@ -1982,12 +2031,27 @@ pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_
block_read = block_total_length - MIN_BLOCK_SIZE;
- /* jump over this unknown block */
- file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
- if (file_offset64 <= 0) {
- if (*err != 0)
+#ifdef HAVE_PLUGINS
+ /*
+ * Do we have a handler for this block type?
+ */
+ handler = (block_handler *)g_hash_table_lookup(block_handlers,
+ GUINT_TO_POINTER(bh->block_type));
+ if (handler != NULL) {
+ /* Yes - call it to read this block type. */
+ if (!handler->read(fh, block_read, pn->byte_swapped,
+ wblock->packet_header, wblock->frame_buffer,
+ err, err_info))
return -1;
- return 0;
+ } else
+#endif
+ {
+ /* No. Skip over this unknown block. */
+ if (!file_skip(fh, block_read, err)) {
+ if (*err != 0)
+ return -1;
+ return 0;
+ }
}
return block_read;
@@ -2063,6 +2127,7 @@ pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t
default:
pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
+ break;
}
if (bytes_read <= 0) {
@@ -3549,21 +3614,48 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
const guint8 *pd, int *err)
{
const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
+#ifdef HAVE_PLUGINS
+ block_handler *handler;
+#endif
pcapng_debug2("pcapng_dump: encap = %d (%s)",
phdr->pkt_encap,
wtap_encap_string(phdr->pkt_encap));
- /* We can only write packet records. */
- if (phdr->rec_type != REC_TYPE_PACKET) {
- *err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
- return FALSE;
- }
-
/* Flush any hostname resolution info we may have */
pcapng_write_name_resolution_block(wdh, err);
- if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
+ switch (phdr->rec_type) {
+
+ case REC_TYPE_PACKET:
+ if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
+ return FALSE;
+ }
+ break;
+
+ case REC_TYPE_FILE_TYPE_SPECIFIC:
+#ifdef HAVE_PLUGINS
+ /*
+ * Do we have a handler for this block type?
+ */
+ handler = (block_handler *)g_hash_table_lookup(block_handlers,
+ GUINT_TO_POINTER(pseudo_header->ftsrec.record_type));
+ if (handler != NULL) {
+ /* Yes. Call it to write out this record. */
+ if (!handler->write(wdh, phdr, pd, err))
+ return FALSE;
+ } else
+#endif
+ {
+ /* No. */
+ *err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
+ return FALSE;
+ }
+ break;
+
+ default:
+ /* We don't support writing this record type. */
+ *err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
return FALSE;
}
diff --git a/wiretap/pcapng_module.h b/wiretap/pcapng_module.h
new file mode 100644
index 0000000000..226a8dd7b1
--- /dev/null
+++ b/wiretap/pcapng_module.h
@@ -0,0 +1,40 @@
+/* pcap_module.h
+ *
+ * Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * 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 __PCAP_MODULE_H__
+#define __PCAP_MODULE_H__
+
+/*
+ * Reader and writer routines for pcap-ng block types.
+ */
+typedef gboolean (*block_reader)(FILE_T, int, gboolean, struct wtap_pkthdr *,
+ Buffer *, int *, gchar **);
+typedef gboolean (*block_writer)(wtap_dumper *, const struct wtap_pkthdr *,
+ const guint8 *, int *);
+
+/*
+ * Register a handler for a pcap-ng block type.
+ */
+WS_DLL_PUBLIC
+void register_pcapng_block_type_handler(guint block_type, block_reader read,
+ block_writer write);
+
+#endif /* __PCAP_MODULE_H__ */
+
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index a0117ab784..f193a04ea8 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -89,7 +89,7 @@ check_for_wtap_plugin(GModule *handle)
void
wtap_register_plugin_types(void)
{
- add_plugin_type("file format", check_for_wtap_plugin);
+ add_plugin_type("libwiretap", check_for_wtap_plugin);
}
static void
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 4c12eb422c..f0e176c1f1 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -888,6 +888,11 @@ struct logcat_phdr {
gint version;
};
+/* Pseudo-header for file-type-specific records */
+struct file_type_specific_record_phdr {
+ guint record_type; /* the type of record this is */
+};
+
union wtap_pseudo_header {
struct eth_phdr eth;
struct x25_phdr x25;
@@ -914,6 +919,7 @@ union wtap_pseudo_header {
struct nokia_phdr nokia;
struct llcp_phdr llcp;
struct logcat_phdr logcat;
+ struct file_type_specific_record_phdr ftsrec;
};
/*