diff options
-rw-r--r-- | epan/dissectors/packet-nfs.c | 42 | ||||
-rw-r--r-- | epan/emem.c | 68 | ||||
-rw-r--r-- | epan/emem.h | 67 |
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 */ |