Ethereal-dev: dcerpc patch (was Re: [Ethereal-dev] Is someone working on a DCOM/ORPC dissector

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Todd Sabin <tas@xxxxxxxxxxx>
Date: 09 Jul 2001 08:03:02 -0400
ulf.lamping@xxxxxx writes:
> 
> Do you know, if the .idl syntax for the DCE-RPC and DCOM are identical? If
> not, do you have an example DCE-RPC idl file (just for my information at this
> devel stage)?
> 
> Do you have some further information about the DCE-RPC protocol?
> 

The IDL for DCOM is defined by Microsoft.  I don't know if there's an
official spec for it, other than what their IDL compiler accepts.  It
is based on the original dce-rpc idl, but has many extensions.  The
original is documented at http://www.opengroup.org.  Search for DCE
RPC 1.1.  It used to be freely available, but seems you may have to
register for it now.  That document also describes the basic DCE/RPC
wire protocol.

> Is the "handoff stage" on your to-do list, or are you already working on it?
> 

Well, I hadn't started, and I was describing what I was going to do,
when it suddenly seemed like it wouldn't be all that bad. :-)
Naturally, it turned out to be more than expected.  Anyway, here's a
patch to do almost all of the handoff, and a few subdissectors which
use it.  None of them dissect any of the actual payload, yet, but they
do show the names of the calls.

Could someone double-check the conversation/hash stuff for leaks?  I
used pretty much the same approach used by packet-rpc.c, so assuming
it's ok, then I think this is as well, but...


Todd

p.s.  I tend to agree with the other poster about putting the
subdissectors for GIOP in a subdirectory or something.  The same is
true for dcerpc.  There are literally hundreds of these things which
can be written.

Index: packet-dcerpc.c
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.c,v
retrieving revision 1.5
diff -u -r1.5 packet-dcerpc.c
--- packet-dcerpc.c	2001/06/18 02:17:45	1.5
+++ packet-dcerpc.c	2001/07/09 11:16:58
@@ -37,6 +37,7 @@
 #include <glib.h>
 #include "packet.h"
 #include "packet-dcerpc.h"
+#include "conversation.h"
 
 static const value_string pckt_vals[] = {
     { 0, "Request"},
@@ -92,6 +93,7 @@
 static int hf_dcerpc_cn_num_trans_items = -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_id = -1;
 static int hf_dcerpc_cn_bind_trans_ver = -1;
 static int hf_dcerpc_cn_alloc_hint = -1;
@@ -99,6 +101,7 @@
 static int hf_dcerpc_cn_num_results = -1;
 static int hf_dcerpc_cn_ack_result = -1;
 static int hf_dcerpc_cn_ack_reason = -1;
+static int hf_dcerpc_cn_cancel_count = -1;
 static int hf_dcerpc_dg_flags1 = -1;
 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
 static int hf_dcerpc_dg_flags1_last_frag = -1;
@@ -137,7 +140,216 @@
 static gint ett_dcerpc_dg_flags1 = -1;
 static gint ett_dcerpc_dg_flags2 = -1;
 
+/*
+ * Subdissectors
+ */
+
+/* the registered subdissectors */
+static GHashTable *dcerpc_uuids;
+
+typedef struct _dcerpc_uuid_key {
+    e_uuid_t uuid;
+    guint16 ver;
+} dcerpc_uuid_key;
+
+typedef struct _dcerpc_uuid_value {
+    int proto;
+    int ett;
+    gchar *name;
+    dcerpc_sub_dissector *procs;
+} dcerpc_uuid_value;
+
+static gint
+dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
+{
+    dcerpc_uuid_key *key1 = (dcerpc_uuid_key *)k1;
+    dcerpc_uuid_key *key2 = (dcerpc_uuid_key *)k2;
+    return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
+            && (key1->ver == key2->ver));
+}
+
+static guint
+dcerpc_uuid_hash (gconstpointer k)
+{
+    dcerpc_uuid_key *key = (dcerpc_uuid_key *)k;
+    /* This isn't perfect, but the Data1 part of these is almost always
+       unique. */
+    return key->uuid.Data1;
+}
+
+void
+dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
+                  dcerpc_sub_dissector *procs)
+{
+    dcerpc_uuid_key *key = g_malloc (sizeof (*key));
+    dcerpc_uuid_value *value = g_malloc (sizeof (*value));
+
+    key->uuid = *uuid;
+    key->ver = ver;
+
+    value->proto = proto;
+    value->ett = ett;
+    value->name = proto_get_protocol_short_name (proto);
+    value->procs = procs;
+
+    g_hash_table_insert (dcerpc_uuids, key, value);
+}
+
+
+/*
+ * To keep track of ctx_id mappings.  Should really use some
+ * generic conversation support instead.
+ */
+static GHashTable *dcerpc_convs;
+
+typedef struct _dcerpc_conv_key {
+    conversation_t *conv;
+    guint16 ctx_id;
+} dcerpc_conv_key;
+
+typedef struct _dcerpc_conv_value {
+    e_uuid_t uuid;
+    guint16 ver;
+} dcerpc_conv_value;
+
+static gint
+dcerpc_conv_equal (gconstpointer k1, gconstpointer k2)
+{
+    dcerpc_conv_key *key1 = (dcerpc_conv_key *)k1;
+    dcerpc_conv_key *key2 = (dcerpc_conv_key *)k2;
+    return (key1->conv == key2->conv
+            && key1->ctx_id == key2->ctx_id);
+}
+
+static guint
+dcerpc_conv_hash (gconstpointer k)
+{
+    dcerpc_conv_key *key = (dcerpc_conv_key *)k;
+    return ((guint)key->conv) + key->ctx_id;
+}
+
+
+
+/*
+ * To keep track of callid mappings.  Should really use some generic
+ * conversation support instead.
+ */
+static GHashTable *dcerpc_calls;
+
+typedef struct _dcerpc_call_key {
+    conversation_t *conv;
+    guint32 call_id;
+} dcerpc_call_key;
+
+typedef struct _dcerpc_call_value {
+    e_uuid_t uuid;
+    guint16 ver;
+    guint16 opnum;
+} dcerpc_call_value;
+
+static gint
+dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
+{
+    dcerpc_call_key *key1 = (dcerpc_call_key *)k1;
+    dcerpc_call_key *key2 = (dcerpc_call_key *)k2;
+    return (key1->conv == key2->conv
+            && key1->call_id == key2->call_id);
+}
+
+static guint
+dcerpc_call_hash (gconstpointer k)
+{
+    dcerpc_call_key *key = (dcerpc_call_key *)k;
+    return ((guint32)key->conv) ^ key->call_id;
+}
+
+static void
+dcerpc_call_add_map (guint32 call_id, conversation_t *conv,
+                     guint16 opnum, guint16 ver, e_uuid_t *uuid)
+{
+    dcerpc_call_key *key = g_malloc (sizeof (*key));
+    dcerpc_call_value *value = g_malloc (sizeof (*value));
+
+    key->call_id = call_id;
+    key->conv = conv;
+    value->uuid = *uuid;
+    value->ver = ver;
+    value->opnum = opnum;
+    g_hash_table_insert (dcerpc_calls, key, value);
+}
+
+static dcerpc_call_value*
+dcerpc_call_lookup (guint32 call_id, conversation_t *conv)
+{
+    dcerpc_call_key key;
+
+    key.call_id = call_id;
+    key.conv = conv;
+    return g_hash_table_lookup (dcerpc_calls, &key);
+}
+
+
+/*
+ * Utility functions.  Modeled after packet-rpc.c
+ */
+
+int
+dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                      proto_tree *tree, char *drep, 
+                      int hfindex, guint8 *pdata)
+{
+    guint8 data;
+
+    data = tvb_get_guint8 (tvb, offset);
+    if (tree) {
+        proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
+    }
+    if (pdata)
+        *pdata = data;
+    return offset + 1;
+}
+
+int
+dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *tree, char *drep, 
+                       int hfindex, guint16 *pdata)
+{
+    guint16 data;
+
+    data = ((drep[0] & 0x10)
+            ? tvb_get_letohs (tvb, offset)
+            : tvb_get_ntohs (tvb, offset));
+    
+    if (tree) {
+        proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
+    }
+    if (pdata)
+        *pdata = data;
+    return offset + 2;
+}
 
