Wireshark-dev: [Wireshark-dev] [PATCH 16/16] NFS: Add support for NFSv4 filename snooping
From: Pali Rohár <pali@xxxxxxxxxx>
Date: Fri, 13 Sep 2024 23:08:51 +0200
One RPC NFS4 procedure call can contain (and in most cases always contains) more operations which changes filehandle between operations. So for correct NFSv4 filename snooping it is required to track not only RPC packet number (xid) but also index in the list of operations calls in that RPC packet. In NFSv4, only replies for GETFH, GETATTR and READDIR operations might return filename mapping. So extend all functions to take operation code and index in the list of operations and track which operation was doing mapping. Note that filename snooping for READDIR replies is not implemented yet. It requires to match directory name from READDIR request with child name from particular entry of READIR response together with filehandle attribute attached to the entry of READDIR response. Which is slightly complicated. This change implements only filename snooping for GETFH and GETATTR. --- epan/dissectors/packet-nfs.c | 248 ++++++++++++++++++++++------------- 1 file changed, 156 insertions(+), 92 deletions(-) diff --git a/epan/dissectors/packet-nfs.c b/epan/dissectors/packet-nfs.c index 57339df19dde..eb2a20ca16ef 100644 --- a/epan/dissectors/packet-nfs.c +++ b/epan/dissectors/packet-nfs.c @@ -971,7 +971,8 @@ static const true_false_string tfs_read_write = { "Read", "Write" }; /* Prototype for function to dissect attribute value */ typedef int (dissect_bitmap_item_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, - rpc_call_info_value *civ, proto_tree *attr_tree, proto_item *attr_item, + rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx, + proto_tree *attr_tree, proto_item *attr_item, uint32_t bit_num, void *battr_data); /* Prototype for function to return the header field for the item label */ @@ -6435,7 +6436,8 @@ dissect_nfs_utf8string(tvbuff_t *tvb, int offset, */ static int dissect_nfs4_bitmap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, - rpc_call_info_value *civ, nfs4_bitmap_info_t *bitmap_info, nfs4_bitmap_type_t type, + rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx, + nfs4_bitmap_info_t *bitmap_info, nfs4_bitmap_type_t type, const char *name) { int attr_offset; @@ -6587,7 +6589,7 @@ dissect_nfs4_bitmap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t /* Display bit value */ attr_tree = proto_item_add_subtree(attr_item, ett_nfs4_bitmap); if (bitmap_info->dissect_battr) - offset = bitmap_info->dissect_battr(tvb, offset, pinfo, civ, + offset = bitmap_info->dissect_battr(tvb, offset, pinfo, civ, opcode, fh_idx, attr_tree, attr_item, bit_num, bitmap_info->battr_data); if (offset == attr_offset) { /* No value was dissected, this attribute is most likely not @@ -7098,8 +7100,29 @@ dissect_nfs4_fattr_aclsupport(tvbuff_t *tvb, int offset, proto_tree *tree) static int dissect_nfs4_fh(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, const char *name, uint32_t *hash, rpc_call_info_value *civ) + proto_tree *tree, const char *name, + uint32_t *hash, int *fh_offset_ptr, int *fh_length_ptr, + rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx) { + int fh_offset, fh_length; + + fh_length = tvb_get_ntohl(tvb, offset); + fh_offset = offset+4; + + /* are we snooping fh to filenames ?*/ + if ((!pinfo->fd->visited) && nfs_file_name_snooping) { + /* NFS v4 GETFH, GETATTR and READDIR replies might give us a mapping */ + /* TODO: Matching NFS v4 READDIR name entry with entry filehandle attribute and with READDIR directory name is not supported yet */ + if (civ->prog == NFS_PROGRAM && civ->vers == 4 && !civ->request && civ->proc == 1 && (opcode == NFS4_OP_GETFH || opcode == NFS4_OP_GETATTR)) { + nfs_name_snoop_add_fh(((uint64_t)fh_idx << 32) | civ->xid, tvb, fh_offset, fh_length); + } + } + + if (fh_offset_ptr) + *fh_offset_ptr = fh_offset; + if (fh_length_ptr) + *fh_length_ptr = fh_length; + return dissect_nfs3_fh(tvb, offset, pinfo, tree, name, hash, civ); } @@ -7258,7 +7281,8 @@ static value_string_ext th4_names_ext_file = VALUE_STRING_EXT_INIT(th4_names_fil /* Dissect the threshold_item4 bit attribute for the files layout type */ static int dissect_nfs4_threshold_item_file(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, - rpc_call_info_value *civ _U_, proto_tree *attr_tree, proto_item *attr_item _U_, + rpc_call_info_value *civ _U_, uint32_t opcode _U_, uint32_t fh_idx _U_, + proto_tree *attr_tree, proto_item *attr_item _U_, uint32_t bit_num, void *battr_data _U_) { uint64_t size; @@ -7315,7 +7339,7 @@ dissect_nfs4_threshold_item(tvbuff_t *tvb, int offset, packet_info *pinfo, bitmap_info_p = &bitmap_info_default; break; } - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, (rpc_call_info_value *)data, bitmap_info_p, NFS4_BITMAP_VALUES, NULL); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, (rpc_call_info_value *)data, -1, -1, bitmap_info_p, NFS4_BITMAP_VALUES, NULL); } @@ -7373,7 +7397,7 @@ static const value_string names_nfs_change_attr_types[] = }; static int -dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ); +dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx); /* Display attribute as either required or recommended */ static int @@ -7389,14 +7413,15 @@ nfs4_fattr_item_label(uint32_t attr_num) /* Dissect the value of the attribute given by attr_num */ static int dissect_nfs4_fattr_value(tvbuff_t *tvb, int offset, packet_info *pinfo, - rpc_call_info_value *civ, proto_tree *attr_tree, + rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx, + proto_tree *attr_tree, proto_item *attr_item, uint32_t attr_num, void *battr_data) { uint32_t *fattr_obj_type_p = (uint32_t *)battr_data; switch (attr_num) { case FATTR4_SUPPORTED_ATTRS: case FATTR4_SUPPATTR_EXCLCREAT: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, attr_tree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, attr_tree, FATTR4_BITMAP_ONLY, civ, opcode, fh_idx); break; case FATTR4_TYPE: @@ -7488,7 +7513,7 @@ dissect_nfs4_fattr_value(tvbuff_t *tvb, int offset, packet_info *pinfo, break; case FATTR4_FILEHANDLE: - offset = dissect_nfs4_fh(tvb, offset, pinfo, attr_tree, "fattr4_filehandle", NULL, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, attr_tree, "fattr4_filehandle", NULL, NULL, NULL, civ, opcode, fh_idx); break; case FATTR4_FILES_FREE: @@ -7681,7 +7706,7 @@ dissect_nfs4_fattr_value(tvbuff_t *tvb, int offset, packet_info *pinfo, /* Display each attrmask bitmap and optionally dissect the value. */ static int -dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ) +dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx) { static uint32_t fattr_obj_type = 0; nfs4_bitmap_type_t bitmap_type; @@ -7697,7 +7722,7 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t fattr_obj_type = 0; bitmap_type = (type == FATTR4_BITMAP_ONLY) ? NFS4_BITMAP_MASK : NFS4_BITMAP_VALUES; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, civ, &bitmap_info, bitmap_type, NULL); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, civ, opcode, fh_idx, &bitmap_info, bitmap_type, NULL); } static const value_string names_open4_share_access[] = { @@ -7825,36 +7850,35 @@ static const value_string names_claim_type4[] = { /* XXX - need a better place to populate name than here, maybe? */ static int dissect_nfs4_open_claim(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, - proto_tree *tree, const char **name, rpc_call_info_value *civ) + proto_tree *tree, const char **name, + int current_fh_offset, int current_fh_length, + rpc_call_info_value *civ, uint32_t fh_idx) { unsigned open_claim_type4; proto_item *fitem; proto_tree *newftree = NULL; uint32_t name_offset, name_len; + if (name) + *name = NULL; /* will be filled later for CLAIM_NULL */ + open_claim_type4 = tvb_get_ntohl(tvb, offset); fitem = proto_tree_add_uint(tree, hf_nfs4_open_claim_type, tvb, offset+0, 4, open_claim_type4); offset += 4; - if (open_claim_type4 == CLAIM_NULL) { - dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, name); - if (nfs_file_name_snooping) { - - name_offset = offset+4; - name_len = tvb_get_ntohl(tvb, offset); - - nfs_name_snoop_add_name(civ->xid, tvb, - name_offset, name_len, 0, 0, NULL); - } - } - newftree = proto_item_add_subtree(fitem, ett_nfs4_open_claim); switch (open_claim_type4) { case CLAIM_NULL: offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, name); + if (nfs_file_name_snooping) { + name_offset = offset+4; + name_len = tvb_get_ntohl(tvb, offset); + nfs_name_snoop_add_name(((uint64_t)fh_idx << 32) | civ->xid, tvb, + name_offset, name_len, current_fh_offset, current_fh_length, NULL); + } break; case CLAIM_PREVIOUS: @@ -7899,7 +7923,7 @@ dissect_nfs4_createhow(tvbuff_t *tvb, int offset, packet_info *pinfo, { case UNCHECKED4: case GUARDED4: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ, -1, -1); break; case EXCLUSIVE4: @@ -7908,7 +7932,7 @@ dissect_nfs4_createhow(tvbuff_t *tvb, int offset, packet_info *pinfo, case EXCLUSIVE4_1: offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ, -1, -1); break; default: @@ -8094,7 +8118,7 @@ dissect_nfs4_gdd_time(tvbuff_t *tvb, int offset, proto_tree *tree, int hfindex) static int dissect_nfs4_gdd_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, - rpc_call_info_value *civ, int hfindex) + rpc_call_info_value *civ, int hfindex, uint32_t opcode, uint32_t fh_idx) { proto_item *item; proto_tree *subtree; @@ -8104,7 +8128,7 @@ dissect_nfs4_gdd_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre item = proto_tree_add_item(tree, hfindex, tvb, offset, len * 4, ENC_NA); subtree = proto_item_add_subtree(item, ett_nfs4_notify_attrs); - return dissect_nfs4_fattrs(tvb, offset, pinfo, subtree, type, civ); + return dissect_nfs4_fattrs(tvb, offset, pinfo, subtree, type, civ, opcode, fh_idx); } /* NFSv4 Operations */ @@ -8270,7 +8294,7 @@ static int *nfs4_operation_ett[] = static int dissect_nfs4_dirlist(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, rpc_call_info_value *civ) + proto_tree *tree, rpc_call_info_value *civ, uint32_t opcode, uint32_t fh_idx) { uint32_t val_follows; uint32_t name_len; @@ -8312,7 +8336,7 @@ dissect_nfs4_dirlist(tvbuff_t *tvb, int offset, packet_info *pinfo, offset = dissect_nfs_utf8string(tvb, offset, entry_tree, hf_nfs4_dir_entry_name, NULL); /* Attrmask(s) */ - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, entry_tree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, entry_tree, FATTR4_DISSECT_VALUES, civ, opcode, fh_idx); proto_item_set_len(eitem, offset - start_off); } else { break; @@ -8464,7 +8488,7 @@ dissect_nfs4_state_protect_bitmap(tvbuff_t *tvb, int offset, packet_info *pinfo, .hf_item_label = &hf_nfs4_op }; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, name); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, -1, -1, &bitmap_info, NFS4_BITMAP_MASK, name); } #define SP4_NONE 0 @@ -8888,7 +8912,7 @@ dissect_nfs4_io_hints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree .hf_item_count = &hf_nfs4_io_hint_count, }; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, NULL); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, -1, -1, &bitmap_info, NFS4_BITMAP_MASK, NULL); } static const value_string cb_recall_any_names[] = { @@ -8931,7 +8955,7 @@ dissect_nfs4_cb_recall_any_mask(tvbuff_t *tvb, int offset, packet_info *pinfo, p .hf_item_label = &hf_nfs4_cb_recall_any_item, }; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, NULL); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, -1, -1, &bitmap_info, NFS4_BITMAP_MASK, NULL); } static int @@ -9042,7 +9066,7 @@ dissect_nfs4_layoutstats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr proto_item_set_len(fitem, offset - old_offset); /* The file handle */ - offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "Filehandle", &last_fh_hash, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "Filehandle", &last_fh_hash, NULL, NULL, civ, -1, -1); /* Read Latency */ offset = dissect_nfs4_io_latency(tvb, offset, tree, "Read"); @@ -9230,7 +9254,7 @@ static const value_string notify_type4[] = { static value_string_ext notify_type4_ext = VALUE_STRING_EXT_INIT(notify_type4); static int -dissect_nfs4_notify_type4_bitmap(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset) +dissect_nfs4_notify_type4_bitmap(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, uint32_t opcode, uint32_t fh_idx) { static nfs4_bitmap_info_t bitmap_info = { .vse_names_ext = ¬ify_type4_ext, @@ -9238,7 +9262,7 @@ dissect_nfs4_notify_type4_bitmap(tvbuff_t *tvb, proto_tree *tree, packet_info *p .hf_item_label = &hf_nfs4_notify_type, }; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, opcode, fh_idx, &bitmap_info, NFS4_BITMAP_MASK, NULL); } @@ -9261,7 +9285,7 @@ dissect_nfs4_notify_deviceid_bitmap(tvbuff_t *tvb, proto_tree *tree, packet_info .hf_item_label = &hf_nfs4_notify_deviceid_type, }; - return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, NULL); + return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, -1, -1, &bitmap_info, NFS4_BITMAP_MASK, NULL); } @@ -9820,8 +9844,9 @@ dissect_nfs4_layoutget(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree ett_nfs4_layoutseg_sub); for (i = 0; i < sub_num; i++) offset = dissect_nfs4_fh(tvb, offset, pinfo, - subtree, "lo_filehandle", NULL, - civ); + subtree, "lo_filehandle", + NULL, NULL, NULL, + civ, -1, -1); } else if (layout_type == LAYOUT4_FLEX_FILES) { unsigned ds_count, fh_count; proto_item *ds_item, *mirrors_item, *subitem; @@ -9873,7 +9898,7 @@ dissect_nfs4_layoutget(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree for (k = 0; k < fh_count; k++) offset = dissect_nfs4_fh(tvb, offset, - pinfo, ds_tree, "fh", NULL, civ); + pinfo, ds_tree, "fh", NULL, NULL, NULL, civ, -1, -1); offset = dissect_nfs_utf8string(tvb, offset, ds_tree, hf_nfs4_ff_synthetic_owner, @@ -10133,8 +10158,12 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre uint32_t ops_counter; uint32_t summary_counter; uint32_t string_length; + int last_fh_offset = 0; + int last_fh_length = 0; uint32_t last_fh_hash = 0; uint32_t saved_fh_hash = 0; + int saved_fh_offset = 0; + int saved_fh_length = 0; uint32_t length; uint32_t hash; uint64_t length64; @@ -10212,7 +10241,8 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre acc_request = (uint32_t *)wmem_memdup(wmem_file_scope(), &amask, sizeof(uint32_t)); civ->private_data = acc_request; - wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); + if (last_fh_hash != 0) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); display_access_items(tvb, offset, pinfo, fitem, amask, amask, 'C', 4, op_summary[ops_counter].optext, "Check") ; offset+=4; @@ -10230,9 +10260,10 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset); length = tvb_get_ntohl(tvb, offset); offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset); - wmem_strbuf_append_printf (op_summary[ops_counter].optext, - " FH: 0x%08x Offset: %"PRIu64" Len: %u", - last_fh_hash, file_offset, length); + if (last_fh_hash != 0) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, + " FH: 0x%08x Offset: %"PRIu64" Len: %u", + last_fh_hash, file_offset, length); break; @@ -10263,8 +10294,12 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; } - offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, NULL); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &name); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, -1); + + if (nfs_file_name_snooping) { + nfs_name_snoop_add_name(((uint64_t)ops_counter << 32) | civ->xid, tvb, -1, strlen(name), last_fh_offset, last_fh_length, name); + } } break; @@ -10278,7 +10313,7 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_GETATTR: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ, opcode, -1); if (last_fh_hash != 0) wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); @@ -10286,7 +10321,6 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_GETFH: - last_fh_hash = 0; break; case NFS4_OP_LINK: @@ -10301,14 +10335,13 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre length64 = tvb_get_ntoh64(tvb, offset); offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset); offset = dissect_nfs4_locker(tvb, offset, newftree); + if (last_fh_hash != 0) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Offset: %"PRIu64, file_offset); if (length64 == UINT64_C(0xffffffffffffffff)) - wmem_strbuf_append_printf (op_summary[ops_counter].optext, - " FH: 0x%08x Offset: %"PRIu64" Length: <End of File>", - last_fh_hash, file_offset); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Length: <End of File>"); else - wmem_strbuf_append_printf (op_summary[ops_counter].optext, - " FH: 0x%08x Offset: %"PRIu64" Length: %"PRIu64" ", - last_fh_hash, file_offset, length64); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Length: %"PRIu64, length64); break; case NFS4_OP_LOCKT: @@ -10326,19 +10359,21 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset); length64 = tvb_get_ntoh64(tvb, offset); offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset); + if (last_fh_hash != 0) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Offset: %"PRIu64, file_offset); if (length64 == UINT64_C(0xffffffffffffffff)) - wmem_strbuf_append_printf (op_summary[ops_counter].optext, - " FH: 0x%08x Offset: %"PRIu64" Length: <End of File>", - last_fh_hash, file_offset); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Length: <End of File>"); else - wmem_strbuf_append_printf (op_summary[ops_counter].optext, - " FH: 0x%08x Offset: %"PRIu64" Length: %"PRIu64 " ", - last_fh_hash, file_offset, length64); + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " Length: %"PRIu64, length64); break; case NFS4_OP_LOOKUP: /*name_offset = offset;*/ offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &name); + if (nfs_file_name_snooping) { + nfs_name_snoop_add_name(((uint64_t)ops_counter << 32) | civ->xid, tvb, -1, strlen(name), last_fh_offset, last_fh_length, name); + } wmem_strbuf_append_printf (op_summary[ops_counter].optext, " "); if (last_fh_hash != 0) wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash); @@ -10350,7 +10385,7 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_NVERIFY: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, -1); if (last_fh_hash != 0) wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); break; @@ -10361,10 +10396,14 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre offset = dissect_nfs4_open_share_deny(tvb, offset, newftree); offset = dissect_nfs4_open_owner(tvb, offset, newftree); offset = dissect_nfs4_openflag(tvb, offset, pinfo, newftree, civ); - offset = dissect_nfs4_open_claim(tvb, offset, pinfo, newftree, &name, civ); + offset = dissect_nfs4_open_claim(tvb, offset, pinfo, newftree, &name, last_fh_offset, last_fh_length, civ, ops_counter); wmem_strbuf_append_printf (op_summary[ops_counter].optext, " "); - if (last_fh_hash != 0) - wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash); + if (last_fh_hash != 0) { + if (name != NULL) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash); + else + wmem_strbuf_append_printf (op_summary[ops_counter].optext, "FH: 0x%08x", last_fh_hash); + } if (name != NULL) wmem_strbuf_append_printf (op_summary[ops_counter].optext, "%s", name); break; @@ -10386,11 +10425,15 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_PUTFH: - offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", &last_fh_hash, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", &last_fh_hash, &last_fh_offset, &last_fh_length, civ, opcode, -1); break; case NFS4_OP_PUTPUBFH: + break; + case NFS4_OP_PUTROOTFH: + if (nfs_file_name_snooping) + nfs_name_snoop_add_name(((uint64_t)ops_counter << 32) | civ->xid, tvb, -1, 1, 0, 0, "/"); break; case NFS4_OP_READ: @@ -10410,7 +10453,7 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie_verf, offset); offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_dircount, offset); offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_maxcount, offset); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ, opcode, -1); if (last_fh_hash != 0) wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); break; @@ -10453,10 +10496,14 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_RESTOREFH: + last_fh_offset = saved_fh_offset; + last_fh_length = saved_fh_length; last_fh_hash = saved_fh_hash; break; case NFS4_OP_SAVEFH: + saved_fh_offset = last_fh_offset; + saved_fh_length = last_fh_length; saved_fh_hash = last_fh_hash; break; @@ -10472,8 +10519,9 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre case NFS4_OP_SETATTR: offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); - wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, -1); + if (last_fh_hash != 0) + wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash); break; case NFS4_OP_SETCLIENTID: @@ -10500,7 +10548,7 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre break; case NFS4_OP_VERIFY: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, -1); break; case NFS4_OP_WRITE: @@ -10569,13 +10617,13 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre case NFS4_OP_GET_DIR_DELEGATION: offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_gdd_signal_deleg_avail, offset); - offset = dissect_nfs4_notify_type4_bitmap(tvb, newftree, pinfo, offset); + offset = dissect_nfs4_notify_type4_bitmap(tvb, newftree, pinfo, offset, opcode, -1); offset = dissect_nfs4_gdd_time(tvb, offset, newftree, hf_nfs4_gdd_child_attr_delay); offset = dissect_nfs4_gdd_time(tvb, offset, newftree, hf_nfs4_gdd_dir_attr_delay); offset = dissect_nfs4_gdd_fattrs(tvb, offset, pinfo, newftree, - FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_child_attrs); + FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_child_attrs, opcode, -1); offset = dissect_nfs4_gdd_fattrs(tvb, offset, pinfo, newftree, - FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_dir_attrs); + FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_dir_attrs, opcode, -1); break; /* pNFS */ @@ -10984,7 +11032,8 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr unsigned current_tier = 5; unsigned first_operation = 1; uint16_t sid_hash = 0; - uint32_t last_fh_hash = 0; + uint32_t last_fh_idx = -1; + uint32_t saved_fh_idx = -1; uint32_t ops, ops_counter; uint32_t summary_counter; uint32_t opcode, status, nfstatus; @@ -11084,22 +11133,28 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr break; case NFS4_OP_CREATE: + last_fh_idx = ops_counter; offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info"); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ, opcode, last_fh_idx); break; case NFS4_OP_GETATTR: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, last_fh_idx); break; case NFS4_OP_GETFH: - offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "Filehandle", &last_fh_hash, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "Filehandle", NULL, NULL, NULL, civ, opcode, last_fh_idx); break; case NFS4_OP_LINK: offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info"); break; + case NFS4_OP_LOOKUP: + case NFS4_OP_LOOKUPP: + last_fh_idx = ops_counter; + break; + case NFS4_OP_LOCK: case NFS4_OP_LOCKT: if (status == NFS4_OK) @@ -11121,7 +11176,7 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info"); offset = dissect_nfs4_open_rflags(tvb, offset, newftree); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ, opcode, -1); offset = dissect_nfs4_open_delegation(tvb, offset, pinfo, newftree); wmem_strbuf_append_printf (op_summary[ops_counter].optext, " StateID: 0x%04x", sid_hash); break; @@ -11131,9 +11186,10 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL); break; - case NFS4_OP_RESTOREFH: - case NFS4_OP_SAVEFH: case NFS4_OP_PUTFH: + case NFS4_OP_PUTPUBFH: + case NFS4_OP_PUTROOTFH: + last_fh_idx = ops_counter; break; case NFS4_OP_READ: @@ -11144,7 +11200,7 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr case NFS4_OP_READDIR: offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset); - offset = dissect_nfs4_dirlist(tvb, offset, pinfo, newftree, civ); + offset = dissect_nfs4_dirlist(tvb, offset, pinfo, newftree, civ, opcode, -1); break; case NFS4_OP_READLINK: @@ -11163,6 +11219,14 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr offset = dissect_nfs4_change_info(tvb, offset, newftree, "target_cinfo"); break; + case NFS4_OP_RESTOREFH: + last_fh_idx = saved_fh_idx; + break; + + case NFS4_OP_SAVEFH: + saved_fh_idx = last_fh_idx; + break; + case NFS4_OP_SECINFO: case NFS4_OP_SECINFO_NO_NAME: offset = dissect_rpc_array(tvb, pinfo, newftree, offset, @@ -11170,7 +11234,7 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr break; case NFS4_OP_SETATTR: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ, opcode, -1); break; case NFS4_OP_SETCLIENTID: @@ -11241,11 +11305,11 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr if (nfstatus == GDD4_OK) { offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset); offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash); - offset = dissect_nfs4_notify_type4_bitmap(tvb, newftree, pinfo, offset); + offset = dissect_nfs4_notify_type4_bitmap(tvb, newftree, pinfo, offset, opcode, -1); offset = dissect_nfs4_gdd_fattrs(tvb, offset, pinfo, newftree, - FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_child_attrs); + FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_child_attrs, opcode, -1); offset = dissect_nfs4_gdd_fattrs(tvb, offset, pinfo, newftree, - FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_dir_attrs); + FATTR4_BITMAP_ONLY, civ, hf_nfs4_gdd_dir_attrs, opcode, -1); } else if (nfstatus == GDD4_UNAVAIL) { offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_gdd_signal_deleg_avail, offset); } @@ -11887,7 +11951,7 @@ dissect_nfs4_cb_layoutrecall(tvbuff_t *tvb, int offset, proto_tree *tree, packet offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_cb_layoutrecall_type, offset); if (recall_type == 1) { /* RECALL_FILE */ - offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, NULL, NULL, civ, -1, -1); offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset); offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset); offset = dissect_nfs4_stateid(tvb, offset, tree, NULL); @@ -11951,11 +12015,11 @@ dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre case NFS4_OP_CB_RECALL: offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL); offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_cb_truncate, offset); - offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, NULL, NULL, civ, opcode, -1); break; case NFS4_OP_CB_GETATTR: - offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, civ); - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_BITMAP_ONLY, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, NULL, NULL, civ, opcode, -1); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_BITMAP_ONLY, civ, opcode, -1); break; case NFS4_OP_CB_LAYOUTRECALL: offset = dissect_nfs4_cb_layoutrecall(tvb, offset, newftree, pinfo, civ); @@ -11980,13 +12044,13 @@ dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre case NFS4_OP_CB_WANTS_CANCELLED: break; case NFS4_OP_CB_NOTIFY_LOCK: - offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, NULL, NULL, civ, opcode, -1); offset = dissect_nfs4_lock_owner(tvb, offset, newftree); break; case NFS4_OP_CB_NOTIFY_DEVICEID: break; case NFS4_OP_CB_OFFLOAD: - offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ); + offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, NULL, NULL, civ, opcode, -1); offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL); offset = dissect_nfs4_status(tvb, offset, newftree, &status); if (status == NFS4_OK) { @@ -12097,7 +12161,7 @@ dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre case NFS4_OP_CB_RECALL: break; case NFS4_OP_CB_GETATTR: - offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ); + offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ, opcode, -1); break; case NFS4_OP_CB_LAYOUTRECALL: break; -- 2.20.1
- References:
- [Wireshark-dev] [PATCH 00/16] NFS: Improve dissector
- From: Pali Rohár
- [Wireshark-dev] [PATCH 00/16] NFS: Improve dissector
- Prev by Date: [Wireshark-dev] [PATCH 14/16] NFS: Fix dissecting NFS4 CREATE_SESSION cb_sec_params
- Next by Date: [Wireshark-dev] [PATCH 08/16] NFS: Update comment about NFS4 callback versions
- Previous by thread: [Wireshark-dev] [PATCH 14/16] NFS: Fix dissecting NFS4 CREATE_SESSION cb_sec_params
- Next by thread: [Wireshark-dev] [PATCH 08/16] NFS: Update comment about NFS4 callback versions
- Index(es):