2 * Routines for DCERPC packet disassembly
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
5 * $Id: packet-dcerpc.c,v 1.21 2001/12/10 00:25:27 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"
43 static const value_string pckt_vals[] = {
58 { 14, "Alter_context"},
59 { 15, "Alter_context_resp"},
67 static const value_string drep_byteorder_vals[] = {
69 { 1, "Little-endian" },
73 static const value_string drep_character_vals[] = {
79 static const value_string drep_fp_vals[] = {
87 static const true_false_string flags_set_truth = {
92 static int proto_dcerpc = -1;
95 static int hf_dcerpc_ver = -1;
96 static int hf_dcerpc_ver_minor = -1;
97 static int hf_dcerpc_packet_type = -1;
98 static int hf_dcerpc_cn_flags = -1;
99 static int hf_dcerpc_cn_flags_first_frag = -1;
100 static int hf_dcerpc_cn_flags_last_frag = -1;
101 static int hf_dcerpc_cn_flags_cancel_pending = -1;
102 static int hf_dcerpc_cn_flags_reserved = -1;
103 static int hf_dcerpc_cn_flags_mpx = -1;
104 static int hf_dcerpc_cn_flags_dne = -1;
105 static int hf_dcerpc_cn_flags_maybe = -1;
106 static int hf_dcerpc_cn_flags_object = -1;
107 static int hf_dcerpc_drep = -1;
108 static int hf_dcerpc_drep_byteorder = -1;
109 static int hf_dcerpc_drep_character = -1;
110 static int hf_dcerpc_drep_fp = -1;
111 static int hf_dcerpc_cn_frag_len = -1;
112 static int hf_dcerpc_cn_auth_len = -1;
113 static int hf_dcerpc_cn_call_id = -1;
114 static int hf_dcerpc_cn_max_xmit = -1;
115 static int hf_dcerpc_cn_max_recv = -1;
116 static int hf_dcerpc_cn_assoc_group = -1;
117 static int hf_dcerpc_cn_num_ctx_items = -1;
118 static int hf_dcerpc_cn_ctx_id = -1;
119 static int hf_dcerpc_cn_num_trans_items = -1;
120 static int hf_dcerpc_cn_bind_if_id = -1;
121 static int hf_dcerpc_cn_bind_if_ver = -1;
122 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
123 static int hf_dcerpc_cn_bind_trans_id = -1;
124 static int hf_dcerpc_cn_bind_trans_ver = -1;
125 static int hf_dcerpc_cn_alloc_hint = -1;
126 static int hf_dcerpc_cn_sec_addr_len = -1;
127 static int hf_dcerpc_cn_num_results = -1;
128 static int hf_dcerpc_cn_ack_result = -1;
129 static int hf_dcerpc_cn_ack_reason = -1;
130 static int hf_dcerpc_cn_ack_trans_id = -1;
131 static int hf_dcerpc_cn_ack_trans_ver = -1;
132 static int hf_dcerpc_cn_cancel_count = -1;
133 static int hf_dcerpc_auth_type = -1;
134 static int hf_dcerpc_auth_level = -1;
135 static int hf_dcerpc_auth_pad_len = -1;
136 static int hf_dcerpc_auth_rsrvd = -1;
137 static int hf_dcerpc_auth_ctx_id = -1;
138 static int hf_dcerpc_dg_flags1 = -1;
139 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
140 static int hf_dcerpc_dg_flags1_last_frag = -1;
141 static int hf_dcerpc_dg_flags1_frag = -1;
142 static int hf_dcerpc_dg_flags1_nofack = -1;
143 static int hf_dcerpc_dg_flags1_maybe = -1;
144 static int hf_dcerpc_dg_flags1_idempotent = -1;
145 static int hf_dcerpc_dg_flags1_broadcast = -1;
146 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
147 static int hf_dcerpc_dg_flags2 = -1;
148 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
149 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
150 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
151 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
152 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
153 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
154 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
155 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
156 static int hf_dcerpc_dg_serial_hi = -1;
157 static int hf_dcerpc_obj_id = -1;
158 static int hf_dcerpc_dg_if_id = -1;
159 static int hf_dcerpc_dg_act_id = -1;
160 static int hf_dcerpc_dg_serial_lo = -1;
161 static int hf_dcerpc_dg_ahint = -1;
162 static int hf_dcerpc_dg_ihint = -1;
163 static int hf_dcerpc_dg_frag_len = -1;
164 static int hf_dcerpc_dg_frag_num = -1;
165 static int hf_dcerpc_dg_auth_proto = -1;
166 static int hf_dcerpc_opnum = -1;
167 static int hf_dcerpc_dg_seqnum = -1;
168 static int hf_dcerpc_dg_server_boot = -1;
169 static int hf_dcerpc_dg_if_ver = -1;
171 static gint ett_dcerpc = -1;
172 static gint ett_dcerpc_cn_flags = -1;
173 static gint ett_dcerpc_drep = -1;
174 static gint ett_dcerpc_dg_flags1 = -1;
175 static gint ett_dcerpc_dg_flags2 = -1;
177 /* try to desegment big DCE/RPC packets over TCP? */
178 static gboolean dcerpc_cn_desegment = TRUE;
184 /* the registered subdissectors */
185 static GHashTable *dcerpc_uuids;
187 typedef struct _dcerpc_uuid_key {
192 typedef struct _dcerpc_uuid_value {
196 dcerpc_sub_dissector *procs;
200 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
202 dcerpc_uuid_key *key1 = (dcerpc_uuid_key *)k1;
203 dcerpc_uuid_key *key2 = (dcerpc_uuid_key *)k2;
204 return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
205 && (key1->ver == key2->ver));
209 dcerpc_uuid_hash (gconstpointer k)
211 dcerpc_uuid_key *key = (dcerpc_uuid_key *)k;
212 /* This isn't perfect, but the Data1 part of these is almost always
214 return key->uuid.Data1;
218 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
219 dcerpc_sub_dissector *procs)
221 dcerpc_uuid_key *key = g_malloc (sizeof (*key));
222 dcerpc_uuid_value *value = g_malloc (sizeof (*value));
227 value->proto = proto;
229 value->name = proto_get_protocol_short_name (proto);
230 value->procs = procs;
232 g_hash_table_insert (dcerpc_uuids, key, value);
237 * To keep track of ctx_id mappings. Should really use some
238 * generic conversation support instead.
240 static GHashTable *dcerpc_convs;
242 typedef struct _dcerpc_conv_key {
243 conversation_t *conv;
248 static GMemChunk *dcerpc_conv_key_chunk;
250 typedef struct _dcerpc_conv_value {
255 static GMemChunk *dcerpc_conv_value_chunk;
258 dcerpc_conv_equal (gconstpointer k1, gconstpointer k2)
260 dcerpc_conv_key *key1 = (dcerpc_conv_key *)k1;
261 dcerpc_conv_key *key2 = (dcerpc_conv_key *)k2;
262 return (key1->conv == key2->conv
263 && key1->ctx_id == key2->ctx_id
264 && key1->smb_fid == key2->smb_fid);
268 dcerpc_conv_hash (gconstpointer k)
270 dcerpc_conv_key *key = (dcerpc_conv_key *)k;
271 return ((guint)key->conv) + key->ctx_id + key->smb_fid;
277 * To keep track of callid mappings. Should really use some generic
278 * conversation support instead.
280 static GHashTable *dcerpc_calls;
282 typedef struct _dcerpc_call_key {
283 conversation_t *conv;
287 static GMemChunk *dcerpc_call_key_chunk;
289 typedef struct _dcerpc_call_value {
295 static GMemChunk *dcerpc_call_value_chunk;
298 dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
300 dcerpc_call_key *key1 = (dcerpc_call_key *)k1;
301 dcerpc_call_key *key2 = (dcerpc_call_key *)k2;
302 return (key1->conv == key2->conv
303 && key1->call_id == key2->call_id);
307 dcerpc_call_hash (gconstpointer k)
309 dcerpc_call_key *key = (dcerpc_call_key *)k;
310 return ((guint32)key->conv) ^ key->call_id;
314 dcerpc_call_add_map (guint32 call_id, conversation_t *conv,
315 guint16 opnum, guint16 ver, e_uuid_t *uuid)
317 dcerpc_call_key *key = g_mem_chunk_alloc (dcerpc_call_key_chunk);
318 dcerpc_call_value *value = g_mem_chunk_alloc (dcerpc_call_value_chunk);
320 key->call_id = call_id;
324 value->opnum = opnum;
325 g_hash_table_insert (dcerpc_calls, key, value);
328 static dcerpc_call_value*
329 dcerpc_call_lookup (guint32 call_id, conversation_t *conv)
333 key.call_id = call_id;
335 return g_hash_table_lookup (dcerpc_calls, &key);
340 * Utility functions. Modeled after packet-rpc.c
344 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
345 proto_tree *tree, char *drep,
346 int hfindex, guint8 *pdata)
350 data = tvb_get_guint8 (tvb, offset);
352 proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
360 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
361 proto_tree *tree, char *drep,
362 int hfindex, guint16 *pdata)
366 data = ((drep[0] & 0x10)
367 ? tvb_get_letohs (tvb, offset)
368 : tvb_get_ntohs (tvb, offset));
371 proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
379 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
380 proto_tree *tree, char *drep,
381 int hfindex, guint32 *pdata)
385 data = ((drep[0] & 0x10)
386 ? tvb_get_letohl (tvb, offset)
387 : tvb_get_ntohl (tvb, offset));
390 proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
398 * a couple simpler things
401 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
403 if (drep[0] & 0x10) {
404 return tvb_get_letohs (tvb, offset);
406 return tvb_get_ntohs (tvb, offset);
411 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
413 if (drep[0] & 0x10) {
414 return tvb_get_letohl (tvb, offset);
416 return tvb_get_ntohl (tvb, offset);
421 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
424 uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
425 uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
426 uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
428 for (i=0; i<sizeof (uuid->Data4); i++) {
429 uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
434 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
435 proto_tree *dcerpc_tree,
436 tvbuff_t *tvb, gint offset,
437 e_uuid_t *uuid, guint16 ver,
438 guint16 opnum, gboolean is_rqst,
442 dcerpc_uuid_value *sub_proto;
444 proto_tree *sub_tree = NULL;
445 dcerpc_sub_dissector *proc;
447 dcerpc_dissect_fnct_t *sub_dissect;
453 if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == 0) {
454 length = tvb_length_remaining (tvb, offset);
456 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
457 "Stub data (%d byte%s)", length,
458 plurality(length, "", "s"));
464 proto_item *sub_item;
465 sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
466 tvb_length (tvb) - offset, FALSE);
469 sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
473 for (proc = sub_proto->procs; proc->name; proc++) {
474 if (proc->num == opnum) {
483 if (check_col (pinfo->cinfo, COL_INFO)) {
484 col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s(...)",
485 is_rqst ? "rqst" : "rply", name);
488 if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
489 col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
492 sub_dissect = is_rqst ? proc->dissect_rqst : proc->dissect_resp;
494 sub_dissect (tvb, offset, pinfo, sub_tree, drep);
496 length = tvb_length_remaining (tvb, offset);
498 proto_tree_add_text (sub_tree, tvb, offset, length,
499 "Stub data (%d byte%s)", length,
500 plurality(length, "", "s"));
507 dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
508 e_dce_cn_common_hdr_t *hdr)
514 * The authentication information is at the *end* of the PDU; in
515 * request and response PDUs, the request and response stub data
518 * If the full packet is here, and we've got an auth len, and it's
519 * valid, then dissect the auth info
521 if (tvb_length (tvb) >= hdr->frag_len
523 && (hdr->auth_len + 8 <= hdr->frag_len)) {
525 offset = hdr->frag_len - (hdr->auth_len + 8);
527 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
528 hf_dcerpc_auth_type, NULL);
529 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
530 hf_dcerpc_auth_level, NULL);
531 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
532 hf_dcerpc_auth_pad_len, &auth_pad_len);
533 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
534 hf_dcerpc_auth_rsrvd, NULL);
535 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
536 hf_dcerpc_auth_ctx_id, NULL);
538 proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, "Auth Data");
540 /* figure out where the auth padding starts */
541 offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len);
542 if (offset > 0 && auth_pad_len) {
543 proto_tree_add_text (dcerpc_tree, tvb, offset,
544 auth_pad_len, "Auth padding");
545 return hdr->auth_len + 8 + auth_pad_len;
547 return hdr->auth_len + 8;
555 /* We need to hash in the SMB fid number to generate a unique hash table
556 key as DCERPC over SMB allows several pipes over the same TCP/IP
559 static guint16 get_smb_fid (void *private_data)
561 dcerpc_private_info *priv = (dcerpc_private_info *)private_data;
564 return 0; /* Nothing to see here */
566 /* DCERPC over smb */
568 if (priv->transport_type == DCERPC_TRANSPORT_SMB)
569 return priv->data.smb.fid;
571 /* Some other transport... */
577 * Connection oriented packet types
581 dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
582 e_dce_cn_common_hdr_t *hdr)
584 conversation_t *conv = NULL;
585 dcerpc_conv_key *key;
586 dcerpc_conv_value *value;
587 guint8 num_ctx_items;
589 gboolean saw_ctx_item = FALSE;
591 guint16 num_trans_items;
596 guint16 if_ver, if_ver_minor;
599 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
600 hf_dcerpc_cn_max_xmit, NULL);
602 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
603 hf_dcerpc_cn_max_recv, NULL);
605 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
606 hf_dcerpc_cn_assoc_group, NULL);
608 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
609 hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
614 for (i = 0; i < num_ctx_items; i++) {
615 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
616 hf_dcerpc_cn_ctx_id, &ctx_id);
618 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
619 hf_dcerpc_cn_num_trans_items, &num_trans_items);
621 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
623 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
625 "Interface UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
626 if_id.Data1, if_id.Data2, if_id.Data3,
627 if_id.Data4[0], if_id.Data4[1],
628 if_id.Data4[2], if_id.Data4[3],
629 if_id.Data4[4], if_id.Data4[5],
630 if_id.Data4[6], if_id.Data4[7]);
634 if (hdr->drep[0] & 0x10) {
635 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
636 hf_dcerpc_cn_bind_if_ver, &if_ver);
637 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
638 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
640 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
641 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
642 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
643 hf_dcerpc_cn_bind_if_ver, &if_ver);
647 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
648 pinfo->srcport, pinfo->destport, 0);
650 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
651 pinfo->srcport, pinfo->destport, 0);
654 key = g_mem_chunk_alloc (dcerpc_conv_key_chunk);
656 key->ctx_id = ctx_id;
657 key->smb_fid = get_smb_fid(pinfo->private_data);
659 value = g_mem_chunk_alloc (dcerpc_conv_value_chunk);
663 g_hash_table_insert (dcerpc_convs, key, value);
665 if (check_col (pinfo->cinfo, COL_INFO)) {
666 col_add_fstr (pinfo->cinfo, COL_INFO, "%s: UUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %d.%d",
667 hdr->ptype == PDU_BIND ? "Bind" : "Alter Ctx",
668 if_id.Data1, if_id.Data2, if_id.Data3,
669 if_id.Data4[0], if_id.Data4[1],
670 if_id.Data4[2], if_id.Data4[3],
671 if_id.Data4[4], if_id.Data4[5],
672 if_id.Data4[6], if_id.Data4[7],
673 if_ver, if_ver_minor);
678 for (j = 0; j < num_trans_items; j++) {
679 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
681 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
683 "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
684 trans_id.Data1, trans_id.Data2, trans_id.Data3,
685 trans_id.Data4[0], trans_id.Data4[1],
686 trans_id.Data4[2], trans_id.Data4[3],
687 trans_id.Data4[4], trans_id.Data4[5],
688 trans_id.Data4[6], trans_id.Data4[7]);
692 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
693 hf_dcerpc_cn_bind_trans_ver, &trans_ver);
697 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
701 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
702 e_dce_cn_common_hdr_t *hdr)
704 guint16 max_xmit, max_recv;
705 guint16 sec_addr_len;
715 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
716 hf_dcerpc_cn_max_xmit, &max_xmit);
718 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
719 hf_dcerpc_cn_max_recv, &max_recv);
721 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
722 hf_dcerpc_cn_assoc_group, NULL);
724 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
725 hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
726 offset += sec_addr_len;
729 offset += 4 - offset % 4;
732 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
733 hf_dcerpc_cn_num_results, &num_results);
738 for (i = 0; i < num_results; i++) {
739 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
740 hdr->drep, hf_dcerpc_cn_ack_result,
742 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
743 hdr->drep, hf_dcerpc_cn_ack_reason,
746 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
748 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
750 "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
751 trans_id.Data1, trans_id.Data2, trans_id.Data3,
752 trans_id.Data4[0], trans_id.Data4[1],
753 trans_id.Data4[2], trans_id.Data4[3],
754 trans_id.Data4[4], trans_id.Data4[5],
755 trans_id.Data4[6], trans_id.Data4[7]);
759 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
760 hf_dcerpc_cn_ack_trans_ver, &trans_ver);
763 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
765 if (check_col (pinfo->cinfo, COL_INFO)) {
766 if (num_results != 0 && result == 0) {
767 col_add_fstr (pinfo->cinfo, COL_INFO, "%s ack: accept max_xmit: %d max_recv: %d",
768 hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
771 /* FIXME: should put in reason */
772 col_add_fstr (pinfo->cinfo, COL_INFO, "%s ack: %s",
773 hdr->ptype == PDU_BIND_ACK ? "Bind" : "Alter ctx",
774 result == 1 ? "User reject" :
775 result == 2 ? "Provider reject" :
782 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
783 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
785 conversation_t *conv;
792 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
793 hf_dcerpc_cn_alloc_hint, NULL);
795 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
796 hf_dcerpc_cn_ctx_id, &ctx_id);
798 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
799 hf_dcerpc_opnum, &opnum);
801 if (check_col (pinfo->cinfo, COL_INFO)) {
802 col_add_fstr (pinfo->cinfo, COL_INFO, "Request: opnum: %d ctx_id:%d",
806 if (hdr->flags & 0x80) {
807 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
809 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
811 "Object UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
812 obj_id.Data1, obj_id.Data2, obj_id.Data3,
825 auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
827 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
828 pinfo->srcport, pinfo->destport, 0);
833 dcerpc_conv_value *value;
834 int length, reported_length, stub_length;
838 key.smb_fid = get_smb_fid(pinfo->private_data);
840 value = g_hash_table_lookup (dcerpc_convs, &key);
842 /* add an entry for this call, so we can catch the reply */
843 dcerpc_call_add_map (hdr->call_id, conv, opnum,
844 value->ver, &value->uuid);
846 /* handoff this call */
847 length = tvb_length_remaining(tvb, offset);
848 reported_length = tvb_reported_length_remaining(tvb, offset);
849 stub_length = hdr->frag_len - offset - auth_sz;
850 if (length > stub_length)
851 length = stub_length;
852 if (reported_length > stub_length)
853 reported_length = stub_length;
854 dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
855 tvb_new_subset (tvb, offset, length,
857 0, &value->uuid, value->ver,
858 opnum, TRUE, hdr->drep);
864 dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
865 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
867 conversation_t *conv;
872 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
873 hf_dcerpc_cn_alloc_hint, NULL);
875 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
876 hf_dcerpc_cn_ctx_id, &ctx_id);
878 if (check_col (pinfo->cinfo, COL_INFO)) {
879 col_add_fstr (pinfo->cinfo, COL_INFO, "Response: call_id: %d ctx_id:%d",
880 hdr->call_id, ctx_id);
883 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
884 hf_dcerpc_cn_cancel_count, NULL);
888 auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
890 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
891 pinfo->srcport, pinfo->destport, 0);
893 /* no point in creating one here, really */
895 dcerpc_call_value *value = dcerpc_call_lookup (hdr->call_id, conv);
896 int length, reported_length, stub_length;
899 /* handoff this call */
900 length = tvb_length_remaining(tvb, offset);
901 reported_length = tvb_reported_length_remaining(tvb, offset);
902 stub_length = hdr->frag_len - offset - auth_sz;
903 if (length > stub_length)
904 length = stub_length;
905 if (reported_length > stub_length)
906 reported_length = stub_length;
907 dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
908 tvb_new_subset (tvb, offset, length,
910 0, &value->uuid, value->ver,
911 value->opnum, FALSE, hdr->drep);
917 * DCERPC dissector for connection oriented calls
920 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
921 proto_tree *tree, gboolean can_desegment)
923 static char nulls[4] = { 0 };
926 proto_item *ti = NULL;
927 proto_item *tf = NULL;
928 proto_tree *dcerpc_tree = NULL;
929 proto_tree *cn_flags_tree = NULL;
930 proto_tree *drep_tree = NULL;
931 e_dce_cn_common_hdr_t hdr;
934 * when done over nbt, dcerpc requests are padded with 4 bytes of null
935 * data for some reason.
937 * XXX - if that's always the case, the right way to do this would
938 * be to have a "dissect_dcerpc_cn_nb" routine which strips off
939 * the 4 bytes of null padding, and make that the dissector
940 * used for "netbios".
942 if (tvb_bytes_exist (tvb, offset, 4) &&
943 tvb_memeql (tvb, offset, nulls, 4) == 0) {
953 * Check if this looks like a C/O DCERPC call
955 if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
958 start_offset = offset;
959 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
960 if (hdr.rpc_ver != 5)
962 hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
963 if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
965 hdr.ptype = tvb_get_guint8 (tvb, offset++);
969 if (check_col (pinfo->cinfo, COL_PROTOCOL))
970 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
971 if (check_col (pinfo->cinfo, COL_INFO))
972 col_set_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
974 hdr.flags = tvb_get_guint8 (tvb, offset++);
975 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
976 offset += sizeof (hdr.drep);
978 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
980 hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
982 hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
985 offset = start_offset;
986 if (can_desegment && pinfo->can_desegment
987 && hdr.frag_len > tvb_length_remaining (tvb, offset)) {
988 pinfo->desegment_offset = offset;
989 pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, offset);
990 return 0; /* desegmentation required */
994 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
996 dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
998 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
999 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
1000 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
1001 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
1002 cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
1003 if (cn_flags_tree) {
1004 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
1005 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
1006 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
1007 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
1008 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
1009 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
1010 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
1011 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
1015 tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
1016 drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
1018 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
1019 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
1020 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
1022 offset += sizeof (hdr.drep);
1024 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
1027 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
1030 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
1034 * Packet type specific stuff is next.
1036 switch (hdr.ptype) {
1039 dissect_dcerpc_cn_bind (tvb, pinfo, dcerpc_tree, &hdr);
1044 dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
1048 dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
1052 dissect_dcerpc_cn_resp (tvb, pinfo, dcerpc_tree, tree, &hdr);
1056 /* might as well dissect the auth info */
1057 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr);
1060 return hdr.frag_len + padding;
1064 * DCERPC dissector for connection oriented calls over packet-oriented
1068 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1071 * Only one PDU per transport packet, and only one transport
1074 if (dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE) == -1) {
1076 * It wasn't a DCERPC PDU.
1088 * DCERPC dissector for connection oriented calls over byte-stream
1092 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1096 gboolean ret = FALSE;
1099 * There may be multiple PDUs per transport packet; keep
1102 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1103 pdu_len = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
1104 dcerpc_cn_desegment);
1105 if (pdu_len == -1) {
1113 * Well, we've seen at least one DCERPC PDU.
1119 * Desegmentation required - bail now.
1125 * Step to the next PDU.
1133 * DCERPC dissector for connectionless calls
1136 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1138 proto_item *ti = NULL;
1139 proto_item *tf = NULL;
1140 proto_tree *dcerpc_tree = NULL;
1141 proto_tree *dg_flags1_tree = NULL;
1142 proto_tree *dg_flags2_tree = NULL;
1143 proto_tree *drep_tree = NULL;
1144 e_dce_dg_common_hdr_t hdr;
1146 conversation_t *conv;
1149 * Check if this looks like a CL DCERPC call. All dg packets
1150 * have an 80 byte header on them. Which starts with
1151 * version (4), pkt_type.
1153 if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
1156 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
1157 if (hdr.rpc_ver != 4)
1159 hdr.ptype = tvb_get_guint8 (tvb, offset++);
1163 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1164 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
1165 if (check_col (pinfo->cinfo, COL_INFO))
1166 col_set_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
1168 hdr.flags1 = tvb_get_guint8 (tvb, offset++);
1169 hdr.flags2 = tvb_get_guint8 (tvb, offset++);
1170 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
1171 offset += sizeof (hdr.drep);
1172 hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
1173 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
1175 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
1177 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
1179 hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
1181 hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
1183 hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
1185 hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
1187 hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
1189 hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
1191 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
1193 hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
1195 hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
1196 hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
1199 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE);
1201 dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
1204 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
1206 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
1208 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
1209 dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
1210 if (dg_flags1_tree) {
1211 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
1212 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
1213 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
1214 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
1215 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
1216 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
1217 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
1218 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
1222 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
1223 dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
1224 if (dg_flags2_tree) {
1225 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
1226 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
1227 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
1228 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
1229 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
1230 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
1231 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
1232 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
1236 tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
1237 drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
1239 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
1240 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
1241 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
1243 offset += sizeof (hdr.drep);
1245 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset++, 1, hdr.serial_hi);
1247 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
1249 "Object: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1250 hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
1251 hdr.obj_id.Data4[0],
1252 hdr.obj_id.Data4[1],
1253 hdr.obj_id.Data4[2],
1254 hdr.obj_id.Data4[3],
1255 hdr.obj_id.Data4[4],
1256 hdr.obj_id.Data4[5],
1257 hdr.obj_id.Data4[6],
1258 hdr.obj_id.Data4[7]);
1261 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
1263 "Interface: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1264 hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
1272 hdr.if_id.Data4[7]);
1275 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
1277 "Activity: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1278 hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
1279 hdr.act_id.Data4[0],
1280 hdr.act_id.Data4[1],
1281 hdr.act_id.Data4[2],
1282 hdr.act_id.Data4[3],
1283 hdr.act_id.Data4[4],
1284 hdr.act_id.Data4[5],
1285 hdr.act_id.Data4[6],
1286 hdr.act_id.Data4[7]);
1289 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_server_boot, tvb, offset, 4, hdr.server_boot);
1292 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
1295 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
1298 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
1301 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
1304 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
1307 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
1310 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
1313 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
1316 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
1320 * keeping track of the conversation shouldn't really be necessary
1321 * for connectionless packets, because everything we need to know
1322 * to dissect is in the header for each packet. Unfortunately,
1323 * Microsoft's implementation is buggy and often puts the
1324 * completely wrong if_id in the header. go figure. So, keep
1325 * track of the seqnum and use that if possible. Note: that's not
1326 * completely correct. It should really be done based on both the
1327 * activity_id and seqnum. I haven't seen anywhere that it would
1328 * make a difference, but for future reference...
1330 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1331 pinfo->srcport, pinfo->destport, 0);
1333 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
1334 pinfo->srcport, pinfo->destport, 0);
1338 * Packet type specific stuff is next.
1340 switch (hdr.ptype) {
1342 dcerpc_call_add_map (hdr.seqnum, conv, hdr.opnum,
1343 hdr.if_ver, &hdr.if_id);
1344 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset,
1345 &hdr.if_id, hdr.if_ver, hdr.opnum, TRUE, hdr.drep);
1349 dcerpc_call_value *v = dcerpc_call_lookup (hdr.seqnum, conv);
1351 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset,
1352 &v->uuid, v->ver, v->opnum, FALSE, hdr.drep);
1354 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset,
1355 &hdr.if_id, hdr.if_ver, hdr.opnum, FALSE, hdr.drep);
1365 dcerpc_init_protocol (void)
1368 g_hash_table_destroy (dcerpc_convs);
1370 g_hash_table_destroy (dcerpc_calls);
1371 if (dcerpc_conv_key_chunk)
1372 g_mem_chunk_destroy (dcerpc_conv_key_chunk);
1373 if (dcerpc_conv_value_chunk)
1374 g_mem_chunk_destroy (dcerpc_conv_value_chunk);
1375 if (dcerpc_call_key_chunk)
1376 g_mem_chunk_destroy (dcerpc_call_key_chunk);
1377 if (dcerpc_call_value_chunk)
1378 g_mem_chunk_destroy (dcerpc_call_value_chunk);
1380 dcerpc_convs = g_hash_table_new (dcerpc_conv_hash, dcerpc_conv_equal);
1381 dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
1382 dcerpc_conv_key_chunk = g_mem_chunk_new ("dcerpc_conv_key_chunk",
1383 sizeof (dcerpc_conv_key),
1384 200 * sizeof (dcerpc_conv_key),
1386 dcerpc_conv_value_chunk = g_mem_chunk_new ("dcerpc_conv_value_chunk",
1387 sizeof (dcerpc_conv_value),
1388 200 * sizeof (dcerpc_conv_value),
1390 dcerpc_call_key_chunk = g_mem_chunk_new ("dcerpc_call_key_chunk",
1391 sizeof (dcerpc_call_key),
1392 200 * sizeof (dcerpc_call_key),
1394 dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
1395 sizeof (dcerpc_call_value),
1396 200 * sizeof (dcerpc_call_value),
1401 proto_register_dcerpc (void)
1403 static hf_register_info hf[] = {
1405 { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1406 { &hf_dcerpc_ver_minor,
1407 { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1408 { &hf_dcerpc_packet_type,
1409 { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_HEX, VALS (pckt_vals), 0x0, "", HFILL }},
1410 { &hf_dcerpc_cn_flags,
1411 { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1412 { &hf_dcerpc_cn_flags_first_frag,
1413 { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x1, "", HFILL }},
1414 { &hf_dcerpc_cn_flags_last_frag,
1415 { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x2, "", HFILL }},
1416 { &hf_dcerpc_cn_flags_cancel_pending,
1417 { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x4, "", HFILL }},
1418 { &hf_dcerpc_cn_flags_reserved,
1419 { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x8, "", HFILL }},
1420 { &hf_dcerpc_cn_flags_mpx,
1421 { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1422 { &hf_dcerpc_cn_flags_dne,
1423 { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1424 { &hf_dcerpc_cn_flags_maybe,
1425 { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1426 { &hf_dcerpc_cn_flags_object,
1427 { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1429 { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
1430 { &hf_dcerpc_drep_byteorder,
1431 { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, "", HFILL }},
1432 { &hf_dcerpc_drep_character,
1433 { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, "", HFILL }},
1434 { &hf_dcerpc_drep_fp,
1435 { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, "", HFILL }},
1436 { &hf_dcerpc_cn_frag_len,
1437 { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1438 { &hf_dcerpc_cn_auth_len,
1439 { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1440 { &hf_dcerpc_cn_call_id,
1441 { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1442 { &hf_dcerpc_cn_max_xmit,
1443 { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1444 { &hf_dcerpc_cn_max_recv,
1445 { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1446 { &hf_dcerpc_cn_assoc_group,
1447 { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1448 { &hf_dcerpc_cn_num_ctx_items,
1449 { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1450 { &hf_dcerpc_cn_ctx_id,
1451 { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1452 { &hf_dcerpc_cn_num_trans_items,
1453 { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1454 { &hf_dcerpc_cn_bind_if_id,
1455 { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1456 { &hf_dcerpc_cn_bind_if_ver,
1457 { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1458 { &hf_dcerpc_cn_bind_if_ver_minor,
1459 { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1460 { &hf_dcerpc_cn_bind_trans_id,
1461 { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1462 { &hf_dcerpc_cn_bind_trans_ver,
1463 { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1464 { &hf_dcerpc_cn_alloc_hint,
1465 { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1466 { &hf_dcerpc_cn_sec_addr_len,
1467 { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1468 { &hf_dcerpc_cn_num_results,
1469 { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1470 { &hf_dcerpc_cn_ack_result,
1471 { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1472 { &hf_dcerpc_cn_ack_reason,
1473 { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1474 { &hf_dcerpc_cn_ack_trans_id,
1475 { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1476 { &hf_dcerpc_cn_ack_trans_ver,
1477 { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1478 { &hf_dcerpc_cn_cancel_count,
1479 { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1480 { &hf_dcerpc_auth_type,
1481 { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1482 { &hf_dcerpc_auth_level,
1483 { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1484 { &hf_dcerpc_auth_pad_len,
1485 { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1486 { &hf_dcerpc_auth_rsrvd,
1487 { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
1488 { &hf_dcerpc_auth_ctx_id,
1489 { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1490 { &hf_dcerpc_dg_flags1,
1491 { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1492 { &hf_dcerpc_dg_flags1_rsrvd_01,
1493 { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "", HFILL }},
1494 { &hf_dcerpc_dg_flags1_last_frag,
1495 { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "", HFILL }},
1496 { &hf_dcerpc_dg_flags1_frag,
1497 { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "", HFILL }},
1498 { &hf_dcerpc_dg_flags1_nofack,
1499 { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "", HFILL }},
1500 { &hf_dcerpc_dg_flags1_maybe,
1501 { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1502 { &hf_dcerpc_dg_flags1_idempotent,
1503 { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1504 { &hf_dcerpc_dg_flags1_broadcast,
1505 { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1506 { &hf_dcerpc_dg_flags1_rsrvd_80,
1507 { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1508 { &hf_dcerpc_dg_flags2,
1509 { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1510 { &hf_dcerpc_dg_flags2_rsrvd_01,
1511 { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "", HFILL }},
1512 { &hf_dcerpc_dg_flags2_cancel_pending,
1513 { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "", HFILL }},
1514 { &hf_dcerpc_dg_flags2_rsrvd_04,
1515 { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "", HFILL }},
1516 { &hf_dcerpc_dg_flags2_rsrvd_08,
1517 { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "", HFILL }},
1518 { &hf_dcerpc_dg_flags2_rsrvd_10,
1519 { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "", HFILL }},
1520 { &hf_dcerpc_dg_flags2_rsrvd_20,
1521 { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "", HFILL }},
1522 { &hf_dcerpc_dg_flags2_rsrvd_40,
1523 { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "", HFILL }},
1524 { &hf_dcerpc_dg_flags2_rsrvd_80,
1525 { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "", HFILL }},
1526 { &hf_dcerpc_dg_serial_lo,
1527 { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1528 { &hf_dcerpc_dg_serial_hi,
1529 { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1530 { &hf_dcerpc_dg_ahint,
1531 { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1532 { &hf_dcerpc_dg_ihint,
1533 { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1534 { &hf_dcerpc_dg_frag_len,
1535 { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1536 { &hf_dcerpc_dg_frag_num,
1537 { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
1538 { &hf_dcerpc_dg_auth_proto,
1539 { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1540 { &hf_dcerpc_dg_seqnum,
1541 { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1542 { &hf_dcerpc_dg_server_boot,
1543 { "Server boot time", "dcerpc.dg_server_boot", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
1544 { &hf_dcerpc_dg_if_ver,
1545 { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
1546 { &hf_dcerpc_obj_id,
1547 { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1548 { &hf_dcerpc_dg_if_id,
1549 { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1550 { &hf_dcerpc_dg_act_id,
1551 { "Activitiy", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1553 { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
1557 static gint *ett[] = {
1559 &ett_dcerpc_cn_flags,
1561 &ett_dcerpc_dg_flags1,
1562 &ett_dcerpc_dg_flags2,
1565 proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
1566 proto_register_field_array (proto_dcerpc, hf, array_length (hf));
1567 proto_register_subtree_array (ett, array_length (ett));
1568 register_init_routine (dcerpc_init_protocol);
1570 prefs_register_bool_preference (prefs_register_protocol (proto_dcerpc,
1573 "Desegment all DCE/RPC over TCP",
1574 "Whether the DCE/RPC dissector should desegment all DCE/RPC over TCP",
1575 &dcerpc_cn_desegment);
1576 dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
1580 proto_reg_handoff_dcerpc (void)
1582 heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
1583 heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
1584 heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
1585 heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc);