From Stefan Metzmacher:
[obnox/wireshark/wip.git] / epan / dissectors / packet-dcerpc.c
index cf10cbd114147fe3fa689a2504634968d27cecc9..14b852147d7a38b381917bd458e96d449f84cb17 100644 (file)
@@ -5,8 +5,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+/* The DCE RPC specification can be found at:
+ * http://www.opengroup.org/dce/
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #include <epan/packet.h>
 #include <epan/dissectors/packet-dcerpc.h>
 #include <epan/conversation.h>
-#include "prefs.h"
-#include "reassemble.h"
-#include "tap.h"
+#include <epan/prefs.h>
+#include <epan/reassemble.h>
+#include <epan/tap.h>
+#include <epan/emem.h>
 #include <epan/dissectors/packet-frame.h>
 #include <epan/dissectors/packet-dcerpc-nt.h>
+#include <epan/expert.h>
+#include <epan/strutil.h>
 
 static int dcerpc_tap = -1;
 
@@ -103,7 +110,7 @@ static const value_string authn_protocol_vals[] = {
        { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
        { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
        { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
-       { DCE_C_RPC_AUTHN_PROTOCOL_DPA, 
+       { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
                "Distributed Password Authentication SSP"},
        { DCE_C_RPC_AUTHN_PROTOCOL_MSN, "MSN SSP"},
        { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST, "Digest SSP"},
@@ -216,6 +223,8 @@ static const value_string p_provider_reason_vals[] = {
 #define DEFAULT_CONTEXT_NOT_SUPPORTED  5 /* not used */
 #define USER_DATA_NOT_READABLE         6 /* not used */
 #define NO_PSAP_AVAILABLE              7 /* not used */