+int
+dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *tree, char *drep, 
+                       int hfindex, guint32 *pdata)
+{
+    guint32 data;
+
+    data = ((drep[0] & 0x10)
+            ? tvb_get_letohl (tvb, offset)
+            : tvb_get_ntohl (tvb, offset));
+    
+    if (tree) {
+        proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
+    }
+    if (pdata)
+        *pdata = data;
+    return offset+4;
+}
+
+/*
+ * a couple simpler things
+ */
 guint16
 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
 {
@@ -171,122 +383,166 @@
     }
 }
 
+static int
+dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
+                    tvbuff_t *tvb, gint offset,
+                    e_uuid_t *uuid, guint16 ver, 
+                    guint16 opnum, gboolean is_rqst)
+{
+    dcerpc_uuid_key key;
+    dcerpc_uuid_value *sub_proto;
+    proto_item *sub_item;
+    proto_tree *sub_tree;
+    dcerpc_sub_dissector *proc;
+    gchar *name = NULL;
+
+    key.uuid = *uuid;
+    key.ver = ver;
+
+    
+    if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == 0)
+        return -1;
 
+    if (tree) {
+        sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset, 
+                                        tvb_length (tvb) - offset, FALSE);
+        if (sub_item) {
+            sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
+        }
+        
+    }
+    for (proc = sub_proto->procs; proc->name; proc++) {
+        if (proc->num == opnum) {
+            name = proc->name;
+            break;
+        }
+    }
+
+    if (!name)
+        name = "Unknown?!";
+
+    if (check_col (pinfo->fd, COL_INFO)) {
+        col_add_fstr (pinfo->fd, COL_INFO, "%s %s:%s(...)",
+                      is_rqst ? "rqst" : "rply",
+                      sub_proto->name, name);
+    }
+
+    if (check_col (pinfo->fd, COL_PROTOCOL)) {
+        col_set_str (pinfo->fd, COL_PROTOCOL, sub_proto->name);
+    }
+    // FIXME: call approp. dissector
+    return 0;
+}
+
+
+/*
+ * Connection oriented packet types
+ */
+
 static void
 dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
                         e_dce_cn_common_hdr_t *hdr)
 {
-    guint16 max_xmit, max_recv;
-    guint32 assoc_group;
+    conversation_t *conv = NULL;
+    dcerpc_conv_key *key;
+    dcerpc_conv_value *value;
     guint8 num_ctx_items;
     guint16 ctx_id;
     guint16 num_trans_items;
     e_uuid_t if_id;
     e_uuid_t trans_id;
-    guint32 if_ver, trans_ver;
+    guint32 trans_ver;
+    guint16 if_ver, if_ver_minor;
     int offset = 16;
 
-    max_xmit = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_max_xmit, NULL);
 
-    max_recv = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_max_recv, NULL);
 
-    assoc_group = dcerpc_tvb_get_ntohl (tvb, offset, hdr->drep);
-    offset += 4;
+    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_assoc_group, NULL);
 
-    num_ctx_items = tvb_get_guint8 (tvb, offset);
-    offset++;
+    offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
 
     /* padding */
     offset += 3;
 
-    ctx_id = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_ctx_id, &ctx_id);
 
-    num_trans_items = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_num_trans_items, &num_trans_items);
 
     dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
-    offset += 16;
-
-    if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr->drep);
-    offset += 4;
-
-    dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
-    offset += 16;
-
-    trans_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr->drep);
-    offset += 4;
-
-    if (check_col (pinfo->fd, COL_INFO)) {
-        col_add_fstr (pinfo->fd, COL_INFO, "Bind: UUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %d",
-                         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 (dcerpc_tree) {
-        offset = 16;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_max_xmit, tvb, offset, 2, max_xmit);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_max_recv, tvb, offset, 2, max_recv);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_assoc_group, tvb, offset, 4, assoc_group);
-        offset += 4;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_num_ctx_items, tvb, offset, 1, num_ctx_items);
-        offset++;
-
-        /* padding */
-        offset += 3;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_ctx_id, tvb, offset, 2, ctx_id);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_num_trans_items, tvb, offset, 2, num_trans_items);
-        offset += 2;
-
         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
                                       offset, 16, "HMMM",
                                       "Interface UUID: %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]);
-        offset += 16;
+                                      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]);
+    }
+    offset += 16;
 
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_bind_if_ver, tvb, offset, 4, if_ver);
-        offset += 4;
+    if (hdr->drep[0] & 0x10) {
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                        hf_dcerpc_cn_bind_if_ver, &if_ver);
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                        hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
+    } else {
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                        hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                        hf_dcerpc_cn_bind_if_ver, &if_ver);
+    }
 
+    dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
+    if (dcerpc_tree) {
         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
                                       offset, 16, "HMMM",
                                       "Transfer Syntax: %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]);
-        offset += 16;
+                                      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]);
+    }
+    offset += 16;
 
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_bind_trans_ver, tvb, offset, 4, trans_ver);
-        offset += 4;
+    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_bind_trans_ver, &trans_ver);
+
+    if (check_col (pinfo->fd, COL_INFO)) {
+        col_add_fstr (pinfo->fd, COL_INFO, "%s: UUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %d.%d",
+                      hdr->ptype == PDU_BIND ? "Bind" : "Alter Ctx",
+                      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);
+    }
+    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+                              pinfo->srcport, pinfo->destport, 0);
+    if (conv == NULL) {
+        conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+                                 pinfo->srcport, pinfo->destport, NULL, 0);
     }
+
+    key = g_malloc (sizeof (*key));
+    key->conv = conv;
+    key->ctx_id = ctx_id;
+
+    value = g_malloc (sizeof (*value));
+    value->uuid = if_id;
+    value->ver = if_ver;
+
+    g_hash_table_insert (dcerpc_convs, key, value);
 }
 
 static void
@@ -294,7 +550,6 @@
                             e_dce_cn_common_hdr_t *hdr)
 {
     guint16 max_xmit, max_recv;
-    guint32 assoc_group;
     guint16 sec_addr_len;
     guint8 num_results;
     guint16 result = 0;
@@ -302,128 +557,77 @@
 
     int offset = 16;
 
-    max_xmit = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_max_xmit, &max_xmit);
 
-    max_recv = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_max_recv, &max_recv);
 
-    assoc_group = dcerpc_tvb_get_ntohl (tvb, offset, hdr->drep);
-    offset += 4;
+    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_assoc_group, NULL);
 
-    sec_addr_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2 + sec_addr_len;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
+    offset += sec_addr_len;
 
     if (offset % 4) {
         offset += 4 - offset % 4;
     }
 
-    num_results = tvb_get_guint8 (tvb, offset);
-    offset++;
+    offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                   hf_dcerpc_cn_num_results, &num_results);
 
     /* padding */
     offset += 3;
 
     if (num_results == 1) {
-        result = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-        offset += 2;
-        
-        reason = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-        offset += 2;
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, 
+                                        hdr->drep, hf_dcerpc_cn_ack_result,
+                                        &result);
+        offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, 
+                                        hdr->drep, hf_dcerpc_cn_ack_reason,
+                                        &reason);
     }
     
     if (check_col (pinfo->fd, COL_INFO)) {
         if (num_results == 1 && result == 0) {
-            col_add_fstr (pinfo->fd, COL_INFO, "Bind ack: accept  max_xmit: %d  max_recv: %d",
-                             max_xmit, max_recv);
-            
+            col_add_fstr (pinfo->fd, COL_INFO, "%s ack: accept  max_xmit: %d  max_recv: %d",
+                          hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
+                          max_xmit, max_recv);
         } else {
             /* FIXME: should put in reason */
-            col_add_fstr (pinfo->fd, COL_INFO, "Bind ack: %s",
-                             result == 1 ? "User reject" :
-                             result == 2 ? "Provider reject" :
-                             "Unknown");
-        }
-    }
-
-    if (dcerpc_tree) {
-        offset = 16;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_max_xmit, tvb, offset, 2, max_xmit);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_max_recv, tvb, offset, 2, max_recv);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_assoc_group, tvb, offset, 4, assoc_group);
-        offset += 4;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_sec_addr_len, tvb, offset, 2, sec_addr_len);
-        offset +=2 + sec_addr_len;
-
-        if (offset % 4) {
-            offset += 4 - offset % 4;
-        }
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_num_results, tvb, offset, 1, num_results);
-        offset++;
-
-        /* padding */
-        offset += 3;
-
-        if (num_results == 1) {
-            proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_ack_result, tvb, offset, 2, result);
-            offset += 2;
-
-            proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_ack_reason, tvb, offset, 2, reason);
-            offset += 2;
+            col_add_fstr (pinfo->fd, COL_INFO, "%s ack: %s",
+                          hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
+                          result == 1 ? "User reject" :
+                          result == 2 ? "Provider reject" :
+                          "Unknown");
         }
     }
 }
 
 static void
 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
