Hi everyone. Here's another msrpc patch. Microsoft DCERPC over SMB
allows more than one DCERPC connection to be open over a single TCP/IP
socket. Unfortunately there is no information in the DCERPC header
to determine which bind a particular request belongs to. This
information is the fid returned by the ntcreate&x and sent in the
smbtrans header.
I've added an extra entry to the conversation hash key which should
be zero for non-MSRPC DCERPC calls but set to the fid for MSRPC.
Hopefully I've done this in a nice transport independent way (I
alluded to this in my last message to the list) without making
the dcerpc dissector too ugly.
Guy, Ronnie, I would appreciate your input on this.
Regards,
Tim.
Index: packet-smb-pipe.c
===================================================================
RCS file: /cvsroot/ethereal/packet-smb-pipe.c,v
retrieving revision 1.41
diff -u -r1.41 packet-smb-pipe.c
--- packet-smb-pipe.c 2001/11/16 07:56:27 1.41
+++ packet-smb-pipe.c 2001/11/17 23:42:34
@@ -54,6 +54,7 @@
#include "smb.h"
#include "packet-smb-pipe.h"
#include "packet-smb-browse.h"
+#include "packet-dcerpc.h"
static int proto_smb_lanman = -1;
static int hf_function_code = -1;
@@ -2198,10 +2199,19 @@
static gboolean
dissect_pipe_msrpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
+ dcerpc_private_info dcerpc_priv;
+ smb_info_t *smb_priv = (smb_info_t *)pinfo->private_data;
gboolean result;
+ dcerpc_priv.transport_type = DCERPC_TRANSPORT_SMB;
+ dcerpc_priv.data.smb.fid = smb_priv->fid;
+
+ pinfo->private_data = &dcerpc_priv;
+
result = dissector_try_heuristic(msrpc_heur_subdissector_list, tvb,
pinfo, parent_tree);
+
+ pinfo->private_data = smb_priv;
if (!result)
dissect_data(tvb, 0, pinfo, parent_tree);
Index: packet-dcerpc.c
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.c,v
retrieving revision 1.14
diff -u -r1.14 packet-dcerpc.c
--- packet-dcerpc.c 2001/11/12 09:04:11 1.14
+++ packet-dcerpc.c 2001/11/17 23:42:40
@@ -234,6 +234,7 @@
typedef struct _dcerpc_conv_key {
conversation_t *conv;
guint16 ctx_id;
+ guint16 smb_fid;
} dcerpc_conv_key;
static GMemChunk *dcerpc_conv_key_chunk;
@@ -251,14 +252,15 @@
dcerpc_conv_key *key1 = (dcerpc_conv_key *)k1;
dcerpc_conv_key *key2 = (dcerpc_conv_key *)k2;
return (key1->conv == key2->conv
- && key1->ctx_id == key2->ctx_id);
+ && key1->ctx_id == key2->ctx_id
+ && key1->smb_fid == key2->smb_fid);
}
static guint
dcerpc_conv_hash (gconstpointer k)
{
dcerpc_conv_key *key = (dcerpc_conv_key *)k;
- return ((guint)key->conv) + key->ctx_id;
+ return ((guint)key->conv) + key->ctx_id + key->smb_fid;
}
@@ -450,8 +452,10 @@
}
if (tree) {
+
sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
tvb_length (tvb) - offset, FALSE);
+
if (sub_item) {
sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
}
@@ -536,6 +540,26 @@
}
+/* We need to hash in the SMB fid number to generate a unique hash table
+ key as DCERPC over SMB allows several pipes over the same TCP/IP
+ socket. */
+
+static guint16 get_smb_fid(void *private_data)
+{
+ dcerpc_private_info *priv = (dcerpc_private_info *)private_data;
+
+ if (!priv)
+ return 0; /* Nothing to see here */
+
+ /* DCERPC over smb */
+
+ if (priv->transport_type == DCERPC_TRANSPORT_SMB)
+ return priv->data.smb.fid;
+
+ /* Some other transport... */
+
+ return 0;
+}
/*
* Connection oriented packet types
@@ -618,6 +642,7 @@
key = g_mem_chunk_alloc (dcerpc_conv_key_chunk);
key->conv = conv;
key->ctx_id = ctx_id;
+ key->smb_fid = get_smb_fid(pinfo->private_data);
value = g_mem_chunk_alloc (dcerpc_conv_value_chunk);
value->uuid = if_id;
@@ -798,6 +823,7 @@
key.conv = conv;
key.ctx_id = ctx_id;
+ key.smb_fid = get_smb_fid(pinfo->private_data);
value = g_hash_table_lookup (dcerpc_convs, &key);
if (value) {
Index: packet-dcerpc.h
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.h,v
retrieving revision 1.2
diff -u -r1.2 packet-dcerpc.h
--- packet-dcerpc.h 2001/07/11 01:25:45 1.2
+++ packet-dcerpc.h 2001/11/17 23:42:41
@@ -100,5 +100,20 @@
/* registration function for subdissectors */
void dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs);
+/* Private data structure to pass to DCERPC dissector. This is used to
+ pass transport specific information down to the dissector from the
+ dissector that parsed this encapsulated calls. */
+
+#define DCERPC_TRANSPORT_SMB 1
+
+typedef struct _dcerpc_private_info {
+ int transport_type; /* Tag */
+
+ union {
+ struct { /* DCERPC_TRANSPORT_SMB */
+ guint16 fid;
+ } smb;
+ } data;
+} dcerpc_private_info;
#endif /* packet-dcerpc.h */