+#define AUTH_TYPE_NOT_RECOGNIZED       8
+#define INVALID_CHECKSUM                       9
 
 static const value_string reject_reason_vals[] = {
        { REASON_NOT_SPECIFIED,           "Reason not specified" },
@@ -226,6 +235,8 @@ static const value_string reject_reason_vals[] = {
        { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
        { USER_DATA_NOT_READABLE,         "User data not readable" },
        { NO_PSAP_AVAILABLE,              "No PSAP available" },
+       { AUTH_TYPE_NOT_RECOGNIZED,       "Authentication type not recognized" },
+       { INVALID_CHECKSUM,               "Invalid checksum" },
        { 0,                              NULL }
 };
 
@@ -234,6 +245,10 @@ static const value_string reject_reason_vals[] = {
  */
 static const value_string reject_status_vals[] = {
        { 0,          "Stub-defined exception" },
+       { 0x00000001, "nca_s_fault_other" },
+       { 0x00000005, "nca_s_fault_access_denied" },
+       { 0x000006f7, "nca_s_fault_ndr" },
+       { 0x000006d8, "nca_s_fault_cant_perform" },
        { 0x1c000001, "nca_s_fault_int_div_by_zero" },
        { 0x1c000002, "nca_s_fault_addr_error" },
        { 0x1c000003, "nca_s_fault_fp_div_zero" },
@@ -275,12 +290,46 @@ static const value_string reject_status_vals[] = {
        { 0x1c010013, "nca_out_args_too_big" },
        { 0x1c010014, "nca_server_too_busy" },
        { 0x1c010017, "nca_unsupported_type" },
+       /* MS Windows specific values
+        * see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
+        * and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
+        * and: http://www.megos.ch/support/doserrors.txt
+        *
+        * XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
+        * at least MS protocols (like DCOM) do it that way ... */
+       { 0x80004001, "E_NOTIMPL" },
+       { 0x80004003, "E_POINTER" },
+       { 0x80004004, "E_ABORT" },
+       { 0x8000FFFF, "E_UNEXPECTED" },
+       { 0x80010105, "RPC_E_SERVERFAULT" },
+       { 0x80010108, "RPC_E_DISCONNECTED" },
+       { 0x80010113, "RPC_E_INVALID_IPID" },
+       { 0x8001011F, "RPC_E_TIMEOUT" },
+       { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
+       { 0x80020006, "DISP_E_UNKNOWNNAME" },
+       { 0x8002000E, "DISP_E_BADPARAMCOUNT" },
+       { 0x8004CB00, "CBA_E_MALFORMED" },
+       { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
+       { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
+       { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
+       { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
+       { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
+       { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
+       { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
+       { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
+       { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
+       { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
+       { 0x8004CB25, "CBA_E_MODECHANGE" },
+       { 0x8007000E, "E_OUTOFMEMORY" },
+       { 0x80070057, "E_INVALIDARG" },
+       { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
+       { 0x80070776, "OR_INVALID_OXID" },
        { 0,          NULL }
 };
 
 
 /* we need to keep track of what transport were used, ie what handle we came
- * in through so we know what kind of pinfo->private_data was passed to us.
+ * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
  */
 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
 #define DCE_TRANSPORT_UNKNOWN          0
@@ -316,11 +365,14 @@ static int hf_dcerpc_cn_max_xmit = -1;
 static int hf_dcerpc_cn_max_recv = -1;
 static int hf_dcerpc_cn_assoc_group = -1;
 static int hf_dcerpc_cn_num_ctx_items = -1;
+static int hf_dcerpc_cn_ctx_item = -1;
 static int hf_dcerpc_cn_ctx_id = -1;
 static int hf_dcerpc_cn_num_trans_items = -1;
+static int hf_dcerpc_cn_bind_abstract_syntax = -1;
 static int hf_dcerpc_cn_bind_if_id = -1;
 static int hf_dcerpc_cn_bind_if_ver = -1;
 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
+static int hf_dcerpc_cn_bind_trans_syntax = -1;
 static int hf_dcerpc_cn_bind_trans_id = -1;
 static int hf_dcerpc_cn_bind_trans_ver = -1;
 static int hf_dcerpc_cn_alloc_hint = -1;
@@ -337,6 +389,7 @@ static int hf_dcerpc_cn_protocol_ver_major = -1;
 static int hf_dcerpc_cn_protocol_ver_minor = -1;
 static int hf_dcerpc_cn_cancel_count = -1;
 static int hf_dcerpc_cn_status = -1;
+static int hf_dcerpc_cn_deseg_req = -1;
 static int hf_dcerpc_auth_type = -1;
 static int hf_dcerpc_auth_level = -1;
 static int hf_dcerpc_auth_pad_len = -1;
@@ -408,6 +461,7 @@ static gint ett_dcerpc = -1;
 static gint ett_dcerpc_cn_flags = -1;
 static gint ett_dcerpc_cn_ctx = -1;
 static gint ett_dcerpc_cn_iface = -1;
+static gint ett_dcerpc_cn_trans_syntax = -1;
 static gint ett_dcerpc_drep = -1;
 static gint ett_dcerpc_dg_flags1 = -1;
 static gint ett_dcerpc_dg_flags2 = -1;
@@ -436,38 +490,6 @@ static const fragment_items dcerpc_frag_items = {
 /* list of hooks to be called when init_protocols is done */
 GHookList dcerpc_hooks_init_protos;
 
-#ifdef _WIN32
-int ResolveWin32UUID(e_uuid_t if_id, char *UUID_NAME, int UUID_NAME_MAX_LEN)
-{
-       char REG_UUID_NAME[MAX_PATH];
-       HKEY hKey = NULL;
-       DWORD UUID_MAX_SIZE = MAX_PATH;
-       char REG_UUID_STR[MAX_PATH];
-       
-       if(UUID_NAME_MAX_LEN < 2)
-               return 0;
-       REG_UUID_NAME[0] = '\0';
-       snprintf(REG_UUID_STR, MAX_PATH, "SOFTWARE\\Classes\\Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-                       if_id.Data1, if_id.Data2, if_id.Data3,
-                       if_id.Data4[0], if_id.Data4[1],
-                       if_id.Data4[2], if_id.Data4[3],
-                       if_id.Data4[4], if_id.Data4[5],
-                       if_id.Data4[6], if_id.Data4[7]);
-       if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)REG_UUID_STR, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
-       {
-               if (RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)REG_UUID_NAME, &UUID_MAX_SIZE) == ERROR_SUCCESS && UUID_MAX_SIZE <= MAX_PATH)
-                       {
-                       snprintf(UUID_NAME, UUID_NAME_MAX_LEN, "%s", REG_UUID_NAME);
-                       RegCloseKey(hKey);
-                       return strlen(REG_UUID_NAME);
-               }
-               RegCloseKey(hKey);
-       }
-       return 0; /* we didn't find anything anyhow. Please don't use the string! */
-       
-}
-#endif
-
 static dcerpc_info *
 get_next_di(void)
 {
@@ -485,19 +507,24 @@ get_next_di(void)
 static gboolean dcerpc_cn_desegment = TRUE;
 
 /* reassemble DCE/RPC fragments */
-/* reassembly of dcerpc fragments will not work for the case where ONE frame
+/* reassembly of cl dcerpc fragments will not work for the case where ONE frame
    might contain multiple dcerpc fragments for different PDUs.
    this case would be so unusual/weird so if you got captures like that:
        too bad
+
+   reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
+   are coming in out of sequence, but that will hurt in a lot of other places as well.
 */
-static gboolean dcerpc_reassemble = FALSE;
+static gboolean dcerpc_reassemble = TRUE;
+static GHashTable *dcerpc_co_fragment_table = NULL;
 static GHashTable *dcerpc_co_reassemble_table = NULL;
 static GHashTable *dcerpc_cl_reassemble_table = NULL;
 
 static void
 dcerpc_reassemble_init(void)
 {
-  fragment_table_init(&dcerpc_co_reassemble_table);
+  fragment_table_init(&dcerpc_co_fragment_table);
+  reassembled_table_init(&dcerpc_co_reassemble_table);
   dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
 }
 
@@ -523,7 +550,7 @@ static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
        for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
                dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
 
-               if (asd->auth_level == auth_level && 
+               if (asd->auth_level == auth_level &&
                    asd->auth_type == auth_type)
                        return &asd->auth_fns;
        }
@@ -551,9 +578,9 @@ void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
 /* Hand off verifier data to a registered dissector */
 
 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
-                             proto_tree *tree, 
+                             proto_tree *tree,
                              dcerpc_auth_subdissector_fns *auth_fns,
-                             e_dce_cn_common_hdr_t *hdr, 
+                             e_dce_cn_common_hdr_t *hdr,
                              dcerpc_auth_info *auth_info)
 {
        dcerpc_dissect_fnct_t *volatile fn = NULL;
@@ -577,7 +604,7 @@ static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
                fn = auth_fns->resp_verf_fn;
                break;
 
-               /* Don't know how to handle authentication data in this 
+               /* Don't know how to handle authentication data in this
                   pdu type. */
 
        default:
@@ -588,20 +615,23 @@ static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
 
        if (fn)
                fn(auth_tvb, 0, pinfo, tree, hdr->drep);
-       else
+       else {
+               tvb_ensure_bytes_exist(auth_tvb, 0, hdr->auth_len);
                proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
-                                   "%s Verifier", 
-                                   val_to_str(auth_info->auth_type, 
+                                   "%s Verifier",
+                                   val_to_str(auth_info->auth_type,
                                               authn_protocol_vals,
                                               "Unknown (%u)"));
+       }
 }
 
 /* Hand off payload data to a registered dissector */
 
-static tvbuff_t *decode_encrypted_data(tvbuff_t *enc_tvb, 
+static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
+                                      tvbuff_t *auth_tvb,
                                       packet_info *pinfo,
                                       dcerpc_auth_subdissector_fns *auth_fns,
-                                      gboolean is_request, 
+                                      gboolean is_request,
                                       dcerpc_auth_info *auth_info)
 {
        dcerpc_decode_data_fnct_t *fn;
@@ -612,7 +642,7 @@ static tvbuff_t *decode_encrypted_data(tvbuff_t *enc_tvb,
                fn = auth_fns->resp_data_fn;
 
        if (fn)
-               return fn(enc_tvb, 0, pinfo, auth_info);
+               return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
 
        return NULL;
 }
@@ -664,12 +694,15 @@ dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
 
     hf_info = proto_registrar_get_nth(opnum_hf);
     hf_info->strings = value_string_from_subdissectors(procs);
+
+    /* add this GUID to the global name resolving */
+    guids_add_uuid(uuid, proto_get_protocol_short_name (value->proto));
 }
 
 /* Function to find the name of a registered protocol
- * or NULL if the protocol/version is not known to ethereal.
+ * or NULL if the protocol/version is not known to wireshark.
  */
-char *
+const char *
 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
 {
     dcerpc_uuid_key key;
@@ -684,7 +717,7 @@ dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
 }
 
 /* Function to find the opnum hf-field of a registered protocol
- * or -1 if the protocol/version is not known to ethereal.
+ * or -1 if the protocol/version is not known to wireshark.
  */
 int
 dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
@@ -729,7 +762,7 @@ value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
 }
 
 /* Function to find the subdissector table of a registered protocol
- * or NULL if the protocol/version is not known to ethereal.
+ * or NULL if the protocol/version is not known to wireshark.
  */
 dcerpc_sub_dissector *
 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
@@ -766,9 +799,6 @@ typedef struct _dcerpc_bind_value {
        guint16 ver;
 } dcerpc_bind_value;
 
-static GMemChunk *dcerpc_bind_key_chunk=NULL;
-static GMemChunk *dcerpc_bind_value_chunk=NULL;
-
 static gint
 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
 {
@@ -783,7 +813,10 @@ static guint
 dcerpc_bind_hash (gconstpointer k)
 {
     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
-    return GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
+    guint hash;
+
+    hash=GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
+    return hash;
 
 }
 
@@ -806,12 +839,6 @@ typedef struct _dcerpc_dg_call_key {
     e_uuid_t act_id ;
 } dcerpc_dg_call_key;
 
-static GMemChunk *dcerpc_cn_call_key_chunk=NULL;
-
-static GMemChunk *dcerpc_dg_call_key_chunk=NULL;
-
-static GMemChunk *dcerpc_call_value_chunk=NULL;
-
 
 static gint
 dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
@@ -837,14 +864,14 @@ static guint
 dcerpc_cn_call_hash (gconstpointer k)
 {
     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
-    return ((guint32)key->conv) + key->call_id + key->smb_fid;
+    return GPOINTER_TO_UINT(key->conv) + key->call_id + key->smb_fid;
 }
 
 static guint
 dcerpc_dg_call_hash (gconstpointer k)
 {
     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
-    return (((guint32)key->conv) + key->seqnum + key->act_id.Data1
+    return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.Data1
             + (key->act_id.Data2 << 16) + key->act_id.Data3
             + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
             + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
@@ -866,8 +893,6 @@ typedef struct _dcerpc_matched_key {
     guint32 call_id;
 } dcerpc_matched_key;
 
-static GMemChunk *dcerpc_matched_key_chunk=NULL;
-
 static gint
 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
 {
@@ -962,7 +987,7 @@ dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
     if (tree) {
         if(data==0xffffffff){
             /* special case,   no time specified */
-            proto_tree_add_time_format(tree, hfindex, tvb, offset, 4, &tv, "%s: No time specified", proto_registrar_get_nth(hfindex)->name);
+            proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
         } else {
             proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
         }
@@ -976,30 +1001,26 @@ dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
 int
 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
                        proto_tree *tree, guint8 *drep,
-                       int hfindex, unsigned char *pdata)
+                       int hfindex, guint64 *pdata)
 {
-    if(pdata){
-      tvb_memcpy(tvb, pdata, offset, 8);
-      if(drep[0] & 0x10){/* XXX this might be the wrong way around */
-       unsigned char data;
-       data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
-       data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
-       data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
-       data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
-      }
-    }
+    guint64 data;
+
+    data = ((drep[0] & 0x10)
+            ? tvb_get_letoh64 (tvb, offset)
+            : tvb_get_ntoh64 (tvb, offset));
 
     if (tree) {
         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
     }
-
+    if (pdata)
+        *pdata = data;
     return offset+8;
 }
 
 
 int
 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
-                    proto_tree *tree, guint8 *drep, 
+                    proto_tree *tree, guint8 *drep,
                     int hfindex, gfloat *pdata)
 {
        gfloat data;
@@ -1033,7 +1054,7 @@ dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
 
 int
 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
-                    proto_tree *tree, guint8 *drep, 
+                    proto_tree *tree, guint8 *drep,
                     int hfindex, gdouble *pdata)
 {
     gdouble data;
@@ -1065,6 +1086,29 @@ dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
 }
 
 
+int
+dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+                    proto_tree *tree, guint8 *drep,
+                    int hfindex, e_uuid_t *pdata)
+{
+    e_uuid_t uuid;
+
+
+    if (drep[0] & 0x10) {
+        tvb_get_letohguid (tvb, offset, (e_guid_t *) &uuid);
+    } else {
+        tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
+    }
+    if (tree) {
+               proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
+    }
+    if (pdata) {
+        *pdata = uuid;
+    }
+    return offset + 16;
+}
+
+
 /*
  * a couple simpler things
  */
@@ -1091,18 +1135,14 @@ dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
 void
 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
 {
-    unsigned int i;
-    uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
-    uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
-    uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
-
-    for (i=0; i<sizeof (uuid->Data4); i++) {
-        uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
+    if (drep[0] & 0x10) {
+        tvb_get_letohguid (tvb, offset, (e_guid_t *) uuid);
+    } else {
+        tvb_get_ntohguid (tvb, offset, (e_guid_t *) uuid);
     }
 }
 
 
-
 /* NDR arrays */
 /* function to dissect a unidimensional conformant array */
 int
@@ -1168,6 +1208,45 @@ dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
                proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
 
+               /* real run, dissect the elements */
+               for(i=0;i<di->array_actual_count;i++){
+                       old_offset = offset;
+                       offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+                        if (offset <= old_offset)
+                                THROW(ReportedBoundsError);
+               }
+       }
+
+       return offset;
+}
+/* function to dissect a unidimensional varying array */
+int
+dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+               proto_tree *tree, guint8 *drep,
+               dcerpc_dissect_fnct_t *fnct)
+{
+       guint32 i;
+       dcerpc_info *di;
+       int old_offset;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /* conformant run, just dissect the max_count header */
+               old_offset=offset;
+               di->conformant_run=0;
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_offset, &di->array_offset);
+               di->array_offset_offset=offset-4;
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_actual_count, &di->array_actual_count);
+               di->array_actual_count_offset=offset-4;
+               di->conformant_run=1;
+               di->conformant_eaten=offset-old_offset;
+       } else {
+               /* we dont dont remember where  in the bytestream these fields were */
+               proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
+               proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
+
                /* real run, dissect the elements */
                for(i=0;i<di->array_actual_count;i++){
                        offset = (*fnct)(tvb, offset, pinfo, tree, drep);
@@ -1193,7 +1272,7 @@ dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
    that are conformant and varying - they're stored like conformant
    varying arrays of bytes.  */
 int
-dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo, 
+dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
                             proto_tree *tree, guint8 *drep)
 {
     dcerpc_info *di;
@@ -1216,9 +1295,11 @@ dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
                                 hf_dcerpc_array_actual_count, &len);
 
-    if (tree && len)
+    if (tree && len) {
+        tvb_ensure_bytes_exist(tvb, offset, len);
         proto_tree_add_item(tree, hf_dcerpc_array_buffer,
                             tvb, offset, len, drep[0] & 0x10);
+    }
 
     offset += len;
 
@@ -1234,7 +1315,7 @@ dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
    XXX - does this need to do all the conformant array stuff that
    "dissect_ndr_ucvarray()" does?  */
 int
-dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
+dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
                     proto_tree *tree, guint8 *drep, int size_is,
                     int hfindex, gboolean add_subtree, char **data)
 {
@@ -1287,6 +1368,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
          */
         if (tree && buffer_len) {
             hfinfo = proto_registrar_get_nth(hfindex);
+            tvb_ensure_bytes_exist(tvb, offset, buffer_len);
             if (hfinfo->type == FT_STRING) {
                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
                                       buffer_len, s);
@@ -1304,6 +1386,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
          * but that's another matter; in any case, that would happen only
          * if we had an immensely large tvbuff....)
          */
+        tvb_ensure_bytes_exist(tvb, offset, buffer_len);
         s = tvb_get_string(tvb, offset, buffer_len);
         if (tree && buffer_len)
             proto_tree_add_item(string_tree, hfindex, tvb, offset,
@@ -1317,7 +1400,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
            *data = s;
     else
            g_free(s);
-    
+
     offset += buffer_len;
 
     proto_item_set_end(string_item, tvb, offset);
@@ -1335,7 +1418,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
    such as C.  Is this ever used for purely counted strings?
    (Not that it matters if it is.) */
 int
-dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
+dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        proto_tree *tree, guint8 *drep)
 {
     dcerpc_info *di;
@@ -1356,7 +1439,7 @@ dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
    such as C.  Is this ever used for purely counted strings?
    (Not that it matters if it is.) */
 int
-dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
+dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        proto_tree *tree, guint8 *drep)
 {
     dcerpc_info *di;
@@ -1367,6 +1450,142 @@ dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
                                FALSE, NULL);
 }
 
+/* Dissect an NDR varying string of elements.
+   The length of each element is given by the 'size_is' parameter;
+   the elements are assumed to be characters or wide characters.
+*/
+int
+dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                    proto_tree *tree, guint8 *drep, int size_is,
+                    int hfindex, gboolean add_subtree, char **data)
+{
+    dcerpc_info *di;
+    proto_item *string_item;
+    proto_tree *string_tree;
+    guint32 len, buffer_len;
+    char *s;
+    header_field_info *hfinfo;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
+
+    if (add_subtree) {
+        string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
+                                          proto_registrar_get_name(hfindex));
+        string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
+    } else {
+        string_item = NULL;
+        string_tree = tree;
+    }
+
+    /* NDR array header */
+    offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
+                                hf_dcerpc_array_offset, NULL);
+
+    offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
+                                hf_dcerpc_array_actual_count, &len);
+
+    buffer_len = size_is * len;
+
+    /* Adjust offset */
+    if (offset % size_is)
+        offset += size_is - (offset % size_is);
+
+    if (size_is == sizeof(guint16)) {
+        /* XXX - use drep to determine the byte order? */
+        s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
+        /*
+         * XXX - we don't support a string type with Unicode
+         * characters, so if this is a string item, we make
+         * its value be the "fake Unicode" string.
+         */
+        if (tree && buffer_len) {
+            hfinfo = proto_registrar_get_nth(hfindex);
+            tvb_ensure_bytes_exist(tvb, offset, buffer_len);
+            if (hfinfo->type == FT_STRING) {
+                proto_tree_add_string(string_tree, hfindex, tvb, offset,
+                                      buffer_len, s);
+            } else {
+                proto_tree_add_item(string_tree, hfindex, tvb, offset,
+                                    buffer_len, drep[0] & 0x10);
+            }
+        }
+    } else {
+        /*
+         * "tvb_get_string()" throws an exception if the entire string
+         * isn't in the tvbuff.  If the length is bogus, this should
+         * keep us from trying to allocate an immensely large buffer.
+         * (It won't help if the length is *valid* but immensely large,
+         * but that's another matter; in any case, that would happen only
+         * if we had an immensely large tvbuff....)
+         */
+        tvb_ensure_bytes_exist(tvb, offset, buffer_len);
+        s = tvb_get_string(tvb, offset, buffer_len);
+        if (tree && buffer_len)
+            proto_tree_add_item(string_tree, hfindex, tvb, offset,
+                                buffer_len, drep[0] & 0x10);
+    }
+
+    if (string_item != NULL)
+        proto_item_append_text(string_item, ": %s", s);
+
+    if (data)
+           *data = s;
+    else
+           g_free(s);
+
+    offset += buffer_len;
+
+    proto_item_set_end(string_item, tvb, offset);
+
+    return offset;
+}
+/* Dissect an varying string of chars.
+   This corresponds to IDL of the form '[string] char *foo'.
+
+   XXX - at least according to the DCE RPC 1.1 spec, a string has
+   a null terminator, which isn't necessary as a terminator for
+   the transfer language (as there's a length), but is presumably
+   there for the benefit of null-terminated-string languages
+   such as C.  Is this ever used for purely counted strings?
+   (Not that it matters if it is.) */
+int
+dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                       proto_tree *tree, guint8 *drep)
+{
+    dcerpc_info *di;
+    di=pinfo->private_data;
+
+    return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
+                               sizeof(guint8), di->hf_index,
+                               FALSE, NULL);
+}
+
+/* Dissect a varying string of wchars (wide characters).
+   This corresponds to IDL of the form '[string] wchar *foo'
+
+   XXX - at least according to the DCE RPC 1.1 spec, a string has
+   a null terminator, which isn't necessary as a terminator for
+   the transfer language (as there's a length), but is presumably
+   there for the benefit of null-terminated-string languages
+   such as C.  Is this ever used for purely counted strings?
+   (Not that it matters if it is.) */
+int
+dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                       proto_tree *tree, guint8 *drep)
+{
+    dcerpc_info *di;
+    di=pinfo->private_data;
+
+    return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
+                               sizeof(guint16), di->hf_index,
+                               FALSE, NULL);
+}
+
+
 /* ndr pointer handling */
 /* list of pointers encountered so far */
 static GSList *ndr_pointer_list = NULL;
@@ -1412,7 +1631,7 @@ init_ndr_pointer_list(packet_info *pinfo)
        pointers_are_top_level=TRUE;
 }
 
-static int
+int
 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
 {
        int found_new_pointer;
@@ -1446,7 +1665,7 @@ dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8
                                old_offset = offset;
                                offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
 
-                               g_assert((offset-old_offset)==di->conformant_eaten);
+                               DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
                                /* This is to check for any bugs in the dissectors.
                                 *
                                 * Basically, the NDR representation will store all
@@ -1510,7 +1729,7 @@ dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8
 
 static void
 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
-                   dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index, 
+                   dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
                    dcerpc_callback_fnct_t *callback, void *callback_args)
 {
        ndr_pointer_data_t *npd;
@@ -1600,10 +1819,12 @@ find_pointer_index(guint32 id)
 int
 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                    proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
-                   int type, char *text, int hf_index, 
+                   int type, const char *text, int hf_index,
                    dcerpc_callback_fnct_t *callback, void *callback_args)
 {
        dcerpc_info *di;
+       proto_tree *tr = NULL;
+       gint start_offset = offset;
 
        di=pinfo->private_data;
        if(di->conformant_run){
@@ -1618,14 +1839,13 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
        if( pointers_are_top_level
        &&(type==NDR_POINTER_REF) ){
                proto_item *item;
-               proto_tree *tr;
 
                /* we must find out a nice way to do the length here */
                item=proto_tree_add_text(tree, tvb, offset, 0,
                        "%s", text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
 
-               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
+               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
                                    hf_index, callback, callback_args);
                goto after_ref_id;
        }
@@ -1636,11 +1856,11 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                int idx;
                guint32 id;
                proto_item *item;
-               proto_tree *tr;
 
                /* get the referent id */
                offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
 
+               tvb_ensure_bytes_exist(tvb, offset-4, 4);
                /* we got a NULL pointer */
                if(id==0){
                        proto_tree_add_text(tree, tvb, offset-4, 4,
@@ -1663,7 +1883,7 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        "%s", text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
                proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
-               add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index, 
+               add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
                                    callback, callback_args);
                goto after_ref_id;
        }
@@ -1672,11 +1892,11 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
        && (type==NDR_POINTER_UNIQUE) ){
                guint32 id;
                proto_item *item;
-               proto_tree *tr;
 
                /* get the referent id */
                offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
 
+               tvb_ensure_bytes_exist(tvb, offset-4, 4);
                /* we got a NULL pointer */
                if(id==0){
                        proto_tree_add_text(tree, tvb, offset-4, 4,
@@ -1689,7 +1909,7 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        "%s", text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
                proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
-               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
+               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
                                    hf_index, callback, callback_args);
                goto after_ref_id;
        }
@@ -1699,17 +1919,17 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
        && (type==NDR_POINTER_REF) ){
                guint32 id;
                proto_item *item;
-               proto_tree *tr;
 
                /* get the referent id */
                offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
 
+               tvb_ensure_bytes_exist(tvb, offset-4, 4);
                /* new pointer */
                item=proto_tree_add_text(tree, tvb, offset-4, 4,
                        "%s",text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
                proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
-               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
+               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
                                    hf_index, callback, callback_args);
                goto after_ref_id;
        }
@@ -1719,11 +1939,11 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
        && (type==NDR_POINTER_UNIQUE) ){
                guint32 id;
                proto_item *item;
-               proto_tree *tr;
 
                /* get the referent id */
                offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
 
+               tvb_ensure_bytes_exist(tvb, offset-4, 4);
                /* we got a NULL pointer */
                if(id==0){
                        proto_tree_add_text(tree, tvb, offset-4, 4,
@@ -1736,7 +1956,7 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        "%s",text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
                proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
-               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
+               add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
                                    hf_index, callback, callback_args);
                goto after_ref_id;
        }
@@ -1747,11 +1967,11 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                int idx;
                guint32 id;
                proto_item *item;
-               proto_tree *tr;
 
                /* get the referent id */
                offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
 
+               tvb_ensure_bytes_exist(tvb, offset-4, 4);
                /* we got a NULL pointer */
                if(id==0){
                        proto_tree_add_text(tree, tvb, offset-4, 4,
@@ -1774,7 +1994,7 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        "%s", text);
                tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
                proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
-               add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index, 
+               add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
                                    callback, callback_args);
                goto after_ref_id;
        }
@@ -1790,24 +2010,55 @@ after_ref_id:
                pointers_are_top_level=TRUE;
        }
 
+       /* Set the length for the new subtree */
+       if (tr){
+               proto_item_set_len(tr, offset-start_offset);
+       }
        return offset;
 }
 
 int
 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                    proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
-                   int type, char *text, int hf_index)
+                   int type, const char *text, int hf_index)
 {
        return dissect_ndr_pointer_cb(
                tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
                NULL, NULL);
 }
+int
+dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                   proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
+                   int type, const char *text, int hf_index)
+{
+       int ret;
+
+       pointers_are_top_level=TRUE;
+       ret=dissect_ndr_pointer_cb(
+               tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
+               NULL, NULL);
+       return ret;
+}
+int
+dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                   proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
+                   int type, const char *text, int hf_index)
+{
+       int ret;
+
+       pointers_are_top_level=FALSE;
+       ret=dissect_ndr_pointer_cb(
+               tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
+               NULL, NULL);
+       return ret;
+}
 
 static void
 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
                 dcerpc_auth_info *auth_info, gboolean is_encrypted)
 {
-    int length;
+    int length, plain_length, auth_pad_len;
+    guint auth_pad_offset;
 
     /*
      * We don't show stub data unless we have some in the tvbuff;
@@ -1816,23 +2067,47 @@ show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
      * that happen to be in the tvbuff.
      */
     if (tvb_length_remaining (tvb, offset) > 0) {
+       auth_pad_len = auth_info?auth_info->auth_pad_len:0;
         length = tvb_reported_length_remaining (tvb, offset);
+
+       /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
+       plain_length = length - auth_pad_len;
+       if (plain_length < 1) {
+           plain_length = length;
+           auth_pad_len = 0;
+       }
+       auth_pad_offset = offset + plain_length;
+
         if (auth_info != NULL &&
             auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
             if (is_encrypted) {
-                proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+               tvb_ensure_bytes_exist(tvb, offset, length);
+                proto_tree_add_text(dcerpc_tree, tvb, offset, length,
                                     "Encrypted stub data (%d byte%s)",
                                     length, plurality(length, "", "s"));
+               /* is the padding is still inside the encrypted blob, don't display it explicit */
+               auth_pad_len = 0;
             } else {
-                proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+               tvb_ensure_bytes_exist(tvb, offset, plain_length);
+                proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
                                     "Decrypted stub data (%d byte%s)",
-                                    length, plurality(length, "", "s"));
+                                    plain_length, plurality(plain_length, "", "s"));
             }
         } else {
-            proto_tree_add_text (dcerpc_tree, tvb, offset, -1,
-                                 "Stub data (%d byte%s)", length,
-                                 plurality(length, "", "s"));
+           tvb_ensure_bytes_exist(tvb, offset, plain_length);
+            proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
+                                 "Stub data (%d byte%s)", plain_length,
+                                 plurality(plain_length, "", "s"));
         }
+        /* If there is auth padding at the end of the stub, display it */
+        if (auth_pad_len != 0) {
+               tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
+                proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
+                                     auth_pad_len,
+                                     "Auth Padding (%u byte%s)",
+                                     auth_pad_len,
+                                     plurality(auth_pad_len, "", "s"));
+            }
     }
 }
 
@@ -1848,17 +2123,16 @@ dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
     dcerpc_uuid_value *sub_proto;
     proto_tree *volatile sub_tree = NULL;
     dcerpc_sub_dissector *proc;
-    gchar *name = NULL;
+    const gchar *name = NULL;
     dcerpc_dissect_fnct_t *volatile sub_dissect;
     const char *volatile saved_proto;
     void *volatile saved_private_data;
-    guint length, reported_length;
+    guint length = 0, reported_length = 0;
     tvbuff_t *volatile stub_tvb;
     volatile guint auth_pad_len;
     volatile int auth_pad_offset;
-#ifdef _WIN32
-    char UUID_NAME[MAX_PATH];
-#endif
+    proto_item *sub_item=NULL;
+    proto_item *pi;
 
     key.uuid = info->call_data->uuid;
     key.ver = info->call_data->ver;
@@ -1874,20 +2148,8 @@ dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
        proto_tree_add_boolean_hidden(dcerpc_tree, hf_dcerpc_unknown_if_id,
                                          tvb, offset, 0, TRUE);
        if (check_col (pinfo->cinfo, COL_INFO)) {
-#ifdef _WIN32
-               if(ResolveWin32UUID(info->call_data->uuid, UUID_NAME, MAX_PATH))
-                       col_append_fstr (pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
-                               UUID_NAME, info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
-                               info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
-                               info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
-                               info->call_data->uuid.Data4[7], info->call_data->ver);
-else
-#endif
-               col_append_fstr (pinfo->cinfo, COL_INFO, " UNKUUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
-                       info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
-                       info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
-                       info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
-                       info->call_data->uuid.Data4[7], info->call_data->ver);
+               col_append_fstr (pinfo->cinfo, COL_INFO, " %s V%u",
+                       guids_resolve_uuid_to_str(&info->call_data->uuid), info->call_data->ver);
        }
 
         if (decrypted_tvb != NULL) {
@@ -1917,10 +2179,13 @@ else
                       name, (info->ptype == PDU_REQ) ? "request" : "response");
     }
 
+    sub_dissect = (info->ptype == PDU_REQ) ?
+           proc->dissect_rqst : proc->dissect_resp;
+
     if (tree) {
-        proto_item *sub_item;
-        sub_item = proto_tree_add_item (tree, sub_proto->proto_id, tvb, 0,
-                                        -1, FALSE);
+        sub_item = proto_tree_add_item (tree, sub_proto->proto_id,
+                                       (decrypted_tvb != NULL)?decrypted_tvb:tvb,
+                                       0, -1, FALSE);
 
         if (sub_item) {
             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
@@ -1931,40 +2196,48 @@ else
          * Put the operation number into the tree along with
          * the operation's name.
          */
-
        if (sub_proto->opnum_hf != -1)
-            proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
-                                       tvb, 0, 0, info->call_data->opnum,
-                                       "Operation: %s (%u)",
-                                       name, info->call_data->opnum);
+                proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
+                                           tvb, 0, 0, info->call_data->opnum,
+                                           "Operation: %s (%u)",
+                                           name, info->call_data->opnum);
        else
-            proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
-                                       0, 0, info->call_data->opnum,
-                                       "Operation: %s (%u)",
-                                       name, info->call_data->opnum);
-    }
-
-    sub_dissect = (info->ptype == PDU_REQ) ? 
-           proc->dissect_rqst : proc->dissect_resp;
+                proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
+                                           0, 0, info->call_data->opnum,
+                                           "Operation: %s (%u)",
+                                           name, info->call_data->opnum);
+
+        if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
+            pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
+                                     tvb, 0, 0, info->call_data->rep_frame);
+            PROTO_ITEM_SET_GENERATED(pi);
+       }
+        if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
+            pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
+                                     tvb, 0, 0, info->call_data->req_frame);
+            PROTO_ITEM_SET_GENERATED(pi);
+       }
+    } /* tree */
 
     if (decrypted_tvb != NULL) {
         /* Either there was no encryption or we successfully decrypted
-           the entrypted payload. */
+           the encrypted payload. */
         if (sub_dissect) {
             /* We have a subdissector - call it. */
             saved_proto = pinfo->current_proto;
             saved_private_data = pinfo->private_data;
             pinfo->current_proto = sub_proto->name;
             pinfo->private_data = (void *)info;
-           
+
             init_ndr_pointer_list(pinfo);
 
+            length = tvb_length(decrypted_tvb);
+            reported_length = tvb_reported_length(decrypted_tvb);
+
             /*
              * Remove the authentication padding from the stub data.
              */
             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
-                length = tvb_length(decrypted_tvb);
-                reported_length = tvb_reported_length(decrypted_tvb);
                 if (reported_length >= auth_info->auth_pad_len) {
                     /*
                      * OK, the padding length isn't so big that it
@@ -1982,7 +2255,7 @@ else
                     if (length > reported_length)
                         length = reported_length;
 
-                    stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
+                    stub_tvb = tvb_new_subset(decrypted_tvb, 0, length, reported_length);
                     auth_pad_len = auth_info->auth_pad_len;
                     auth_pad_offset = reported_length;
                 } else {
@@ -1995,6 +2268,8 @@ else
                     stub_tvb = NULL;
                     auth_pad_len = reported_length;
                     auth_pad_offset = 0;
+                    length = 0;
+                    reported_length = 0;
                 }
             } else {
                 /*
@@ -2005,6 +2280,10 @@ else
                 auth_pad_offset = 0;
             }
 
+            if (sub_item) {
+               proto_item_set_len(sub_item, length);
+            }
+
             if (stub_tvb != NULL) {
                 /*
                  * Catch all exceptions other than BoundsError, so that even
@@ -2016,27 +2295,37 @@ else
                  * dissect; just re-throw that exception.
                  */
                 TRY {
-                    offset = sub_dissect (decrypted_tvb, 0, pinfo, sub_tree,
+                    int remaining;
+
+                    offset = sub_dissect (stub_tvb, 0, pinfo, sub_tree,
                                           drep);
 
                     /* If we have a subdissector and it didn't dissect all
                        data in the tvb, make a note of it. */
-
-                    if (tvb_reported_length_remaining(stub_tvb, offset) > 0) {
+                    remaining = tvb_reported_length_remaining(stub_tvb, offset);
+                    if (remaining > 0) {
+                        proto_tree_add_text(sub_tree, stub_tvb, offset,
+                                            remaining,
+                                            "[Long frame (%d byte%s)]",
+                                            remaining,
+                                            plurality(remaining, "", "s"));
                         if (check_col(pinfo->cinfo, COL_INFO))
                             col_append_fstr(pinfo->cinfo, COL_INFO,
-                                            "[Long frame (%d bytes)]",
-                                            tvb_reported_length_remaining(stub_tvb, offset));
+                                            "[Long frame (%d byte%s)]",
+                                            remaining,
+                                            plurality(remaining, "", "s"));
+
                     }
                 } CATCH(BoundsError) {
                     RETHROW;
                 } CATCH_ALL {
-                    show_exception(decrypted_tvb, pinfo, tree, EXCEPT_CODE);
+                    show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
                 } ENDTRY;
             }
 
             /* If there is auth padding at the end of the stub, display it */
             if (auth_pad_len != 0) {
+               tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
                 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
                                      auth_pad_len,
                                      "Auth Padding (%u byte%s)",
@@ -2062,7 +2351,7 @@ else
 }
 
 static int
-dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo, 
+dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
                         dcerpc_auth_info *auth_info)
 {
@@ -2091,9 +2380,10 @@ dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
                dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
                                  hdr, auth_info);
            } CATCH_ALL {
-               show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+               show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
            } ENDTRY;
        } else {
+            tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
            proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
                                 "Auth Verifier");
        }
@@ -2110,14 +2400,14 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
     volatile int offset;
 
     /*
-     * Initially set auth_level and auth_type to zero to indicate that we 
+     * Initially set auth_level and auth_type to zero to indicate that we
      * haven't yet seen any authentication level information.
      */
     auth_info->auth_level = 0;
     auth_info->auth_type = 0;
     auth_info->auth_size = 0;
     auth_info->auth_pad_len = 0;
-    
+
     /*
      * The authentication information is at the *end* of the PDU; in
      * request and response PDUs, the request and response stub data
@@ -2154,14 +2444,14 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
              */
             TRY {
                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
-                                               hf_dcerpc_auth_type, 
+                                               hf_dcerpc_auth_type,
                                                &auth_info->auth_type);
                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
-                                               hf_dcerpc_auth_level, 
+                                               hf_dcerpc_auth_level,
                                                &auth_info->auth_level);
 
                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
-                                               hf_dcerpc_auth_pad_len, 
+                                               hf_dcerpc_auth_pad_len,
                                                &auth_info->auth_pad_len);
                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                                hf_dcerpc_auth_rsrvd, NULL);
@@ -2175,24 +2465,25 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
                     tvbuff_t *auth_tvb;
                     dcerpc_auth_subdissector_fns *auth_fns;
 
-                    auth_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
-                                              hdr->auth_len);
+                    auth_tvb = tvb_new_subset(tvb, offset,
+                                   MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
+                                   hdr->auth_len);
 
                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
                                                               auth_info->auth_type)))
-                        dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns, 
+                        dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
                                           hdr, auth_info);
                     else
                         proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
                                              "Auth Credentials");
                 }
-       
-                /* Compute the size of the auth block.  Note that this should not 
+
+                /* Compute the size of the auth block.  Note that this should not
                    include auth padding, since when NTLMSSP encryption is used, the
                    padding is actually inside the encrypted stub */
                    auth_info->auth_size = hdr->auth_len + 8;
             } CATCH_ALL {
-                show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+                show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
             } ENDTRY;
         }
     }
@@ -2201,24 +2492,19 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
 
 /* 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. 
+ * socket.
  * We pass this function the transport type here to make sure we only look
  * at this function if it came across an SMB pipe.
  * Other transports might need to mix in their own extra multiplexing data
  * as well in the future.
  */
 