-                        e_dce_cn_common_hdr_t *hdr)
+                        proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
 {
-    guint32 alloc_hint;
+    conversation_t *conv;
     guint16 ctx_id;
     guint16 opnum;
     e_uuid_t obj_id;
 
     int offset = 16;
 
-    alloc_hint = dcerpc_tvb_get_ntohl (tvb, offset, hdr->drep);
-    offset += 4;
+    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_alloc_hint, NULL);
 
-    ctx_id = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_ctx_id, &ctx_id);
 
-    opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr->drep);
-    offset += 2;
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_opnum, &opnum);
 
     if (hdr->flags & 0x80) {
         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
-        offset += 16;
-    }
-
-    if (check_col (pinfo->fd, COL_INFO)) {
-        col_add_fstr (pinfo->fd, COL_INFO, "Request: opnum: %d  ctx_id:%d",
-                         opnum, ctx_id);
-    }
-
-    if (dcerpc_tree) {
-        offset = 16;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_alloc_hint, tvb, offset, 4, alloc_hint);
-        offset += 4;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_ctx_id, tvb, offset, 2, ctx_id);
-        offset += 2;
-
-        proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, opnum);
-        offset += 2;
-
-        if (hdr->flags & 0x80) {
+        if (dcerpc_tree) {
             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
                                           offset, 16, "HMMM",
                                           "Object UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
@@ -436,7 +640,75 @@
                                           obj_id.Data4[5],
                                           obj_id.Data4[6],
                                           obj_id.Data4[7]);
-            offset += 16;
+        }
+        offset += 16;
+    }
+
+    if (check_col (pinfo->fd, COL_INFO)) {
+        col_add_fstr (pinfo->fd, COL_INFO, "Request: opnum: %d  ctx_id:%d",
+                         opnum, ctx_id);
+    }
+
+    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+                              pinfo->srcport, pinfo->destport, 0);
+    if (!conv) {
+
+    } else {
+        dcerpc_conv_key key;
+        dcerpc_conv_value *value;
+
+        key.conv = conv;
+        key.ctx_id = ctx_id;
+
+        value = g_hash_table_lookup (dcerpc_convs, &key);
+        if (value) {
+            /* add an entry for this call, so we can catch the reply */
+            dcerpc_call_add_map (hdr->call_id, conv, opnum,
+                                 value->ver, &value->uuid);
+
+            /* handoff this call */
+            dcerpc_try_handoff (pinfo, tree, tvb, offset,
+                                &value->uuid, value->ver,
+                                opnum, TRUE);
+        }
+    }
+}
+
+static void
+dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
+                        proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
+{
+    conversation_t *conv;
+    guint16 ctx_id;
+
+    int offset = 16;
+
+    offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_alloc_hint, NULL);
+
+    offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                    hf_dcerpc_cn_ctx_id, &ctx_id);
+
+    offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                   hf_dcerpc_cn_cancel_count, NULL);
+    /* padding */
+    offset++;
+
+    if (check_col (pinfo->fd, COL_INFO)) {
+        col_add_fstr (pinfo->fd, COL_INFO, "Response: call_id: %d  ctx_id:%d",
+                      hdr->call_id, ctx_id);
+    }
+
+    conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+                              pinfo->srcport, pinfo->destport, 0);
+    if (!conv) {
+        /* no point in creating one here, really */
+    } else {
+        dcerpc_call_value *value = dcerpc_call_lookup (hdr->call_id, conv);
+        if (value) {
+            dcerpc_try_handoff (pinfo, tree, tvb, offset, 
+                                &value->uuid, value->ver,
+                                value->opnum, FALSE);
         }
     }
 }
