Ethereal-dev: [Ethereal-dev] packet-nfs.c
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: "Pia Sahlberg" <piabar@xxxxxxxxxxx>
Date: Mon, 13 Aug 2001 02:07:11 +0000
Hi list, Resending two files for a neat (IMHO) new feature for NFS filehandles. One is a description of the option/feature to be merged with the manpage and perhaps Richards quite nice users guide. The other is a patch to (mainly) packet-nfs.c to enable etherealto snoop v3LOOKUP packets to learn the mapping between filenames and filehandles. The one can search for a nfs filename and (if learnt) also match all fhandle structures which match that filename.
Comments , please best regards ronnie sahlberg _________________________________________________________________ Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp
nfs filename snooping ===================== [Menu: Edit/Preferences/NFS/snoop fhandle to filename mappings] When enabled, this option will enable ethereal to snoop all LOOKUP packets to learn the mapping between fhandles and filenames. For every fhandle where the corresponding filename is learned an additional item will be displayed in the tree pane : Example: "Filename: foo.txt (snooped from frames 29 and 30)" This entry use the same "nfs.name" display filter variable as the normalnfs filenames which means that applying the display filter "nfs.name=='foo.txt'"
will find both where the filename "foo.txt" was found in a packet as well as all fhandle structures seen which corresponds to that name.This setting also affects the nfs related protocols, NLM and MOUNT, which use
the same fhandle structures as NFS. This feature can only be used in ethereal and is not available in tethereal.By enabling this feature the memory requirement for the ethereal will increase.
Performance can be (but not be noticeably) affected by this feature. BUG: This feature will currently only examine NFSv3:LOOKUP packets. Please expand to other versions of NFS/other commands as required.diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-nfs.c ethereal/packet-nfs.c
--- ethereal-orig/packet-nfs.c Tue Aug 7 08:45:13 2001 +++ ethereal/packet-nfs.c Thu Aug 9 10:37:57 2001 @@ -37,7 +37,7 @@ #include <string.h> - +#include "prefs.h" #include "packet-rpc.h" #include "packet-nfs.h" @@ -350,6 +350,152 @@ static gint ett_nfs_fs_location4 = -1; static gint ett_nfs_open4_result_flags = -1; + +/* + * functions to map fhandle<->filename + */ +static gboolean nfs_fhandle2name_snooping = FALSE; +static GHashTable *lookup_trace_table = NULL; +static GHashTable *fhandle2name_table = NULL; +static GMemChunk *lookup_trace_key_chunk = NULL; +static GMemChunk *lookup_trace_data_chunk = NULL; +static int lookup_trace_init_count = 100; + +typedef struct _lookup_trace_key { + address src; + address dst; + guint32 xid; +} lookup_trace_key; + +typedef struct _fhandle_name { + int request_frame; + int response_frame; + int fhandle_len; + char *fhandle; + int name_len; + char *name; +} fhandle_name; + +static gint +lookup_trace_equal(gconstpointer k1, gconstpointer k2) +{ + lookup_trace_key *key1 = (lookup_trace_key *)k1; + lookup_trace_key *key2 = (lookup_trace_key *)k2; + + return ( ( (ADDRESSES_EQUAL(&key1->src, &key2->src)) && + (ADDRESSES_EQUAL(&key1->dst, &key2->dst)) && + (key1->xid == key2->xid) + ) ? + TRUE : FALSE); +} + +static gint +fhandle2name_equal(gconstpointer k1, gconstpointer k2) +{ + fhandle_name *key1 = (fhandle_name *)k1; + fhandle_name *key2 = (fhandle_name *)k2; + + if(key1->fhandle_len!=key2->fhandle_len){ + return FALSE; + } + + return (!memcmp(key1->fhandle, key2->fhandle, key1->fhandle_len)); +} + +static guint +lookup_trace_hash(gconstpointer k) +{ + lookup_trace_key *key = (lookup_trace_key *)k; + + return key->xid; /* this is probably good enough*/ +} + +static guint +fhandle2name_hash(gconstpointer k) +{ + fhandle_name *key = (fhandle_name *)k; + int hash, i; + + hash=0; + for(i=0;i<key->fhandle_len;i++){ + hash|=key->fhandle[i]; + } + + return hash; +} + +static gboolean +lookup_trace_free_all(gpointer key_arg, gpointer value, gpointer user_data) +{ + lookup_trace_key *key = (lookup_trace_key *)key_arg; + fhandle_name *fhn = (fhandle_name *)value; + + g_free((gpointer)key->src.data); + g_free((gpointer)key->dst.data); + + if(fhn->fhandle){ + g_free(fhn->fhandle); + } + if(fhn->name){ + g_free(fhn->name); + } + + return TRUE; +} + +static gboolean +fhandle2name_free_all(gpointer key_arg, gpointer value, gpointer user_data) +{ + return TRUE; +} + +static void +lookup_trace_table_init(void) +{ + if(lookup_trace_table){ + g_hash_table_foreach_remove(lookup_trace_table, + lookup_trace_free_all, NULL); + } else { + lookup_trace_table = g_hash_table_new(lookup_trace_hash, + lookup_trace_equal); + } + + if(fhandle2name_table){ + g_hash_table_foreach_remove(fhandle2name_table, + fhandle2name_free_all, NULL); + } else { + fhandle2name_table = g_hash_table_new(fhandle2name_hash, + fhandle2name_equal); + } +} + +void +lookup_trace_init(void) +{ + lookup_trace_table_init(); + + if(lookup_trace_key_chunk){ + g_mem_chunk_destroy(lookup_trace_key_chunk); + } + lookup_trace_key_chunk = g_mem_chunk_new("lookup_trace_key_chunk", + sizeof(lookup_trace_key), + lookup_trace_init_count*sizeof(lookup_trace_key), + G_ALLOC_ONLY); + + if(lookup_trace_data_chunk){ + g_mem_chunk_destroy(lookup_trace_data_chunk); + } + lookup_trace_data_chunk = g_mem_chunk_new("lookup_trace_data_chunk", + sizeof(fhandle_name), + lookup_trace_init_count*sizeof(fhandle_name), + G_ALLOC_ONLY); +} + + + + + + /* file handle dissection */ #define FHT_UNKNOWN 0 @@ -1855,6 +2001,48 @@ dissect_filename3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf, char **string_ret) { + + /* is filehandle->filename snooping activated? (only check new frames)*/ + if(nfs_fhandle2name_snooping && (!pinfo->fd->flags.visited)){ + rpc_call_info_value *civ = pinfo->private; + + /* v3 LOOKUP calls will give us a filename */ + if( (civ->vers==3) + &&(civ->proc==3) + &&(civ->call)){ + lookup_trace_key ltk; + fhandle_name *fhn; + + COPY_ADDRESS(<k.src, &pinfo->src); + COPY_ADDRESS(<k.dst, &pinfo->dst); + ltk.xid = civ->xid; + + fhn = g_hash_table_lookup(lookup_trace_table, <k); + if(!fhn){ + /* we havnt seen this call before */ + lookup_trace_key *new_ltk; + fhandle_name *new_fhn; + + new_ltk = g_mem_chunk_alloc(lookup_trace_key_chunk); + COPY_ADDRESS(&new_ltk->src, &pinfo->src); + COPY_ADDRESS(&new_ltk->dst, &pinfo->dst); + new_ltk->xid = civ->xid; + + new_fhn = g_mem_chunk_alloc(lookup_trace_data_chunk); + new_fhn->request_frame=civ->req_num; + new_fhn->response_frame=-1; + new_fhn->name_len=tvb_get_ntohl(tvb, offset); + new_fhn->name=g_malloc(new_fhn->name_len+1); + tvb_memcpy(tvb, new_fhn->name, offset+4, new_fhn->name_len);+ new_fhn->name[new_fhn->name_len]=0; /* make sure it is null-terminated */
+ new_fhn->fhandle_len=0; + new_fhn->fhandle=NULL; + + g_hash_table_insert(lookup_trace_table, new_ltk, new_fhn); + } + } + } + offset = dissect_rpc_string(tvb, pinfo, tree, hf, offset, string_ret); return offset; } @@ -2086,6 +2274,39 @@ guint fh3_fill; proto_item* fitem; proto_tree* ftree = NULL; + fhandle_name *fhn = NULL; + + /* is filehandle->filename snooping activated? (only check new frames)*/ + if(nfs_fhandle2name_snooping && (!pinfo->fd->flags.visited)){ + rpc_call_info_value *civ = pinfo->private; + + /* v3 LOOKUP replies will give us a filehandle */ + if( (civ->vers==3) + &&(civ->proc==3) + &&(!civ->call)){ + + /* ok so we have got a filehandle in this reply packet. + Do we know the matching filename from the call packet? */ + lookup_trace_key ltk; + + /* the reply has src/dst swapped compared to the call*/ + COPY_ADDRESS(<k.src, &pinfo->dst); + COPY_ADDRESS(<k.dst, &pinfo->src); + ltk.xid = civ->xid; + + fhn = g_hash_table_lookup(lookup_trace_table, <k); + if(fhn){ + /* ok we know the filename from the call and + the filehandle from this packet. store it*/ + fhn->response_frame=civ->rep_num; + fhn->fhandle_len=tvb_get_ntohl(tvb, offset); + fhn->fhandle=g_malloc(fhn->fhandle_len); + tvb_memcpy(tvb, fhn->fhandle, offset+4, fhn->fhandle_len); + + g_hash_table_insert(fhandle2name_table, fhn, fhn); + } + } + } fh3_len = tvb_get_ntohl(tvb, offset+0); fh3_len_full = rpc_roundup(fh3_len); @@ -2102,7 +2323,23 @@ proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4, fh3_len); dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len); + + } + + /* is filehandle->filename snooping activated? */ + if(nfs_fhandle2name_snooping){ + if(!fhn){ + static fhandle_name fhn_key; + fhn_key.fhandle_len=tvb_get_ntohl(tvb, offset); + fhn_key.fhandle=g_malloc(fhn_key.fhandle_len); + tvb_memcpy(tvb, fhn_key.fhandle, offset+4, fhn_key.fhandle_len); + fhn = g_hash_table_lookup(fhandle2name_table, &fhn_key); + } + if(fhn){+ proto_tree_add_string_format(ftree, hf_nfs_name, tvb, 0, 0, fhn->name, "Filename: %s (snooped from frames %d and %d)", fhn->name, fhn->request_frame, fhn->response_frame);
+ } } + offset += 4 + fh3_len_full; return offset; } @@ -6723,9 +6960,20 @@ &ett_nfs_fs_location4, &ett_nfs_open4_result_flags }; + module_t *nfs_module; + + proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs"); proto_register_field_array(proto_nfs, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); + + /* register configuration options */ + nfs_module = prefs_register_protocol(proto_nfs, NULL); + prefs_register_bool_preference(nfs_module, "nfs filename snooping", + "fhandle/filename LOOPKUP snooping",+ "This option will snoop LOOKUP calls to map all fhandles to filenames where possible",
+ &nfs_fhandle2name_snooping); + register_init_routine(lookup_trace_init); } voiddiff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-rpc.c ethereal/packet-rpc.c
--- ethereal-orig/packet-rpc.c Tue Aug 7 08:45:14 2001 +++ ethereal/packet-rpc.c Wed Aug 8 09:21:02 2001 @@ -371,18 +371,6 @@ static GMemChunk *rpc_call_info_key_chunk; -typedef struct _rpc_call_info_value { - guint32 req_num; /* frame number of first request seen */ - guint32 rep_num; /* frame number of first reply seen */ - guint32 prog; - guint32 vers; - guint32 proc; - guint32 flavor; - guint32 gss_proc; - guint32 gss_svc; - rpc_proc_info_value* proc_info; -} rpc_call_info_value; - static GMemChunk *rpc_call_info_value_chunk; static GHashTable *rpc_calls; @@ -1417,6 +1405,10 @@ conversation, so it's probably not an RPC reply. */ return FALSE; } + /* pass rpc_info to subdissectors */ + rpc_call->call = FALSE; + pinfo->private = rpc_call; + break; default: @@ -1593,6 +1585,7 @@ rpc_call->prog = prog; rpc_call->vers = vers; rpc_call->proc = proc; + rpc_call->xid = xid; rpc_call->flavor = flavor; rpc_call->gss_proc = gss_proc; rpc_call->gss_svc = gss_svc; @@ -1606,6 +1599,10 @@ offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset); offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type); + + /* pass rpc_info to subdissectors */ + rpc_call->call = TRUE; + pinfo->private = rpc_call; /* go to the next dissector */diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-rpc.h ethereal/packet-rpc.h
--- ethereal-orig/packet-rpc.h Tue Aug 7 08:45:14 2001 +++ ethereal/packet-rpc.h Wed Aug 8 09:21:05 2001 @@ -77,6 +77,20 @@typedef int (old_dissect_function_t)(const u_char* pd, int offset, frame_data* fd, proto_tree* tree); typedef int (dissect_function_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree);
+typedef struct _rpc_call_info_value { + guint32 req_num; /* frame number for first request seen */ + guint32 rep_num; /* frame number for first reply seen */ + guint32 prog; + guint32 vers; + guint32 proc; + guint32 xid; + guint32 flavor; + guint32 gss_proc; + guint32 gss_svc; + struct _rpc_proc_info_value *proc_info; + gboolean call; +} rpc_call_info_value; + typedef struct _old_vsff { guint32 value; gchar *strptr;
- Follow-Ups:
- [Ethereal-dev] Re: packet-nfs.c
- From: Mike Frisch
- Re: [Ethereal-dev] packet-nfs.c
- From: Guy Harris
- [Ethereal-dev] Re: packet-nfs.c
- Prev by Date: Re: [Ethereal-dev] Unicode strings ...
- Next by Date: [Ethereal-dev] Re: packet-nfs.c
- Previous by thread: [Ethereal-dev] Consequence of adding FT_UCS2_LE?
- Next by thread: [Ethereal-dev] Re: packet-nfs.c
- Index(es):