-guint16 dcerpc_get_transport_salt (packet_info *pinfo, int transport_type)
+guint16 dcerpc_get_transport_salt (packet_info *pinfo)
 {
-    dcerpc_private_info *priv = (dcerpc_private_info *)pinfo->private_data;
-
-    if (!priv)
-        return 0;      /* Nothing to see here */
-
-    switch(transport_type){
+    switch(pinfo->dcetransporttype){
        case DCE_CN_TRANSPORT_SMBPIPE:
            /* DCERPC over smb */
-           return priv->fid;
+           return pinfo->dcetransportsalt;
     }
 
     /* Some other transport... */
@@ -2230,27 +2516,24 @@ guint16 dcerpc_get_transport_salt (packet_info *pinfo, int transport_type)
  */
 
 static void
-dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
-                       proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
-                       int transport_type)
+dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
 {
     conversation_t *conv = NULL;
     guint8 num_ctx_items = 0;
     guint i;
     gboolean saw_ctx_item = FALSE;
     guint16 ctx_id;
-    guint16 num_trans_items;
+    guint8 num_trans_items;
     guint j;
     e_uuid_t if_id;
     e_uuid_t trans_id;
     guint32 trans_ver;
     guint16 if_ver, if_ver_minor;
-    char uuid_str[DCERPC_UUID_STR_LEN]; 
-    int uuid_str_len;
     dcerpc_auth_info auth_info;
-#ifdef _WIN32
-    char UUID_NAME[MAX_PATH];
-#endif
+    char *uuid_str;
+    const char *uuid_name = NULL;
+       proto_item *iface_item;
 
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_max_xmit, NULL);
@@ -2268,54 +2551,64 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     offset += 3;
 
     for (i = 0; i < num_ctx_items; i++) {
+           proto_item *ctx_item;
            proto_tree *ctx_tree = NULL, *iface_tree = NULL;
+        gint ctx_offset = offset;
 
-      offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
+      dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
                                       hf_dcerpc_cn_ctx_id, &ctx_id);
 
+      if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
+               if(pinfo->dcectxid == 0) {
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
+               } else {
+                       /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+                        * prepend a delimiter */
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
+               }
+      }
+
       /* save context ID for use with dcerpc_add_conv_to_bind_table() */
       /* (if we have multiple contexts, this might cause "decode as"
        *  to behave unpredictably) */
       pinfo->dcectxid = ctx_id;
-      pinfo->dcetransporttype = transport_type;
 
       if (dcerpc_tree) {
-             proto_item *ctx_item;
-
-             ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_id,
-                                            tvb, offset - 2, 2, 
+             ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
+                                            tvb, offset, 0,
                                             hdr->drep[0] & 0x10);
-
              ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
       }
 
       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
+                                      hf_dcerpc_cn_ctx_id, &ctx_id);
+      offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
 
-      /* XXX - use "dissect_ndr_uuid_t()"? */
+      if(dcerpc_tree) {
+        proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
+      }
+
+      /* padding */
+      offset += 1;
+
       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
       if (ctx_tree) {
-         proto_item *iface_item;
-
-         uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                  if_id.Data1, if_id.Data2, if_id.Data3,
-                                  if_id.Data4[0], if_id.Data4[1],
-                                  if_id.Data4[2], if_id.Data4[3],
-                                  if_id.Data4[4], if_id.Data4[5],
-                                  if_id.Data4[6], if_id.Data4[7]);
-
-         if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-#ifdef _WIN32
-         if(ResolveWin32UUID(if_id, UUID_NAME, MAX_PATH))
-                 iface_item = proto_tree_add_string_format (ctx_tree, hf_dcerpc_cn_bind_if_id, tvb,
-                                        offset, 16, uuid_str, "Interface [%s] UUID: %s", UUID_NAME, uuid_str);
-         else
-#endif
-          iface_item = proto_tree_add_string_format (ctx_tree, hf_dcerpc_cn_bind_if_id, tvb,
-                                        offset, 16, uuid_str, "Interface UUID: %s", uuid_str);
+
+      iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
          iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
+
+      uuid_str = guid_to_str((e_guid_t*)&if_id);
+      uuid_name = guids_get_uuid_name(&if_id);
+      if(uuid_name) {
+                 proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
+                                        offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
+          proto_item_append_text(iface_item, ": %s", uuid_name);
+      } else {
+          proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
+                                        offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
+          proto_item_append_text(iface_item, ": %s", uuid_str);
+      }
       }
       offset += 16;
 
@@ -2331,11 +2624,16 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
       }
 
+      if (ctx_tree) {
+          proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
+          proto_item_set_len(iface_item, 20);
+      }
+
       if (!saw_ctx_item) {
-        conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+        conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                                   pinfo->srcport, pinfo->destport, 0);
         if (conv == NULL) {
-            conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+            conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                                      pinfo->srcport, pinfo->destport, 0);
         }
 
@@ -2349,12 +2647,12 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                dcerpc_bind_key *key;
                dcerpc_bind_value *value;
 
-               key = g_mem_chunk_alloc (dcerpc_bind_key_chunk);
+               key = se_alloc (sizeof (dcerpc_bind_key));
                key->conv = conv;
                key->ctx_id = ctx_id;
-               key->smb_fid = dcerpc_get_transport_salt(pinfo, transport_type);
+               key->smb_fid = dcerpc_get_transport_salt(pinfo);
 
-               value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
+               value = se_alloc (sizeof (dcerpc_bind_value));
                value->uuid = if_id;
                value->ver = if_ver;
 
@@ -2368,60 +2666,42 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
        }
 
         if (check_col (pinfo->cinfo, COL_INFO)) {
-         dcerpc_uuid_key key;
-         dcerpc_uuid_value *value;
-
-         key.uuid = if_id;
-         key.ver = if_ver;
-
          if (num_ctx_items > 1)
                  col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
-               
-         if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
-                 col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
-         else
-#ifdef _WIN32
-               if(ResolveWin32UUID(if_id, UUID_NAME, MAX_PATH))
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
-                           UUID_NAME, if_id.Data1, if_id.Data2, if_id.Data3,
-                           if_id.Data4[0], if_id.Data4[1],
-                           if_id.Data4[2], if_id.Data4[3],
-                           if_id.Data4[4], if_id.Data4[5],
-                           if_id.Data4[6], if_id.Data4[7],
-                           if_ver, if_ver_minor);
-         else
-#endif
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
-                           if_id.Data1, if_id.Data2, if_id.Data3,
-                           if_id.Data4[0], if_id.Data4[1],
-                           if_id.Data4[2], if_id.Data4[3],
-                           if_id.Data4[4], if_id.Data4[5],
-                           if_id.Data4[6], if_id.Data4[7],
-                           if_ver, if_ver_minor);
+
+               col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u.%u",
+                       guids_resolve_uuid_to_str(&if_id), if_ver, if_ver_minor);
         }
         saw_ctx_item = TRUE;
       }
 
       for (j = 0; j < num_trans_items; j++) {
-        /* XXX - use "dissect_ndr_uuid_t()"? */
+           proto_tree *trans_tree = NULL;
+           proto_item *trans_item = NULL;
+
         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
-        if (iface_tree) {
-           uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                  "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                  trans_id.Data1, trans_id.Data2, trans_id.Data3,
-                                  trans_id.Data4[0], trans_id.Data4[1],
-                                  trans_id.Data4[2], trans_id.Data4[3],
-                                  trans_id.Data4[4], trans_id.Data4[5],
-                                  trans_id.Data4[6], trans_id.Data4[7]);
-            if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-                memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-            proto_tree_add_string_format (iface_tree, hf_dcerpc_cn_bind_trans_id, tvb,
-                                          offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
+        if (ctx_tree) {
+
+        trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
+        trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
+
+        uuid_str = guid_to_str((e_guid_t *) &trans_id);
+            proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
+                                          offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
+            proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
         }
         offset += 16;
 
-        offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, iface_tree, hdr->drep,
+        offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
+        if (ctx_tree) {
+          proto_item_set_len(trans_item, 20);
+          proto_item_append_text(trans_item, " V%u", trans_ver);
+        }
+      }
+
+      if(ctx_tree) {
+        proto_item_set_len(ctx_item, offset - ctx_offset);
       }
     }
 
@@ -2434,7 +2714,7 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 }
 
 static void
-dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
+dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                            proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
 {
     guint16 max_xmit, max_recv;
@@ -2445,8 +2725,6 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     guint16 reason;
     e_uuid_t trans_id;
     guint32 trans_ver;
-    char uuid_str[DCERPC_UUID_STR_LEN]; 
-    int uuid_str_len;
     dcerpc_auth_info auth_info;
 
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
@@ -2461,6 +2739,7 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
     if (sec_addr_len != 0) {
+       tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
                              sec_addr_len, FALSE);
         offset += sec_addr_len;
@@ -2477,11 +2756,19 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     offset += 3;
 
     for (i = 0; i < num_results; i++) {
-        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+       proto_tree *ctx_tree = NULL;
+
+       if(dcerpc_tree){
+               proto_item *ctx_item;
+               ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
+               ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
+       }
+
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
                                         hdr->drep, hf_dcerpc_cn_ack_result,
                                         &result);
         if (result != 0) {
-            offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+            offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
                                             hdr->drep, hf_dcerpc_cn_ack_reason,
                                             &reason);
         } else {
@@ -2492,24 +2779,15 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
             offset += 2;
         }
 
-        /* XXX - use "dissect_ndr_uuid_t()"? */
         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
-        if (dcerpc_tree) {
-           uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                  "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                  trans_id.Data1, trans_id.Data2, trans_id.Data3,
-                                  trans_id.Data4[0], trans_id.Data4[1],
-                                  trans_id.Data4[2], trans_id.Data4[3],
-                                  trans_id.Data4[4], trans_id.Data4[5],
-                                  trans_id.Data4[6], trans_id.Data4[7]);
-           if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-            proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
-                                          offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
+        if (ctx_tree) {
+            proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
+                                          offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s",
+                                          guid_to_str((e_guid_t *) &trans_id));
         }
         offset += 16;
 
-        offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+        offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
     }
 
@@ -2537,7 +2815,7 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 }
 
 static void
-dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
+dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                            proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
 {
     guint16 reason;
@@ -2574,7 +2852,7 @@ dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
 #define PFC_FRAG_MASK  0x03
 
-static char *
+static const char *
 fragment_type(guint8 flags)
 {
        flags = flags & PFC_FRAG_MASK;
@@ -2600,15 +2878,17 @@ static void
 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
                         proto_tree *dcerpc_tree, proto_tree *tree,
                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
-                        dcerpc_auth_info *auth_info, guint32 alloc_hint,
+                        dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
                         guint32 frame)
 {
     gint length, reported_length;
     gboolean save_fragmented;
     fragment_data *fd_head=NULL;
-    guint32 tot_len;
-    tvbuff_t *payload_tvb, *decrypted_tvb;
+
+    tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
     proto_item *pi;
+    proto_item *parent_pi;
+    proto_item *dcerpc_tree_item;
 
     save_fragmented = pinfo->fragmented;
 
@@ -2625,6 +2905,17 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
        length = reported_length;
     payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
 
+    auth_tvb=NULL;
+    /*dont bother if we dont have the entire tvb */
+    /*XXX we should really make sure we calculate auth_info->auth_data
+       and use that one instead of this auth_tvb hack
+    */
+    if(tvb_length(tvb)==tvb_reported_length(tvb)){
+       if(tvb_length_remaining(tvb, offset+length)>8){
+           auth_tvb = tvb_new_subset(tvb, offset+length+8, -1, -1);
+       }
+    }
+
     /* Decrypt the PDU if it is encrypted */
 
     if (auth_info->auth_type &&
@@ -2635,18 +2926,18 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
             * encrypted; attempt to decrypt it.
             */
            dcerpc_auth_subdissector_fns *auth_fns;
-           
+
            /* Start out assuming we won't succeed in decrypting. */
            decrypted_tvb = NULL;
 
            if ((auth_fns = get_auth_subdissector_fns(
                         auth_info->auth_level, auth_info->auth_type))) {
                    tvbuff_t *result;
-                   
+
                    result = decode_encrypted_data(
-                           payload_tvb, pinfo, auth_fns,
-                           hdr->ptype == PDU_REQ, auth_info);      
-                   
+                           payload_tvb, auth_tvb, pinfo, auth_fns,
+                           hdr->ptype == PDU_REQ, auth_info);
+
                    if (result) {
                            if (dcerpc_tree)
                                proto_tree_add_text(
@@ -2658,7 +2949,7 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
 
                            add_new_data_source(
                                    pinfo, result, "Decrypted stub data");
-                           
+
                            /* We succeeded. */
                            decrypted_tvb = result;
                    }
@@ -2673,7 +2964,7 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
        dcerpc_try_handoff(
                pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
                hdr->drep, di, auth_info);
-       
+
        pinfo->fragmented = save_fragmented;
        return;
     }
@@ -2681,6 +2972,11 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
     /* The packet is fragmented. */
     pinfo->fragmented = TRUE;
 
+       /* debug output of essential fragment data. */
+       /* leave it here for future debugging sessions */
+       /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
+                  pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
+
     /* if we are not doing reassembly and this is the first fragment
        then just dissect it and exit
        XXX - if we're not doing reassembly, can we decrypt an
@@ -2691,21 +2987,23 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
        dcerpc_try_handoff(
                pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
                hdr->drep, di, auth_info);
-       
+
         if (check_col(pinfo->cinfo, COL_INFO)) {
             col_append_fstr(pinfo->cinfo, COL_INFO,
                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
         }
+               expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
+                       "%s fragment", fragment_type(hdr->flags));
         pinfo->fragmented = save_fragmented;
         return;
     }
 
     /* if we have already seen this packet, see if it was reassembled
        and if so dissect the full pdu.
-       then exit 
+       then exit
     */
     if(pinfo->fd->flags.visited){
-       fd_head=fragment_get(pinfo, frame, dcerpc_co_reassemble_table);
+       fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
        goto end_cn_stub;
     }
 
@@ -2713,16 +3011,16 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
        nor the first fragment then there is nothing more we can do
        so we just have to exit
     */
-    if( !dcerpc_reassemble )
+    if( !dcerpc_reassemble || (tvb_length(tvb)!=tvb_reported_length(tvb)) )
         goto end_cn_stub;
 
     /* if we didnt get 'frame' we dont know where the PDU started and thus
-       it is pointless to continue 
+       it is pointless to continue
     */
     if(!frame)
         goto end_cn_stub;
 
-    /* from now on we must attempt to reassemble the PDU 
+    /* from now on we must attempt to reassemble the PDU
     */
 
     /* if we get here we know it is the first time we see the packet
@@ -2736,76 +3034,83 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
       goto end_cn_stub;
     }
 
-    /* if this is the first fragment we need to start reassembly
-    */
-    if(hdr->flags&PFC_FIRST_FRAG){
-       fragment_add(decrypted_tvb, 0, pinfo, frame, dcerpc_co_reassemble_table,
-                    0, tvb_length(decrypted_tvb), TRUE);
-       fragment_set_tot_len(pinfo, frame,
-                dcerpc_co_reassemble_table, alloc_hint);
-
-       goto end_cn_stub;
-    }
-
-    /* if this is a middle fragment, just add it and exit */
-    if(!(hdr->flags&PFC_LAST_FRAG)){
-       tot_len = fragment_get_tot_len(pinfo, frame,
-                dcerpc_co_reassemble_table);
-       fragment_add(decrypted_tvb, 0, pinfo, frame,
-                dcerpc_co_reassemble_table,
-                tot_len-alloc_hint, tvb_length(decrypted_tvb),
-                TRUE);
-
-       goto end_cn_stub;
-    }
-
-    /* this was the last fragment add it to reassembly
-    */
-    tot_len = fragment_get_tot_len(pinfo, frame,
-               dcerpc_co_reassemble_table);
-    fd_head = fragment_add(decrypted_tvb, 0, pinfo,
-               frame,
-               dcerpc_co_reassemble_table,
-               tot_len-alloc_hint, tvb_length(decrypted_tvb),
-               TRUE);
+    /* defragmentation is a bit tricky, as there's no offset of the fragment
+     * in the protocol data.
+     *
+     * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
+     * in with the correct sequence.
+     */
+    fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
+               dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
+               tvb_length(decrypted_tvb),
+               hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
 
 end_cn_stub:
 
-    /* if reassembly is complete, dissect the full PDU
-    */
+    /* if reassembly is complete and this is the last fragment
+        * (multiple fragments in one PDU are possible!)
+        * dissect the full PDU
+     */
     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
 
-       if(pinfo->fd->num==fd_head->reassembled_in){
+       if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
            tvbuff_t *next_tvb;
+        proto_item *frag_tree_item;
 
-           next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
-           tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
+           next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+           if(decrypted_tvb){
+               tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
+           } else {
+               tvb_set_child_real_data_tvbuff(payload_tvb, next_tvb);
+           }
            add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
            show_fragment_tree(fd_head, &dcerpc_frag_items,
-               dcerpc_tree, pinfo, next_tvb);
+                       tree, pinfo, next_tvb, &frag_tree_item);
+               /* the toplevel fragment subtree is now behind all desegmented data,
+                * move it right behind the DCE/RPC tree */
+               dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
+               if(frag_tree_item && dcerpc_tree_item) {
+                       proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
+               }
 
            pinfo->fragmented = FALSE;
 
+               expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
+                       "%s fragment, reassembled",
+                       fragment_type(hdr->flags));
+
            dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
                next_tvb, hdr->drep, di, auth_info);
 
        } else {
-           pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
+           if(decrypted_tvb){
+               pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
                                decrypted_tvb, 0, 0, fd_head->reassembled_in);
+           } else {
+               pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
+                               payload_tvb, 0, 0, fd_head->reassembled_in);
+           }
         PROTO_ITEM_SET_GENERATED(pi);