@@ -526,15 +798,21 @@
      */
     switch (hdr.ptype) {
     case PDU_BIND:
+    case PDU_ALTER:
         dissect_dcerpc_cn_bind (tvb, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_BIND_ACK:
+    case PDU_ALTER_ACK:
         dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
         break;
 
     case PDU_REQ:
-        dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, &hdr);
+        dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
+        break;
+
+    case PDU_RESP:
+        dissect_dcerpc_cn_resp (tvb, pinfo, dcerpc_tree, tree, &hdr);
         break;
 
     default:
@@ -556,6 +834,7 @@
     proto_tree *dg_flags2_tree = NULL;
     e_dce_dg_common_hdr_t hdr;
     int offset = 0;
+    conversation_t *conv;
 
     /*
      * Check if this looks like a CL DCERPC call.  All dg packets
@@ -722,16 +1001,65 @@
         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
         offset++;
     }
+    /* 
+     * keeping track of the conversation shouldn't really be necessary
+     * for connectionless packets, because everything we need to know
+     * to dissect is in the header for each packet.  Unfortunately,
+     * Microsoft's implementation is buggy and often puts the
+     * completely wrong if_id in the header.  go figure.  So, keep
+     * track of the seqnum and use that if possible.  Note: that's not
+     * completely correct.  It should really be done based on both the
+     * 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,
+                              pinfo->srcport, pinfo->destport, 0);
+    if (!conv) {
+        conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+                                 pinfo->srcport, pinfo->destport, NULL, 0);
+    }
+
     /*
      * Packet type specific stuff is next.
      */
+    switch (hdr.ptype) {
+    case PDU_REQ:
+        dcerpc_call_add_map (hdr.seqnum, conv, hdr.opnum,
+                             hdr.if_ver, &hdr.if_id);
+        dcerpc_try_handoff (pinfo, tree, tvb, offset,
+                            &hdr.if_id, hdr.if_ver, hdr.opnum, TRUE);
+        break;
+    case PDU_RESP:
+        {
+            dcerpc_call_value *v = dcerpc_call_lookup (hdr.seqnum, conv);
+            if (v) {
+                dcerpc_try_handoff (pinfo, tree, tvb, offset,
+                                    &v->uuid, v->ver, v->opnum, FALSE);
+            } else {
+                dcerpc_try_handoff (pinfo, tree, tvb, offset,
+                                    &hdr.if_id, hdr.if_ver, hdr.opnum, FALSE);
+            }
+        }
+        break;
+    }
 
     return TRUE;
 }
 
+static void
+dcerpc_init_protocol (void)
+{
+    if (dcerpc_convs != NULL)
+        g_hash_table_destroy (dcerpc_convs);
+    if (dcerpc_calls != NULL)
+        g_hash_table_destroy (dcerpc_calls);
 
+    dcerpc_convs = g_hash_table_new (dcerpc_conv_hash, dcerpc_conv_equal);
+    dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
+}
+
 void
