2 * Routines for DCERPC packet disassembly
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
5 * $Id: packet-dcerpc.c,v 1.7 2001/07/11 04:49:34 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
39 #include "packet-dcerpc.h"
40 #include "conversation.h"
42 static const value_string pckt_vals[] = {
57 { 14, "Alter_context"},
58 { 15, "Alter_context_resp"},
65 static const true_false_string flags_set_truth = {
70 static int proto_dcerpc = -1;
73 static int hf_dcerpc_ver = -1;
74 static int hf_dcerpc_ver_minor = -1;
75 static int hf_dcerpc_packet_type = -1;
76 static int hf_dcerpc_cn_flags = -1;
77 static int hf_dcerpc_cn_flags_first_frag = -1;
78 static int hf_dcerpc_cn_flags_last_frag = -1;
79 static int hf_dcerpc_cn_flags_cancel_pending = -1;
80 static int hf_dcerpc_cn_flags_reserved = -1;
81 static int hf_dcerpc_cn_flags_mpx = -1;
82 static int hf_dcerpc_cn_flags_dne = -1;
83 static int hf_dcerpc_cn_flags_maybe = -1;
84 static int hf_dcerpc_cn_flags_object = -1;
85 static int hf_dcerpc_cn_frag_len = -1;
86 static int hf_dcerpc_cn_auth_len = -1;
87 static int hf_dcerpc_cn_call_id = -1;
88 static int hf_dcerpc_cn_max_xmit = -1;
89 static int hf_dcerpc_cn_max_recv = -1;
90 static int hf_dcerpc_cn_assoc_group = -1;
91 static int hf_dcerpc_cn_num_ctx_items = -1;
92 static int hf_dcerpc_cn_ctx_id = -1;
93 static int hf_dcerpc_cn_num_trans_items = -1;
94 static int hf_dcerpc_cn_bind_if_id = -1;
95 static int hf_dcerpc_cn_bind_if_ver = -1;
96 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
97 static int hf_dcerpc_cn_bind_trans_id = -1;
98 static int hf_dcerpc_cn_bind_trans_ver = -1;
99 static int hf_dcerpc_cn_alloc_hint = -1;
100 static int hf_dcerpc_cn_sec_addr_len = -1;
101 static int hf_dcerpc_cn_num_results = -1;
102 static int hf_dcerpc_cn_ack_result = -1;
103 static int hf_dcerpc_cn_ack_reason = -1;
104 static int hf_dcerpc_cn_cancel_count = -1;
105 static int hf_dcerpc_dg_flags1 = -1;
106 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
107 static int hf_dcerpc_dg_flags1_last_frag = -1;
108 static int hf_dcerpc_dg_flags1_frag = -1;
109 static int hf_dcerpc_dg_flags1_nofack = -1;
110 static int hf_dcerpc_dg_flags1_maybe = -1;
111 static int hf_dcerpc_dg_flags1_idempotent = -1;
112 static int hf_dcerpc_dg_flags1_broadcast = -1;
113 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
114 static int hf_dcerpc_dg_flags2 = -1;
115 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
116 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
117 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
118 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
119 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
120 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
121 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
122 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
123 static int hf_dcerpc_dg_serial_hi = -1;
124 static int hf_dcerpc_obj_id = -1;
125 static int hf_dcerpc_dg_if_id = -1;
126 static int hf_dcerpc_dg_act_id = -1;
127 static int hf_dcerpc_dg_serial_lo = -1;
128 static int hf_dcerpc_dg_ahint = -1;
129 static int hf_dcerpc_dg_ihint = -1;
130 static int hf_dcerpc_dg_frag_len = -1;
131 static int hf_dcerpc_dg_frag_num = -1;
132 static int hf_dcerpc_dg_auth_proto = -1;
133 static int hf_dcerpc_opnum = -1;
134 static int hf_dcerpc_dg_seqnum = -1;
135 static int hf_dcerpc_dg_server_boot = -1;
136 static int hf_dcerpc_dg_if_ver = -1;
138 static gint ett_dcerpc = -1;
139 static gint ett_dcerpc_cn_flags = -1;
140 static gint ett_dcerpc_dg_flags1 = -1;
141 static gint ett_dcerpc_dg_flags2 = -1;
147 /* the registered subdissectors */
148 static GHashTable *dcerpc_uuids;
150 typedef struct _dcerpc_uuid_key {
155 typedef struct _dcerpc_uuid_value {
159 dcerpc_sub_dissector *procs;
163 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
165 dcerpc_uuid_key *key1 = (dcerpc_uuid_key *)k1;
166 dcerpc_uuid_key *key2 = (dcerpc_uuid_key *)k2;
167 return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
168 && (key1->ver == key2->ver));
172 dcerpc_uuid_hash (gconstpointer k)
174 dcerpc_uuid_key *key = (dcerpc_uuid_key *)k;
175 /* This isn't perfect, but the Data1 part of these is almost always
177 return key->uuid.Data1;
181 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
182 dcerpc_sub_dissector *procs)
184 dcerpc_uuid_key *key = g_malloc (sizeof (*key));
185 dcerpc_uuid_value *value = g_malloc (sizeof (*value));
190 value->proto = proto;
192 value->name = proto_get_protocol_short_name (proto);
193 value->procs = procs;
195 g_hash_table_insert (dcerpc_uuids, key, value);
200 * To keep track of ctx_id mappings. Should really use some
201 * generic conversation support instead.
203 static GHashTable *dcerpc_convs;
205 typedef struct _dcerpc_conv_key {
206 conversation_t *conv;
210 static GMemChunk *dcerpc_conv_key_chunk;
212 typedef struct _dcerpc_conv_value {
217 static GMemChunk *dcerpc_conv_value_chunk;
220 dcerpc_conv_equal (gconstpointer k1, gconstpointer k2)
222 dcerpc_conv_key *key1 = (dcerpc_conv_key *)k1;
223 dcerpc_conv_key *key2 = (dcerpc_conv_key *)k2;
224 return (key1->conv == key2->conv
225 && key1->ctx_id == key2->ctx_id);
229 dcerpc_conv_hash (gconstpointer k)
231 dcerpc_conv_key *key = (dcerpc_conv_key *)k;
232 return ((guint)key->conv) + key->ctx_id;
238 * To keep track of callid mappings. Should really use some generic
239 * conversation support instead.
241 static GHashTable *dcerpc_calls;
243 typedef struct _dcerpc_call_key {
244 conversation_t *conv;
248 static GMemChunk *dcerpc_call_key_chunk;
250 typedef struct _dcerpc_call_value {
256 static GMemChunk *dcerpc_call_value_chunk;
259 dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
261 dcerpc_call_key *key1 = (dcerpc_call_key *)k1;
262 dcerpc_call_key *key2 = (dcerpc_call_key *)k2;
263 return (key1->conv == key2->conv
264 && key1->call_id == key2->call_id);
268 dcerpc_call_hash (gconstpointer k)
270 dcerpc_call_key *key = (dcerpc_call_key *)k;
271 return ((guint32)key->conv) ^ key->call_id;
275 dcerpc_call_add_map (guint32 call_id, conversation_t *conv,
276 guint16 opnum, guint16 ver, e_uuid_t *uuid)
278 dcerpc_call_key *key = g_mem_chunk_alloc (dcerpc_call_key_chunk);
279 dcerpc_call_value *value = g_mem_chunk_alloc (dcerpc_call_value_chunk);
281 key->call_id = call_id;
285 value->opnum = opnum;
286 g_hash_table_insert (dcerpc_calls, key, value);
289 static dcerpc_call_value*
290 dcerpc_call_lookup (guint32 call_id, conversation_t *conv)
294 key.call_id = call_id;
296 return g_hash_table_lookup (dcerpc_calls, &key);
301 * Utility functions. Modeled after packet-rpc.c
305 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
306 proto_tree *tree, char *drep,
307 int hfindex, guint8 *pdata)
311 data = tvb_get_guint8 (tvb, offset);
313 proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
321 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
322 proto_tree *tree, char *drep,
323 int hfindex, guint16 *pdata)
327 data = ((drep[0] & 0x10)
328 ? tvb_get_letohs (tvb, offset)
329 : tvb_get_ntohs (tvb, offset));
332 proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
340 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
341 proto_tree *tree, char *drep,
342 int hfindex, guint32 *pdata)
346 data = ((drep[0] & 0x10)
347 ? tvb_get_letohl (tvb, offset)
348 : tvb_get_ntohl (tvb, offset));
351 proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
359 * a couple simpler things
362 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
364 if (drep[0] & 0x10) {
365 return tvb_get_letohs (tvb, offset);
367 return tvb_get_ntohs (tvb, offset);
372 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
374 if (drep[0] & 0x10) {
375 return tvb_get_letohl (tvb, offset);
377 return tvb_get_ntohl (tvb, offset);
382 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
385 uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
386 uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
387 uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
389 for (i=0; i<sizeof (uuid->Data4); i++) {
390 uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
395 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
396 tvbuff_t *tvb, gint offset,
397 e_uuid_t *uuid, guint16 ver,
398 guint16 opnum, gboolean is_rqst)
401 dcerpc_uuid_value *sub_proto;
402 proto_item *sub_item;
403 proto_tree *sub_tree;
404 dcerpc_sub_dissector *proc;
411 if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == 0)
415 sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
416 tvb_length (tvb) - offset, FALSE);
418 sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
422 for (proc = sub_proto->procs; proc->name; proc++) {
423 if (proc->num == opnum) {
432 if (check_col (pinfo->fd, COL_INFO)) {
433 col_add_fstr (pinfo->fd, COL_INFO, "%s %s:%s(...)",
434 is_rqst ? "rqst" : "rply",
435 sub_proto->name, name);
438 if (check_col (pinfo->fd, COL_PROTOCOL)) {
439 col_set_str (pinfo->fd, COL_PROTOCOL, sub_proto->name);
441 /* FIXME: call approp. dissector */
447 * Connection oriented packet types
451 dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
452 e_dce_cn_common_hdr_t *hdr)
454 conversation_t *conv = NULL;
455 dcerpc_conv_key *key;
456 dcerpc_conv_value *value;
457 guint8 num_ctx_items;
459 guint16 num_trans_items;
463 guint16 if_ver, if_ver_minor;
466 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
467 hf_dcerpc_cn_max_xmit, NULL);
469 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
470 hf_dcerpc_cn_max_recv, NULL);
472 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
473 hf_dcerpc_cn_assoc_group, NULL);
475 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
476 hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
481 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
482 hf_dcerpc_cn_ctx_id, &ctx_id);
484 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
485 hf_dcerpc_cn_num_trans_items, &num_trans_items);
487 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
489 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
491 "Interface UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
492 if_id.Data1, if_id.Data2, if_id.Data3,
493 if_id.Data4[0], if_id.Data4[1],
494 if_id.Data4[2], if_id.Data4[3],
495 if_id.Data4[4], if_id.Data4[5],
496 if_id.Data4[6], if_id.Data4[7]);
500 if (hdr->drep[0] & 0x10) {
501 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
502 hf_dcerpc_cn_bind_if_ver, &if_ver);
503 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
504 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
506 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
507 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
508 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
509 hf_dcerpc_cn_bind_if_ver, &if_ver);
512 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
514 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
516 "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
517 trans_id.Data1, trans_id.Data2, trans_id.Data3,
518 trans_id.Data4[0], trans_id.Data4[1],
519 trans_id.Data4[2], trans_id.Data4[3],
520 trans_id.Data4[4], trans_id.Data4[5],
521 trans_id.Data4[6], trans_id.Data4[7]);
525 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
526 hf_dcerpc_cn_bind_trans_ver, &trans_ver);
528 if (check_col (pinfo->fd, COL_INFO)) {
529 col_add_fstr (pinfo->fd, COL_INFO, "%s: UUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %d.%d",
530 hdr->ptype == PDU_BIND ? "Bind" : "Alter Ctx",
531 if_id.Data1, if_id.Data2, if_id.Data3,
532 if_id.Data4[0], if_id.Data4[1],
533 if_id.Data4[2], if_id.Data4[3],
534 if_id.Data4[4], if_id.Data4[5],
535 if_id.Data4[6], if_id.Data4[7],
536 if_ver, if_ver_minor);
538 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
539 pinfo->srcport, pinfo->destport, 0);
541 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
542 pinfo->srcport, pinfo->destport, NULL, 0);
545 key = g_mem_chunk_alloc (dcerpc_conv_key_chunk);
547 key->ctx_id = ctx_id;
549 value = g_mem_chunk_alloc (dcerpc_conv_value_chunk);
553 g_hash_table_insert (dcerpc_convs, key, value);
557 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
558 e_dce_cn_common_hdr_t *hdr)
560 guint16 max_xmit, max_recv;
561 guint16 sec_addr_len;
568 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
569 hf_dcerpc_cn_max_xmit, &max_xmit);
571 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
572 hf_dcerpc_cn_max_recv, &max_recv);
574 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
575 hf_dcerpc_cn_assoc_group, NULL);
577 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
578 hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
579 offset += sec_addr_len;
582 offset += 4 - offset % 4;
585 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
586 hf_dcerpc_cn_num_results, &num_results);
591 if (num_results == 1) {
592 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
593 hdr->drep, hf_dcerpc_cn_ack_result,
595 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
596 hdr->drep, hf_dcerpc_cn_ack_reason,
600 if (check_col (pinfo->fd, COL_INFO)) {
601 if (num_results == 1 && result == 0) {
602 col_add_fstr (pinfo->fd, COL_INFO, "%s ack: accept max_xmit: %d max_recv: %d",
603 hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
606 /* FIXME: should put in reason */
607 col_add_fstr (pinfo->fd, COL_INFO, "%s ack: %s",
608 hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
609 result == 1 ? "User reject" :
610 result == 2 ? "Provider reject" :
617 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
618 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
620 conversation_t *conv;
627 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
628 hf_dcerpc_cn_alloc_hint, NULL);
630 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
631 hf_dcerpc_cn_ctx_id, &ctx_id);
633 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
634 hf_dcerpc_opnum, &opnum);
636 if (hdr->flags & 0x80) {
637 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
639 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
641 "Object UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
642 obj_id.Data1, obj_id.Data2, obj_id.Data3,
655 if (check_col (pinfo->fd, COL_INFO)) {
656 col_add_fstr (pinfo->fd, COL_INFO, "Request: opnum: %d ctx_id:%d",
660 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
661 pinfo->srcport, pinfo->destport, 0);
666 dcerpc_conv_value *value;
671 value = g_hash_table_lookup (dcerpc_convs, &key);
673 /* add an entry for this call, so we can catch the reply */
674 dcerpc_call_add_map (hdr->call_id, conv, opnum,
675 value->ver, &value->uuid);
677 /* handoff this call */
678 dcerpc_try_handoff (pinfo, tree, tvb, offset,
679 &value->uuid, value->ver,
686 dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
687 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
689 conversation_t *conv;
694 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
695 hf_dcerpc_cn_alloc_hint, NULL);
697 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
698 hf_dcerpc_cn_ctx_id, &ctx_id);
700 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
701 hf_dcerpc_cn_cancel_count, NULL);
705 if (check_col (pinfo->fd, COL_INFO)) {
706 col_add_fstr (pinfo->fd, COL_INFO, "Response: call_id: %d ctx_id:%d",
707 hdr->call_id, ctx_id);
710 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
711 pinfo->srcport, pinfo->destport, 0);
713 /* no point in creating one here, really */
715 dcerpc_call_value *value = dcerpc_call_lookup (hdr->call_id, conv);
717 dcerpc_try_handoff (pinfo, tree, tvb, offset,
718 &value->uuid, value->ver,
719 value->opnum, FALSE);
725 * DCERPC dissector for connection oriented calls
728 dissect_dcerpc_cn (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
730 proto_item *ti = NULL;
731 proto_item *tf = NULL;
732 proto_tree *dcerpc_tree = NULL;
733 proto_tree *cn_flags_tree = NULL;
734 e_dce_cn_common_hdr_t hdr;
738 * Check if this looks like a C/O DCERPC call
740 if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
743 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
744 if (hdr.rpc_ver != 5)
746 hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
747 if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
749 hdr.ptype = tvb_get_guint8 (tvb, offset++);
753 if (check_col (pinfo->fd, COL_PROTOCOL))
754 col_set_str (pinfo->fd, COL_PROTOCOL, "DCERPC");
755 if (check_col (pinfo->fd, COL_INFO))
756 col_set_str (pinfo->fd, COL_INFO, pckt_vals[hdr.ptype].strptr);
758 hdr.flags = tvb_get_guint8 (tvb, offset++);
759 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
760 offset += sizeof (hdr.drep);
762 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
764 hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
766 hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
770 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE);
772 dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
775 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
776 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
777 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
778 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
779 cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
781 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
782 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
783 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
784 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
785 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
786 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
787 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
788 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
792 proto_tree_add_text (dcerpc_tree, tvb, offset, sizeof (hdr.drep), "Data Rep");
793 offset += sizeof (hdr.drep);
795 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
798 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
801 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
805 * Packet type specific stuff is next.
810 dissect_dcerpc_cn_bind (tvb, pinfo, dcerpc_tree, &hdr);
815 dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
819 dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
823 dissect_dcerpc_cn_resp (tvb, pinfo, dcerpc_tree, tree, &hdr);
833 * DCERPC dissector for connectionless calls
836 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
838 proto_item *ti = NULL;
839 proto_item *tf = NULL;
840 proto_tree *dcerpc_tree = NULL;
841 proto_tree *dg_flags1_tree = NULL;
842 proto_tree *dg_flags2_tree = NULL;
843 e_dce_dg_common_hdr_t hdr;
845 conversation_t *conv;
848 * Check if this looks like a CL DCERPC call. All dg packets
849 * have an 80 byte header on them. Which starts with
850 * version (4), pkt_type.
852 if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
855 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
856 if (hdr.rpc_ver != 4)
858 hdr.ptype = tvb_get_guint8 (tvb, offset++);
862 if (check_col (pinfo->fd, COL_PROTOCOL))
863 col_set_str (pinfo->fd, COL_PROTOCOL, "DCERPC");
864 if (check_col (pinfo->fd, COL_INFO))
865 col_set_str (pinfo->fd, COL_INFO, pckt_vals[hdr.ptype].strptr);
867 hdr.flags1 = tvb_get_guint8 (tvb, offset++);
868 hdr.flags2 = tvb_get_guint8 (tvb, offset++);
869 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
870 offset += sizeof (hdr.drep);
871 hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
872 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
874 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
876 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
878 hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
880 hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
882 hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
884 hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
886 hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
888 hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
890 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
892 hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
894 hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
895 hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
898 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE);
900 dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
903 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
905 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
907 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
908 dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
909 if (dg_flags1_tree) {
910 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
911 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
912 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
913 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
914 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
915 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
916 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
917 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
921 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
922 dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
923 if (dg_flags2_tree) {
924 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
925 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
926 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
927 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
928 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
929 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
930 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
931 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
935 proto_tree_add_text (dcerpc_tree, tvb, offset, sizeof (hdr.drep), "Data Rep");
936 offset += sizeof (hdr.drep);
938 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset++, 1, hdr.serial_hi);
940 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
942 "Object: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
943 hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
951 hdr.obj_id.Data4[7]);
954 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
956 "Interface: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
957 hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
968 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
970 "Activity: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
971 hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
979 hdr.act_id.Data4[7]);
982 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_server_boot, tvb, offset, 4, hdr.server_boot);
985 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
988 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
991 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
994 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
997 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
1000 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
1003 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
1006 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
1009 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
1013 * keeping track of the conversation shouldn't really be necessary
1014 * for connectionless packets, because everything we need to know
1015 * to dissect is in the header for each packet. Unfortunately,
1016 * Microsoft's implementation is buggy and often puts the
1017 * completely wrong if_id in the header. go figure. So, keep
1018 * track of the seqnum and use that if possible. Note: that's not
1019 * completely correct. It should really be done based on both the
1020 * activity_id and seqnum. I haven't seen anywhere that it would
1021 * make a difference, but for future reference...
1023 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1024 pinfo->srcport, pinfo->destport, 0);
1026 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
1027 pinfo->srcport, pinfo->destport, NULL, 0);
1031 * Packet type specific stuff is next.
1033 switch (hdr.ptype) {
1035 dcerpc_call_add_map (hdr.seqnum, conv, hdr.opnum,
1036 hdr.if_ver, &hdr.if_id);
1037 dcerpc_try_handoff (pinfo, tree, tvb, offset,
1038 &hdr.if_id, hdr.if_ver, hdr.opnum, TRUE);
1042 dcerpc_call_value *v = dcerpc_call_lookup (hdr.seqnum, conv);
1044 dcerpc_try_handoff (pinfo, tree, tvb, offset,
1045 &v->uuid, v->ver, v->opnum, FALSE);
1047 dcerpc_try_handoff (pinfo, tree, tvb, offset,
1048 &hdr.if_id, hdr.if_ver, hdr.opnum, FALSE);
1058 dcerpc_init_protocol (void)
1061 g_hash_table_destroy (dcerpc_convs);
1063 g_hash_table_destroy (dcerpc_calls);
1064 if (dcerpc_conv_key_chunk)
1065 g_mem_chunk_destroy (dcerpc_conv_key_chunk);
1066 if (dcerpc_conv_value_chunk)
1067 g_mem_chunk_destroy (dcerpc_conv_value_chunk);
1068 if (dcerpc_call_key_chunk)
1069 g_mem_chunk_destroy (dcerpc_call_key_chunk);
1070 if (dcerpc_call_value_chunk)
1071 g_mem_chunk_destroy (dcerpc_call_value_chunk);
1073 dcerpc_convs = g_hash_table_new (dcerpc_conv_hash, dcerpc_conv_equal);
1074 dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
1075 dcerpc_conv_key_chunk = g_mem_chunk_new ("dcerpc_conv_key_chunk",
1076 sizeof (dcerpc_conv_key),
1077 200 * sizeof (dcerpc_conv_key),
1079 dcerpc_conv_value_chunk = g_mem_chunk_new ("dcerpc_conv_value_chunk",
1080 sizeof (dcerpc_conv_value),
1081 200 * sizeof (dcerpc_conv_value),
1083 dcerpc_call_key_chunk = g_mem_chunk_new ("dcerpc_call_key_chunk",
1084 sizeof (dcerpc_call_key),
1085 200 * sizeof (dcerpc_call_key),
1087 dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
1088 sizeof (dcerpc_call_value),
1089 200 * sizeof (dcerpc_call_value),
1094 proto_register_dcerpc (void)
1096 static hf_register_info hf[] = {
1098 { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1099 { &hf_dcerpc_ver_minor,
1100 { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1101 { &hf_dcerpc_packet_type,
1102 { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_HEX, VALS (pckt_vals), 0x0, "", HFILL }},
1103 { &hf_dcerpc_cn_flags,
1104 { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1105 { &hf_dcerpc_cn_flags_first_frag,
1106 { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x1, "", HFILL }},
1107 { &hf_dcerpc_cn_flags_last_frag,
1108 { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x2, "", HFILL }},
1109 { &hf_dcerpc_cn_flags_cancel_pending,
1110 { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x4, "", HFILL }},
1111 { &hf_dcerpc_cn_flags_reserved,
1112 { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x8, "", HFILL }},
1113 { &hf_dcerpc_cn_flags_mpx,
1114 { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1115 { &hf_dcerpc_cn_flags_dne,
1116 { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1117 { &hf_dcerpc_cn_flags_maybe,
1118 { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1119 { &hf_dcerpc_cn_flags_object,
1120 { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1121 { &hf_dcerpc_cn_frag_len,
1122 { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1123 { &hf_dcerpc_cn_auth_len,
1124 { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1125 { &hf_dcerpc_cn_call_id,
1126 { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1127 { &hf_dcerpc_cn_max_xmit,
1128 { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1129 { &hf_dcerpc_cn_max_recv,
1130 { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1131 { &hf_dcerpc_cn_assoc_group,
1132 { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1133 { &hf_dcerpc_cn_num_ctx_items,
1134 { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1135 { &hf_dcerpc_cn_ctx_id,
1136 { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1137 { &hf_dcerpc_cn_num_trans_items,
1138 { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1139 { &hf_dcerpc_cn_bind_if_id,
1140 { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1141 { &hf_dcerpc_cn_bind_if_ver,
1142 { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1143 { &hf_dcerpc_cn_bind_if_ver_minor,
1144 { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1145 { &hf_dcerpc_cn_bind_trans_id,
1146 { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1147 { &hf_dcerpc_cn_bind_trans_ver,
1148 { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1149 { &hf_dcerpc_cn_alloc_hint,
1150 { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1151 { &hf_dcerpc_cn_sec_addr_len,
1152 { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1153 { &hf_dcerpc_cn_num_results,
1154 { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1155 { &hf_dcerpc_cn_ack_result,
1156 { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1157 { &hf_dcerpc_cn_ack_reason,
1158 { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1159 { &hf_dcerpc_cn_cancel_count,
1160 { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1161 { &hf_dcerpc_dg_flags1,
1162 { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1163 { &hf_dcerpc_dg_flags1_rsrvd_01,
1164 { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "", HFILL }},
1165 { &hf_dcerpc_dg_flags1_last_frag,
1166 { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "", HFILL }},
1167 { &hf_dcerpc_dg_flags1_frag,
1168 { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "", HFILL }},
1169 { &hf_dcerpc_dg_flags1_nofack,
1170 { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "", HFILL }},
1171 { &hf_dcerpc_dg_flags1_maybe,
1172 { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1173 { &hf_dcerpc_dg_flags1_idempotent,
1174 { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1175 { &hf_dcerpc_dg_flags1_broadcast,
1176 { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1177 { &hf_dcerpc_dg_flags1_rsrvd_80,
1178 { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1179 { &hf_dcerpc_dg_flags2,
1180 { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1181 { &hf_dcerpc_dg_flags2_rsrvd_01,
1182 { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "", HFILL }},
1183 { &hf_dcerpc_dg_flags2_cancel_pending,
1184 { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "", HFILL }},
1185 { &hf_dcerpc_dg_flags2_rsrvd_04,
1186 { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "", HFILL }},
1187 { &hf_dcerpc_dg_flags2_rsrvd_08,
1188 { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "", HFILL }},
1189 { &hf_dcerpc_dg_flags2_rsrvd_10,
1190 { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1191 { &hf_dcerpc_dg_flags2_rsrvd_20,
1192 { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1193 { &hf_dcerpc_dg_flags2_rsrvd_40,
1194 { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1195 { &hf_dcerpc_dg_flags2_rsrvd_80,
1196 { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1197 { &hf_dcerpc_dg_serial_lo,
1198 { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1199 { &hf_dcerpc_dg_serial_hi,
1200 { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1201 { &hf_dcerpc_dg_ahint,
1202 { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1203 { &hf_dcerpc_dg_ihint,
1204 { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1205 { &hf_dcerpc_dg_frag_len,
1206 { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1207 { &hf_dcerpc_dg_frag_num,
1208 { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1209 { &hf_dcerpc_dg_auth_proto,
1210 { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1211 { &hf_dcerpc_dg_seqnum,
1212 { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1213 { &hf_dcerpc_dg_server_boot,
1214 { "Server boot time", "dcerpc.dg_server_boot", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1215 { &hf_dcerpc_dg_if_ver,
1216 { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1217 { &hf_dcerpc_obj_id,
1218 { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1219 { &hf_dcerpc_dg_if_id,
1220 { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1221 { &hf_dcerpc_dg_act_id,
1222 { "Activitiy", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1224 { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1228 static gint *ett[] = {
1230 &ett_dcerpc_cn_flags,
1231 &ett_dcerpc_dg_flags1,
1232 &ett_dcerpc_dg_flags2,
1235 proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
1236 proto_register_field_array (proto_dcerpc, hf, array_length (hf));
1237 proto_register_subtree_array (ett, array_length (ett));
1238 register_init_routine (dcerpc_init_protocol);
1240 dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
1244 proto_reg_handoff_dcerpc (void)
1246 heur_dissector_add ("tcp", dissect_dcerpc_cn, proto_dcerpc);
1247 heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);