+        parent_pi = proto_tree_get_parent(dcerpc_tree);
+        if(parent_pi != NULL) {
+            proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
+        }
            if (check_col(pinfo->cinfo, COL_INFO)) {
                col_append_fstr(pinfo->cinfo, COL_INFO,
                        " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
            }
+               expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
+                       "%s fragment, reassembled in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
        }
     } else {
        /* Reassembly not complete - some fragments
           are missing.  Just show the stub data. */
-
        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO,
                        " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
        }
+       expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
+               "%s fragment", fragment_type(hdr->flags));
 
        if(decrypted_tvb){
                show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
@@ -2821,9 +3126,9 @@ end_cn_stub:
  *  Registers a conversation/UUID binding association, so that
  *  we can invoke the proper sub-dissector for a given DCERPC
  *  conversation.
- * 
+ *
  *  @param binding all values needed to create and bind a new conversation
- * 
+ *
  *  @return Pointer to newly-added UUID/conversation binding.
  */
 struct _dcerpc_bind_value *
@@ -2834,32 +3139,34 @@ dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
     conversation_t *conv;
 
     conv = find_conversation (
-        &binding->addr_a, 
-        &binding->addr_b, 
-        binding->ptype, 
-        binding->port_a, 
-        binding->port_b, 
+        0,
+        &binding->addr_a,
+        &binding->addr_b,
+        binding->ptype,
+        binding->port_a,
+        binding->port_b,
         0);
+
     if (!conv) {
         conv = conversation_new (
-            &binding->addr_a, 
-            &binding->addr_b, 
-            binding->ptype, 
-            binding->port_a, 
-            binding->port_b, 
+            0,
+            &binding->addr_a,
+            &binding->addr_b,
+            binding->ptype,
+            binding->port_a,
+            binding->port_b,
             0);
     }
 
-    bind_value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
+    bind_value = se_alloc (sizeof (dcerpc_bind_value));
     bind_value->uuid = binding->uuid;
     bind_value->ver = binding->ver;
 
-    key = g_mem_chunk_alloc(dcerpc_bind_key_chunk);
+    key = se_alloc(sizeof (dcerpc_bind_key));
     key->conv = conv;
     key->ctx_id = binding->ctx_id;
     key->smb_fid = binding->smb_fid;
+
     /* add this entry to the bind table, first removing any
        previous ones that are identical
      */
@@ -2873,32 +3180,44 @@ dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
 }
 
 static void
-dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
+dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        proto_tree *dcerpc_tree, proto_tree *tree,
-                       e_dce_cn_common_hdr_t *hdr, int transport_type)
+                       e_dce_cn_common_hdr_t *hdr)
 {
     conversation_t *conv;
     guint16 ctx_id;
     guint16 opnum;
-    e_uuid_t obj_id;
+    e_uuid_t obj_id = DCERPC_UUID_NULL;
     dcerpc_auth_info auth_info;
     guint32 alloc_hint;
-    char uuid_str[DCERPC_UUID_STR_LEN]; 
-    int uuid_str_len;
     proto_item *pi;
+    proto_item *parent_pi;
 
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
 
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_ctx_id, &ctx_id);
+    parent_pi = proto_tree_get_parent(dcerpc_tree);
+    if(parent_pi != NULL) {
+        proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
+    }
+
+    if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
+               if(pinfo->dcectxid == 0) {
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
+               } else {
+                       /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+                        * prepend a delimiter */
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
+               }
+    }
 
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_opnum, &opnum);
 
     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
     pinfo->dcectxid = ctx_id;
-    pinfo->dcetransporttype = transport_type;
 
     if (check_col (pinfo->cinfo, COL_INFO)) {
         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
@@ -2906,24 +3225,11 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     }
 
     if (hdr->flags & PFC_OBJECT_UUID) {
-        /* XXX - use "dissect_ndr_uuid_t()"? */
         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
         if (dcerpc_tree) {
-           uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                    obj_id.Data1, obj_id.Data2, obj_id.Data3,
-                                    obj_id.Data4[0],
-                                    obj_id.Data4[1],
-                                    obj_id.Data4[2],
-                                    obj_id.Data4[3],
-                                    obj_id.Data4[4],
-                                    obj_id.Data4[5],
-                                    obj_id.Data4[6],
-                                    obj_id.Data4[7]);
-           if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-            proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
-                                          offset, 16, uuid_str, "Object UUID: %s", uuid_str);
+            proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
+                                          offset, 16, (e_guid_t *) &obj_id, "Object UUID: %s",
+                                          guid_to_str((e_guid_t *) &obj_id));
         }
         offset += 16;
     }
@@ -2934,7 +3240,7 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
      */
     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
 
-    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+    conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                               pinfo->srcport, pinfo->destport, 0);
     if (!conv)
         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
@@ -2956,7 +3262,7 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
                bind_key.conv=conv;
                bind_key.ctx_id=ctx_id;
-               bind_key.smb_fid=dcerpc_get_transport_salt(pinfo, transport_type);
+               bind_key.smb_fid=dcerpc_get_transport_salt(pinfo);
 
                if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
                        if(!(hdr->flags&PFC_FIRST_FRAG)){
@@ -2965,9 +3271,9 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
                                call_key.conv=conv;
                                call_key.call_id=hdr->call_id;
-                               call_key.smb_fid=dcerpc_get_transport_salt(pinfo, transport_type);
+                               call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
                                if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
-                                       new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+                                       new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
                                        *new_matched_key = matched_key;
                                        g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
                                        value = call_value;
@@ -2976,15 +3282,15 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                                dcerpc_cn_call_key *call_key;
                                dcerpc_call_value *call_value;
 
-                               /* We found the binding and it is the first fragment 
-                                  (or a complete PDU) of a dcerpc pdu so just add 
-                                  the call to both the call table and the 
+                               /* We found the binding and it is the first fragment
+                                  (or a complete PDU) of a dcerpc pdu so just add
+                                  the call to both the call table and the
                                   matched table
                                */
-                               call_key=g_mem_chunk_alloc (dcerpc_cn_call_key_chunk);
+                               call_key=se_alloc (sizeof (dcerpc_cn_call_key));
                                call_key->conv=conv;
                                call_key->call_id=hdr->call_id;
-                               call_key->smb_fid=dcerpc_get_transport_salt(pinfo, transport_type);
+                               call_key->smb_fid=dcerpc_get_transport_salt(pinfo);
 
                                /* if there is already a matching call in the table
                                   remove it so it is replaced with the new one */
@@ -2992,19 +3298,20 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                                        g_hash_table_remove(dcerpc_cn_calls, call_key);
                                }
 
-                               call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
+                               call_value=se_alloc (sizeof (dcerpc_call_value));
                                call_value->uuid = bind_value->uuid;
                                call_value->ver = bind_value->ver;
+                call_value->object_uuid = obj_id;
                                call_value->opnum = opnum;
                                call_value->req_frame=pinfo->fd->num;
-                               call_value->req_time.secs=pinfo->fd->abs_secs;
-                               call_value->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+                               call_value->req_time=pinfo->fd->abs_ts;
                                call_value->rep_frame=0;
                                call_value->max_ptr=0;
+                               call_value->se_data = NULL;
                                call_value->private_data = NULL;
                                g_hash_table_insert (dcerpc_cn_calls, call_key, call_value);
 
-                               new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+                               new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
                                *new_matched_key = matched_key;
                                g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
                                value = call_value;
@@ -3019,7 +3326,7 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
             /* handoff this call */
            di->conv = conv;
            di->call_id = hdr->call_id;
-           di->smb_fid = dcerpc_get_transport_salt(pinfo, transport_type);
+           di->smb_fid = dcerpc_get_transport_salt(pinfo);
            di->ptype = PDU_REQ;
            di->call_data = value;
                di->hf_index = -1;
@@ -3028,13 +3335,22 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
                                    tvb, 0, 0, value->rep_frame);
         PROTO_ITEM_SET_GENERATED(pi);
+        if(parent_pi != NULL) {
+            proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
+        }
            }
 
            dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
                                    hdr, di, &auth_info, alloc_hint,
                                    value->req_frame);
-       } else
+        } else {
+        /* no bind information, simply show stub data */
+        pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
+        PROTO_ITEM_SET_GENERATED(pi);
+           expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",
+            ctx_id);
            show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+        }
     }
 
     /* Dissect the verifier */
@@ -3045,7 +3361,7 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 static void
 dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                        proto_tree *dcerpc_tree, proto_tree *tree,
-                       e_dce_cn_common_hdr_t *hdr, int transport_type)
+                       e_dce_cn_common_hdr_t *hdr)
 {
     dcerpc_call_value *value = NULL;
     conversation_t *conv;
@@ -3053,16 +3369,32 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     dcerpc_auth_info auth_info;
     guint32 alloc_hint;
     proto_item *pi;
+    proto_item *parent_pi;
+    e_uuid_t obj_id_null = DCERPC_UUID_NULL;
 
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
 
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_ctx_id, &ctx_id);
+    parent_pi = proto_tree_get_parent(dcerpc_tree);
+    if(parent_pi != NULL) {
+        proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
+    }
+
+    if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
+               if(pinfo->dcectxid == 0) {
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
+               } else {
+                       /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+                        * prepend a delimiter */
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
+               }
+    }
+
 
     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
     pinfo->dcectxid = ctx_id;
-    pinfo->dcetransporttype = transport_type;
 
     if (check_col (pinfo->cinfo, COL_INFO)) {
         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
@@ -3079,7 +3411,7 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
      */
     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
 
-    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+    conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                               pinfo->srcport, pinfo->destport, 0);
 
     if (!conv) {
@@ -3102,15 +3434,19 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
                call_key.conv=conv;
                call_key.call_id=hdr->call_id;
-               call_key.smb_fid=dcerpc_get_transport_salt(pinfo, transport_type);
+               call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
 
                if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
-                       new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
-                       *new_matched_key = matched_key;
-                       g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
-                       value = call_value;
-                       if(call_value->rep_frame==0){
-                               call_value->rep_frame=pinfo->fd->num;
+                       /* extra sanity check,  only match them if the reply
+                          came after the request */
+                       if(call_value->req_frame<pinfo->fd->num){
+                               new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
+                               *new_matched_key = matched_key;
+                               g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+                               value = call_value;
+                               if(call_value->rep_frame==0){
+                                       call_value->rep_frame=pinfo->fd->num;
+                               }
                        }
                }
        }
@@ -3122,31 +3458,50 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
             /* handoff this call */
            di->conv = conv;
            di->call_id = hdr->call_id;