-proto_register_dcerpc(void)
+proto_register_dcerpc (void)
 {
     static hf_register_info hf[] = {
         { &hf_dcerpc_ver,
@@ -779,7 +1107,9 @@
         { &hf_dcerpc_cn_bind_if_id,
           { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_if_ver,
-          { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+          { "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_id,
           { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_bind_trans_ver,
@@ -794,6 +1124,8 @@
           { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_ack_reason,
           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_cn_cancel_count,
+          { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_flags1,
           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_flags1_rsrvd_01,
@@ -871,10 +1203,15 @@
     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
     proto_register_subtree_array (ett, array_length (ett));
+    register_init_routine (dcerpc_init_protocol);
+
+    dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
+    dcerpc_convs = g_hash_table_new (dcerpc_conv_hash, dcerpc_conv_equal);
+    dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
 }
 
 void
-proto_reg_handoff_dcerpc(void)
+proto_reg_handoff_dcerpc (void)
 {
     heur_dissector_add ("tcp", dissect_dcerpc_cn, proto_dcerpc);
     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
Index: packet-dcerpc.h
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.h,v
retrieving revision 1.1
diff -u -r1.1 packet-dcerpc.h
--- packet-dcerpc.h	2001/04/19 23:39:27	1.1
+++ packet-dcerpc.h	2001/07/09 11:20:25
@@ -88,6 +88,17 @@
 guint32 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep);
 void dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid);
 
+typedef int (dcerpc_dissect_fnct_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+typedef struct _dcerpc_sub_dissector {
+    guint16 num;
+    gchar   *name;
+    dcerpc_dissect_fnct_t *dissect_rqst;
+    dcerpc_dissect_fnct_t *dissect_resp;
+} dcerpc_sub_dissector;
+
+/* registration function for subdissectors */
+void dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs);
 
 
 #endif /* packet-dcerpc.h */
Index: Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/Makefile.am,v
retrieving revision 1.343
diff -u -r1.343 Makefile.am
--- Makefile.am	2001/07/04 06:25:03	1.343
+++ Makefile.am	2001/07/09 11:19:59
@@ -94,6 +94,11 @@
 	packet-cups.c  \
 	packet-data.c  \
 	packet-dcerpc.c  \
+	packet-dcerpc-conv.c  \
+	packet-dcerpc-epm.c  \
+	packet-dcerpc-mgmt.c  \
+	packet-dcerpc-remact.c  \
+	packet-dcerpc-oxid.c  \
 	packet-ddtp.c  \
 	packet-dec-bpdu.c \
 	packet-diameter.c \
/* packet-dcerpc-epm.c
 * Routines for dcerpc endpoint mapper dissection
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <string.h>

#include <glib.h>
#include "packet.h"
#include "packet-dcerpc.h"


static int proto_epm = -1;

static gint ett_epm = -1;


static e_uuid_t uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
static guint16  ver_epm = 3;


static dcerpc_sub_dissector epm_dissectors[] = {
    { 0, "ept_insert", NULL, NULL },
    { 1, "ept_delete", NULL, NULL },
    { 2, "ept_lookup", NULL, NULL },
    { 3, "ept_map", NULL, NULL },
    { 4, "ept_lookup_handle_free", NULL, NULL },
    { 5, "ept_inq_object", NULL, NULL },
    { 6, "ept_mgmt_delete", NULL, NULL },
    { 0, NULL, NULL, NULL },
};


void
proto_register_epm (void)
{
	static hf_register_info hf[] = {
	};

	static gint *ett[] = {
		&ett_epm,
	};
	proto_epm = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm");
	proto_register_field_array (proto_epm, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_epm (void)
{
	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_epm, ett_epm, &uuid_epm, ver_epm, epm_dissectors);
}
/* packet-dcerpc-mgmt.c
 * Routines for dcerpc mgmt dissection
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <string.h>

#include <glib.h>
#include "packet.h"
#include "packet-dcerpc.h"


static int proto_mgmt = -1;

static gint ett_mgmt = -1;


static e_uuid_t uuid_mgmt = { 0xafa8bd80, 0x7d8a, 0x11c9, { 0xbe, 0xf4, 0x08, 0x00, 0x2b, 0x10, 0x29, 0x89 } };
static guint16  ver_mgmt = 1;


static dcerpc_sub_dissector mgmt_dissectors[] = {
    { 0, "rpc__mgmt_inq_if_ids", NULL, NULL },
    { 1, "rpc__mgmt_inq_stats", NULL, NULL },
    { 2, "rpc__mgmt_is_server_listening", NULL, NULL },
    { 3, "rpc__mgmt_stop_server_listening", NULL, NULL },
    { 4, "rpc__mgmt_inq_princ_name", NULL, NULL },
    { 0, NULL, NULL, NULL },
};


void
proto_register_mgmt (void)
{
	static hf_register_info hf[] = {
	};

	static gint *ett[] = {
		&ett_mgmt,
	};
	proto_mgmt = proto_register_protocol ("DCE/RPC Remote Management", "MGMT", "mgmt");
	proto_register_field_array (proto_mgmt, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_mgmt (void)
{
	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_mgmt, ett_mgmt, &uuid_mgmt, ver_mgmt, mgmt_dissectors);
}
/* packet-dcerpc-conv.c
 * Routines for dcerpc conv dissection
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <string.h>

#include <glib.h>
#include "packet.h"
#include "packet-dcerpc.h"


static int proto_conv = -1;

static gint ett_conv = -1;


static e_uuid_t uuid_conv = { 0x333a2276, 0x0000, 0x0000, { 0x0d, 0x00, 0x00, 0x80, 0x9c, 0x00, 0x00, 0x00 } };
static guint16  ver_conv = 3;


static dcerpc_sub_dissector conv_dissectors[] = {
    { 0, "conv_who_are_you", NULL, NULL },
    { 1, "conv_who_are_you2", NULL, NULL },
    { 2, "conv_are_you_there", NULL, NULL },
    { 3, "conv_who_are_you_auth", NULL, NULL },
    { 4, "conv_who_are_you_auth_more", NULL, NULL },
    { 0, NULL, NULL, NULL },
};


void
proto_register_conv (void)
{
	static hf_register_info hf[] = {
	};

	static gint *ett[] = {
		&ett_conv,
	};
	proto_conv = proto_register_protocol ("DCE/RPC Conversation Manager", "CONV", "conv");
	proto_register_field_array (proto_conv, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_conv (void)
{
	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_conv, ett_conv, &uuid_conv, ver_conv, conv_dissectors);
}
/* packet-dcerpc-remact.c
 * Routines for DCOM Remote Activation
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <string.h>

#include <glib.h>
#include "packet.h"
#include "packet-dcerpc.h"


static int proto_remact = -1;

static gint ett_remact = -1;


static e_uuid_t uuid_remact = { 0x4d9f4ab8, 0x7dac, 0x11cf, { 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57 } };
static guint16  ver_remact = 0;


static dcerpc_sub_dissector remact_dissectors[] = {
    { 0, "RemoteActivation", NULL, NULL },
    { 0, NULL, NULL, NULL },
};


void
proto_register_remact (void)
{
	static hf_register_info hf[] = {
	};

	static gint *ett[] = {
		&ett_remact,
	};
	proto_remact = proto_register_protocol ("DCOM Remote Activation", "REMACT", "remact");
	proto_register_field_array (proto_remact, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_remact (void)
{
	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_remact, ett_remact, &uuid_remact, ver_remact, remact_dissectors);
}
/* packet-dcerpc-oxid.c
 * Routines for DCOM OXID Resolver
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <string.h>

#include <glib.h>
#include "packet.h"
#include "packet-dcerpc.h"


static int proto_oxid = -1;

static gint ett_oxid = -1;

static e_uuid_t uuid_oxid = { 0x99fcfec4, 0x5260, 0x101b, { 0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a } };
static guint16  ver_oxid = 0;


static dcerpc_sub_dissector oxid_dissectors[] = {
    { 0, "ResolveOxid", NULL, NULL },
    { 1, "SimplePing", NULL, NULL },
    { 2, "ComplexPing", NULL, NULL },
    { 3, "ServerAlive", NULL, NULL },
    { 0, NULL, NULL, NULL },
};


void
proto_register_oxid (void)
{
	static hf_register_info hf[] = {
	};

	static gint *ett[] = {
		&ett_oxid,
	};
	proto_oxid = proto_register_protocol ("DCOM OXID Resolver", "OXID", "oxid");
	proto_register_field_array (proto_oxid, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_oxid (void)
{
	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_oxid, ett_oxid, &uuid_oxid, ver_oxid, oxid_dissectors);
}