aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>2005-11-12 07:45:01 +0000
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>2005-11-12 07:45:01 +0000
commit7c3b0a0d6d82fc27a103e7c93e89b5c77da56a58 (patch)
treed1747244274c961e6c7ca2834abe3ddfcbf312b3 /epan/dissectors
parent230c83e69604eb305fb22edc9be56b478b5976e2 (diff)
in order to handle dcerpc over smb2 later and to make the heuristics stronger for determining what might and what might not be a pipe
add TID tracking. for all TreeConnect requests/resposnes seen, store the name->tid mapping and other metadata. as a freebee the disswection of the tid in the ehader is aware of this table so when a tid value is dissected in the header and we known the name for this tid then put it in an expansion below the tid. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@16483 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/packet-smb2.c186
-rw-r--r--epan/dissectors/packet-smb2.h14
2 files changed, 151 insertions, 49 deletions
diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c
index ae244cab2a..54820cb82e 100644
--- a/epan/dissectors/packet-smb2.c
+++ b/epan/dissectors/packet-smb2.c
@@ -111,6 +111,7 @@ static gint ett_smb2_file_info_0d = -1;
static gint ett_smb2_fs_info_01 = -1;
static gint ett_smb2_fs_info_05 = -1;
static gint ett_smb2_sec_info_00 = -1;
+static gint ett_smb2_tid_tree = -1;
static dissector_handle_t gssapi_handle = NULL;
@@ -176,6 +177,30 @@ smb2_saved_info_hash_matched(gconstpointer k)
return hash;
}
+/* For Tids of a specific conversation.
+ This keeps track of tid->sharename mappings and other information about the
+ tid.
+ qqq
+ We might need to refine this if it occurs that tids are reused on a single
+ conversation. we dont worry about that yet for simplicity
+*/
+static gint
+smb2_tid_info_equal(gconstpointer k1, gconstpointer k2)
+{
+ smb2_tid_info_t *key1 = (smb2_tid_info_t *)k1;
+ smb2_tid_info_t *key2 = (smb2_tid_info_t *)k2;
+ return key1->tid==key2->tid;
+}
+static guint
+smb2_tid_info_hash(gconstpointer k)
+{
+ smb2_tid_info_t *key = (smb2_tid_info_t *)k;
+ guint32 hash;
+
+ hash=key->tid;
+ return hash;
+}
+
@@ -223,8 +248,8 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
case FID_MODE_OPEN:
offset = dissect_nt_guid_hnd(tvb, offset, pinfo, tree, drep, hf_smb2_fid, &policy_hnd, &hnd_item, TRUE, FALSE);
if(!pinfo->fd->flags.visited){
- if(si->saved && si->saved->create_name){
- fid_name = se_strdup_printf("File:%s", si->saved->create_name);
+ if(si->saved && si->saved->private_data){
+ fid_name = se_strdup_printf("File:%s", (char *)si->saved->private_data);
} else {
fid_name = se_strdup_printf("File: ");
}
@@ -232,8 +257,8 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
fid_name);
}
/*
- if (hnd_item && si->saved && si->saved->create_name)
- proto_item_append_text(hnd_item, "%s", si->saved->create_name);
+ if (hnd_item && si->saved && si->saved->private_data)
+ proto_item_append_text(hnd_item, "%s", si->saved->private_data);
*/
break;
case FID_MODE_CLOSE:
@@ -559,6 +584,13 @@ dissect_smb2_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree
}
offset += tree_len;
+ /* tree_len +1 is overkill here if the string is unicode,
+ * but who ever has more than a handful of TCON in a trace anyways
+ */
+ if(!pinfo->fd->flags.visited && si->saved && name && tree_len){
+ si->saved->private_data=se_alloc(tree_len+1);
+ g_snprintf((char *)si->saved->private_data,tree_len+1,"%s",name);
+ }
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, " Tree:%s",
@@ -568,6 +600,33 @@ dissect_smb2_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree
return offset;
}
+static int
+dissect_smb2_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_)
+{
+ if(!pinfo->fd->flags.visited && si->saved && si->saved->private_data) {
+ smb2_tid_info_t *tid, tid_key;
+
+
+ tid_key.tid=si->tid;
+ tid=g_hash_table_lookup(si->conv->tids, &tid_key);
+ if(tid){
+ g_hash_table_remove(si->conv->tids, &tid_key);
+ }
+ tid=se_alloc(sizeof(smb2_tid_info_t));
+ tid->tid=si->tid;
+ tid->flags=0;
+ tid->name=(char *)si->saved->private_data;
+ g_hash_table_insert(si->conv->tids, tid, tid);
+
+ si->saved->private_data=NULL;
+ }
+
+ /* some unknown bytes */
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, TRUE);
+ offset += 16;
+
+ return offset;
+}
static int
@@ -1034,13 +1093,13 @@ dissect_smb2_create_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* save the name if it looks sane */
if(!pinfo->fd->flags.visited){
- if(si->saved && si->saved->create_name){
- g_free(si->saved->create_name);
- si->saved->create_name=NULL;
+ if(si->saved && si->saved->private_data){
+ g_free(si->saved->private_data);
+ si->saved->private_data=NULL;
}
if(si->saved && length && (length<256)){
- si->saved->create_name=g_malloc(length+1);
- g_snprintf(si->saved->create_name, length+1, "%s", name);
+ si->saved->private_data=g_malloc(length+1);
+ g_snprintf(si->saved->private_data, length+1, "%s", name);
}
}
@@ -1091,10 +1150,10 @@ dissect_smb2_create_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
/* fid */
offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_OPEN);
- /* free si->saved->create_name we dont need it any more */
- if(si->saved && si->saved->create_name){
- g_free(si->saved->create_name);
- si->saved->create_name=NULL;
+ /* free si->saved->private_data we dont need it any more */
+ if(si->saved && si->saved->private_data){
+ g_free(si->saved->private_data);
+ si->saved->private_data=NULL;
}
/* some unknown bytes */
@@ -1434,7 +1493,7 @@ static smb2_function smb2_dissector[256] = {
/* 0x02 */ {NULL, NULL},
/* 0x03 TreeConnect*/
{dissect_smb2_tree_connect_request,
- NULL},
+ dissect_smb2_tree_connect_response},
/* 0x04 */ {NULL, NULL},
/* 0x05 Create*/
{dissect_smb2_create_request,
@@ -1735,6 +1794,32 @@ dissect_smb2_command(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int of
return offset;
}
+static int
+dissect_smb2_tid(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, smb2_info_t *si)
+{
+ proto_item *tid_item=NULL;
+ proto_tree *tid_tree=NULL;
+ smb2_tid_info_t *tid, tid_key;
+
+ /* Tree ID */
+ si->tid=tvb_get_letohl(tvb, offset);
+ tid_item=proto_tree_add_item(tree, hf_smb2_tid, tvb, offset, 4, TRUE);
+ if(tree){
+ tid_tree=proto_item_add_subtree(tid_item, ett_smb2_tid_tree);
+ }
+
+ /* see if we can find the name for this tid */
+ tid_key.tid=si->tid;
+ tid=g_hash_table_lookup(si->conv->tids, &tid_key);
+ if(tid){
+ proto_tree_add_string(tid_tree, hf_smb2_tree, tvb, offset, 4, tid->name);
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
static void
dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
@@ -1746,7 +1831,6 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
int old_offset;
guint16 header_len;
conversation_t *conversation;
- smb2_conv_info_t *sci;
smb2_saved_info_t *ssi=NULL, ssi_key;
smb2_info_t *si;
@@ -1754,6 +1838,35 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
si->conv=NULL;
si->saved=NULL;
+
+ /* find which conversation we are part of and get the data for that
+ * conversation
+ */
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if(!conversation){
+ /* OK this is a new conversation so lets create it */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ si->conv=conversation_get_proto_data(conversation, proto_smb2);
+ if(!si->conv){
+ /* no smb2_into_t structure for this conversation yet,
+ * create it.
+ */
+ si->conv=se_alloc(sizeof(smb2_conv_info_t));
+ /* qqq this leaks memory for now since we never free
+ the hashtables */
+ si->conv->matched= g_hash_table_new(smb2_saved_info_hash_matched,
+ smb2_saved_info_equal_matched);
+ si->conv->unmatched= g_hash_table_new(smb2_saved_info_hash_unmatched,
+ smb2_saved_info_equal_unmatched);
+ si->conv->tids= g_hash_table_new(smb2_tid_info_hash,
+ smb2_tid_info_equal);
+
+ conversation_add_proto_data(conversation, proto_smb2, si->conv);
+ }
+
+
if (check_col(pinfo->cinfo, COL_PROTOCOL)){
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB2");
}
@@ -1767,6 +1880,7 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
tree = proto_item_add_subtree(item, ett_smb2);
}
+
if (tree) {
header_item = proto_tree_add_text(tree, tvb, offset, -1, "SMB2 Header");
header_tree = proto_item_add_subtree(header_item, ett_smb2_header);
@@ -1821,8 +1935,7 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
offset += 4;
/* Tree ID */
- proto_tree_add_item(header_tree, hf_smb2_tid, tvb, offset, 4, TRUE);
- offset += 4;
+ offset = dissect_smb2_tid(pinfo, header_tree, tvb, offset, si);
/* User ID */
proto_tree_add_item(header_tree, hf_smb2_uid, tvb, offset, 8, TRUE);
@@ -1853,33 +1966,9 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
}
- /* find which conversation we are part of and get the tables for that
- * conversation
- */
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
- if(!conversation){
- /* OK this is a new conversation so lets create it */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
- pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
- }
- sci=conversation_get_proto_data(conversation, proto_smb2);
- if(!sci){
- /* no smb2_into_t structure for this conversation yet,
- * create it.
- */
- sci=se_alloc(sizeof(smb2_conv_info_t));
- /* qqq this leaks memory for now since we never free
- the hashtables */
- sci->matched= g_hash_table_new(smb2_saved_info_hash_matched,
- smb2_saved_info_equal_matched);
- sci->unmatched= g_hash_table_new(smb2_saved_info_hash_unmatched,
- smb2_saved_info_equal_unmatched);
-
- conversation_add_proto_data(conversation, proto_smb2, sci);
- }
if(!pinfo->fd->flags.visited){
/* see if we can find this seqnum in the unmatched table */
- ssi=g_hash_table_lookup(sci->unmatched, &ssi_key);
+ ssi=g_hash_table_lookup(si->conv->unmatched, &ssi_key);
if(!si->response){
/* This is a request */
@@ -1888,7 +1977,7 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
* an older ssi so just delete the previous
* one
*/
- g_hash_table_remove(sci->unmatched, ssi);
+ g_hash_table_remove(si->conv->unmatched, ssi);
ssi=NULL;
}
@@ -1900,24 +1989,24 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
ssi->class=0;
ssi->infolevel=0;
ssi->seqnum=ssi_key.seqnum;
- ssi->create_name=NULL;
+ ssi->private_data=NULL;
ssi->frame_req=pinfo->fd->num;
ssi->frame_res=0;
ssi->req_time=pinfo->fd->abs_ts;
- g_hash_table_insert(sci->unmatched, ssi, ssi);
+ g_hash_table_insert(si->conv->unmatched, ssi, ssi);
}
} else {
/* This is a response */
if(ssi){
/* just set the response frame and move it to the matched table */
ssi->frame_res=pinfo->fd->num;
- g_hash_table_remove(sci->unmatched, ssi);
- g_hash_table_insert(sci->matched, ssi, ssi);
+ g_hash_table_remove(si->conv->unmatched, ssi);
+ g_hash_table_insert(si->conv->matched, ssi, ssi);
}
}
} else {
/* see if we can find this seqnum in the matched table */
- ssi=g_hash_table_lookup(sci->matched, &ssi_key);
+ ssi=g_hash_table_lookup(si->conv->matched, &ssi_key);
}
if(ssi){
@@ -2166,6 +2255,7 @@ proto_register_smb2(void)
&ett_smb2_fs_info_01,
&ett_smb2_fs_info_05,
&ett_smb2_sec_info_00,
+ &ett_smb2_tid_tree,
};
proto_smb2 = proto_register_protocol("SMB2 (Server Message Block Protocol version 2)",
diff --git a/epan/dissectors/packet-smb2.h b/epan/dissectors/packet-smb2.h
index 7cc81bce93..55a5b8e6cb 100644
--- a/epan/dissectors/packet-smb2.h
+++ b/epan/dissectors/packet-smb2.h
@@ -37,16 +37,26 @@ ETH_VAR_IMPORT const value_string smb2_cmd_vals[];
* There is no guarantee we will have this structure available for all
* SMB2 packets so a dissector must check this pointer for NULL
* before dereferencing it.
+ *
+ * private data is set to NULL when the structure is created. It is used
+ * for communications between the Request and the Response packets.
*/
typedef struct _smb2_saved_info_t {
guint8 class;
guint8 infolevel;
guint64 seqnum;
- char *create_name;
+ void *private_data;
guint32 frame_req, frame_res;
nstime_t req_time;
} smb2_saved_info_t;
+#define SMB2_FLAGS_TID_IS_IPC 0x00000001
+typedef struct _smb2_tid_info_t {
+ guint32 tid;
+ guint32 flags;
+ char *name;
+} smb2_tid_info_t;
+
/* Structure to keep track of conversations and the hash tables.
* There is one such structure for each conversation.
*/
@@ -54,6 +64,7 @@ typedef struct _smb2_conv_info_t {
/* these two tables are used to match requests with responses */
GHashTable *unmatched;
GHashTable *matched;
+ GHashTable *tids;
} smb2_conv_info_t;
/* This structure contains information from the SMB2 header
@@ -63,6 +74,7 @@ typedef struct _smb2_conv_info_t {
typedef struct _smb2_info_t {
guint16 opcode;
guint32 status;
+ guint32 tid;
guint64 seqnum;
gboolean response; /* is this a response ? */
smb2_conv_info_t *conv;