-           di->smb_fid = dcerpc_get_transport_salt(pinfo, transport_type);
+           di->smb_fid = dcerpc_get_transport_salt(pinfo);
            di->ptype = PDU_RESP;
            di->call_data = value;
 
            proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+
+        /* (optional) "Object UUID" from request */
+        if (value && dcerpc_tree && memcmp(&value->object_uuid, &obj_id_null, sizeof(obj_id_null)) != 0) {
+                pi = proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
+                                              offset, 0, (e_guid_t *) &value->object_uuid, "Object UUID: %s",
+                                              guid_to_str((e_guid_t *) &value->object_uuid));
+                PROTO_ITEM_SET_GENERATED(pi);
+        }
+
+        /* request in */
            if(value->req_frame!=0){
-               nstime_t ns;
+               nstime_t delta_ts;
                pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
                                    tvb, 0, 0, value->req_frame);
         PROTO_ITEM_SET_GENERATED(pi);
-               ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
-               ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
-               if(ns.nsecs<0){
-                       ns.nsecs+=1000000000;
-                       ns.secs--;
-               }
-               pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+        if(parent_pi != NULL) {
+            proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
+        }
+               nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+               pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
         PROTO_ITEM_SET_GENERATED(pi);
+        } else {
+                   pi = proto_tree_add_text(dcerpc_tree,
+                                       tvb, 0, 0, "No request to this DCE/RPC call found");
+                   expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
+                           "No request to this DCE/RPC call found");
            }
 
            dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
                                    hdr, di, &auth_info, alloc_hint,
                                    value->rep_frame);
-        } else
+        } else {
+            /* no bind information, simply show stub data */
+            pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
+            PROTO_ITEM_SET_GENERATED(pi);
+               expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",
+                ctx_id);
             show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+        }
     }
 
     /* Dissect the verifier */
@@ -3155,8 +3510,7 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
 static void
 dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
-                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
-                        int transport_type)
+                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
 {
     dcerpc_call_value *value = NULL;
     conversation_t *conv;
@@ -3164,7 +3518,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     guint32 status;
     guint32 alloc_hint;
     dcerpc_auth_info auth_info;
-    proto_item *pi;
+    proto_item *pi = NULL;
 
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
@@ -3172,17 +3526,37 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_ctx_id, &ctx_id);
 
+    if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
+               if(pinfo->dcectxid == 0) {
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
+               } else {
+                       /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+                        * prepend a delimiter */
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
+               }
+    }
+
     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                    hf_dcerpc_cn_cancel_count, NULL);
     /* padding */
     offset++;
 
-    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
-                                    hf_dcerpc_cn_status, &status);
+    /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_status, &status);*/
+    status = ((hdr->drep[0] & 0x10)
+            ? tvb_get_letohl (tvb, offset)
+            : tvb_get_ntohl (tvb, offset));
+
+    if (dcerpc_tree) {
+        pi = proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_status, tvb, offset, 4, (hdr->drep[0] & 0x10));
+    }
+       offset+=4;
+
+       expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "Fault: %s",
+               val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
 
     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
     pinfo->dcectxid = ctx_id;
-    pinfo->dcetransporttype = transport_type;
 
     if (check_col (pinfo->cinfo, COL_INFO)) {
         col_append_fstr (pinfo->cinfo, COL_INFO,
@@ -3200,7 +3574,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
      */
     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
 
-    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+    conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                               pinfo->srcport, pinfo->destport, 0);
     if (!conv) {
         /* no point in creating one here, really */
@@ -3221,10 +3595,10 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 
                call_key.conv=conv;
                call_key.call_id=hdr->call_id;
-               call_key.smb_fid=dcerpc_get_transport_salt(pinfo, transport_type);
+               call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
 
                if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
-                       new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+                       new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
                        *new_matched_key = matched_key;
                        g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
                        value = call_value;
@@ -3238,34 +3612,45 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
         if (value) {
             int length, reported_length, stub_length;
             dcerpc_info *di;
+            proto_item *parent_pi;
 
             di=get_next_di();
             /* handoff this call */
            di->conv = conv;
            di->call_id = hdr->call_id;
-           di->smb_fid = dcerpc_get_transport_salt(pinfo, transport_type);
+           di->smb_fid = dcerpc_get_transport_salt(pinfo);
            di->ptype = PDU_FAULT;
            di->call_data = value;
 
            proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
            if(value->req_frame!=0){
-               nstime_t ns;
+               nstime_t delta_ts;
                pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
                                    tvb, 0, 0, value->req_frame);
         PROTO_ITEM_SET_GENERATED(pi);
-               ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
-               ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
-               if(ns.nsecs<0){
-                       ns.nsecs+=1000000000;
-                       ns.secs--;
-               }
-               pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+        parent_pi = proto_tree_get_parent(dcerpc_tree);
+        if(parent_pi != NULL) {
+            proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
+        }
+               nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+               pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
         PROTO_ITEM_SET_GENERATED(pi);
+        } else {
+                   pi = proto_tree_add_text(dcerpc_tree,
+                                       tvb, 0, 0, "No request to this DCE/RPC call found");
+                   expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
+                           "No request to this DCE/RPC call found");
            }
 
            length = tvb_length_remaining(tvb, offset);
            reported_length = tvb_reported_length_remaining(tvb, offset);
-           stub_length = hdr->frag_len - offset - auth_info.auth_size;
+               /* as we now create a tvb in dissect_dcerpc_cn() containing only the
+                * stub_data, the following calculation is no longer valid:
+            * stub_length = hdr->frag_len - offset - auth_info.auth_size;
+                * simply use the remaining length of the tvb instead.
+                * XXX - or better use the reported_length?!?
+                */
+           stub_length = length;
            if (length > stub_length)
              length = stub_length;
            if (reported_length > stub_length)
@@ -3291,6 +3676,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                     */
                    if (dcerpc_tree) {
                        if (stub_length > 0) {
+                           tvb_ensure_bytes_exist(tvb, offset, stub_length);
                            proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                                 "Fault stub data (%d byte%s)",
                                                 stub_length,
@@ -3305,6 +3691,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                    }
                    if (dcerpc_tree) {
                        if (stub_length > 0) {
+                           tvb_ensure_bytes_exist(tvb, offset, stub_length);
                            proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                                 "Fragment data (%d byte%s)",
                                                 stub_length,
@@ -3319,6 +3706,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                   third means we can attempt reassembly. */
                if (dcerpc_tree) {
                    if (length > 0) {
+                       tvb_ensure_bytes_exist(tvb, offset, stub_length);
                        proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                             "Fragment data (%d byte%s)",
                                             stub_length,
@@ -3327,13 +3715,10 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                }
                if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
                    if( (!pinfo->fd->flags.visited) && value->rep_frame ){
-                       fragment_add(tvb, offset, pinfo, value->rep_frame,
-                            dcerpc_co_reassemble_table,
-                            0,
+                       fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
+                            dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
                             stub_length,
                             TRUE);
-                       fragment_set_tot_len(pinfo, value->rep_frame,
-                            dcerpc_co_reassemble_table, alloc_hint);
                    }
                    if (check_col(pinfo->cinfo, COL_INFO)) {
                        col_append_fstr(pinfo->cinfo, COL_INFO,
@@ -3342,26 +3727,23 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
                    if( value->rep_frame ){
                        fragment_data *fd_head;
-                       guint32 tot_len;
 
-                       tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
-                                      dcerpc_co_reassemble_table);
-                       fd_head = fragment_add(tvb, offset, pinfo,
+                       fd_head = fragment_add_seq_next(tvb, offset, pinfo,
                             value->rep_frame,
-                            dcerpc_co_reassemble_table,
-                            tot_len-alloc_hint,
+                            dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
                             stub_length,
                             TRUE);
 
                        if(fd_head){
                            /* We completed reassembly */
                            tvbuff_t *next_tvb;
+                proto_item *frag_tree_item;
 
-                           next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
+                           next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
                            tvb_set_child_real_data_tvbuff(tvb, next_tvb);
                            add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
                            show_fragment_tree(fd_head, &dcerpc_frag_items,
-                               dcerpc_tree, pinfo, next_tvb);
+                               dcerpc_tree, pinfo, next_tvb, &frag_tree_item);
 
                            /*
                             * XXX - should there be a third routine for each
@@ -3375,6 +3757,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                             */
                            if (dcerpc_tree) {
                                if (length > 0) {
+                                   tvb_ensure_bytes_exist(tvb, offset, stub_length);
                                     proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                                          "Fault stub data (%d byte%s)",
                                                          stub_length,
@@ -3392,12 +3775,8 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                    }
                } else {  /* MIDDLE fragment(s) */
                    if( (!pinfo->fd->flags.visited) && value->rep_frame ){
-                       guint32 tot_len;
-                       tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
-                                      dcerpc_co_reassemble_table);
-                       fragment_add(tvb, offset, pinfo, value->rep_frame,
-                            dcerpc_co_reassemble_table,
-                            tot_len-alloc_hint,
+                       fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
+                            dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
                             stub_length,
                             TRUE);
                    }
@@ -3418,8 +3797,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
  */
 static gboolean
 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
-                   proto_tree *tree, gboolean can_desegment, int *pkt_len,
-                  int transport_type)
+                   proto_tree *tree, gboolean can_desegment, int *pkt_len)
 {
     static const guint8 nulls[4] = { 0 };
     int start_offset;
@@ -3431,6 +3809,7 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
     proto_tree *drep_tree = NULL;
     e_dce_cn_common_hdr_t hdr;
     dcerpc_auth_info auth_info;
+       tvbuff_t *fragment_tvb;
 
     /*
      * when done over nbt, dcerpc requests are padded with 4 bytes of null
@@ -3449,7 +3828,6 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
         offset += 4;
         padding += 4;
     }
-
     /*
      * Check if this looks like a C/O DCERPC call
      */
@@ -3478,6 +3856,16 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
     offset += 4;
 
+    if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
+               if(pinfo->dcectxid == 0) {
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.call_id);
+               } else {
+                       /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+                        * prepend a delimiter */
+                       col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "#%u", hdr.call_id);
+               }
+    }
+
     if (can_desegment && pinfo->can_desegment
         && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
         pinfo->desegment_offset = start_offset;
@@ -3488,50 +3876,96 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
 
     if (check_col (pinfo->cinfo, COL_PROTOCOL))
         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
-    if (check_col (pinfo->cinfo, COL_INFO))
+
+    if (check_col (pinfo->cinfo, COL_INFO)) {
+        if(pinfo->dcectxid != 0) {
+            /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
+             * append a delimiter and set a column fence */
+            col_append_str (pinfo->cinfo, COL_INFO, " # ");
+            col_set_fence(pinfo->cinfo,COL_INFO);
+        }
         col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
-           pckt_vals[hdr.ptype].strptr, hdr.call_id);
+               pckt_vals[hdr.ptype].strptr, hdr.call_id);
+    }
+
+    if(pinfo->dcectxid != 0) {
+        /* this is not the first DCE-RPC request/response in this (TCP?-)PDU */
+               expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_CHAT, "Multiple DCE/RPC fragments/PDU's in one packet");
+       }
 
+    offset = start_offset;
+    tvb_ensure_bytes_exist(tvb, offset, 16);
     if (tree) {
-        offset = start_offset;
         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
-        if (ti) {
-            dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
-        }
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
+        dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
+    }
+
+    proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
+    offset++;
+
+    proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset, 1, hdr.rpc_ver_minor);
+    offset++;
+
+    tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
+    offset++;
+
+    /* XXX - too much "output noise", removed for now
+    if(hdr.ptype == PDU_BIND || hdr.ptype == PDU_ALTER ||
+        hdr.ptype == PDU_BIND_ACK || hdr.ptype == PDU_ALTER_ACK)
+        expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_CHAT, "Context change: %s",
+            val_to_str(hdr.ptype, pckt_vals, "(0x%x)"));*/
+    if(hdr.ptype == PDU_BIND_NAK)
+        expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_WARN, "Bind not acknowledged");
+
+    if (tree) {
+       proto_item_append_text(ti, " %s, Fragment:", val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"));
+
         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
-        if (cn_flags_tree) {
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
-            proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
+    }
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
+    proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
+    if( (hdr.flags & PFC_FIRST_FRAG) && (hdr.flags & PFC_LAST_FRAG) ) {
+        proto_item_append_text(ti, " Single");
+    } else {
+        if(hdr.flags & PFC_FIRST_FRAG) {
+            proto_item_append_text(ti, " 1st");
+        }
+        if(hdr.flags & PFC_LAST_FRAG) {
+            proto_item_append_text(ti, " Last");
         }
-        offset++;
+        if( !(hdr.flags & PFC_FIRST_FRAG) && !(hdr.flags & PFC_LAST_FRAG) ) {
+            proto_item_append_text(ti, " Mid");
+        }
+    }
+    offset++;
 
+    if(dcerpc_tree){
         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
-        if (drep_tree) {
-            proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
-            proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
-            proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
-        }
-        offset += sizeof (hdr.drep);
+    }
+    proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
+    proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
+    proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
+    offset += sizeof (hdr.drep);
+
+    proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
+    offset += 2;
 
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
-        offset += 2;
+    proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
+    offset += 2;
 
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
-        offset += 2;
+    proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
+    offset += 4;
 
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
-        offset += 4;
+    if(ti){
+        proto_item_append_text(ti, ", FragLen: %u, Call: %u", hdr.frag_len, hdr.call_id);
     }
 
     /*
@@ -3551,42 +3985,53 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
     if (pkt_len != NULL)
         *pkt_len = hdr.frag_len + padding;
 
+    /* The remaining bytes in the current tvb might contain multiple
+     * DCE/RPC fragments, so create a new tvb subset for this fragment.
+     * Only limit the end of the fragment, but not the offset start,
+     * as the authentication function dissect_dcerpc_cn_auth() will fail
+     * (and other functions might fail as well) computing the right start
+     * offset otherwise.
+     */
+    fragment_tvb = tvb_new_subset(tvb, 0,
+        MIN((hdr.frag_len + (guint) start_offset), tvb_length(tvb)) /* length */,
+        hdr.frag_len + start_offset /* reported_length */);
+
     /*
      * Packet type specific stuff is next.
      */
     switch (hdr.ptype) {
     case PDU_BIND:
     case PDU_ALTER:
-        dissect_dcerpc_cn_bind (tvb, offset, pinfo, dcerpc_tree, &hdr, transport_type);
+        dissect_dcerpc_cn_bind (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_BIND_ACK:
     case PDU_ALTER_ACK:
-        dissect_dcerpc_cn_bind_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+        dissect_dcerpc_cn_bind_ack (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_AUTH3:
         /*
          * Nothing after the common header other than credentials.
          */
-        dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE, 
+        dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
                                &auth_info);
         break;
 
     case PDU_REQ:
-        dissect_dcerpc_cn_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, transport_type);
+        dissect_dcerpc_cn_rqst (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
         break;
 
     case PDU_RESP:
-        dissect_dcerpc_cn_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, transport_type);
+        dissect_dcerpc_cn_resp (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
         break;
 
     case PDU_FAULT:
-        dissect_dcerpc_cn_fault (tvb, offset, pinfo, dcerpc_tree, &hdr, transport_type);
+        dissect_dcerpc_cn_fault (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_BIND_NAK:
-        dissect_dcerpc_cn_bind_nak (tvb, offset, pinfo, dcerpc_tree, &hdr);
+        dissect_dcerpc_cn_bind_nak (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_CO_CANCEL:
@@ -3595,7 +4040,7 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
          * Nothing after the common header other than an authentication
          * verifier.
          */
-        dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE, 
+        dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
                                &auth_info);
         break;
 
@@ -3608,7 +4053,7 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
 
     default:
         /* might as well dissect the auth info */
-        dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE, 
+        dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
                                &auth_info);
         break;
     }
@@ -3626,7 +4071,8 @@ dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
      * Only one PDU per transport packet, and only one transport
      * packet per PDU.
      */
-    if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL, DCE_TRANSPORT_UNKNOWN)) {
+    pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
+    if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL)) {
         /*
          * It wasn't a DCERPC PDU.
          */
@@ -3646,11 +4092,11 @@ dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  * to be able to know what kind of private_data structure to expect.
  */
 static gboolean
-dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int transport_type)
+dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
     volatile int offset = 0;
     int pdu_len;
