diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-05-24 13:57:11 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-05-24 20:57:57 +0000 |
commit | 1b6cc6320ee8d07293b3741738ee601bc86ba068 (patch) | |
tree | f35044e157310e4207ddbd0fca6c090b8770268a /wiretap | |
parent | 6db77b000fe58173eeed23b91b32c92c681feda2 (diff) |
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.common | 1 | ||||
-rw-r--r-- | wiretap/pcapng.c | 118 | ||||
-rw-r--r-- | wiretap/pcapng_module.h | 40 | ||||
-rw-r--r-- | wiretap/wtap.c | 2 | ||||
-rw-r--r-- | wiretap/wtap.h | 6 |
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; }; /* |