* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
#include <glib.h>
#include "tvbuff.h"
#include "plugins.h"
#include "epan_dissect.h"
+
#include "emem.h"
+#include "wmem/wmem.h"
#include <epan/reassemble.h>
#include <epan/stream.h>
static dissector_handle_t frame_handle = NULL;
static dissector_handle_t data_handle = NULL;
+/**
+ * A data source.
+ * Has a tvbuff and a name.
+ */
+struct data_source {
+ tvbuff_t *tvb;
+ char *name;
+};
+
void
packet_init(void)
{
- frame_handle = find_dissector("frame");
- data_handle = find_dissector("data");
- proto_malformed = proto_get_id_by_filter_name("malformed");
+ frame_handle = find_dissector("frame");
+ data_handle = find_dissector("data");
+ proto_malformed = proto_get_id_by_filter_name("malformed");
}
void
* of the tvbuff to reflect the specified length.
*/
void
-set_actual_length(tvbuff_t *tvb, guint specified_len)
+set_actual_length(tvbuff_t *tvb, const guint specified_len)
{
- if (specified_len < tvb_reported_length(tvb)) {
- /* Adjust the length of this tvbuff to include only the specified
- payload length.
+ if (specified_len < tvb_reported_length(tvb)) {
+ /* Adjust the length of this tvbuff to include only the specified
+ payload length.
- The dissector above the one calling us (the dissector above is
- probably us) may use that to determine how much of its packet
- was padding. */
- tvb_set_reported_length(tvb, specified_len);
- }
+ The dissector above the one calling us (the dissector above is
+ probably us) may use that to determine how much of its packet
+ was padding. */
+ tvb_set_reported_length(tvb, specified_len);
+ }
}
/* Allow protocols to register "init" routines, which are called before
/* Reclaim and reinitialize all memory of seasonal scope */
se_free_all();
+ wmem_enter_file_scope();
+
+ /*
+ * Reinitialize resolution information. We do initialization here in
+ * case we need to resolve between captures.
+ */
+ host_name_lookup_cleanup();
+ host_name_lookup_init();
+
/* Initialize the table of conversations. */
epan_conversation_init();
/* Initialize protocol-specific variables. */
g_slist_foreach(init_routines, &call_init_routine, NULL);
- /* Initialize the common data structures for fragment reassembly.
- Must be done *after* calling init routines, as those routines
- may free up space for fragments, which they find by using the
- data structures that "reassemble_init()" frees. */
- reassemble_init();
-
/* Initialize the stream-handling tables */
stream_init();
void
cleanup_dissection(void)
{
- init_dissection();
+ /* Cleanup the table of conversations. Do this before freeing seasonal
+ * memory (at least until conversation's use of g_slist is changed).
+ */
+ epan_conversation_cleanup();
+
+ /* Reclaim all memory of seasonal scope */
+ se_free_all();
+
+ /* Cleanup the table of circuits. */
+ epan_circuit_cleanup();
+
+ /* TODO: Introduce cleanup_routines */
+ /* Cleanup protocol-specific variables. */
+ g_slist_foreach(init_routines, &call_init_routine, NULL);
+
+ /* Cleanup the stream-handling tables */
+ stream_cleanup();
+
+ /* Initialize the expert infos */
+ expert_cleanup();
+
+ wmem_leave_file_scope();
+
+ /*
+ * Reinitialize resolution information. We do initialization here in
+ * case we need to resolve between captures.
+ */
+ host_name_lookup_cleanup();
+ host_name_lookup_init();
}
/* Allow protocols to register a "cleanup" routine to be
void
add_new_data_source(packet_info *pinfo, tvbuff_t *tvb, const char *name)
{
- data_source *src;
+ struct data_source *src;
- src = ep_alloc(sizeof (data_source));
+ src = g_malloc(sizeof(struct data_source));
src->tvb = tvb;
- /*
- * XXX - if we require this argument to be a string constant,
- * we don't need to allocate a buffer for a copy and make a
- * copy, and wouldn't need to free the buffer, either.
- */
- src->name = ep_strdup_printf("%s (%u bytes)", name, tvb_length(tvb));
+ src->name = g_strdup(name);
pinfo->data_src = g_slist_append(pinfo->data_src, src);
}
+const char*
+get_data_source_name(const struct data_source *src)
+{
+ return ep_strdup_printf("%s (%u bytes)", src->name, tvb_length(src->tvb));
+}
+
+tvbuff_t *
+get_data_source_tvb(const struct data_source *src)
+{
+ return src->tvb;
+}
+
/*
* Free up a frame's list of data sources.
*/
void
free_data_sources(packet_info *pinfo)
{
- g_slist_free(pinfo->data_src);
- pinfo->data_src = NULL;
+ if (pinfo->data_src) {
+ GSList *l;
+
+ for (l = pinfo->data_src; l; l = l->next) {
+ struct data_source *src = l->data;
+
+ g_free(src->name);
+ g_free(src);
+ }
+ g_slist_free(pinfo->data_src);
+ pinfo->data_src = NULL;
+ }
+}
+
+void
+mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num)
+{
+ /* Don't mark a frame as dependent on itself */
+ if (frame_num != PINFO_FD_NUM(pinfo)) {
+ pinfo->dependent_frames = g_slist_prepend(pinfo->dependent_frames, GUINT_TO_POINTER(frame_num));
+ }
}
/* Allow dissectors to register a "final_registration" routine
/* Creates the top-most tvbuff and calls dissect_frame() */
void
-dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header,
+dissect_packet(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
const guchar *pd, frame_data *fd, column_info *cinfo)
{
if (cinfo != NULL)
col_init(cinfo);
+ memset(&edt->pi, 0, sizeof(edt->pi));
edt->pi.current_proto = "<Missing Protocol Name>";
edt->pi.cinfo = cinfo;
edt->pi.fd = fd;
- edt->pi.pseudo_header = pseudo_header;
- edt->pi.data_src = NULL;
+ edt->pi.phdr = phdr;
+ edt->pi.pseudo_header = &phdr->pseudo_header;
edt->pi.dl_src.type = AT_NONE;
- edt->pi.dl_src.len = 0;
- edt->pi.dl_src.data = NULL;
edt->pi.dl_dst.type = AT_NONE;
- edt->pi.dl_dst.len = 0;
- edt->pi.dl_dst.data = NULL;
edt->pi.net_src.type = AT_NONE;
- edt->pi.net_src.len = 0;
- edt->pi.net_src.data = NULL;
edt->pi.net_dst.type = AT_NONE;
- edt->pi.net_dst.len = 0;
- edt->pi.net_dst.data = NULL;
edt->pi.src.type = AT_NONE;
- edt->pi.src.len = 0;
- edt->pi.src.data = NULL;
edt->pi.dst.type = AT_NONE;
- edt->pi.dst.len = 0;
- edt->pi.dst.data = NULL;
- edt->pi.ethertype = 0;
- edt->pi.ipproto = 0;
- edt->pi.ipxptype = 0;
edt->pi.ctype = CT_NONE;
- edt->pi.circuit_id = 0;
edt->pi.noreassembly_reason = "";
- edt->pi.fragmented = FALSE;
- edt->pi.in_error_pkt = FALSE;
edt->pi.ptype = PT_NONE;
- edt->pi.srcport = 0;
- edt->pi.destport = 0;
- edt->pi.match_port = 0;
- edt->pi.match_string = NULL;
- edt->pi.can_desegment = 0;
- edt->pi.want_pdu_tracking = 0;
edt->pi.p2p_dir = P2P_DIR_UNKNOWN;
- edt->pi.private_data = NULL;
- edt->pi.oxid = 0;
- edt->pi.rxid = 0;
- edt->pi.r_ctl = 0;
- edt->pi.src_idx = 0;
- edt->pi.dst_idx = 0;
- edt->pi.vsan = 0;
- edt->pi.dcectxid = 0;
edt->pi.dcetransporttype = -1;
- edt->pi.decrypt_gssapi_tvb = 0;
- edt->pi.gssapi_wrap_tvb = NULL;
- edt->pi.gssapi_encrypted_tvb = NULL;
- edt->pi.gssapi_decrypted_tvb = NULL;
- edt->pi.layer_names = NULL;
- edt->pi.link_number = 0;
edt->pi.annex_a_used = MTP2_ANNEX_A_USED_UNKNOWN;
- edt->pi.profinet_conv = NULL;
- edt->pi.profinet_type = 0;
- edt->pi.usb_conv_info = NULL;
- edt->pi.tcp_tree = NULL;
edt->pi.dcerpc_procedure_name="";
- edt->pi.sccp_info = NULL;
-
+ edt->pi.link_dir = LINK_DIR_UNKNOWN;
+ edt->tvb = NULL;
+
+ /* to enable decode as for ethertype=0x0000 (fix for bug 4721) */
+ edt->pi.ethertype = G_MAXINT;
+
+ EP_CHECK_CANARY(("before dissecting frame %d",fd->num));
+
TRY {
- edt->tvb = tvb_new_real_data(pd, fd->cap_len, fd->pkt_len);
+ /*
+ * XXX - currently, the length arguments to
+ * tvb_new_real_data() are signed, but the captured
+ * and reported length values are unsigned; this means
+ * that length values > 2^31 - 1 will appear as
+ * negative lengths in tvb_new_real_data().
+ *
+ * Captured length values that large will already
+ * have been filtered out by the Wiretap modules
+ * (the file will be reported as corrupted), to
+ * avoid trying to allocate large chunks of data.
+ *
+ * Reported length values will not have been
+ * filtered out, and should not be filtered out,
+ * as those lengths are not necessarily invalid.
+ *
+ * For now, we clip the reported length at G_MAXINT,
+ * so that tvb_new_real_data() doesn't fail. It
+ * would throw an exception, which we'd catch, but
+ * that would mean we would have no tvbuffs
+ * associated with edt, which would upset much of
+ * the rest of the application.
+ */
+ edt->tvb = tvb_new_real_data(pd, fd->cap_len,
+ fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len);
/* Add this tvbuffer into the data_src list */
add_new_data_source(&edt->pi, edt->tvb, "Frame");
CATCH(ReportedBoundsError) {
if(proto_malformed != -1){
proto_tree_add_protocol_format(edt->tree, proto_malformed, edt->tvb, 0, 0,
- "[Malformed Frame: Packet Length]" );
+ "[Malformed Frame: Packet Length]" );
} else {
g_assert_not_reached();
}
}
ENDTRY;
+ EP_CHECK_CANARY(("after dissecting frame %d",fd->num));
+
fd->flags.visited = 1;
}
/*********************** code added for sub-dissector lookup *********************/
/*
- * An dissector handle.
+ * A dissector handle.
*/
struct dissector_handle {
const char *name; /* dissector name */
*/
static int
call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb,
- packet_info *pinfo, proto_tree *tree)
+ packet_info *pinfo, proto_tree *tree, void *data)
{
const char *saved_proto;
- int ret;
+ int ret;
saved_proto = pinfo->current_proto;
if (handle->protocol != NULL) {
pinfo->current_proto =
- proto_get_protocol_short_name(handle->protocol);
+ proto_get_protocol_short_name(handle->protocol);
}
if (handle->is_new) {
- ret = (*handle->dissector.new)(tvb, pinfo, tree);
+ EP_CHECK_CANARY(("before calling handle->dissector.new for %s",handle->name));
+ ret = (*handle->dissector.new)(tvb, pinfo, tree, data);
+ EP_CHECK_CANARY(("after calling handle->dissector.new for %s",handle->name));
} else {
+ EP_CHECK_CANARY(("before calling handle->dissector.old for %s",handle->name));
(*handle->dissector.old)(tvb, pinfo, tree);
+ EP_CHECK_CANARY(("after calling handle->dissector.old for %s",handle->name));
ret = tvb_length(tvb);
if (ret == 0) {
/*
* dissector and return its return value, otherwise call it and return
* the length of the tvbuff pointed to by the argument.
*/
+
+static int
+call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb,
+ packet_info *pinfo_arg, proto_tree *tree, void *);
+
static int
-call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb,
- packet_info *pinfo_arg, proto_tree *tree)
+call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo_arg,
+ proto_tree *tree, gboolean add_proto_name, void *data)
{
- packet_info *volatile pinfo = pinfo_arg;
- const char *saved_proto;
- guint16 saved_can_desegment;
- volatile int ret = 0;
- gboolean save_writable;
- volatile address save_dl_src;
- volatile address save_dl_dst;
- volatile address save_net_src;
- volatile address save_net_dst;
- volatile address save_src;
- volatile address save_dst;
- volatile gint saved_layer_names_len = 0;
+ packet_info *pinfo = pinfo_arg;
+ const char *saved_proto;
+ guint16 saved_can_desegment;
+ int ret;
+ gint saved_layer_names_len = 0;
if (handle->protocol != NULL &&
!proto_is_protocol_enabled(handle->protocol)) {
saved_can_desegment = pinfo->can_desegment;
if (pinfo->layer_names != NULL)
- saved_layer_names_len = pinfo->layer_names->len;
+ saved_layer_names_len = (gint) pinfo->layer_names->len;
/*
* can_desegment is set to 2 by anyone which offers the
pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
if (handle->protocol != NULL) {
pinfo->current_proto =
- proto_get_protocol_short_name(handle->protocol);
+ proto_get_protocol_short_name(handle->protocol);
/*
* Add the protocol name to the layers
+ * if not told not to. Asn2wrs generated dissectors may be added multiple times otherwise.
*/
- if (pinfo->layer_names) {
+ if ((pinfo->layer_names)&&(add_proto_name)) {
if (pinfo->layer_names->len > 0)
g_string_append(pinfo->layer_names, ":");
- g_string_append(pinfo->layer_names,
- proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
+ g_string_append(pinfo->layer_names,
+ proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
}
}
- if (pinfo->in_error_pkt) {
+ if (pinfo->flags.in_error_pkt) {
+ ret = call_dissector_work_error(handle, tvb, pinfo, tree, data);
+ } else {
/*
- * This isn't a packet being transported inside
- * the protocol whose dissector is calling us,
- * it's a copy of a packet that caused an error
- * in some protocol included in a packet that
- * reports the error (e.g., an ICMP Unreachable
- * packet).
- */
-
+ * Just call the subdissector.
+ */
+ ret = call_dissector_through_handle(handle, tvb, pinfo, tree, data);
+ }
+ if (ret == 0) {
/*
- * Save the current state of the writability of
- * the columns, and restore them after the
- * dissector returns, so that the columns
- * don't reflect the packet that got the error,
- * they reflect the packet that reported the
- * error.
+ * That dissector didn't accept the packet, so
+ * remove its protocol's name from the list
+ * of protocols.
*/
- save_writable = col_get_writable(pinfo->cinfo);
- col_set_writable(pinfo->cinfo, FALSE);
- save_dl_src = pinfo->dl_src;
- save_dl_dst = pinfo->dl_dst;
- save_net_src = pinfo->net_src;
- save_net_dst = pinfo->net_dst;
- save_src = pinfo->src;
- save_dst = pinfo->dst;
-
- /* Dissect the contained packet. */
- TRY {
- ret = call_dissector_through_handle(handle, tvb,
- pinfo, tree);
+ if ((pinfo->layer_names != NULL)&&(add_proto_name)) {
+ g_string_truncate(pinfo->layer_names, saved_layer_names_len);
}
- CATCH(BoundsError) {
- /*
- * Restore the column writability and addresses.
- */
- col_set_writable(pinfo->cinfo, save_writable);
- pinfo->dl_src = save_dl_src;
- pinfo->dl_dst = save_dl_dst;
- pinfo->net_src = save_net_src;
- pinfo->net_dst = save_net_dst;
- pinfo->src = save_src;
- pinfo->dst = save_dst;
+ }
+ pinfo->current_proto = saved_proto;
+ pinfo->can_desegment = saved_can_desegment;
+ return ret;
+}
- /*
- * Restore the current protocol, so any
- * "Short Frame" indication reflects that
- * protocol, not the protocol for the
- * packet that got the error.
- */
- pinfo->current_proto = saved_proto;
- /*
- * Restore the desegmentability state.
- */
- pinfo->can_desegment = saved_can_desegment;
+static int
+call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb,
+ packet_info *pinfo_arg, proto_tree *tree, void *data)
+{
+ packet_info *pinfo = pinfo_arg;
+ const char *saved_proto;
+ guint16 saved_can_desegment;
+ volatile int ret = 0;
+ gboolean save_writable;
+ address save_dl_src;
+ address save_dl_dst;
+ address save_net_src;
+ address save_net_dst;
+ address save_src;
+ address save_dst;
- /*
- * Rethrow the exception, so this will be
- * reported as a short frame.
- */
- RETHROW;
- }
- CATCH(ReportedBoundsError) {
- /*
- * "ret" wasn't set because an exception was thrown
- * before "call_dissector_through_handle()" returned.
- * As it called something, at least one dissector
- * accepted the packet, and, as an exception was
- * thrown, not only was all the tvbuff dissected,
- * a dissector tried dissecting past the end of
- * the data in some tvbuff, so we'll assume that
- * the entire tvbuff was dissected.
- */
- ret = tvb_length(tvb);
- }
- CATCH(OutOfMemoryError) {
- RETHROW;
- }
- ENDTRY;
+ /*
+ * This isn't a packet being transported inside
+ * the protocol whose dissector is calling us,
+ * it's a copy of a packet that caused an error
+ * in some protocol included in a packet that
+ * reports the error (e.g., an ICMP Unreachable
+ * packet).
+ */
+ /*
+ * Save the current state of the writability of
+ * the columns, and restore them after the
+ * dissector returns, so that the columns
+ * don't reflect the packet that got the error,
+ * they reflect the packet that reported the
+ * error.
+ */
+ saved_proto = pinfo->current_proto;
+ saved_can_desegment = pinfo->can_desegment;
+
+ save_writable = col_get_writable(pinfo->cinfo);
+ col_set_writable(pinfo->cinfo, FALSE);
+ save_dl_src = pinfo->dl_src;
+ save_dl_dst = pinfo->dl_dst;
+ save_net_src = pinfo->net_src;
+ save_net_dst = pinfo->net_dst;
+ save_src = pinfo->src;
+ save_dst = pinfo->dst;
+
+ /* Dissect the contained packet. */
+ TRY {
+ ret = call_dissector_through_handle(handle, tvb,pinfo, tree, data);
+ }
+ CATCH(BoundsError) {
+ /*
+ * Restore the column writability and addresses.
+ */
col_set_writable(pinfo->cinfo, save_writable);
- pinfo->dl_src = save_dl_src;
- pinfo->dl_dst = save_dl_dst;
+ pinfo->dl_src = save_dl_src;
+ pinfo->dl_dst = save_dl_dst;
pinfo->net_src = save_net_src;
pinfo->net_dst = save_net_dst;
- pinfo->src = save_src;
- pinfo->dst = save_dst;
- pinfo->want_pdu_tracking = 0;
- } else {
+ pinfo->src = save_src;
+ pinfo->dst = save_dst;
+
/*
- * Just call the subdissector.
- */
- ret = call_dissector_through_handle(handle, tvb, pinfo, tree);
- }
+ * Restore the current protocol, so any
+ * "Short Frame" indication reflects that
+ * protocol, not the protocol for the
+ * packet that got the error.
+ */
+ pinfo->current_proto = saved_proto;
- if (ret == 0) {
/*
- * That dissector didn't accept the packet, so
- * remove its protocol's name from the list
- * of protocols.
- */
- if (pinfo->layer_names != NULL) {
- g_string_truncate(pinfo->layer_names,
- saved_layer_names_len);
- }
+ * Restore the desegmentability state.
+ */
+ pinfo->can_desegment = saved_can_desegment;
+
+ /*
+ * Rethrow the exception, so this will be
+ * reported as a short frame.
+ */
+ RETHROW;
}
- pinfo->current_proto = saved_proto;
- pinfo->can_desegment = saved_can_desegment;
+ CATCH(ReportedBoundsError) {
+ /*
+ * "ret" wasn't set because an exception was thrown
+ * before "call_dissector_through_handle()" returned.
+ * As it called something, at least one dissector
+ * accepted the packet, and, as an exception was
+ * thrown, not only was all the tvbuff dissected,
+ * a dissector tried dissecting past the end of
+ * the data in some tvbuff, so we'll assume that
+ * the entire tvbuff was dissected.
+ */
+ ret = tvb_length(tvb);
+ }
+ CATCH(OutOfMemoryError) {
+ RETHROW;
+ }
+ ENDTRY;
+
+ col_set_writable(pinfo->cinfo, save_writable);
+ pinfo->dl_src = save_dl_src;
+ pinfo->dl_dst = save_dl_dst;
+ pinfo->net_src = save_net_src;
+ pinfo->net_dst = save_net_dst;
+ pinfo->src = save_src;
+ pinfo->dst = save_dst;
+ pinfo->want_pdu_tracking = 0;
return ret;
}
*
* "hash_table" is a hash table, indexed by port number, supplying
* a "struct dtbl_entry"; it records what dissector is assigned to
- * that port number in that table.
+ * that uint or string value in that table.
*
* "dissector_handles" is a list of all dissectors that *could* be
* used in that table; not all of them are necessarily in the table,
- * as they may be for protocols that don't have a fixed port number.
+ * as they may be for protocols that don't have a fixed uint value,
+ * e.g. for TCP or UDP port number tables and protocols with no fixed
+ * port number.
*
* "ui_name" is the name the dissector table has in the user interface.
*
- * "type" is a field type giving the width of the port number for that
- * dissector table.
+ * "type" is a field type giving the width of the uint value for that
+ * dissector table, if it's a uint dissector table.
*
- * "base" is the base in which to display the port number for that
- * dissector table.
+ * "base" is the base in which to display the uint value for that
+ * dissector table, if it's a uint dissector table.
*/
struct dissector_table {
GHashTable *hash_table;
/* Find an entry in a uint dissector table. */
static dtbl_entry_t *
-find_uint_dtbl_entry(dissector_table_t sub_dissectors, guint32 pattern)
+find_uint_dtbl_entry(dissector_table_t sub_dissectors, const guint32 pattern)
{
switch (sub_dissectors->type) {
case FT_UINT24:
case FT_UINT32:
/*
- * You can do a port lookup in these tables.
+ * You can do a uint lookup in these tables.
*/
break;
default:
/*
- * But you can't do a port lookup in any other types
+ * But you can't do a uint lookup in any other types
* of tables.
*/
g_assert_not_reached();
* Find the entry.
*/
return g_hash_table_lookup(sub_dissectors->hash_table,
- GUINT_TO_POINTER(pattern));
+ GUINT_TO_POINTER(pattern));
+}
+
+#if 0
+static void
+dissector_add_uint_sanity_check(const char *name, guint32 pattern, dissector_handle_t handle, dissector_table_t sub_dissectors)
+{
+ dtbl_entry_t *dtbl_entry;
+
+ if (pattern == 0) {
+ g_warning("%s: %s registering using a pattern of 0",
+ name, proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
+ }
+
+ dtbl_entry = g_hash_table_lookup(sub_dissectors->hash_table, GUINT_TO_POINTER(pattern));
+ if (dtbl_entry != NULL) {
+ g_warning("%s: %s registering using pattern %d already registered by %s",
+ name, proto_get_protocol_filter_name(proto_get_id(handle->protocol)),
+ pattern, proto_get_protocol_filter_name(proto_get_id(dtbl_entry->initial->protocol)));
+ }
}
+#endif
/* Add an entry to a uint dissector table. */
void
-dissector_add(const char *name, guint32 pattern, dissector_handle_t handle)
+dissector_add_uint(const char *name, const guint32 pattern, dissector_handle_t handle)
{
- dissector_table_t sub_dissectors;
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors;
+ dtbl_entry_t *dtbl_entry;
sub_dissectors = find_dissector_table(name);
-/* sanity checks */
- g_assert(sub_dissectors);
+
+ /*
+ * Make sure the dissector table exists.
+ */
+ if (sub_dissectors == NULL) {
+ fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+ name);
+ fprintf(stderr, "Protocol being registered is \"%s\"\n",
+ proto_get_protocol_long_name(handle->protocol));
+ if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+ abort();
+ return;
+ }
+
+ /* sanity checks */
+ g_assert(handle!=NULL);
switch (sub_dissectors->type) {
case FT_UINT8:
case FT_UINT24:
case FT_UINT32:
/*
- * You can do a port lookup in these tables.
+ * You can do a uint lookup in these tables.
*/
break;
default:
/*
- * But you can't do a port lookup in any other types
+ * But you can't do a uint lookup in any other types
* of tables.
*/
g_assert_not_reached();
}
+#if 0
+ dissector_add_uint_sanity_check(name, pattern, handle, sub_dissectors);
+#endif
+
dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
dtbl_entry->current = handle;
dtbl_entry->initial = dtbl_entry->current;
-/* do the table insertion */
- g_hash_table_insert( sub_dissectors->hash_table,
- GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
+ /* do the table insertion */
+ g_hash_table_insert( sub_dissectors->hash_table,
+ GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
/*
* Now add it to the list of handles that could be used with this
with a particular pattern. */
/* NOTE: this doesn't use the dissector call variable. It is included to */
-/* be consistant with the dissector_add and more importantly to be used */
+/* be consistant with the dissector_add_uint and more importantly to be used */
/* if the technique of adding a temporary dissector is implemented. */
/* If temporary dissectors are deleted, then the original dissector must */
/* be available. */
void
-dissector_delete(const char *name, guint32 pattern,
+dissector_delete_uint(const char *name, const guint32 pattern,
dissector_handle_t handle _U_)
{
dissector_table_t sub_dissectors = find_dissector_table( name);
dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
* Found - remove it.
*/
g_hash_table_remove(sub_dissectors->hash_table,
- GUINT_TO_POINTER(pattern));
-
- /*
- * Now free up the entry.
- */
- g_free(dtbl_entry);
+ GUINT_TO_POINTER(pattern));
}
}
/* Change the entry for a dissector in a uint dissector table
with a particular pattern to use a new dissector handle. */
void
-dissector_change(const char *name, guint32 pattern, dissector_handle_t handle)
+dissector_change_uint(const char *name, const guint32 pattern, dissector_handle_t handle)
{
dissector_table_t sub_dissectors = find_dissector_table( name);
dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
*/
dtbl_entry = find_uint_dtbl_entry(sub_dissectors, pattern);
if (dtbl_entry != NULL) {
- dtbl_entry->current = handle;
- return;
+ dtbl_entry->current = handle;
+ return;
}
/*
* in the first place.
*/
if (handle == NULL)
- return;
+ return;
dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
dtbl_entry->initial = NULL;
dtbl_entry->current = handle;
-/* do the table insertion */
- g_hash_table_insert( sub_dissectors->hash_table,
- GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
+ /* do the table insertion */
+ g_hash_table_insert( sub_dissectors->hash_table,
+ GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
}
/* Reset an entry in a uint dissector table to its initial value. */
void
-dissector_reset(const char *name, guint32 pattern)
+dissector_reset_uint(const char *name, const guint32 pattern)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
dtbl_entry->current = dtbl_entry->initial;
} else {
g_hash_table_remove(sub_dissectors->hash_table,
- GUINT_TO_POINTER(pattern));
- g_free(dtbl_entry);
+ GUINT_TO_POINTER(pattern));
}
}
/* Look for a given value in a given uint dissector table and, if found,
call the dissector with the arguments supplied, and return TRUE,
otherwise return FALSE. */
+
gboolean
-dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
- tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissector_try_uint_new(dissector_table_t sub_dissectors, const guint32 uint_val,
+ tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const gboolean add_proto_name, void *data)
{
- dtbl_entry_t *dtbl_entry;
+ dtbl_entry_t *dtbl_entry;
struct dissector_handle *handle;
- guint32 saved_match_port;
+ guint32 saved_match_uint;
int ret;
- dtbl_entry = find_uint_dtbl_entry(sub_dissectors, port);
+ dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val);
if (dtbl_entry != NULL) {
/*
* Is there currently a dissector handle for this entry?
}
/*
- * Save the current value of "pinfo->match_port",
- * set it to the port that matched, call the
- * dissector, and restore "pinfo->match_port".
+ * Save the current value of "pinfo->match_uint",
+ * set it to the uint_val that matched, call the
+ * dissector, and restore "pinfo->match_uint".
*/
- saved_match_port = pinfo->match_port;
- pinfo->match_port = port;
- ret = call_dissector_work(handle, tvb, pinfo, tree);
- pinfo->match_port = saved_match_port;
+ saved_match_uint = pinfo->match_uint;
+ pinfo->match_uint = uint_val;
+ ret = call_dissector_work(handle, tvb, pinfo, tree, add_proto_name, data);
+ pinfo->match_uint = saved_match_uint;
/*
* If a new-style dissector returned 0, it means that
return FALSE;
}
+gboolean
+dissector_try_uint(dissector_table_t sub_dissectors, const guint32 uint_val,
+ tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ return dissector_try_uint_new(sub_dissectors, uint_val, tvb, pinfo, tree, TRUE, NULL);
+}
+
/* Look for a given value in a given uint dissector table and, if found,
return the dissector handle for that value. */
dissector_handle_t
-dissector_get_port_handle(dissector_table_t sub_dissectors, guint32 port)
+dissector_get_uint_handle(dissector_table_t const sub_dissectors, const guint32 uint_val)
{
dtbl_entry_t *dtbl_entry;
- dtbl_entry = find_uint_dtbl_entry(sub_dissectors, port);
+ dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val);
if (dtbl_entry != NULL)
return dtbl_entry->current;
else
/* Find an entry in a string dissector table. */
static dtbl_entry_t *
-find_string_dtbl_entry(dissector_table_t sub_dissectors, const gchar *pattern)
+find_string_dtbl_entry(dissector_table_t const sub_dissectors, const gchar *pattern)
{
switch (sub_dissectors->type) {
/* Add an entry to a string dissector table. */
void
dissector_add_string(const char *name, const gchar *pattern,
- dissector_handle_t handle)
+ dissector_handle_t handle)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ dtbl_entry_t *dtbl_entry;
-/* sanity check */
- g_assert( sub_dissectors);
+ /*
+ * Make sure the dissector table exists.
+ */
+ if (sub_dissectors == NULL) {
+ fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+ name);
+ fprintf(stderr, "Protocol being registered is \"%s\"\n",
+ proto_get_protocol_long_name(handle->protocol));
+ if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+ abort();
+ return;
+ }
+ /* sanity checks */
+ g_assert(handle!=NULL);
switch (sub_dissectors->type) {
case FT_STRING:
dtbl_entry->current = handle;
dtbl_entry->initial = dtbl_entry->current;
-/* do the table insertion */
- g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
- (gpointer)dtbl_entry);
+ /* do the table insertion */
+ g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
+ (gpointer)dtbl_entry);
/*
* Now add it to the list of handles that could be used with this
dissector_delete_string(const char *name, const gchar *pattern,
dissector_handle_t handle _U_)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
* Found - remove it.
*/
g_hash_table_remove(sub_dissectors->hash_table, pattern);
-
- /*
- * Now free up the entry.
- */
- g_free(dtbl_entry);
}
}
/* Change the entry for a dissector in a string dissector table
with a particular pattern to use a new dissector handle. */
void
-dissector_change_string(const char *name, gchar *pattern,
- dissector_handle_t handle)
+dissector_change_string(const char *name, const gchar *pattern,
+ dissector_handle_t handle)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
*/
dtbl_entry = find_string_dtbl_entry(sub_dissectors, pattern);
if (dtbl_entry != NULL) {
- dtbl_entry->current = handle;
- return;
+ dtbl_entry->current = handle;
+ return;
}
/*
* in the first place.
*/
if (handle == NULL)
- return;
+ return;
dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
dtbl_entry->initial = NULL;
dtbl_entry->current = handle;
-/* do the table insertion */
- g_hash_table_insert( sub_dissectors->hash_table, pattern,
- (gpointer)dtbl_entry);
+ /* do the table insertion */
+ g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
+ (gpointer)dtbl_entry);
}
/* Reset an entry in a string sub-dissector table to its initial value. */
void
dissector_reset_string(const char *name, const gchar *pattern)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- dtbl_entry_t *dtbl_entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ dtbl_entry_t *dtbl_entry;
-/* sanity check */
+ /* sanity check */
g_assert( sub_dissectors);
/*
dtbl_entry->current = dtbl_entry->initial;
} else {
g_hash_table_remove(sub_dissectors->hash_table, pattern);
- g_free(dtbl_entry);
}
}
return FALSE. */
gboolean
dissector_try_string(dissector_table_t sub_dissectors, const gchar *string,
- tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+ tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- dtbl_entry_t *dtbl_entry;
+ dtbl_entry_t *dtbl_entry;
struct dissector_handle *handle;
- int ret;
- const gchar *saved_match_string;
+ int ret;
+ const gchar *saved_match_string;
+ /* XXX ASSERT instead ? */
+ if (!string) return FALSE;
dtbl_entry = find_string_dtbl_entry(sub_dissectors, string);
if (dtbl_entry != NULL) {
/*
*/
saved_match_string = pinfo->match_string;
pinfo->match_string = string;
- ret = call_dissector_work(handle, tvb, pinfo, tree);
+ ret = call_dissector_work(handle, tvb, pinfo, tree, TRUE, NULL);
pinfo->match_string = saved_match_string;
/*
return the dissector handle for that value. */
dissector_handle_t
dissector_get_string_handle(dissector_table_t sub_dissectors,
- const gchar *string)
+ const gchar *string)
{
dtbl_entry_t *dtbl_entry;
return dtbl_entry->current;
}
+gint
+dissector_compare_filter_name(gconstpointer dissector_a, gconstpointer dissector_b)
+{
+ dissector_handle_t a = (dissector_handle_t)dissector_a;
+ dissector_handle_t b = (dissector_handle_t)dissector_b;
+ const char *a_name, *b_name;
+ gint ret;
+
+ if (a->protocol == NULL)
+ a_name = "";
+ else
+ a_name = proto_get_protocol_filter_name(proto_get_id(a->protocol));
+
+ if (b->protocol == NULL)
+ b_name = "";
+ else
+ b_name = proto_get_protocol_filter_name(proto_get_id(b->protocol));
+
+ ret = strcmp(a_name, b_name);
+ return ret;
+}
+
/* Add a handle to the list of handles that *could* be used with this
table. That list is used by code in the UI. */
void
dissector_add_handle(const char *name, dissector_handle_t handle)
{
- dissector_table_t sub_dissectors = find_dissector_table( name);
- GSList *entry;
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+ GSList *entry;
- /* sanity check */
- g_assert(sub_dissectors != NULL);
+ /*
+ * Make sure the dissector table exists.
+ */
+ if (sub_dissectors == NULL) {
+ fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+ name);
+ fprintf(stderr, "Protocol being registered is \"%s\"\n",
+ proto_get_protocol_long_name(handle->protocol));
+ if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+ abort();
+ return;
+ }
/* Is it already in this list? */
entry = g_slist_find(sub_dissectors->dissector_handles, (gpointer)handle);
/* Add it to the list. */
sub_dissectors->dissector_handles =
- g_slist_append(sub_dissectors->dissector_handles, (gpointer)handle);
+ g_slist_insert_sorted(sub_dissectors->dissector_handles, (gpointer)handle, (GCompareFunc)dissector_compare_filter_name);
}
dissector_handle_t
/**************************************************/
typedef struct dissector_foreach_info {
- gpointer caller_data;
- DATFunc caller_func;
- GHFunc next_func;
- const gchar *table_name;
- ftenum_t selector_type;
+ gpointer caller_data;
+ DATFunc caller_func;
+ GHFunc next_func;
+ const gchar *table_name;
+ ftenum_t selector_type;
} dissector_foreach_info_t;
/*
dissector_table_foreach_func (gpointer key, gpointer value, gpointer user_data)
{
dissector_foreach_info_t *info;
- dtbl_entry_t *dtbl_entry;
+ dtbl_entry_t *dtbl_entry;
g_assert(value);
g_assert(user_data);
info = user_data;
info->caller_func(info->table_name, info->selector_type, key, value,
- info->caller_data);
+ info->caller_data);
}
/*
static void
dissector_all_tables_foreach_func (gpointer key, gpointer value, gpointer user_data)
{
- dissector_table_t sub_dissectors;
+ dissector_table_t sub_dissectors;
dissector_foreach_info_t *info;
g_assert(value);
info.caller_data = user_data;
info.caller_func = func;
- info.next_func = dissector_table_foreach_func;
+ info.next_func = dissector_table_foreach_func;
g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info);
}
*/
void
dissector_table_foreach (const char *name,
- DATFunc func,
- gpointer user_data)
+ DATFunc func,
+ gpointer user_data)
{
dissector_foreach_info_t info;
- dissector_table_t sub_dissectors = find_dissector_table( name);
+ dissector_table_t sub_dissectors = find_dissector_table( name);
- info.table_name = name;
+ info.table_name = name;
info.selector_type = sub_dissectors->type;
- info.caller_func = func;
- info.caller_data = user_data;
+ info.caller_func = func;
+ info.caller_data = user_data;
g_hash_table_foreach(sub_dissectors->hash_table, dissector_table_foreach_func, &info);
}
* function on each entry.
*/
void
-dissector_table_foreach_handle(const char *name,
- DATFunc_handle func,
- gpointer user_data)
+dissector_table_foreach_handle(const char *name,
+ DATFunc_handle func,
+ gpointer user_data)
{
dissector_table_t sub_dissectors = find_dissector_table( name);
GSList *tmp;
for (tmp = sub_dissectors->dissector_handles; tmp != NULL;
- tmp = g_slist_next(tmp))
+ tmp = g_slist_next(tmp))
func(name, tmp->data, user_data);
}
static void
dissector_table_foreach_changed_func (gpointer key, gpointer value, gpointer user_data)
{
- dtbl_entry_t *dtbl_entry;
+ dtbl_entry_t *dtbl_entry;
dissector_foreach_info_t *info;
g_assert(value);
info = user_data;
info->caller_func(info->table_name, info->selector_type, key, value,
- info->caller_data);
+ info->caller_data);
}
/*
* any entry that has been changed from its original state.
*/
void
-dissector_all_tables_foreach_changed (DATFunc func,
+dissector_all_tables_foreach_changed (DATFunc func,
gpointer user_data)
{
dissector_foreach_info_t info;
info.caller_data = user_data;
info.caller_func = func;
- info.next_func = dissector_table_foreach_changed_func;
+ info.next_func = dissector_table_foreach_changed_func;
g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info);
}
*/
void
dissector_table_foreach_changed (const char *name,
- DATFunc func,
- gpointer user_data)
+ DATFunc func,
+ gpointer user_data)
{
dissector_foreach_info_t info;
dissector_table_t sub_dissectors = find_dissector_table( name);
- info.table_name = name;
+ info.table_name = name;
info.selector_type = sub_dissectors->type;
- info.caller_func = func;
- info.caller_data = user_data;
+ info.caller_func = func;
+ info.caller_data = user_data;
g_hash_table_foreach(sub_dissectors->hash_table,
- dissector_table_foreach_changed_func, &info);
+ dissector_table_foreach_changed_func, &info);
}
typedef struct dissector_foreach_table_info {
- gpointer caller_data;
- DATFunc_table caller_func;
+ gpointer caller_data;
+ DATFunc_table caller_func;
} dissector_foreach_table_info_t;
/*
* Called for each entry in the table of all dissector tables.
*/
static void
-dissector_all_tables_foreach_table_func (gpointer key, gpointer value, gpointer user_data)
+dissector_all_tables_foreach_table_func (gpointer key, const gpointer value, const gpointer user_data)
{
- dissector_table_t table;
+ dissector_table_t table;
dissector_foreach_table_info_t *info;
table = value;
(*info->caller_func)((gchar*)key, table->ui_name, info->caller_data);
}
+/*
+ * Called for each key in the table of all dissector tables.
+ */
+static void
+dissector_all_tables_foreach_list_func (gpointer key, gpointer user_data)
+{
+ dissector_table_t table;
+ dissector_foreach_table_info_t *info;
+
+ table = g_hash_table_lookup( dissector_tables, key );
+ info = user_data;
+ (*info->caller_func)((gchar*)key, table->ui_name, info->caller_data);
+}
+
/*
* Walk all dissector tables calling a user supplied function on each
* table.
*/
void
dissector_all_tables_foreach_table (DATFunc_table func,
- gpointer user_data)
+ gpointer user_data,
+ GCompareFunc compare_key_func)
{
dissector_foreach_table_info_t info;
+ GList* list;
info.caller_data = user_data;
info.caller_func = func;
- g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_table_func, &info);
+ if (compare_key_func != NULL)
+ {
+ list = g_hash_table_get_keys(dissector_tables);
+ list = g_list_sort(list, compare_key_func);
+ g_list_foreach(list, dissector_all_tables_foreach_list_func, &info);
+ g_list_free(list);
+ }
+ else
+ {
+ g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_table_func, &info);
+ }
}
dissector_table_t
-register_dissector_table(const char *name, const char *ui_name, ftenum_t type,
- int base)
+register_dissector_table(const char *name, const char *ui_name, const ftenum_t type,
+ const int base)
{
dissector_table_t sub_dissectors;
}
/* Make sure the registration is unique */
- g_assert(!g_hash_table_lookup( dissector_tables, name ));
+ if(g_hash_table_lookup( dissector_tables, name )) {
+ g_error("The filter name %s (%s) is already registered - do you use a buggy plugin?", name, ui_name);
+ }
/* Create and register the dissector table for this name; returns */
/* a pointer to the dissector table. */
* XXX - there's no "g_uint_hash()" or "g_uint_equal()",
* so we use "g_direct_hash()" and "g_direct_equal()".
*/
- sub_dissectors->hash_table = g_hash_table_new( g_direct_hash,
- g_direct_equal );
+ sub_dissectors->hash_table = g_hash_table_new_full( g_direct_hash,
+ g_direct_equal,
+ NULL,
+ &g_free );
break;
case FT_STRING:
case FT_STRINGZ:
- sub_dissectors->hash_table = g_hash_table_new( g_str_hash,
- g_str_equal );
+ sub_dissectors->hash_table = g_hash_table_new_full( g_str_hash,
+ g_str_equal,
+ NULL,
+ &g_free );
break;
default:
}
sub_dissectors->dissector_handles = NULL;
sub_dissectors->ui_name = ui_name;
- sub_dissectors->type = type;
- sub_dissectors->base = base;
+ sub_dissectors->type = type;
+ sub_dissectors->base = base;
g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
return sub_dissectors;
}
static GHashTable *heur_dissector_lists = NULL;
-typedef struct {
- heur_dissector_t dissector;
- protocol_t *protocol;
-} heur_dtbl_entry_t;
-/* Finds a heuristic dissector table by field name. */
+/* Finds a heuristic dissector table by table name. */
static heur_dissector_list_t *
find_heur_dissector_list(const char *name)
{
}
void
-heur_dissector_add(const char *name, heur_dissector_t dissector, int proto)
+heur_dissector_add(const char *name, heur_dissector_t dissector, const int proto)
{
heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
- heur_dtbl_entry_t *dtbl_entry;
+ const char *proto_name;
+ heur_dtbl_entry_t *hdtbl_entry;
- /* sanity check */
- g_assert(sub_dissectors != NULL);
+ /*
+ * Make sure the dissector table exists.
+ */
+ if (sub_dissectors == NULL) {
+ fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+ name);
+ proto_name = proto_get_protocol_name(proto);
+ if (proto_name != NULL) {
+ fprintf(stderr, "Protocol being registered is \"%s\"\n",
+ proto_name);
+ }
+ if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+ abort();
+ return;
+ }
- dtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
- dtbl_entry->dissector = dissector;
- dtbl_entry->protocol = find_protocol_by_id(proto);
+ /* XXX: Should verify that sub-dissector is not already in the list ? */
+
+ hdtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
+ hdtbl_entry->dissector = dissector;
+ hdtbl_entry->protocol = find_protocol_by_id(proto);
+ hdtbl_entry->enabled = TRUE;
/* do the table insertion */
- *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
+ *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)hdtbl_entry);
}
-static int find_matching_heur_dissector( gconstpointer a, gconstpointer b) {
- const heur_dtbl_entry_t *dtbl_entry_a = (const heur_dtbl_entry_t *) a;
- const heur_dtbl_entry_t *dtbl_entry_b = (const heur_dtbl_entry_t *) b;
- return (dtbl_entry_a->dissector == dtbl_entry_b->dissector) &&
- (dtbl_entry_a->protocol == dtbl_entry_b->protocol) ? 0 : 1;
+static int
+find_matching_heur_dissector( gconstpointer a, gconstpointer b) {
+ const heur_dtbl_entry_t *hdtbl_entry_a = (const heur_dtbl_entry_t *) a;
+ const heur_dtbl_entry_t *hdtbl_entry_b = (const heur_dtbl_entry_t *) b;
+ return (hdtbl_entry_a->dissector == hdtbl_entry_b->dissector) &&
+ (hdtbl_entry_a->protocol == hdtbl_entry_b->protocol) ? 0 : 1;
}
-void heur_dissector_delete(const char *name, heur_dissector_t dissector, int proto) {
+void
+heur_dissector_delete(const char *name, heur_dissector_t dissector, const int proto) {
heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
- heur_dtbl_entry_t dtbl_entry;
- GSList* found_entry;
-
+ heur_dtbl_entry_t hdtbl_entry;
+ GSList *found_entry;
+
/* sanity check */
g_assert(sub_dissectors != NULL);
- dtbl_entry.dissector = dissector;
+ hdtbl_entry.dissector = dissector;
- dtbl_entry.protocol = find_protocol_by_id(proto);
+ hdtbl_entry.protocol = find_protocol_by_id(proto);
- found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &dtbl_entry, find_matching_heur_dissector);
+ found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &hdtbl_entry, find_matching_heur_dissector);
if (found_entry) {
*sub_dissectors = g_slist_remove_link(*sub_dissectors, found_entry);
}
}
+void
+heur_dissector_set_enabled(const char *name, heur_dissector_t dissector, const int proto, const gboolean enabled) {
+ heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
+ GSList *found_entry;
+ heur_dtbl_entry_t hdtbl_entry;
+
+ /* sanity check */
+ g_assert(sub_dissectors != NULL);
+
+ hdtbl_entry.dissector = dissector;
+
+ hdtbl_entry.protocol = find_protocol_by_id(proto);
+
+ found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &hdtbl_entry, find_matching_heur_dissector);
+
+ if (found_entry) {
+ heur_dtbl_entry_t *hdtbl_entry_p;
+ hdtbl_entry_p = (heur_dtbl_entry_t *)found_entry->data;
+ hdtbl_entry_p->enabled = enabled;
+ }
+}
gboolean
-dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
- tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
+ packet_info *pinfo, proto_tree *tree, void *data)
{
- gboolean status;
- const char *saved_proto;
- GSList *entry;
- heur_dtbl_entry_t *dtbl_entry;
- guint16 saved_can_desegment;
- gint saved_layer_names_len = 0;
+ gboolean status;
+ const char *saved_proto;
+ GSList *entry;
+ heur_dtbl_entry_t *hdtbl_entry;
+ guint16 saved_can_desegment;
+ gint saved_layer_names_len = 0;
/* can_desegment is set to 2 by anyone which offers this api/service.
then everytime a subdissector is called it is decremented by one.
can restore it and allow the dissectors they call to use
the desegmentation service.
*/
- saved_can_desegment=pinfo->can_desegment;
+ saved_can_desegment = pinfo->can_desegment;
pinfo->saved_can_desegment = saved_can_desegment;
- pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
+ pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
- status = FALSE;
+ status = FALSE;
saved_proto = pinfo->current_proto;
if (pinfo->layer_names != NULL)
- saved_layer_names_len = pinfo->layer_names->len;
+ saved_layer_names_len = (gint) pinfo->layer_names->len;
for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
/* XXX - why set this now and above? */
pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
- dtbl_entry = (heur_dtbl_entry_t *)entry->data;
+ hdtbl_entry = (heur_dtbl_entry_t *)entry->data;
- if (dtbl_entry->protocol != NULL &&
- !proto_is_protocol_enabled(dtbl_entry->protocol)) {
+ if (hdtbl_entry->protocol != NULL &&
+ (!proto_is_protocol_enabled(hdtbl_entry->protocol)||(hdtbl_entry->enabled==FALSE))) {
/*
* No - don't try this dissector.
*/
continue;
}
- if (dtbl_entry->protocol != NULL) {
+ if (hdtbl_entry->protocol != NULL) {
pinfo->current_proto =
- proto_get_protocol_short_name(dtbl_entry->protocol);
+ proto_get_protocol_short_name(hdtbl_entry->protocol);
/*
* Add the protocol name to the layers; we'll remove it
if (pinfo->layer_names) {
if (pinfo->layer_names->len > 0)
g_string_append(pinfo->layer_names, ":");
- g_string_append(pinfo->layer_names,
- proto_get_protocol_filter_name(proto_get_id(dtbl_entry->protocol)));
+ g_string_append(pinfo->layer_names,
+ proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol)));
}
}
-
- if ((*dtbl_entry->dissector)(tvb, pinfo, tree)) {
+ EP_CHECK_CANARY(("before calling heuristic dissector for protocol: %s",
+ proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
+ if ((*hdtbl_entry->dissector)(tvb, pinfo, tree, data)) {
+ EP_CHECK_CANARY(("after heuristic dissector for protocol: %s has accepted and dissected packet",
+ proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
status = TRUE;
break;
} else {
+ EP_CHECK_CANARY(("after heuristic dissector for protocol: %s has returned false",
+ proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
+
/*
* That dissector didn't accept the packet, so
* remove its protocol's name from the list
* of protocols.
*/
if (pinfo->layer_names != NULL) {
- g_string_truncate(pinfo->layer_names,
- saved_layer_names_len);
+ g_string_truncate(pinfo->layer_names, saved_layer_names_len);
}
}
}
return status;
}
+/*
+ * Called for each entry in the table of all heuristic dissector tables.
+ */
+typedef struct heur_dissector_foreach_table_info {
+ gpointer caller_data;
+ DATFunc_heur_table caller_func;
+} heur_dissector_foreach_table_info_t;
+
+
+static void
+dissector_dump_heur_decodes_display(const gchar *table_name, const gpointer value, const gpointer user_data _U_)
+{
+ heur_dissector_list_t sub_dissectors = *(heur_dissector_list_t *)value;
+ GSList *entry;
+ heur_dtbl_entry_t *hdtbl_entry;
+
+ for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
+ hdtbl_entry = (heur_dtbl_entry_t *)entry->data;
+ if (hdtbl_entry->protocol != NULL) {
+ printf("%s\t%s\t%c\n",
+ table_name,
+ proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol)),
+ (proto_is_protocol_enabled(hdtbl_entry->protocol) && hdtbl_entry->enabled) ? 'T' : 'F');
+ }
+ }
+}
+
+
+static void
+dissector_all_heur_tables_foreach_table_func (gpointer key, const gpointer value, const gpointer user_data)
+{
+ heur_dissector_foreach_table_info_t *info;
+
+ info = user_data;
+ (*info->caller_func)((gchar*)key, value, info->caller_data);
+}
+
+/*
+ * Walk all heuristic dissector tables calling a user supplied function on each
+ * table.
+ */
+void
+dissector_all_heur_tables_foreach_table (DATFunc_heur_table func,
+ gpointer user_data)
+{
+ heur_dissector_foreach_table_info_t info;
+
+ info.caller_data = user_data;
+ info.caller_func = func;
+ g_hash_table_foreach(heur_dissector_lists, dissector_all_heur_tables_foreach_table_func, &info);
+}
+
+/*
+ * For each heuristic dissector table, dump list of dissectors (filter_names) for that table
+ */
+void
+dissector_dump_heur_decodes(void)
+{
+ dissector_all_heur_tables_foreach_table(dissector_dump_heur_decodes_display, NULL);
+}
+
+
void
register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
{
*sub_dissectors = NULL; /* initially empty */
g_hash_table_insert(heur_dissector_lists, (gpointer)name,
- (gpointer) sub_dissectors);
+ (gpointer) sub_dissectors);
}
/*
*/
static GHashTable *registered_dissectors = NULL;
+/* Get the long name of the protocol for a dissector handle, if it has
+ a protocol. */
+const char *
+dissector_handle_get_long_name(const dissector_handle_t handle)
+{
+ if (handle == NULL || handle->protocol == NULL) {
+ return NULL;
+ }
+ return proto_get_protocol_long_name(handle->protocol);
+}
+
/* Get the short name of the protocol for a dissector handle, if it has
a protocol. */
const char *
-dissector_handle_get_short_name(dissector_handle_t handle)
+dissector_handle_get_short_name(const dissector_handle_t handle)
{
if (handle->protocol == NULL) {
/*
/* Get the index of the protocol for a dissector handle, if it has
a protocol. */
int
-dissector_handle_get_protocol_index(dissector_handle_t handle)
+dissector_handle_get_protocol_index(const dissector_handle_t handle)
{
if (handle->protocol == NULL) {
/*
/* Create an anonymous handle for a dissector. */
dissector_handle_t
-create_dissector_handle(dissector_t dissector, int proto)
+create_dissector_handle(dissector_t dissector, const int proto)
{
struct dissector_handle *handle;
- handle = g_malloc(sizeof (struct dissector_handle));
- handle->name = NULL;
- handle->is_new = FALSE;
+ handle = g_malloc(sizeof (struct dissector_handle));
+ handle->name = NULL;
+ handle->is_new = FALSE;
handle->dissector.old = dissector;
- handle->protocol = find_protocol_by_id(proto);
+ handle->protocol = find_protocol_by_id(proto);
return handle;
}
dissector_handle_t
-new_create_dissector_handle(new_dissector_t dissector, int proto)
+new_create_dissector_handle(new_dissector_t dissector, const int proto)
{
struct dissector_handle *handle;
- handle = g_malloc(sizeof (struct dissector_handle));
- handle->name = NULL;
- handle->is_new = TRUE;
+ handle = g_malloc(sizeof (struct dissector_handle));
+ handle->name = NULL;
+ handle->is_new = TRUE;
handle->dissector.new = dissector;
- handle->protocol = find_protocol_by_id(proto);
+ handle->protocol = find_protocol_by_id(proto);
return handle;
}
/* Register a dissector by name. */
void
-register_dissector(const char *name, dissector_t dissector, int proto)
+register_dissector(const char *name, dissector_t dissector, const int proto)
{
struct dissector_handle *handle;
/* Make sure the registration is unique */
g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
- handle = g_malloc(sizeof (struct dissector_handle));
- handle->name = name;
- handle->is_new = FALSE;
+ handle = g_malloc(sizeof (struct dissector_handle));
+ handle->name = name;
+ handle->is_new = FALSE;
handle->dissector.old = dissector;
- handle->protocol = find_protocol_by_id(proto);
+ handle->protocol = find_protocol_by_id(proto);
g_hash_table_insert(registered_dissectors, (gpointer)name,
- (gpointer) handle);
+ (gpointer) handle);
}
void
-new_register_dissector(const char *name, new_dissector_t dissector, int proto)
+new_register_dissector(const char *name, new_dissector_t dissector, const int proto)
{
struct dissector_handle *handle;
/* Make sure the registration is unique */
g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
- handle = g_malloc(sizeof (struct dissector_handle));
- handle->name = name;
- handle->is_new = TRUE;
+ handle = g_malloc(sizeof (struct dissector_handle));
+ handle->name = name;
+ handle->is_new = TRUE;
handle->dissector.new = dissector;
- handle->protocol = find_protocol_by_id(proto);
+ handle->protocol = find_protocol_by_id(proto);
g_hash_table_insert(registered_dissectors, (gpointer)name,
- (gpointer) handle);
+ (gpointer) handle);
+}
+
+/* Call a dissector through a handle but if the dissector rejected it
+ * return 0.
+ */
+int
+call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
+ packet_info *pinfo, proto_tree *tree, void *data)
+{
+ int ret;
+
+ g_assert(handle != NULL);
+ ret = call_dissector_work(handle, tvb, pinfo, tree, TRUE, data);
+ return ret;
}
/* Call a dissector through a handle and if this fails call the "data"
* dissector.
*/
int
-call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
- packet_info *pinfo, proto_tree *tree)
+call_dissector_with_data(dissector_handle_t handle, tvbuff_t *tvb,
+ packet_info *pinfo, proto_tree *tree, void *data)
{
int ret;
- g_assert(handle != NULL);
- ret = call_dissector_work(handle, tvb, pinfo, tree);
+ ret = call_dissector_only(handle, tvb, pinfo, tree, data);
if (ret == 0) {
/*
* The protocol was disabled, or the dissector rejected
* it. Just dissect this packet as data.
*/
- g_assert(data_handle != NULL);
+ g_assert(data_handle != NULL);
g_assert(data_handle->protocol != NULL);
- call_dissector(data_handle, tvb, pinfo, tree);
+ call_dissector_work(data_handle, tvb, pinfo, tree, TRUE, NULL);
return tvb_length(tvb);
}
return ret;
}
-/* Call a dissector through a handle but if the dissector rejected it
- * return 0 instead of using the default "data" dissector.
- */
int
-call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
- packet_info *pinfo, proto_tree *tree)
+call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
+ packet_info *pinfo, proto_tree *tree)
{
- int ret;
-
- ret = call_dissector_work(handle, tvb, pinfo, tree);
- return ret;
+ return call_dissector_with_data(handle, tvb, pinfo, tree, NULL);
}
/*
static void
dissector_dump_decodes_display(const gchar *table_name,
- ftenum_t selector_type _U_, gpointer key, gpointer value,
- gpointer user_data _U_)
+ ftenum_t selector_type _U_, const gpointer key, const gpointer value,
+ gpointer user_data _U_)
{
- guint32 selector = (guint32)(unsigned long) key;
- dissector_table_t sub_dissectors = find_dissector_table(table_name);
- dtbl_entry_t *dtbl_entry;
- dissector_handle_t handle;
- gint proto_id;
- const gchar *decode_as;
+ guint32 selector = (guint32)(unsigned long) key;
+ dissector_table_t sub_dissectors = find_dissector_table(table_name);
+ dtbl_entry_t *dtbl_entry;
+ dissector_handle_t handle;
+ gint proto_id;
+ const gchar *decode_as;
g_assert(sub_dissectors);
switch (sub_dissectors->type) {
dtbl_entry = value;
g_assert(dtbl_entry);
- handle = dtbl_entry->current;
+ handle = dtbl_entry->current;
g_assert(handle);
proto_id = dissector_handle_get_protocol_index(handle);
}
void
-dissector_dump_decodes() {
+dissector_dump_decodes(void)
+{
dissector_all_tables_foreach(dissector_dump_decodes_display, NULL);
}
static GPtrArray* post_dissectors = NULL;
static guint num_of_postdissectors = 0;
-void register_postdissector(dissector_handle_t handle) {
- if (!post_dissectors)
- post_dissectors = g_ptr_array_new();
+void
+register_postdissector(dissector_handle_t handle)
+{
+ if (!post_dissectors)
+ post_dissectors = g_ptr_array_new();
+
+ g_ptr_array_add(post_dissectors, handle);
+ num_of_postdissectors++;
+}
+
+gboolean
+have_postdissector(void)
+{
+ guint i;
+ dissector_handle_t handle;
- g_ptr_array_add(post_dissectors, handle);
- num_of_postdissectors++;
+ for(i = 0; i < num_of_postdissectors; i++) {
+ handle = (dissector_handle_t) g_ptr_array_index(post_dissectors,i);
+
+ if (handle->protocol != NULL
+ && proto_is_protocol_enabled(handle->protocol)) {
+ /* We have at least one enabled postdissector */
+ return TRUE;
+ }
+ }
+ return FALSE;
}
-extern void call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
- guint i;
- for(i=0;i<num_of_postdissectors;i++) {
- call_dissector((dissector_handle_t) g_ptr_array_index(post_dissectors,i),
- tvb,pinfo,tree);
- }
+void
+call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint i;
+
+ for(i = 0; i < num_of_postdissectors; i++) {
+ call_dissector_only((dissector_handle_t) g_ptr_array_index(post_dissectors,i),
+ tvb,pinfo,tree, NULL);
+ }
}
+/*
+ * 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:
+ */