-    volatile gboolean is_dcerpc_pdu;
+    volatile gboolean dcerpc_pdus = 0;
     volatile gboolean ret = FALSE;
 
     /*
@@ -3667,18 +4113,24 @@ dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
          * snapshot length, so there's nothing more to dissect; just
          * re-throw that exception.
          */
-        is_dcerpc_pdu = FALSE;
         TRY {
-            is_dcerpc_pdu = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
-                                               dcerpc_cn_desegment, &pdu_len,
-                                              transport_type);
+            pdu_len = 0;
+            if(dissect_dcerpc_cn (tvb, offset, pinfo, tree,
+                dcerpc_cn_desegment, &pdu_len)) {
+                dcerpc_pdus++;
+            }
         } CATCH(BoundsError) {
             RETHROW;
         } CATCH(ReportedBoundsError) {
             show_reported_bounds_error(tvb, pinfo, tree);
+            /*
+             * Presumably it looked enough like a DCE RPC PDU that we
+             * dissected enough of it to throw an exception.
+             */
+            dcerpc_pdus++;
         } ENDTRY;
 
-        if (!is_dcerpc_pdu) {
+        if (!dcerpc_pdus) {
             /*
              * Not a DCERPC PDU.
              */
@@ -3690,10 +4142,21 @@ dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
          */
         ret = TRUE;
 
+        /* if we had more than one Req/Resp in this PDU change the protocol column */
+        /* this will formerly contain the last interface name, which may not be the same for all Req/Resp */
+        if (dcerpc_pdus >= 2 && check_col (pinfo->cinfo, COL_PROTOCOL))
+            col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%u*DCERPC", dcerpc_pdus);
+
         if (pdu_len == 0) {
             /*
-             * Desegmentation required - bail now.
+             * Desegmentation required - bail now, but give the user a hint that desegmentation might be done later.
              */
+            proto_tree_add_uint_format(tree, hf_dcerpc_cn_deseg_req, tvb, offset,
+                0,
+                tvb_reported_length_remaining(tvb, offset),
+                "[DCE RPC: %u byte%s left, desegmentation might follow]",
+                tvb_reported_length_remaining(tvb, offset),
+                plurality(tvb_reported_length_remaining(tvb, offset), "", "s"));
             break;
        }
 
@@ -3708,13 +4171,22 @@ dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 static gboolean
 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree, DCE_TRANSPORT_UNKNOWN);
+       pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
+       return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
 }
 
 static gboolean
 dissect_dcerpc_cn_smbpipe (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree, DCE_CN_TRANSPORT_SMBPIPE);
+       pinfo->dcetransporttype=DCE_CN_TRANSPORT_SMBPIPE;
+       return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
+}
+
+static gboolean
+dissect_dcerpc_cn_smb2 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
+       return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
 }
 
 
@@ -3902,9 +4374,10 @@ dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
     fragment_data *fd_head;
     tvbuff_t *next_tvb;
     proto_item *pi;
+    proto_item *parent_pi;
 
     if (check_col (pinfo->cinfo, COL_INFO))
-        col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u", 
+        col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u",
             di->call_data->opnum, hdr->frag_len );
 
     length = tvb_length_remaining (tvb, offset);
@@ -3944,6 +4417,7 @@ dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
            }
            if (dcerpc_tree) {
                if (length > 0) {
+                   tvb_ensure_bytes_exist(tvb, offset, stub_length);
                    proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                         "Fragment data (%d byte%s)",
                                         stub_length,
@@ -3958,37 +4432,42 @@ dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
           third means we can attempt reassembly. */
        if (dcerpc_tree) {
            if (length > 0) {
+               tvb_ensure_bytes_exist(tvb, offset, stub_length);
                proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
                                     "Fragment data (%d byte%s)", stub_length,
                                     plurality(stub_length, "", "s"));
            }
        }
 
-       fd_head = fragment_add_dcerpc(tvb, offset, pinfo,
+       fd_head = fragment_add_dcerpc_dg(tvb, offset, pinfo,
                        hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table,
                        hdr->frag_num, stub_length,
                        !(hdr->flags1 & PFCL1_LASTFRAG));
-       if (fd_head != NULL) {
+    if (fd_head != NULL) {
            /* We completed reassembly... */
         if(pinfo->fd->num==fd_head->reassembled_in) {
             /* ...and this is the reassembled RPC PDU */
-           next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
-           tvb_set_child_real_data_tvbuff(tvb, next_tvb);
-           add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
-           show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
-                                  dcerpc_tree, pinfo, next_tvb);
-
-           /*
-            * XXX - authentication info?
-            */
-           pinfo->fragmented = FALSE;
-           dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
-                               next_tvb, hdr->drep, di, NULL);
-       } else {
+               next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+               tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+               add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
+               show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
+                                          tree, pinfo, next_tvb, &pi);
+
+               /*
+                * XXX - authentication info?
+                */
+               pinfo->fragmented = FALSE;
+               dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
+                                       next_tvb, hdr->drep, di, NULL);
+               } else {
             /* ...and this isn't the reassembled RPC PDU */
                pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
                                    tvb, 0, 0, fd_head->reassembled_in);
             PROTO_ITEM_SET_GENERATED(pi);
+            parent_pi = proto_tree_get_parent(dcerpc_tree);
+            if(parent_pi != NULL) {
+                proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
+            }
                if (check_col(pinfo->cinfo, COL_INFO)) {
                    col_append_fstr(pinfo->cinfo, COL_INFO,
                            " [DCE/RPC fragment, reas: #%u]", fd_head->reassembled_in);
@@ -4013,30 +4492,32 @@ dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
     dcerpc_call_value *value, v;
     dcerpc_matched_key matched_key, *new_matched_key;
     proto_item *pi;
+    proto_item *parent_pi;
 
     di=get_next_di();
     if(!(pinfo->fd->flags.visited)){
        dcerpc_call_value *call_value;
        dcerpc_dg_call_key *call_key;
 
-       call_key=g_mem_chunk_alloc (dcerpc_dg_call_key_chunk);
+       call_key=se_alloc (sizeof (dcerpc_dg_call_key));
        call_key->conv=conv;
        call_key->seqnum=hdr->seqnum;
        call_key->act_id=hdr->act_id;
 
-       call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
+       call_value=se_alloc (sizeof (dcerpc_call_value));
        call_value->uuid = hdr->if_id;
        call_value->ver = hdr->if_ver;
+       call_value->object_uuid = hdr->obj_id;
        call_value->opnum = hdr->opnum;
        call_value->req_frame=pinfo->fd->num;
-       call_value->req_time.secs=pinfo->fd->abs_secs;
-       call_value->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+       call_value->req_time=pinfo->fd->abs_ts;
        call_value->rep_frame=0;
        call_value->max_ptr=0;
+       call_value->se_data = NULL;
        call_value->private_data = NULL;
        g_hash_table_insert (dcerpc_dg_calls, call_key, call_value);
 
-       new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+       new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
        new_matched_key->frame = pinfo->fd->num;
        new_matched_key->call_id = hdr->seqnum;
        g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
@@ -4048,10 +4529,12 @@ dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
     if (!value) {
         v.uuid = hdr->if_id;
         v.ver = hdr->if_ver;
+        v.object_uuid = hdr->obj_id;
         v.opnum = hdr->opnum;
         v.req_frame = pinfo->fd->num;
         v.rep_frame = 0;
         v.max_ptr = 0;
+        v.se_data=NULL;
         v.private_data=NULL;
         value = &v;
     }
@@ -4066,6 +4549,10 @@ dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
        pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
                            tvb, 0, 0, value->rep_frame);
     PROTO_ITEM_SET_GENERATED(pi);
+    parent_pi = proto_tree_get_parent(dcerpc_tree);
+    if(parent_pi != NULL) {
+        proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
+    }
     }
     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
 }
@@ -4079,6 +4566,7 @@ dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
     dcerpc_call_value *value, v;
     dcerpc_matched_key matched_key, *new_matched_key;
     proto_item *pi;
+    proto_item *parent_pi;
 
     di=get_next_di();
     if(!(pinfo->fd->flags.visited)){
@@ -4090,7 +4578,7 @@ dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
        call_key.act_id=hdr->act_id;
 
        if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
-           new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+           new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
            new_matched_key->frame = pinfo->fd->num;
            new_matched_key->call_id = hdr->seqnum;
            g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
@@ -4106,9 +4594,11 @@ dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
     if (!value) {
         v.uuid = hdr->if_id;
         v.ver = hdr->if_ver;
+        v.object_uuid = hdr->obj_id;
         v.opnum = hdr->opnum;
         v.req_frame=0;
         v.rep_frame=pinfo->fd->num;
+        v.se_data=NULL;
         v.private_data=NULL;
         value = &v;
     }
@@ -4120,22 +4610,62 @@ dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
     di->call_data = value;
 
     if(value->req_frame!=0){
-       nstime_t ns;
+       nstime_t delta_ts;
        pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
                            tvb, 0, 0, value->req_frame);
     PROTO_ITEM_SET_GENERATED(pi);
-       ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
-       ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
-       if(ns.nsecs<0){
-               ns.nsecs+=1000000000;
-               ns.secs--;
-       }
-       pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+    parent_pi = proto_tree_get_parent(dcerpc_tree);
+    if(parent_pi != NULL) {
+        proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
+    }
+       nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+       pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
     PROTO_ITEM_SET_GENERATED(pi);
+    } else {
+               pi = proto_tree_add_text(dcerpc_tree,
+                                   tvb, 0, 0, "No request to this DCE/RPC call found");
+               expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
+                       "No request to this DCE/RPC call found");
     }
     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
 }
 
+static void
+dissect_dcerpc_dg_ping_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
+                        proto_tree *dcerpc_tree,
+                        e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
+{
+    proto_item *parent_pi;
+/*    if(!(pinfo->fd->flags.visited)){*/
+       dcerpc_call_value *call_value;
+       dcerpc_dg_call_key call_key;
+
+       call_key.conv=conv;
+       call_key.seqnum=hdr->seqnum;
+       call_key.act_id=hdr->act_id;
+
+       if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
+        proto_item *pi;
+               nstime_t delta_ts;
+
+               pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
+                                   tvb, 0, 0, call_value->req_frame);
+        PROTO_ITEM_SET_GENERATED(pi);
+        parent_pi = proto_tree_get_parent(dcerpc_tree);
+        if(parent_pi != NULL) {
+            proto_item_append_text(parent_pi, ", [Req: #%u]", call_value->req_frame);
+        }
+
+        if (check_col (pinfo->cinfo, COL_INFO))
+            col_append_fstr(pinfo->cinfo, COL_INFO, " [req: #%u]", call_value->req_frame);
+
+               nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &call_value->req_time);
+               pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
+        PROTO_ITEM_SET_GENERATED(pi);
+/*    }*/
+    }
+}
+
 /*
  * DCERPC dissector for connectionless calls
  */
@@ -4152,8 +4682,8 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     int offset = 0;
     conversation_t *conv;
     int auth_level;
-    char uuid_str[DCERPC_UUID_STR_LEN]; 
-    int uuid_str_len;
+    char *uuid_str;
+    const char *uuid_name = NULL;
 
     /*
      * Check if this looks like a CL DCERPC call.  All dg packets
@@ -4163,20 +4693,37 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
         return FALSE;
     }
+
+    /* Version must be 4 */
     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
     if (hdr.rpc_ver != 4)
         return FALSE;
+
+    /* Type must be <=19 or its not DCE/RPC */
     hdr.ptype = tvb_get_guint8 (tvb, offset++);
     if (hdr.ptype > 19)
         return FALSE;
 
+    /* flags1 has bit 1 and 8 as reserved so if any of them are set, it is
+       probably not a DCE/RPC packet
+     */
+    hdr.flags1 = tvb_get_guint8 (tvb, offset++);
+    if(hdr.flags1&0x81)
+        return FALSE;
+
+    /* flags2 has all bits except bit 2 as reserved so if any of them are set
+       it is probably not DCE/RPC.
+     */
+    hdr.flags2 = tvb_get_guint8 (tvb, offset++);
+    if(hdr.flags2&0xfd)
+        return FALSE;
+
+
     if (check_col (pinfo->cinfo, COL_PROTOCOL))
         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
     if (check_col (pinfo->cinfo, COL_INFO))
         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
 
