From e542b9cafe2404f06410f4f84111e64d55a858bc Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Sun, 15 Feb 2009 13:43:57 +0000 Subject: [PATCH] NFSv4.1: Add support for backchannel decoding --- wireshark-1.1.2-nfs41-backchnl-decode.patch | 455 ++++++++++++++++++++ wireshark.spec | 7 +- 2 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 wireshark-1.1.2-nfs41-backchnl-decode.patch diff --git a/wireshark-1.1.2-nfs41-backchnl-decode.patch b/wireshark-1.1.2-nfs41-backchnl-decode.patch new file mode 100644 index 0000000..119a7e5 --- /dev/null +++ b/wireshark-1.1.2-nfs41-backchnl-decode.patch @@ -0,0 +1,455 @@ +diff -up wireshark-1.1.2/epan/dissectors/packet-nfs.c.orig wireshark-1.1.2/epan/dissectors/packet-nfs.c +--- wireshark-1.1.2/epan/dissectors/packet-nfs.c.orig 2009-02-15 08:22:57.000000000 -0500 ++++ wireshark-1.1.2/epan/dissectors/packet-nfs.c 2009-02-15 08:31:28.000000000 -0500 +@@ -652,6 +652,8 @@ static emem_tree_t *nfs_file_handles = N + + static int dissect_nfs_stateid4(tvbuff_t *tvb, int offset, proto_tree *tree); + ++static void reg_callback(int cbprog); ++ + /* This function will store one nfs filehandle in our global tree of + * filehandles. + * We store all filehandles we see in this tree so that every unique +@@ -8648,6 +8650,7 @@ dissect_nfs_argop4(tvbuff_t *tvb, int of + proto_item *fitem; + proto_tree *ftree = NULL; + proto_tree *newftree = NULL; ++ int cbprog; + + ops = tvb_get_ntohl(tvb, offset+0); + +@@ -8969,6 +8972,8 @@ dissect_nfs_argop4(tvbuff_t *tvb, int of + hf_nfs_create_session_flags4, offset); + offset = dissect_rpc_chanattrs4(tvb, offset, newftree); + offset = dissect_rpc_chanattrs4(tvb, offset, newftree); ++ cbprog = tvb_get_ntohl(tvb, offset); ++ reg_callback(cbprog); + offset = dissect_rpc_uint32(tvb, newftree, + hf_nfs_cb_program, offset); + offset = dissect_rpc_secparms4(tvb, offset, newftree); +@@ -9612,6 +9617,313 @@ static const value_string layoutreturn_n + { 0, NULL } + }; + ++static const value_string layoutrecall_names[] = { ++ { 1, "RECALL_FILE"}, ++ { 2, "RECALL_FSID"}, ++ { 3, "RECALL_ALL"}, ++ { 0, NULL } ++}; ++ ++/* NFS Callback */ ++static int hf_nfs_cb_procedure = -1; ++static int hf_nfs_cb_argop = -1; ++static int hf_nfs_cb_resop = -1; ++static int hf_nfs_cb_truncate = -1; ++static int hf_nfs_cb_layoutrecall_type = -1; ++static int hf_nfs_cb_clorachanged = -1; ++ ++static gint ett_nfs_cb_argop = -1; ++static gint ett_nfs_cb_resop = -1; ++static gint ett_nfs_cb_getattr = -1; ++static gint ett_nfs_cb_recall = -1; ++static gint ett_nfs_cb_layoutrecall = -1; ++static gint ett_nfs_cb_pushdeleg = -1; ++static gint ett_nfs_cb_recallany = -1; ++static gint ett_nfs_cb_recallableobjavail = -1; ++static gint ett_nfs_cb_recallslot = -1; ++static gint ett_nfs_cb_sequence = -1; ++static gint ett_nfs_cb_wantscancelled = -1; ++static gint ett_nfs_cb_notifylock = -1; ++static gint ett_nfs_cb_notifydeviceid = -1; ++static gint ett_nfs_cb_notify = -1; ++static gint ett_nfs_cb_illegal = -1; ++ ++static const value_string names_nfs_cb_operation[] = { ++ { NFS4_OP_CB_GETATTR, "CB_GETATTR" }, ++ { NFS4_OP_CB_RECALL, "CB_RECALL" }, ++ { NFS4_OP_CB_LAYOUTRECALL, "CB_LAYOUTRECALL" }, ++ { NFS4_OP_CB_NOTIFY, "CB_NOTIFY" }, ++ { NFS4_OP_CB_PUSH_DELEG, "CB_PUSH_DELEG" }, ++ { NFS4_OP_CB_RECALL_ANY, "CB_RECALL_ANY" }, ++ { NFS4_OP_CB_RECALLABLE_OBJ_AVAIL, "CB_RECALLABLE_OBJ_AVAIL" }, ++ { NFS4_OP_CB_RECALL_SLOT, "CB_RECALL_SLOT"}, ++ { NFS4_OP_CB_SEQUENCE, "CB_SEQUENCE" }, ++ { NFS4_OP_CB_WANTS_CANCELLED, "CB_WANTS_CANCELLED" }, ++ { NFS4_OP_CB_NOTIFY_LOCK, "CB_NOTIFY_LOCK"}, ++ { NFS4_OP_CB_NOTIFY_DEVICEID, "CB_NOTIFY_DEVICEID" }, ++ { NFS4_OP_CB_ILLEGAL, "CB_ILLEGAL"}, ++ { 0, NULL } ++}; ++ ++gint *nfs_cb_operation_ett[] = ++{ ++ &ett_nfs_cb_getattr, ++ &ett_nfs_cb_recall, ++ &ett_nfs_cb_layoutrecall, ++ &ett_nfs_cb_notify, ++ &ett_nfs_cb_pushdeleg, ++ &ett_nfs_cb_recallany, ++ &ett_nfs_cb_recallableobjavail, ++ &ett_nfs_cb_recallslot, ++ &ett_nfs_cb_sequence, ++ &ett_nfs_cb_wantscancelled, ++ &ett_nfs_cb_notifylock, ++ &ett_nfs_cb_notifydeviceid, ++ &ett_nfs_cb_illegal ++}; ++ ++static int ++dissect_nfs_cb_layoutrecall(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo) ++{ ++ guint recalltype = hf_nfs_layouttype4; ++ ++ if (recalltype == 1) { /* RETURN_FILE */ ++ offset = dissect_nfs_fh4(tvb, offset, pinfo, tree, "filehandle"); ++ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset); ++ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset); ++ offset = dissect_nfs_stateid4(tvb, offset, tree); ++ } else if (recalltype == 2) { /* RETURN_FSID */ ++ offset = dissect_nfs_fsid4(tvb, offset, tree, "fsid"); ++ } ++ ++ return offset; ++} ++ ++static int ++dissect_nfs_cb_argop(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) ++{ ++ guint32 ops, ops_counter; ++ guint opcode; ++ proto_item *fitem; ++ proto_tree *ftree = NULL; ++ proto_tree *newftree = NULL; ++ ++ ops = tvb_get_ntohl(tvb, offset+0); ++ ++ fitem = proto_tree_add_text(tree, tvb, offset, 4, "Operations (count: %u)", ops); ++ offset += 4; ++ ++ if (fitem) ++ ftree = proto_item_add_subtree(fitem, ett_nfs_cb_argop); ++ ++ for (ops_counter=0; ops_countercinfo, COL_INFO)) ++ col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s", ops_counter==0?' ':';', ++ val_to_str(opcode, names_nfs_cb_operation, "Unknown")); ++ ++ fitem = proto_tree_add_uint(ftree, hf_nfs_cb_argop, tvb, offset, 4, opcode); ++ offset += 4; ++ ++ /* the opcodes are not contiguous */ ++ if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) && ++ (opcode != NFS4_OP_CB_ILLEGAL)) ++ break; ++ ++ /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */ ++ if (opcode == NFS4_OP_CB_ILLEGAL) ++ newftree = proto_item_add_subtree(fitem, ett_nfs_cb_illegal); ++ else if (nfs_cb_operation_ett[opcode - 3]) ++ newftree = proto_item_add_subtree(fitem, *nfs_cb_operation_ett[opcode - 3]); ++ else ++ break; ++ ++ switch (opcode) ++ { ++ case NFS4_OP_CB_RECALL: ++ offset = dissect_nfs_stateid4(tvb, offset, newftree); ++ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cb_truncate, offset); ++ offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle"); ++ break; ++ case NFS4_OP_CB_GETATTR: ++ case NFS4_OP_CB_LAYOUTRECALL: ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_iomode4, offset); ++ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cb_clorachanged, offset); ++ offset = dissect_nfs_cb_layoutrecall(tvb, offset, newftree, pinfo); ++ break; ++ case NFS4_OP_CB_NOTIFY: ++ case NFS4_OP_CB_PUSH_DELEG: ++ case NFS4_OP_CB_RECALL_ANY: ++ case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL: ++ case NFS4_OP_CB_RECALL_SLOT: ++ break; ++ case NFS4_OP_CB_SEQUENCE: ++ offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL, hf_nfs_sessionid4, ++ TRUE, 16, FALSE, NULL, NULL); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset); ++ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cachethis4, offset); ++ /* skip refs -- assume 0 */ ++ offset = offset + 4; ++ break; ++ case NFS4_OP_CB_WANTS_CANCELLED: ++ case NFS4_OP_CB_NOTIFY_LOCK: ++ case NFS4_OP_CB_NOTIFY_DEVICEID: ++ break; ++ case NFS4_OP_ILLEGAL: ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return offset; ++} ++ ++static int ++dissect_nfs_cb_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree) ++{ ++ char *tag=NULL; ++ ++ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag); ++ ++ if (check_col(pinfo->cinfo, COL_INFO)) ++ col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag); ++ ++ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_minorversion, offset); ++ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_callback_ident, offset); ++ offset = dissect_nfs_cb_argop(tvb, offset, pinfo, tree); ++ ++ return offset; ++} ++ ++static int ++dissect_nfs_cb_resop(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) ++{ ++ guint32 ops, ops_counter; ++ guint32 opcode; ++ proto_item *fitem; ++ proto_tree *ftree = NULL; ++ proto_tree *newftree = NULL; ++ guint32 status; ++ ++ ops = tvb_get_ntohl(tvb, offset+0); ++ fitem = proto_tree_add_text(tree, tvb, offset, 4, "Operations (count: %u)", ops); ++ offset += 4; ++ ++ if (fitem) ++ ftree = proto_item_add_subtree(fitem, ett_nfs_cb_resop); ++ ++ for (ops_counter = 0; ops_counter < ops; ops_counter++) ++ { ++ opcode = tvb_get_ntohl(tvb, offset); ++ ++ /* sanity check for bogus packets */ ++ if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) && ++ (opcode != NFS4_OP_ILLEGAL)) ++ break; ++ ++ if (check_col(pinfo->cinfo, COL_INFO)) ++ col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s", ops_counter==0?' ':';', ++ val_to_str(opcode, names_nfs_cb_operation, "Unknown")); ++ ++ fitem = proto_tree_add_uint(ftree, hf_nfs_cb_resop, tvb, offset, 4, opcode); ++ offset += 4; ++ ++ /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */ ++ if (opcode == NFS4_OP_ILLEGAL) ++ newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4); ++ else if (nfs_cb_operation_ett[opcode - 3]) ++ newftree = proto_item_add_subtree(fitem, *nfs_cb_operation_ett[opcode - 3]); ++ else ++ break; ++ ++ offset = dissect_nfs_nfsstat4(tvb, offset, newftree, &status); ++ ++ /* are there any ops that return data with a failure (?) */ ++ if (status != NFS4_OK) ++ continue; ++ ++ /* These parsing routines are only executed if the status is NFS4_OK */ ++ switch (opcode) ++ { ++ case NFS4_OP_CB_RECALL: ++ break; ++ case NFS4_OP_CB_GETATTR: ++ case NFS4_OP_CB_LAYOUTRECALL: ++ break; ++ case NFS4_OP_CB_NOTIFY: ++ case NFS4_OP_CB_PUSH_DELEG: ++ case NFS4_OP_CB_RECALL_ANY: ++ case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL: ++ case NFS4_OP_CB_RECALL_SLOT: ++ break; ++ case NFS4_OP_CB_SEQUENCE: ++ offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL, ++ hf_nfs_sessionid4, TRUE, 16, ++ FALSE, NULL, NULL); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset); ++ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset); ++ break; ++ case NFS4_OP_CB_WANTS_CANCELLED: ++ case NFS4_OP_CB_NOTIFY_LOCK: ++ case NFS4_OP_CB_NOTIFY_DEVICEID: ++ break; ++ case NFS4_OP_ILLEGAL: ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return offset; ++} ++ ++static int ++dissect_nfs_cb_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, ++ proto_tree* tree) ++{ ++ guint32 status; ++ char *tag=NULL; ++ ++ offset = dissect_nfs_nfsstat4(tvb, offset, tree, &status); ++ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag); ++ if (check_col(pinfo->cinfo, COL_INFO)) ++ col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag); ++ ++ offset = dissect_nfs_cb_resop(tvb, offset, pinfo, tree); ++ ++ return offset; ++} ++ ++static const vsff nfs_cb_proc[] = { ++ { 0, "CB_NULL", ++ dissect_nfs3_null_call, dissect_nfs3_null_reply }, ++ { 1, "CB_COMPOUND", ++ dissect_nfs_cb_compound_call, dissect_nfs_cb_compound_reply }, ++ { 0, NULL, NULL, NULL } ++}; ++ ++static const value_string nfs_cb_proc_vals[] = { ++ { 0, "CB_NULL" }, ++ { 1, "CB_COMPOUND" }, ++ { 0, NULL } ++}; ++ ++void reg_callback(int cbprog) ++{ ++ /* Register the protocol as RPC */ ++ rpc_init_prog(proto_nfs, cbprog, ett_nfs); ++ ++ /* Register the procedure tables */ ++ rpc_init_proc_table(cbprog, 1, nfs_cb_proc, hf_nfs_cb_procedure); ++} ++ + void + proto_register_nfs(void) + { +@@ -10964,10 +11276,29 @@ proto_register_nfs(void) + { &hf_nfs_cachethis4, { + "Cache this?", "nfs.cachethis4", FT_BOOLEAN, BASE_NONE, + TFS(&tfs_yes_no), 0, NULL, HFILL }}, +- ++ ++ { &hf_nfs_cb_procedure, { ++ "CB Procedure", "nfs.cb_procedure", FT_UINT32, BASE_DEC, ++ VALS(nfs_cb_proc_vals), 0, NULL, HFILL }}, ++ ++ { &hf_nfs_cb_argop, { ++ "Opcode", "nfs.call.operation", FT_UINT32, BASE_DEC, ++ VALS(names_nfs_cb_operation), 0, NULL, HFILL }}, ++ { &hf_nfs_cb_resop, { ++ "Opcode", "nfs.reply.operation", FT_UINT32, BASE_DEC, ++ VALS(names_nfs_cb_operation), 0, NULL, HFILL }}, + { &hf_nfs_lrs_present, { + "Stateid present?", "nfs.lrs_present", FT_BOOLEAN, BASE_NONE, + TFS(&tfs_yes_no), 0, NULL, HFILL }}, ++ { &hf_nfs_cb_truncate, { ++ "Truncate?", "nfs.truncate", FT_BOOLEAN, BASE_NONE, ++ TFS(&tfs_yes_no), 0, NULL, HFILL }}, ++ { &hf_nfs_cb_layoutrecall_type, { ++ "recall type", "nfs.recalltype", FT_UINT32, BASE_DEC, ++ VALS(layoutrecall_names), 0, NULL, HFILL }}, ++ { &hf_nfs_cb_clorachanged, { ++ "Clora changed", "nfs.clorachanged", FT_BOOLEAN, BASE_NONE, ++ TFS(&tfs_yes_no), 0, NULL, HFILL }}, + + /* Hidden field for v2, v3, and v4 status */ + { &hf_nfs_nfsstat, { +@@ -11132,8 +11463,23 @@ proto_register_nfs(void) + &ett_nfs_gid4, + &ett_nfs_service4, + &ett_nfs_sessionid4, +- &ett_nfs_layoutseg, +- &ett_nfs_layoutseg_fh ++ &ett_nfs_layoutseg, ++ &ett_nfs_layoutseg_fh, ++ &ett_nfs_cb_argop, ++ &ett_nfs_cb_resop, ++ &ett_nfs_cb_getattr, ++ &ett_nfs_cb_recall, ++ &ett_nfs_cb_layoutrecall, ++ &ett_nfs_cb_pushdeleg, ++ &ett_nfs_cb_recallany, ++ &ett_nfs_cb_recallableobjavail, ++ &ett_nfs_cb_recallslot, ++ &ett_nfs_cb_sequence, ++ &ett_nfs_cb_wantscancelled, ++ &ett_nfs_cb_notifylock, ++ &ett_nfs_cb_notifydeviceid, ++ &ett_nfs_cb_notify, ++ &ett_nfs_cb_illegal, + }; + module_t *nfs_module; + +@@ -11169,9 +11515,9 @@ proto_register_nfs(void) + nfs_file_handles=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nfs_file_handles"); + nfs_fhandle_frame_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nfs_fhandle_frame_table"); + register_init_routine(nfs_name_snoop_init); +- + } + ++ + void + proto_reg_handoff_nfs(void) + { +@@ -11179,7 +11525,7 @@ proto_reg_handoff_nfs(void) + + /* 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); +@@ -11208,7 +11554,4 @@ proto_reg_handoff_nfs(void) + + fhandle_handle=create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs); + dissector_add("nfs_fhandle.type", FHT_UNKNOWN, fhandle_handle); +- +- + } +- +diff -up wireshark-1.1.2/epan/dissectors/packet-nfs.h.orig wireshark-1.1.2/epan/dissectors/packet-nfs.h +--- wireshark-1.1.2/epan/dissectors/packet-nfs.h.orig 2009-01-15 10:28:17.000000000 -0500 ++++ wireshark-1.1.2/epan/dissectors/packet-nfs.h 2009-02-15 08:31:28.000000000 -0500 +@@ -127,6 +127,23 @@ + + #define NFS4_OP_ILLEGAL 10044 + ++/* ++ * NFSv41 callback ops ++ */ ++#define NFS4_OP_CB_GETATTR 3 ++#define NFS4_OP_CB_RECALL 4 ++#define NFS4_OP_CB_LAYOUTRECALL 5 ++#define NFS4_OP_CB_NOTIFY 6 ++#define NFS4_OP_CB_PUSH_DELEG 7 ++#define NFS4_OP_CB_RECALL_ANY 8 ++#define NFS4_OP_CB_RECALLABLE_OBJ_AVAIL 9 ++#define NFS4_OP_CB_RECALL_SLOT 10 ++#define NFS4_OP_CB_SEQUENCE 11 ++#define NFS4_OP_CB_WANTS_CANCELLED 12 ++#define NFS4_OP_CB_NOTIFY_LOCK 13 ++#define NFS4_OP_CB_NOTIFY_DEVICEID 14 ++#define NFS4_OP_CB_ILLEGAL 10044 ++ + /* for write */ + #define UNSTABLE 0 + #define DATA_SYNC 1 diff --git a/wireshark.spec b/wireshark.spec index cafef43..9b883c5 100644 --- a/wireshark.spec +++ b/wireshark.spec @@ -7,7 +7,7 @@ Summary: Network traffic analyzer Name: wireshark Version: 1.1.2 -Release: 0.pre1%{?dist} +Release: 1.pre1%{?dist} License: GPL+ Group: Applications/Internet %if %{svn_version} @@ -21,6 +21,7 @@ Source3: wireshark.desktop Patch1: wireshark-1.0.2-pie.patch Patch2: wireshark-nfsv4-opts.patch Patch3: wireshark-0.99.7-path.patch +Patch4: wireshark-1.1.2-nfs41-backchnl-decode.patch Url: http://www.wireshark.org/ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -85,6 +86,7 @@ Contains wireshark for Gnome 2 and desktop integration file #%patch1 -p1 -b .pie %patch2 -p1 %patch3 -p1 +%patch4 -p1 %build %ifarch s390 s390x sparcv9 sparc64 @@ -208,6 +210,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Sun Feb 15 2009 Steve Dickson - 1.1.2-1.pre1 +- NFSv4.1: Add support for backchannel decoding + * Mon Jan 19 2009 Radek Vokal - 1.1.2-0.pre1 - upgrade to latest development release - added support for portaudio (#480195)