aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>2006-06-21 09:45:50 +0000
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>2006-06-21 09:45:50 +0000
commit4750a2c08ee8d80752ff5dcadfa60ca34481488e (patch)
tree75c91ba94b0d48659fc1c96b74c5c564aa183ee7
parent92cc0ff6286056305f200863db5592c019f14a85 (diff)
two things have irritated me immensly with nfs filehandles
1, (minor) the heuristics are too weak and everyting is always decoded either as netapp filehandles or one of the others even when just capturing ibetween say two classic unix boxens 2, (major) you can not filter on specific subfields of the filehandle observation: 5 people or less in the world care about implementation specific storage of data inside an opaque blob. remove the too weak heuristics for nfs filehandles. make decoding of filehandles accorrding to specific implementations controlled by a preference setting. default this setting to "unknown" display unknown filehandles using proto_tree_add_item() FT_BYTES/BASE_HEX to make it fitlerable instead of a useless proto_tree_add_text() wiki needs to be updated tomorrow git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@18530 f5534014-38df-0310-8fa8-9805f1628bb7
-rw-r--r--epan/dissectors/packet-nfs.c240
-rw-r--r--epan/dissectors/packet-nfs.h2
2 files changed, 93 insertions, 149 deletions
diff --git a/epan/dissectors/packet-nfs.c b/epan/dissectors/packet-nfs.c
index ee073f265d..89d0b23bb5 100644
--- a/epan/dissectors/packet-nfs.c
+++ b/epan/dissectors/packet-nfs.c
@@ -37,6 +37,7 @@
#include "packet-rpc.h"
#include "packet-nfs.h"
#include <epan/prefs.h>
+#include <epan/packet.h>
#include <epan/emem.h>
static int proto_nfs = -1;
@@ -46,6 +47,7 @@ static int hf_nfs_procedure_v3 = -1;
static int hf_nfs_procedure_v4 = -1;
static int hf_nfs_fh_length = -1;
static int hf_nfs_fh_hash = -1;
+static int hf_nfs_fh_fhandle_data = -1;
static int hf_nfs_fh_mount_fileid = -1;
static int hf_nfs_fh_mount_generation = -1;
static int hf_nfs_fh_snapid = -1;
@@ -410,6 +412,27 @@ static gint ett_nfs_clientaddr4 = -1;
static gint ett_nfs_aceflag4 = -1;
static gint ett_nfs_acemask4 = -1;
+/* what type of fhandles shoudl we dissect as */
+static dissector_table_t nfs_fhandle_table;
+
+
+#define FHT_UNKNOWN 0
+#define FHT_SVR4 1
+#define FHT_LINUX_KNFSD_LE 2
+#define FHT_LINUX_NFSD_LE 3
+#define FHT_LINUX_KNFSD_NEW 4
+#define FHT_NETAPP 5
+static enum_val_t nfs_fhandle_types[] = {
+ { "unknown", "Unknown", FHT_UNKNOWN },
+ { "svr4", "SVR4", FHT_SVR4 },
+ { "knfsd_le", "KNFSD_LE", FHT_LINUX_KNFSD_LE },
+ { "nfsd_le", "NFSD_LE", FHT_LINUX_NFSD_LE },
+ { "knfsd_new", "KNFSD_NEW", FHT_LINUX_KNFSD_NEW },
+ { "netapp", "NetApp", FHT_NETAPP },
+ { NULL, NULL, 0 }
+};
+/* decode all nfs filehandles as this type */
+gint default_nfs_fhandle_type=FHT_UNKNOWN;
/* For dissector helpers which take a "levels" argument to indicate how
* many expansions up they should populate the expansion items with
@@ -476,7 +499,7 @@ store_nfs_file_handle(nfs_fhandle_data_t *nfs_fh)
fhkey[0].length=1;
fhkey[0].key=&fhlen;
fhkey[1].length=fhlen;
- fhkey[1].key=nfs_fh->fh;
+ fhkey[1].key=(guint32 *)nfs_fh->fh;
fhkey[2].length=0;
new_nfs_fh=se_tree_lookup32_array(nfs_file_handles, &fhkey[0]);
@@ -493,7 +516,7 @@ store_nfs_file_handle(nfs_fhandle_data_t *nfs_fh)
fhkey[0].length=1;
fhkey[0].key=&fhlen;
fhkey[1].length=fhlen;
- fhkey[1].key=nfs_fh->fh;
+ fhkey[1].key=(guint32 *)nfs_fh->fh;
fhkey[2].length=0;
se_tree_insert32_array(nfs_file_handles, &fhkey[0], new_nfs_fh);
@@ -755,7 +778,7 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
fhkey[0].length=1;
fhkey[0].key=&fhlen;
fhkey[1].length=fhlen/4;
- fhkey[1].key=nns->fh;
+ fhkey[1].key=(guint32 *)nns->fh;
fhkey[2].length=0;
se_tree_insert32_array(nfs_name_snoop_known, &fhkey[0], nns);
@@ -781,7 +804,7 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
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[1].key=(guint32 *)tvb_get_ptr(tvb, fh_offset, fh_length);
fhkey[2].length=0;
nns=se_tree_lookup32_array(nfs_name_snoop_known, &fhkey[0]);
@@ -815,13 +838,6 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
/* file handle dissection */
-#define FHT_UNKNOWN 0
-#define FHT_SVR4 1
-#define FHT_LINUX_KNFSD_LE 2
-#define FHT_LINUX_NFSD_LE 3
-#define FHT_LINUX_KNFSD_NEW 4
-#define FHT_NETAPP 5
-
static const value_string names_fhtype[] =
{
{ FHT_UNKNOWN, "unknown" },
@@ -837,10 +853,9 @@ static const value_string names_fhtype[] =
/* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45) */
static void
-dissect_fhandle_data_SVR4(tvbuff_t* tvb, int offset, proto_tree *tree,
- int fhlen _U_)
+dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
{
- guint32 nof = offset;
+ guint32 nof=0;
/* file system id */
{
@@ -988,9 +1003,9 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, int offset, proto_tree *tree,
/* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
static void
-dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
- int fhlen _U_)
+dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
{
+ int offset=0;
guint32 dentry;
guint32 inode;
guint32 dirinode;
@@ -1069,9 +1084,10 @@ dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
/* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
static void
-dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
- int fhlen _U_)
+dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
{
+ int offset=0;
+
/* pseudo inode */
{
guint32 pinode;
@@ -1139,9 +1155,10 @@ static const value_string fileid_type_names[] = {
};
static void
-dissect_fhandle_data_NETAPP(tvbuff_t* tvb, int offset, proto_tree *tree,
- int fhlen _U_)
+dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
{
+ int offset=0;
+
if (tree) {
guint32 mount = tvb_get_letohl(tvb, offset + 0);
guint32 mount_gen = tvb_get_letohl(tvb, offset + 4);
@@ -1203,9 +1220,9 @@ dissect_fhandle_data_NETAPP(tvbuff_t* tvb, int offset, proto_tree *tree,
}
static void
-dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, int offset, proto_tree *tree,
- int fhlen _U_)
+dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
{
+ int offset=0;
guint8 version;
guint8 auth_type;
guint8 fsid_type;
@@ -1374,28 +1391,11 @@ out:
static void
-dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree,
- guint fhlen)
+dissect_fhandle_data_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
{
- guint sublen;
- guint bytes_left;
- gboolean first_line;
+ guint fhlen=tvb_length(tvb);
- bytes_left = fhlen;
- first_line = TRUE;
- while (bytes_left != 0) {
- sublen = 16;
- if (sublen > bytes_left)
- sublen = bytes_left;
- proto_tree_add_text(tree, tvb, offset, sublen,
- "%s%s",
- first_line ? "data: " :
- " ",
- tvb_bytes_to_str(tvb,offset,sublen));
- bytes_left -= sublen;
- offset += sublen;
- first_line = FALSE;
- }
+ proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, -1, FALSE);
}
@@ -1403,14 +1403,6 @@ static void
dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, unsigned int fhlen, gboolean hidden, guint32 *hash)
{
- unsigned int fhtype = FHT_UNKNOWN;
-
- /* filehandle too long */
- if (fhlen>64) goto type_ready;
- /* Not all bytes there. Any attempt to deduce the type would be
- senseless. */
- if (!tvb_bytes_exist(tvb,offset,fhlen)) goto type_ready;
-
/* this is to set up fhandle display filters to find both packets
of an RPC call */
if(nfs_fhandle_reqrep_matching && (!hidden) ){
@@ -1464,109 +1456,20 @@ dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
}
if(!hidden){
- /* calculate (heuristically) fhtype */
- switch (fhlen) {
- case 12:
- if (tvb_get_ntohl(tvb,offset) == 0x01000000) {
- fhtype=FHT_LINUX_KNFSD_NEW;
- }
- break;
- case 20:
- if (tvb_get_ntohl(tvb,offset) == 0x01000001) {
- fhtype=FHT_LINUX_KNFSD_NEW;
- }
- break;
- case 24:
- if (tvb_get_ntohl(tvb,offset) == 0x01000002) {
- fhtype=FHT_LINUX_KNFSD_NEW;
- }
- break;
- case 32: {
- guint32 len1;
- guint32 len2;
- if (tvb_get_ntohs(tvb,offset+4) == 0) {
- len1=tvb_get_ntohs(tvb,offset+8);
- if (tvb_bytes_exist(tvb,offset+10+len1,2)) {
- len2=tvb_get_ntohs(tvb,
- offset+10+len1);
- if (fhlen==12+len1+len2) {
- fhtype=FHT_SVR4;
- goto type_ready;
- }
- }
- }
- /* For a NetApp filehandle, the flag bits must
- include WAFL_FH_MULTIVOLUME, and the fileid
- and generation number need to be nonzero in
- the mount point, file, and export. */
- if ((tvb_get_ntohl(tvb,offset+8) & 0x20000000)
- && tvb_get_ntohl(tvb,offset+0)
- && tvb_get_ntohl(tvb,offset+4)
- && tvb_get_ntohl(tvb,offset+12)
- && tvb_get_ntohl(tvb,offset+16)
- && tvb_get_ntohl(tvb,offset+24)
- && tvb_get_ntohl(tvb,offset+28)) {
- fhtype=FHT_NETAPP;
- goto type_ready;
- }
- len1 = tvb_get_guint8(tvb,offset+4);
- if (len1<28 && tvb_bytes_exist(tvb,offset+5,len1)) {
- int wrong=0;
- for (len2=5+len1;len2<32;len2++) {
- if (tvb_get_guint8(tvb,offset+len2)) {
- wrong=1;
- break;
- }
- }
- if (!wrong) {
- fhtype=FHT_LINUX_NFSD_LE;
- goto type_ready;
- }
- }
- if (tvb_get_ntohl(tvb,offset+28) == 0) {
- if (tvb_get_ntohs(tvb,offset+14) == 0) {
- if (tvb_get_ntohs(tvb,offset+18) == 0) {
- fhtype=FHT_LINUX_KNFSD_LE;
- goto type_ready;
- }
- }
- }
- } break;
- }
- }
+ tvbuff_t *fh_tvb;
+ int real_length;
-type_ready:
-
- if(!hidden){
proto_tree_add_text(tree, tvb, offset, 0,
- "type: %s", val_to_str(fhtype, names_fhtype, "Unknown"));
+ "decode type as: %s", val_to_str(default_nfs_fhandle_type, names_fhtype, "Unknown"));
- switch (fhtype) {
- case FHT_SVR4:
- dissect_fhandle_data_SVR4 (tvb, offset, tree,
- fhlen);
- break;
- case FHT_LINUX_KNFSD_LE:
- dissect_fhandle_data_LINUX_KNFSD_LE(tvb, offset, tree,
- fhlen);
- break;
- case FHT_LINUX_NFSD_LE:
- dissect_fhandle_data_LINUX_NFSD_LE (tvb, offset, tree,
- fhlen);
- break;
- case FHT_LINUX_KNFSD_NEW:
- dissect_fhandle_data_LINUX_KNFSD_NEW (tvb, offset, tree,
- fhlen);
- break;
- case FHT_NETAPP:
- dissect_fhandle_data_NETAPP (tvb, offset, tree,
- fhlen);
- break;
- case FHT_UNKNOWN:
- default:
- dissect_fhandle_data_unknown(tvb, offset, tree, fhlen);
- break;
+ real_length=fhlen;
+ if(real_length<tvb_length_remaining(tvb, offset)){
+ real_length=tvb_length_remaining(tvb, offset);
+ }
+ fh_tvb=tvb_new_subset(tvb, offset, real_length, fhlen);
+ if(!dissector_try_port(nfs_fhandle_table, default_nfs_fhandle_type, fh_tvb, pinfo, tree)){
+ dissect_fhandle_data_unknown(fh_tvb, pinfo, tree);
}
}
}
@@ -8718,6 +8621,10 @@ proto_register_nfs(void)
"r_addr", "nfs.r_addr", FT_BYTES, BASE_DEC, NULL, 0,
"r_addr", HFILL }},
+ { &hf_nfs_fh_fhandle_data, {
+ "filehandle", "nfs.fhandle", FT_BYTES, BASE_HEX, NULL, 0,
+ "Opaque nfs filehandle", HFILL }},
+
{ &hf_nfs_secinfo_arr4, {
"Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
NULL, 0, "Flavors Info", HFILL }},
@@ -8854,19 +8761,54 @@ 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_fhandle_table = register_dissector_table("nfs_fhandle.type",
+ "NFS Filehandle types", FT_UINT8, BASE_HEX);
+
+ prefs_register_enum_preference(nfs_module,
+ "default_fhandle_type",
+ "Decode nfs fhandles as",
+ "Decode all NFS file handles as if they are of this type",
+ &default_nfs_fhandle_type,
+ nfs_fhandle_types,
+ FALSE);
+
nfs_name_snoop_known=se_tree_create(SE_TREE_TYPE_RED_BLACK, "nfs_name_snoop_known");
nfs_file_handles=se_tree_create(SE_TREE_TYPE_RED_BLACK, "nfs_file_handles");
nfs_fhandle_frame_table=se_tree_create(SE_TREE_TYPE_RED_BLACK, "nfs_fhandle_frame_table");
register_init_routine(nfs_name_snoop_init);
+
}
void
proto_reg_handoff_nfs(void)
{
+ dissector_handle_t fhandle_handle;
+
/* Register the protocol as RPC */
rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
/* Register the procedure tables */
rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs_procedure_v2);
rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs_procedure_v3);
rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs_procedure_v4);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_SVR4, fhandle_handle);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_LINUX_KNFSD_LE, fhandle_handle);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_LINUX_NFSD_LE, fhandle_handle);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_LINUX_KNFSD_NEW, fhandle_handle);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_NETAPP, fhandle_handle);
+
+ fhandle_handle=create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs);
+ dissector_add("nfs_fhandle.type", FHT_UNKNOWN, fhandle_handle);
+
+
}
+
diff --git a/epan/dissectors/packet-nfs.h b/epan/dissectors/packet-nfs.h
index f0da25b053..a97827ef7f 100644
--- a/epan/dissectors/packet-nfs.h
+++ b/epan/dissectors/packet-nfs.h
@@ -127,5 +127,7 @@ extern int dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree,
extern int dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
const char* name);
+extern gint default_nfs_fhandle_type;
+
#endif /* packet-nfs.h */