-    hdr.flags1 = tvb_get_guint8 (tvb, offset++);
-    hdr.flags2 = tvb_get_guint8 (tvb, offset++);
     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
     offset += sizeof (hdr.drep);
     hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
@@ -4209,6 +4756,10 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
         if (ti) {
             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
+                   proto_item_append_text(ti, " %s, Seq: %u, Serial: %u, Frag: %u, FragLen: %u",
+                val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"),
+                hdr.seqnum, hdr.serial_hi*256+hdr.serial_lo,
+                hdr.frag_num, hdr.frag_len);
         }
     }
     offset = 0;
@@ -4233,6 +4784,15 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
+            if(hdr.flags1) {
+                       proto_item_append_text(tf, " %s%s%s%s%s%s",
+                    (hdr.flags1 & PFCL1_BROADCAST) ? "\"Broadcast\" " : "",
+                    (hdr.flags1 & PFCL1_IDEMPOTENT) ? "\"Idempotent\" " : "",
+                    (hdr.flags1 & PFCL1_MAYBE) ? "\"Maybe\" " : "",
+                    (hdr.flags1 & PFCL1_NOFACK) ? "\"No Fack\" " : "",
+                    (hdr.flags1 & PFCL1_FRAG) ? "\"Fragment\" " : "",
+                    (hdr.flags1 & PFCL1_LASTFRAG) ? "\"Last Fragment\" " : "");
+            }
         }
     }
     offset++;
@@ -4249,6 +4809,10 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
+            if(hdr.flags2) {
+                       proto_item_append_text(tf, " %s",
+                    (hdr.flags2 & PFCL2_CANCEL_PENDING) ? "\"Cancel Pending\" " : "");
+            }
         }
     }
     offset++;
@@ -4260,6 +4824,10 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
+                   proto_item_append_text(tf, " (Order: %s, Char: %s, Float: %s)",
+                val_to_str(hdr.drep[0] >> 4, drep_byteorder_vals, "Unknown"),
+                val_to_str(hdr.drep[0] & 0x0f, drep_character_vals, "Unknown"),
+                val_to_str(hdr.drep[1], drep_fp_vals, "Unknown"));
         }
     }
     offset += sizeof (hdr.drep);
@@ -4269,62 +4837,29 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     offset++;
 
     if (tree) {
-        /* XXX - use "dissect_ndr_uuid_t()"? */
-       uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
-                                hdr.obj_id.Data4[0],
-                                hdr.obj_id.Data4[1],
-                                hdr.obj_id.Data4[2],
-                                hdr.obj_id.Data4[3],
-                                hdr.obj_id.Data4[4],
-                                hdr.obj_id.Data4[5],
-                                hdr.obj_id.Data4[6],
-                                hdr.obj_id.Data4[7]);
-        if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-               memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-        proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
-                                      offset, 16, uuid_str, "Object UUID: %s", uuid_str);
+        proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
+            offset, 16, (e_guid_t *) &hdr.obj_id, "Object UUID: %s",
+            guid_to_str((e_guid_t *) &hdr.obj_id));
     }
     offset += 16;
 
     if (tree) {
-        /* XXX - use "dissect_ndr_uuid_t()"? */
-       uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
-                                hdr.if_id.Data4[0],
-                                hdr.if_id.Data4[1],
-                                hdr.if_id.Data4[2],
-                                hdr.if_id.Data4[3],
-                                hdr.if_id.Data4[4],
-                                hdr.if_id.Data4[5],
-                                hdr.if_id.Data4[6],
-                                hdr.if_id.Data4[7]);
-        if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-               memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-        proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
-                                      offset, 16, uuid_str, "Interface: %s", uuid_str);
+        uuid_str = guid_to_str((e_guid_t*)&hdr.if_id);
+        uuid_name = guids_get_uuid_name(&hdr.if_id);
+        if(uuid_name) {
+                 proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
+                                        offset, 16, (e_guid_t *) &hdr.if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
+        } else {
+          proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
+                                        offset, 16, (e_guid_t *) &hdr.if_id, "Interface UUID: %s", uuid_str);
+        }
     }
     offset += 16;
 
     if (tree) {
-        /* XXX - use "dissect_ndr_uuid_t()"? */
-       uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
-                                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
-                                hdr.act_id.Data4[0],
-                                hdr.act_id.Data4[1],
-                                hdr.act_id.Data4[2],
-                                hdr.act_id.Data4[3],
-                                hdr.act_id.Data4[4],
-                                hdr.act_id.Data4[5],
-                                hdr.act_id.Data4[6],
-                                hdr.act_id.Data4[7]);
-        if (uuid_str_len >= DCERPC_UUID_STR_LEN)
-               memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
-        proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
-                                      offset, 16, uuid_str, "Activity: %s", uuid_str);
+        proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
+                                      offset, 16, (e_guid_t *) &hdr.act_id, "Activity: %s",
+                                      guid_to_str((e_guid_t *) &hdr.act_id));
     }
     offset += 16;
 
@@ -4353,6 +4888,9 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     if (check_col (pinfo->cinfo, COL_INFO)) {
         col_append_fstr (pinfo->cinfo, COL_INFO, ": seq: %u", hdr.seqnum);
     }
+    if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
+        col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.seqnum);
+    }
     offset += 4;
 
     if (tree)
@@ -4418,10 +4956,10 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
      * activity_id and seqnum.  I haven't seen anywhere that it would
      * make a difference, but for future reference...
      */
-    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+    conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                               pinfo->srcport, pinfo->destport, 0);
     if (!conv) {
-        conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+        conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                                  pinfo->srcport, pinfo->destport, 0);
     }
 
@@ -4457,7 +4995,10 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         break;
 
     case PDU_FACK:
-        dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+        /* Body is optional */
+        /* XXX - we assume "frag_len" is the length of the body */
+        if (hdr.frag_len != 0)
+            dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_REJECT:
@@ -4476,6 +5017,8 @@ dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     /* these requests have no body */
     case PDU_ACK:
     case PDU_PING:
+        dissect_dcerpc_dg_ping_ack (tvb, offset, pinfo, dcerpc_tree, &hdr, conv);
+        break;
     case PDU_WORKING:
     default:
         break;
@@ -4490,23 +5033,12 @@ dcerpc_init_protocol (void)
        /* structures and data for BIND */
        if (dcerpc_binds){
                g_hash_table_destroy (dcerpc_binds);
+               dcerpc_binds=NULL;
        }
-       dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
-
-       if (dcerpc_bind_key_chunk){
-               g_mem_chunk_destroy (dcerpc_bind_key_chunk);
-       }
-       dcerpc_bind_key_chunk = g_mem_chunk_new ("dcerpc_bind_key_chunk",
-                                             sizeof (dcerpc_bind_key),
-                                             200 * sizeof (dcerpc_bind_key),
-                                             G_ALLOC_ONLY);
-       if (dcerpc_bind_value_chunk){
-               g_mem_chunk_destroy (dcerpc_bind_value_chunk);
+       if(!dcerpc_binds){
+               dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
        }
-       dcerpc_bind_value_chunk = g_mem_chunk_new ("dcerpc_bind_value_chunk",
-                                             sizeof (dcerpc_bind_value),
-                                             200 * sizeof (dcerpc_bind_value),
-                                             G_ALLOC_ONLY);
+
        /* structures and data for CALL */
        if (dcerpc_cn_calls){
                g_hash_table_destroy (dcerpc_cn_calls);
@@ -4516,41 +5048,12 @@ dcerpc_init_protocol (void)
                g_hash_table_destroy (dcerpc_dg_calls);
        }
        dcerpc_dg_calls = g_hash_table_new (dcerpc_dg_call_hash, dcerpc_dg_call_equal);
-       if (dcerpc_cn_call_key_chunk){
-               g_mem_chunk_destroy (dcerpc_cn_call_key_chunk);
-       }
-       dcerpc_cn_call_key_chunk = g_mem_chunk_new ("dcerpc_cn_call_key_chunk",
-               sizeof (dcerpc_cn_call_key),
-               200 * sizeof (dcerpc_cn_call_key),
-               G_ALLOC_ONLY);
-       if (dcerpc_dg_call_key_chunk){
-               g_mem_chunk_destroy (dcerpc_dg_call_key_chunk);
-       }
-       dcerpc_dg_call_key_chunk = g_mem_chunk_new ("dcerpc_dg_call_key_chunk",
-               sizeof (dcerpc_dg_call_key),
-               200 * sizeof (dcerpc_dg_call_key),
-               G_ALLOC_ONLY);
-
-       if (dcerpc_call_value_chunk){
-               g_mem_chunk_destroy (dcerpc_call_value_chunk);
-       }
-       dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
-                                             sizeof (dcerpc_call_value),
-                                             200 * sizeof (dcerpc_call_value),
-                                             G_ALLOC_ONLY);
 
        /* structure and data for MATCHED */
        if (dcerpc_matched){
                g_hash_table_destroy (dcerpc_matched);
        }
        dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
-       if (dcerpc_matched_key_chunk){
-               g_mem_chunk_destroy (dcerpc_matched_key_chunk);
-       }
-       dcerpc_matched_key_chunk = g_mem_chunk_new ("dcerpc_matched_key_chunk",
-                                             sizeof (dcerpc_matched_key),
-                                             200 * sizeof (dcerpc_matched_key),
-                                             G_ALLOC_ONLY);
 
     /* call the registered hooks */
     g_hook_list_invoke(&dcerpc_hooks_init_protos, FALSE /* not may_recurse */);
@@ -4615,20 +5118,26 @@ proto_register_dcerpc (void)
           { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_num_ctx_items,
           { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_cn_ctx_item,
+          { "Ctx Item", "dcerpc.cn_ctx_item", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_ctx_id,
           { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_num_trans_items,
-          { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+          { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_cn_bind_abstract_syntax,
+          { "Abstract Syntax", "dcerpc.cn_bind_abstract_syntax", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_if_id,
-          { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_if_ver,
           { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_if_ver_minor,
           { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_cn_bind_trans_syntax,
+          { "Transfer Syntax", "dcerpc.cn_bind_trans", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_trans_id,
-          { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "ID", "dcerpc.cn_bind_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_trans_ver,
-          { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+          { "ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_alloc_hint,
           { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_sec_addr_len,
@@ -4642,7 +5151,7 @@ proto_register_dcerpc (void)
         { &hf_dcerpc_cn_ack_reason,
           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, "", HFILL }},
         { &hf_dcerpc_cn_ack_trans_id,
-          { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_ack_trans_ver,
           { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_reject_reason,
@@ -4657,6 +5166,8 @@ proto_register_dcerpc (void)
           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_status,
           { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
+        { &hf_dcerpc_cn_deseg_req,
+          { "Desegmentation Required", "dcerpc.cn_deseg_req", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_auth_type,
           { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
         { &hf_dcerpc_auth_level,
@@ -4730,11 +5241,11 @@ proto_register_dcerpc (void)
         { &hf_dcerpc_krb5_av_key_auth_verifier,
           { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_obj_id,
-          { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "Object", "dcerpc.obj_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_if_id,
-          { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "Interface", "dcerpc.dg_if_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_act_id,
-          { "Activity", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+          { "Activity", "dcerpc.dg_act_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_opnum,
           { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
 
@@ -4782,12 +5293,12 @@ proto_register_dcerpc (void)
 
        { &hf_dcerpc_array_buffer,
          { "Buffer", "dcerpc.array.buffer", FT_BYTES, BASE_NONE, NULL, 0x0, "Buffer: Buffer containing elements of the array", HFILL }},
-               
+
         { &hf_dcerpc_op,
           { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
 
        { &hf_dcerpc_fragments,
-         { "DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
+         { "Reassembled DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
          NULL, 0x0, "DCE/RPC Fragments", HFILL }},
 
        { &hf_dcerpc_fragment,
@@ -4795,34 +5306,34 @@ proto_register_dcerpc (void)
          NULL, 0x0, "DCE/RPC Fragment", HFILL }},
 
        { &hf_dcerpc_fragment_overlap,
-         { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, 
+         { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE,
       NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
 
        { &hf_dcerpc_fragment_overlap_conflict,
-         { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, 
+         { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE,
       NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
 
        { &hf_dcerpc_fragment_multiple_tails,
-         { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, 
+         { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE,
       NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
 
        { &hf_dcerpc_fragment_too_long_fragment,
-         { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, 
+         { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
       NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
 
        { &hf_dcerpc_fragment_error,
-         { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE, 
+         { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE,
       NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
 
-       { &hf_dcerpc_time, 
-         { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE, 
+       { &hf_dcerpc_time,
+         { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE,
       NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }},
 
        { &hf_dcerpc_reassembled_in,
-         { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE, 
+      { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE,
       NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }},
 
-       { &hf_dcerpc_unknown_if_id, 
+       { &hf_dcerpc_unknown_if_id,
          { "Unknown DCERPC interface id", "dcerpc.unknown_if_id", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
    };
     static gint *ett[] = {
@@ -4830,6 +5341,7 @@ proto_register_dcerpc (void)
         &ett_dcerpc_cn_flags,
         &ett_dcerpc_cn_ctx,
         &ett_dcerpc_cn_iface,
+        &ett_dcerpc_cn_trans_syntax,
         &ett_dcerpc_drep,
         &ett_dcerpc_dg_flags1,
         &ett_dcerpc_dg_flags2,
@@ -4860,7 +5372,7 @@ proto_register_dcerpc (void)
     register_init_routine(dcerpc_reassemble_init);
     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
     dcerpc_tap=register_tap("dcerpc");
-    
+
     g_hook_list_init(&dcerpc_hooks_init_protos, sizeof(GHook));
 }
 
@@ -4871,5 +5383,7 @@ proto_reg_handoff_dcerpc (void)
     heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
     heur_dissector_add ("smb_transact", dissect_dcerpc_cn_smbpipe, proto_dcerpc);
+    heur_dissector_add ("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, proto_dcerpc);
+    heur_dissector_add ("http", dissect_dcerpc_cn_bs, proto_dcerpc);
     dcerpc_smb_init(proto_dcerpc);
 }