diff options
author | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-09-20 19:24:07 +0000 |
---|---|---|
committer | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-09-20 19:24:07 +0000 |
commit | 3c545fe1e2b4288da40c47f88e364393a98052c1 (patch) | |
tree | e60dc20157b7051bc2ba096088363d22b5adba52 /epan/dissectors/packet-afp.c | |
parent | 9343f33984457fec88ef0d9ab63c3c54d1d7ed26 (diff) |
From Frank Lahm: Complete dissection of AFP FPSpotlightRPC function.
From me: don't use global variables in FPSpotlightRPC dissection.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@39065 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-afp.c')
-rw-r--r-- | epan/dissectors/packet-afp.c | 474 |
1 files changed, 320 insertions, 154 deletions
diff --git a/epan/dissectors/packet-afp.c b/epan/dissectors/packet-afp.c index 22bed435b7..f70b544eaf 100644 --- a/epan/dissectors/packet-afp.c +++ b/epan/dissectors/packet-afp.c @@ -693,7 +693,6 @@ static int hf_afp_spotlight_returncode = -1; static int hf_afp_spotlight_volflags = -1; static int hf_afp_spotlight_reqlen = -1; static int hf_afp_spotlight_toc_query_end = -1; -static int hf_afp_spotlight_mdstring = -1; static const value_string flag_vals[] = { {0, "Start" }, @@ -1014,10 +1013,14 @@ static int hf_afp_acl_access_bitmap_generic_read = -1; #define hash_init_count 20 +/* Forward declarations */ + /* Hash functions */ static gint afp_equal (gconstpointer v, gconstpointer v2); static guint afp_hash (gconstpointer v); +static gint dissect_spotlight(tvbuff_t *tvb, proto_tree *tree, gint offset); + typedef struct { guint32 conversation; guint16 seq; @@ -1028,20 +1031,24 @@ static GHashTable *afp_request_hash = NULL; static guint Vol; /* volume */ static guint Did; /* parent directory ID */ -#define SPOTLIGHT_BIG_ENDIAN 0 -#define SPOTLIGHT_LITTLE_ENDIAN 1 - -static gint spotlight_endianess; - static guint64 -spotlight_ntoh64(tvbuff_t *tvb, gint offset) +spotlight_ntoh64(tvbuff_t *tvb, gint offset, guint encoding) { - if (spotlight_endianess == SPOTLIGHT_LITTLE_ENDIAN) + if (encoding == ENC_LITTLE_ENDIAN) return tvb_get_letoh64(tvb, offset); else return tvb_get_ntoh64(tvb, offset); } +static gdouble +spotlight_ntohieee_double(tvbuff_t *tvb, gint offset, guint encoding) +{ + if (encoding == ENC_LITTLE_ENDIAN) + return tvb_get_letohieee_double(tvb, offset); + else + return tvb_get_ntohieee_double(tvb, offset); +} + /* Hash Functions */ static gint afp_equal (gconstpointer v, gconstpointer v2) { @@ -3976,45 +3983,292 @@ dissect_query_afp_with_did(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr } /* ************************** */ + +#define SQ_TYPE_NULL 0x0000 +#define SQ_TYPE_COMPLEX 0x0200 +#define SQ_TYPE_INT64 0x8400 +#define SQ_TYPE_BOOL 0x0100 +#define SQ_TYPE_FLOAT 0x8500 +#define SQ_TYPE_DATA 0x0700 +#define SQ_TYPE_CNIDS 0x8700 + +#define SQ_CPX_TYPE_ARRAY 0x0a00 +#define SQ_CPX_TYPE_STRING 0x0c00 +#define SQ_CPX_TYPE_DICT 0x0d00 +#define SQ_CPX_TYPE_CNIDS 0x1a00 +#define SQ_CPX_TYPE_FILEMETA 0x1b00 + +static gint +spotlight_int64(tvbuff_t *tvb, proto_tree *tree, gint offset, guint encoding) +{ + gint count, i; + guint64 query_data64; + + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + proto_tree_add_text(tree, tvb, offset, 8, "int64: 0x%016" G_GINT64_MODIFIER "x", query_data64); + offset += 8; + } + + return count; +} + +static gint +spotlight_float(tvbuff_t *tvb, proto_tree *tree, gint offset, guint encoding) +{ + gint count, i; + guint64 query_data64; + gdouble fval; + + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + fval = spotlight_ntohieee_double(tvb, offset, encoding); + proto_tree_add_text(tree, tvb, offset, 8, "float: %f", fval); + offset += 8; + } + + return count; +} + +static gint +spotlight_CNID_array(tvbuff_t *tvb, proto_tree *tree, gint offset, guint encoding) +{ + gint count; + guint64 query_data64; + guint16 unknown1; + guint32 unknown2; + + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + count = query_data64 & 0xffff; + unknown1 = (query_data64 & 0xffff0000) >> 16; + unknown2 = query_data64 >> 32; + + proto_tree_add_text(tree, tvb, offset + 2, 2, "unknown1: 0x%04" G_GINT16_MODIFIER "x", + unknown1); + proto_tree_add_text(tree, tvb, offset + 4, 4, "unknown2: 0x%08" G_GINT32_MODIFIER "x", + unknown2); + offset += 8; + + + while (count --) { + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + proto_tree_add_text(tree, tvb, offset, 8, "CNID: %" G_GINT64_MODIFIER "u", + query_data64); + offset += 8; + } + + return 0; +} + +static const char *spotlight_get_qtype_string(guint64 query_type) +{ + switch (query_type) { + case SQ_TYPE_NULL: + return "null"; + case SQ_TYPE_COMPLEX: + return "complex"; + case SQ_TYPE_INT64: + return "int64"; + case SQ_TYPE_BOOL: + return "bool"; + case SQ_TYPE_FLOAT: + return "float"; + case SQ_TYPE_DATA: + return "data"; + case SQ_TYPE_CNIDS: + return "CNIDs"; + default: + return "unknown"; + } +} + +static const char *spotlight_get_cpx_qtype_string(guint64 cpx_query_type) +{ + switch (cpx_query_type) { + case SQ_CPX_TYPE_ARRAY: + return "array"; + case SQ_CPX_TYPE_STRING: + return "string"; + case SQ_CPX_TYPE_DICT: + return "dictionary"; + case SQ_CPX_TYPE_CNIDS: + return "CNIDs"; + case SQ_CPX_TYPE_FILEMETA: + return "FileMeta"; + default: + return "unknown"; + } +} + +static gint +spotlight_dissect_query_loop(tvbuff_t *tvb, proto_tree *tree, gint offset, guint64 cpx_query_type, gint count, gint toc_offset, guint encoding) +{ + gint j; + gint subquery_count; + gint toc_index; + guint64 query_data64; + guint64 query_length; + guint64 query_type; + guint64 complex_query_type; + + proto_item *item_query; + proto_tree *sub_tree; + + /* + * This loops through a possibly nested query data structure. + * The outermost one is always without count and called from + * dissect_spotlight() with count = INT_MAX thus the while (...) + * loop terminates if (offset >= toc_offset). + * If nested structures are found, these will have an encoded element + * count which is used in a recursive call to + * spotlight_dissect_query_loop as count parameter, thus in this case + * the while (...) loop will terminate when count reaches 0. + */ + while ((offset < (toc_offset - 8)) && (count > 0)) { + query_data64 = spotlight_ntoh64(tvb, offset, encoding); + query_length = (query_data64 & 0xffff) * 8; + query_type = (query_data64 & 0xffff0000) >> 16; + + switch (query_type) { + case SQ_TYPE_COMPLEX: + toc_index = (gint)((query_data64 >> 32) - 1); + query_data64 = spotlight_ntoh64(tvb, toc_offset + toc_index * 8, encoding); + complex_query_type = (query_data64 & 0xffff0000) >> 16; + + switch (complex_query_type) { + case SQ_CPX_TYPE_ARRAY: + case SQ_CPX_TYPE_DICT: + subquery_count = (gint)(query_data64 >> 32); + item_query = proto_tree_add_text(tree, tvb, offset, query_length, + "%s, toc index: %u, children: %u", + spotlight_get_cpx_qtype_string(complex_query_type), + toc_index + 1, + subquery_count); + break; + case SQ_CPX_TYPE_STRING: + subquery_count = 1; + query_data64 = spotlight_ntoh64(tvb, offset + 8, encoding); + query_length = (query_data64 & 0xffff) * 8; + item_query = proto_tree_add_text(tree, tvb, offset, query_length + 8, + "%s, toc index: %u, string: '%s'", + spotlight_get_cpx_qtype_string(complex_query_type), + toc_index + 1, + tvb_get_ephemeral_string(tvb, offset + 16, query_length - 8)); + break; + default: + subquery_count = 1; + item_query = proto_tree_add_text(tree, tvb, offset, query_length, + "type: %s (%s), toc index: %u, children: %u", + spotlight_get_qtype_string(query_type), + spotlight_get_cpx_qtype_string(complex_query_type), + toc_index + 1, + subquery_count); + break; + } + + sub_tree = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); + offset += 8; + offset = spotlight_dissect_query_loop(tvb, sub_tree, offset, complex_query_type, subquery_count, toc_offset, encoding); + break; + case SQ_TYPE_NULL: + subquery_count = (gint)(query_data64 >> 32); + j = 0; + while (j++ < subquery_count) { + proto_tree_add_text(tree, tvb, offset, 8, "null"); + } + count -= subquery_count; + offset += query_length; + break; + case SQ_TYPE_BOOL: + item_query = proto_tree_add_text(tree, tvb, offset, query_length, "bool: %s", + (query_data64 >> 32) ? "true" : "false"); + offset += query_length; + break; + case SQ_TYPE_INT64: + item_query = proto_tree_add_text(tree, tvb, offset, 8, "int64"); + sub_tree = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); + j = spotlight_int64(tvb, sub_tree, offset, encoding) - 1; + count -= j; + offset += query_length; + break; + case SQ_TYPE_FLOAT: + item_query = proto_tree_add_text(tree, tvb, offset, 8, "float"); + sub_tree = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); + j = spotlight_float(tvb, sub_tree, offset, encoding) - 1; + count -= j; + offset += query_length; + break; + case SQ_TYPE_DATA: + switch (cpx_query_type) { + case SQ_CPX_TYPE_STRING: + proto_tree_add_text(tree, tvb, offset, query_length, "string: '%s'", + tvb_get_ephemeral_string(tvb, offset + 8, query_length - 8)); + break; + case SQ_CPX_TYPE_FILEMETA: + item_query = proto_tree_add_text(tree, tvb, offset, query_length, "filemeta"); + sub_tree = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); + (void)dissect_spotlight(tvb, sub_tree, offset + 8); + break; + } + offset += query_length; + break; + case SQ_TYPE_CNIDS: + item_query = proto_tree_add_text(tree, tvb, offset, query_length, "CNID Array"); + sub_tree = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); + spotlight_CNID_array(tvb, sub_tree, offset + 8, encoding); + offset += query_length; + break; + default: + item_query = proto_tree_add_text(tree, tvb, offset, query_length, "type: %s", + spotlight_get_qtype_string(query_type)); + offset += query_length; + break; + } + count--; + } + + return offset; +} + static gint dissect_spotlight(tvbuff_t *tvb, proto_tree *tree, gint offset) { + guint encoding; gint i; - gint mdlen; - gint query_offset; - gint query_offset_next; gint querylen; gint toc_offset; - gint num_queries; - gint query_data_len; - guint64 query_data64; + gint toc_entries; guint64 toc_entry; - guint8 *mds; - + proto_item *item_queries_data; proto_tree *sub_tree_queries; proto_item *item_toc; proto_tree *sub_tree_toc; - proto_item *item_query; - proto_tree *sub_tree_query; - proto_item *item_data; - proto_tree *sub_tree_data; if (strncmp(tvb_get_ephemeral_string(tvb, offset, 8), "md031234", 8) == 0) - spotlight_endianess = SPOTLIGHT_BIG_ENDIAN; + encoding = ENC_BIG_ENDIAN; else - spotlight_endianess = SPOTLIGHT_LITTLE_ENDIAN; + encoding = ENC_LITTLE_ENDIAN; proto_tree_add_text(tree, tvb, offset, 8, "Endianess: %s", - spotlight_endianess == SPOTLIGHT_BIG_ENDIAN ? + encoding == ENC_BIG_ENDIAN ? "Big Endian" : "Litte Endian"); offset += 8; - toc_offset = (gint)(spotlight_ntoh64(tvb, offset) >> 32) * 8 - 8; - querylen = (gint)(spotlight_ntoh64(tvb, offset) & 0xffffffff) * 8 - 8; + toc_offset = (gint)(spotlight_ntoh64(tvb, offset, encoding) >> 32) * 8 - 8; + querylen = (gint)(spotlight_ntoh64(tvb, offset, encoding) & 0xffffffff) * 8 - 8; proto_tree_add_text(tree, tvb, offset, @@ -4024,144 +4278,61 @@ dissect_spotlight(tvbuff_t *tvb, proto_tree *tree, gint offset) querylen); offset += 8; - num_queries = (gint)(spotlight_ntoh64(tvb, offset + toc_offset) & 0xffff) - 1; + toc_offset += offset; + toc_entries = (gint)(spotlight_ntoh64(tvb, toc_offset, encoding) & 0xffff) - 1; item_queries_data = proto_tree_add_text(tree, tvb, offset, toc_offset, - "Query data (%u queries)", - num_queries); - + "Spotlight RPC data"); sub_tree_queries = proto_item_add_subtree(item_queries_data, ett_afp_spotlight_queries); - /* Queries */ - query_offset_next = (gint)(spotlight_ntoh64(tvb, offset + toc_offset + 8) & 0xff) * 8 - 16; - for (i = 0; i < num_queries; i++) { - query_offset = query_offset_next; - if (i == num_queries - 1) - /* last */ - query_offset_next = toc_offset; - else - /* peek at next offset */ - query_offset_next = (gint)(spotlight_ntoh64(tvb, offset + toc_offset + 8 + (i+1)*8) & 0xff) * 8 - 16; - - /* this is obviously the length of one query */ - query_data_len = query_offset_next - query_offset; - - if (query_data_len > 8) - item_query = proto_tree_add_text(sub_tree_queries, - tvb, - offset + query_offset, - query_data_len, - "Query %u", - i + 1); - else - item_query = proto_tree_add_text(sub_tree_queries, - tvb, - offset + query_offset, - query_data_len, - "Query %u (empty?)", - i + 1); - - /* tree per query */ - sub_tree_query = proto_item_add_subtree(item_query, ett_afp_spotlight_query_line); - query_data64 = spotlight_ntoh64(tvb, offset + query_offset); - - /* print the query line */ - proto_tree_add_text(sub_tree_query, - tvb, - offset + query_offset, - 8, - "Index: %" G_GINT64_MODIFIER "u, ?: 0x%08" G_GINT64_MODIFIER "x", - query_data64 >> 32, - query_data64 & 0xffffffff); - - /* really any data in the query */ - if (query_data_len > 8) { - /* populate the query tree */ - query_data64 = spotlight_ntoh64(tvb, offset + query_offset + 8); - mdlen = (gint)((query_data64 & 0xffff) - 1) * 8; - proto_tree_add_text(sub_tree_query, - tvb, - offset + query_offset + 8, - 8, - "?(reappears in ToC): 0x%08" G_GINT64_MODIFIER "x, ?: 0x%04" G_GINT64_MODIFIER "x, strlen: ((%u-1)*8 = ) %u", - query_data64 >> 32, - (query_data64 & 0xffff0000) >> 16, - mdlen/8+1, - mdlen); - - mds = tvb_get_ephemeral_string(tvb, offset + query_offset + 16, mdlen); - proto_item_append_text(item_query, ": \"%s\"", mds); - - proto_tree_add_text(sub_tree_query, - tvb, - offset + query_offset + 16, - mdlen, - "mdstring: \"%s\" (%u bytes)", - mds, - mdlen); - - item_data = proto_tree_add_text(sub_tree_query, - tvb, - offset + query_offset + 16 + mdlen, - query_data_len - 16 - mdlen, - "data: %u bytes", - query_data_len - 16 - mdlen); - - /* If there are more then 8 bytes theres at least x*8+8 bytes */ - if ((query_data_len - 16 - mdlen) >= 16) { - sub_tree_data = proto_item_add_subtree(item_data, ett_afp_spotlight_data); - query_data64 = spotlight_ntoh64(tvb, offset + query_offset + 16 + mdlen); - - proto_tree_add_text(sub_tree_data, - tvb, - offset + query_offset + 16 + mdlen, - 8, - "data: %" G_GINT64_MODIFIER "u * 8 (= %" G_GINT64_MODIFIER "u) bytes, ?: 0x%04" G_GINT64_MODIFIER "x", - (query_data64 & G_GINT64_CONSTANT(0xffffffff00000000)) >> 32, - ((query_data64 & G_GINT64_CONSTANT(0xffffffff00000000)) >> 32) * 8, - query_data64 & 0xffffffff); - proto_tree_add_text(sub_tree_data, - tvb, - offset + query_offset + 16 + mdlen + 8, - query_data_len - 16 - mdlen - 8, - "data: %u bytes", - query_data_len - 16 - mdlen - 8); - } - } - } - offset += toc_offset; + /* Queries */ + offset = spotlight_dissect_query_loop(tvb, sub_tree_queries, offset, SQ_CPX_TYPE_ARRAY, INT_MAX, toc_offset + 8, encoding); /* ToC */ + offset = toc_offset; item_toc = proto_tree_add_text(tree, tvb, offset, querylen - toc_offset, - "ToC (%u entries)", - num_queries); + "Complex types ToC (%u entries)", + toc_entries); sub_tree_toc = proto_item_add_subtree(item_toc, ett_afp_spotlight_toc); - proto_tree_add_text(sub_tree_toc, - tvb, - offset, - 8, - "Number of entries (%u)", - num_queries); - for (i = 0; i < num_queries; i++) { - toc_entry = spotlight_ntoh64(tvb, offset + 8 + i*8); - proto_tree_add_text(sub_tree_toc, - tvb, - offset + 8 + i*8, - 8, - "Index: %u, ?(reappears in queries): 0x%08" G_GINT64_MODIFIER "x, ?: 0x%04" G_GINT64_MODIFIER "x, Offset: %" G_GINT64_MODIFIER "u", - i+1, - toc_entry >> 32, - (toc_entry & 0xffff0000) >> 16, - (toc_entry & 0xffff) * 8); - } - - offset += querylen - toc_offset; + proto_tree_add_text(sub_tree_toc, tvb, offset, 2, "Number of entries (%u)", toc_entries); + proto_tree_add_text(sub_tree_toc, tvb, offset + 2, 2, "unknown"); + proto_tree_add_text(sub_tree_toc, tvb, offset + 4, 4, "unknown"); + + offset += 8; + for (i = 0; i < toc_entries; i++, offset += 8) { + toc_entry = spotlight_ntoh64(tvb, offset, encoding); + if ((((toc_entry & 0xffff0000) >> 16) == SQ_CPX_TYPE_ARRAY) + || (((toc_entry & 0xffff0000) >> 16) == SQ_CPX_TYPE_DICT)) { + proto_tree_add_text(sub_tree_toc, + tvb, + offset, + 8, + "%u: count: %" G_GINT64_MODIFIER "u, type: %s, offset: %" G_GINT64_MODIFIER "u", + i+1, + toc_entry >> 32, + spotlight_get_cpx_qtype_string((toc_entry & 0xffff0000) >> 16), + (toc_entry & 0xffff) * 8); + } else { + proto_tree_add_text(sub_tree_toc, + tvb, + offset, + 8, + "%u: unknown: 0x%08" G_GINT64_MODIFIER "x, type: %s, offset: %" G_GINT64_MODIFIER "u", + i+1, + toc_entry >> 32, + spotlight_get_cpx_qtype_string((toc_entry & 0xffff0000) >> 16), + (toc_entry & 0xffff) * 8); + } + + + } + return offset; } @@ -6278,11 +6449,6 @@ proto_register_afp(void) FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_afp_spotlight_mdstring, - { "mdquery string", "afp.spotlight.mds", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - NULL, HFILL }}, - { &hf_afp_unknown, { "Unknown parameter", "afp.unknown", FT_BYTES, BASE_NONE, NULL, 0x0, |