aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-nfs.c42
-rw-r--r--epan/emem.c68
-rw-r--r--epan/emem.h67
3 files changed, 156 insertions, 21 deletions
diff --git a/epan/dissectors/packet-nfs.c b/epan/dissectors/packet-nfs.c
index 17702998e7..27a454243a 100644
--- a/epan/dissectors/packet-nfs.c
+++ b/epan/dissectors/packet-nfs.c
@@ -521,7 +521,7 @@ static GHashTable *nfs_name_snoop_unmatched = NULL;
static GHashTable *nfs_name_snoop_matched = NULL;
-static GHashTable *nfs_name_snoop_known = NULL;
+static se_tree_t *nfs_name_snoop_known = NULL;
static gint
nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
@@ -608,15 +608,6 @@ nfs_name_snoop_init(void)
nfs_name_snoop_matched=g_hash_table_new(nfs_name_snoop_matched_hash,
nfs_name_snoop_matched_equal);
}
- if (nfs_name_snoop_known != NULL) {
- g_hash_table_foreach_remove(nfs_name_snoop_known,
- nfs_name_snoop_unmatched_free_all, NULL);
- } else {
- /* The fragment table does not exist. Create it */
- nfs_name_snoop_known=g_hash_table_new(nfs_name_snoop_matched_hash,
- nfs_name_snoop_matched_equal);
- }
-
}
void
@@ -780,12 +771,16 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
if(nns){
- nfs_name_snoop_key_t *k;
- k=se_alloc(sizeof(nfs_name_snoop_key_t));
- k->key=pinfo->fd->num;
- k->fh_length=nns->fh_length;
- k->fh=nns->fh;
- g_hash_table_insert(nfs_name_snoop_known, k, nns);
+ guint32 fhlen;
+ se_tree_key_t fhkey[3];
+
+ fhlen=nns->fh_length;
+ fhkey[0].length=1;
+ fhkey[0].key=&fhlen;
+ fhkey[1].length=fhlen/4;
+ fhkey[1].key=nns->fh;
+ fhkey[2].length=0;
+ se_tree_insert32_array(nfs_name_snoop_known, &fhkey[0], nns);
if(nfs_file_name_full_snooping){
unsigned char *name=NULL, *pos=NULL;
@@ -802,11 +797,17 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
/* see if we know this mapping */
if(!nns){
- key.key=pinfo->fd->num;
- key.fh_length=fh_length;
- key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
+ guint32 fhlen;
+ se_tree_key_t fhkey[3];
- nns=g_hash_table_lookup(nfs_name_snoop_known, &key);
+ fhlen=fh_length;
+ fhkey[0].length=1;
+ fhkey[0].key=&fhlen;
+ fhkey[1].length=fhlen/4;
+ fhkey[1].key=tvb_get_ptr(tvb, fh_offset, fh_length);
+ fhkey[2].length=0;
+
+ nns=se_tree_lookup32_array(nfs_name_snoop_known, &fhkey[0]);
}
/* if we know the mapping, print the filename */
@@ -8826,6 +8827,7 @@ proto_register_nfs(void)
"Fhandle filters finds both request/response",
"With this option display filters for nfs fhandles (nfs.fh.{name|full_name|hash}) will find both the request and response packets for a RPC call, even if the actual fhandle is only present in one of the packets",
&nfs_fhandle_reqrep_matching);
+ nfs_name_snoop_known=se_tree_create(SE_TREE_TYPE_RED_BLACK);
register_init_routine(nfs_name_snoop_init);
register_init_routine(nfs_fhandle_reqrep_matching_init);
}
diff --git a/epan/emem.c b/epan/emem.c
index 09432ccff5..6242fb149e 100644
--- a/epan/emem.c
+++ b/epan/emem.c
@@ -718,7 +718,6 @@ void* ep_stack_pop(ep_stack_t stack) {
/* routines to manage se allocated red-black trees */
se_tree_t *se_trees=NULL;
-/* keylen is length of key in number of guint32 fields */
se_tree_t *
se_tree_create(int type)
{
@@ -1030,3 +1029,70 @@ se_tree_insert32(se_tree_t *se_tree, guint32 key, void *data)
}
+/* When the se data is released, this entire tree will dissapear as if it
+ * never existed including all metadata associated with the tree.
+ */
+se_tree_t *
+se_tree_create_non_persistent(int type)
+{
+ se_tree_t *tree_list;
+
+ tree_list=se_alloc(sizeof(se_tree_t));
+ tree_list->next=NULL;
+ tree_list->type=type;
+ tree_list->tree=NULL;
+
+ return tree_list;
+}
+
+/* insert a new node in the tree. if this node matches an already existing node
+ * then just replace the data for that node */
+void
+se_tree_insert32_array(se_tree_t *se_tree, se_tree_key_t *key, void *data)
+{
+ se_tree_t *next_tree;
+
+ if((key[0].length<1)||(key[0].length>100)){
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ if((key[0].length==1)&&(key[1].length==0)){
+ se_tree_insert32(se_tree, *key[0].key, data);
+ return;
+ }
+ next_tree=se_tree_lookup32(se_tree, *key[0].key);
+ if(!next_tree){
+ next_tree=se_tree_create_non_persistent(se_tree->type);
+ se_tree_insert32(se_tree, *key[0].key, next_tree);
+ }
+ if(key[0].length==1){
+ key++;
+ } else {
+ key[0].length--;
+ key[0].key++;
+ }
+ se_tree_insert32_array(next_tree, key, data);
+}
+
+void *
+se_tree_lookup32_array(se_tree_t *se_tree, se_tree_key_t *key)
+{
+ se_tree_t *next_tree;
+
+ if((key[0].length<1)||(key[0].length>100)){
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ if((key[0].length==1)&&(key[1].length==0)){
+ return se_tree_lookup32(se_tree, *key[0].key);
+ }
+ next_tree=se_tree_lookup32(se_tree, *key[0].key);
+ if(!next_tree){
+ return NULL;
+ }
+ if(key[0].length==1){
+ key++;
+ } else {
+ key[0].length--;
+ key[0].key++;
+ }
+ se_tree_lookup32_array(next_tree, key);
+}
diff --git a/epan/emem.h b/epan/emem.h
index e4b8f5e000..d09ea557d3 100644
--- a/epan/emem.h
+++ b/epan/emem.h
@@ -190,8 +190,75 @@ typedef struct _se_tree_t {
} se_tree_t;
extern se_tree_t *se_trees;
+
+/* This function is used to create a se based tree with monitoring.
+ * When the SE heap is released back to the system the pointer to the
+ * tree is automatically reset to NULL.
+ *
+ * type is : SE_TREE_TYPE_RED_BLACK for a standard red/black tree.
+ */
se_tree_t *se_tree_create(int type);
+
+/* This function is used to insert a node indexed by a guint32 key value.
+ * The data pointer should be allocated by SE allocators so that the
+ * data will be released at the same time as the tree itself is destroyed.
+ */
void se_tree_insert32(se_tree_t *se_tree, guint32 key, void *data);
+
+/* This function will look up a node in the tree indexed by a guint32 integer
+ * value.
+ */
void *se_tree_lookup32(se_tree_t *se_tree, guint32 key);
+
+/* This function is similar to the se_tree_create() call but with the
+ * difference that when the se memory is release everything including the
+ * pointer to the tree itself will be released.
+ * This tree will not be just reset to zero it will be completely forgotten
+ * by the allocator.
+ * Use this function for when you want to store the pointer to a tree inside
+ * another structure that is also se allocated so that when the structure is
+ * released, the tree will be completely released as well.
+ */
+se_tree_t *se_tree_create_non_persistent(int type);
+
+typedef struct _se_tree_key_t {
+ guint32 length; /*length in guint32 words */
+ guint32 *key;
+} se_tree_key_t;
+
+/* This function is used to insert a node indexed by a sequence of guint32
+ * key values.
+ * The data pointer should be allocated by SE allocators so that the
+ * data will be released at the same time as the tree itself is destroyed.
+ *
+ * If you use ...32_array() calls you MUST make sure that every single node
+ * you add to a specific tree always has a key of exactly the same number of
+ * keylen words or things will most likely crash. Or at least that every single
+ * item that sits behind the same top level node always have exactly the same
+ * number of words.
+ *
+ * One way to guarantee this is the way that NFS does this for the
+ * nfs_name_snoop_known tree which holds filehandles for both v2 and v3.
+ * v2 filehandles are always 32 bytes (8 words) while v3 filehandles can have
+ * any length (though 32bytes are most common).
+ * The NFS dissector handles this by providing a guint32 containing the length
+ * as the very first item in this vector :
+ *
+ * se_tree_key_t fhkey[3];
+ *
+ * fhlen=nns->fh_length;
+ * fhkey[0].length=1;
+ * fhkey[0].key=&fhlen;
+ * fhkey[1].length=fhlen/4;
+ * fhkey[1].key=nns->fh;
+ * fhkey[2].length=0;
+ */
+void se_tree_insert32_array(se_tree_t *se_tree, se_tree_key_t *key, void *data);
+
+/* This function will look up a node in the tree indexed by a sequence of
+ * guint32 integer values.
+ */
+void *se_tree_lookup32_array(se_tree_t *se_tree, se_tree_key_t *key);
+
#endif /* emem.h */