2 * Routines for DCERPC packet disassembly
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
5 * $Id: packet-dcerpc.c,v 1.71 2002/08/13 07:25:36 tpot 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.
34 #include <epan/packet.h>
35 #include "packet-dcerpc.h"
36 #include <epan/conversation.h>
38 #include "reassemble.h"
40 static const value_string pckt_vals[] = {
41 { PDU_REQ, "Request"},
43 { PDU_RESP, "Response"},
44 { PDU_FAULT, "Fault"},
45 { PDU_WORKING, "Working"},
46 { PDU_NOCALL, "Nocall"},
47 { PDU_REJECT, "Reject"},
49 { PDU_CL_CANCEL, "Cl_cancel"},
51 { PDU_CANCEL_ACK, "Cancel_ack"},
53 { PDU_BIND_ACK, "Bind_ack"},
54 { PDU_BIND_NAK, "Bind_nak"},
55 { PDU_ALTER, "Alter_context"},
56 { PDU_ALTER_ACK, "Alter_context_resp"},
57 { PDU_AUTH3, "AUTH3?"},
58 { PDU_SHUTDOWN, "Shutdown"},
59 { PDU_CO_CANCEL, "Co_cancel"},
60 { PDU_ORPHANED, "Orphaned"},
64 static const value_string drep_byteorder_vals[] = {
66 { 1, "Little-endian" },
70 static const value_string drep_character_vals[] = {
76 static const value_string drep_fp_vals[] = {
84 static const true_false_string flags_set_truth = {
90 * Authentication services.
92 #define DCE_C_RPC_AUTHN_PROTOCOL_NONE 0
93 #define DCE_C_RPC_AUTHN_PROTOCOL_KRB5 1
94 #define DCE_C_RPC_AUTHN_PROTOCOL_SNEGO 9
95 #define DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP 10
97 static const value_string authn_protocol_vals[] = {
98 { DCE_C_RPC_AUTHN_PROTOCOL_NONE, "None" },
99 { DCE_C_RPC_AUTHN_PROTOCOL_KRB5, "Kerberos 5" },
100 { DCE_C_RPC_AUTHN_PROTOCOL_SNEGO, "Snego" },
101 { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
108 #define DCE_C_AUTHN_LEVEL_NONE 1
109 #define DCE_C_AUTHN_LEVEL_CONNECT 2
110 #define DCE_C_AUTHN_LEVEL_CALL 3
111 #define DCE_C_AUTHN_LEVEL_PKT 4
112 #define DCE_C_AUTHN_LEVEL_PKT_INTEGRITY 5
113 #define DCE_C_AUTHN_LEVEL_PKT_PRIVACY 6
115 static const value_string authn_level_vals[] = {
116 { DCE_C_AUTHN_LEVEL_NONE, "None" },
117 { DCE_C_AUTHN_LEVEL_CONNECT, "Connect" },
118 { DCE_C_AUTHN_LEVEL_CALL, "Call" },
119 { DCE_C_AUTHN_LEVEL_PKT, "Packet" },
120 { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
121 { DCE_C_AUTHN_LEVEL_PKT_PRIVACY, "Packet privacy" },
126 * Flag bits in first flag field in connectionless PDU header.
128 #define PFCL1_RESERVED_01 0x01 /* Reserved for use by implementations */
129 #define PFCL1_LASTFRAG 0x02 /* If set, the PDU is the last
130 * fragment of a multi-PDU
132 #define PFCL1_FRAG 0x04 /* If set, the PDU is a fragment of
133 a multi-PDU transmission */
134 #define PFCL1_NOFACK 0x08 /* If set, the receiver is not
135 * requested to send a `fack' PDU
136 * for the fragment */
137 #define PFCL1_MAYBE 0x10 /* If set, the PDU is for a `maybe'
139 #define PFCL1_IDEMPOTENT 0x20 /* If set, the PDU is for an idempotent
141 #define PFCL1_BROADCAST 0x40 /* If set, the PDU is for a broadcast
143 #define PFCL1_RESERVED_80 0x80 /* Reserved for use by implementations */
146 * Flag bits in second flag field in connectionless PDU header.
148 #define PFCL2_RESERVED_01 0x01 /* Reserved for use by implementations */
149 #define PFCL2_CANCEL_PENDING 0x02 /* Cancel pending at the call end */
150 #define PFCL2_RESERVED_04 0x04 /* Reserved for future use */
151 #define PFCL2_RESERVED_08 0x08 /* Reserved for future use */
152 #define PFCL2_RESERVED_10 0x10 /* Reserved for future use */
153 #define PFCL2_RESERVED_20 0x20 /* Reserved for future use */
154 #define PFCL2_RESERVED_40 0x40 /* Reserved for future use */
155 #define PFCL2_RESERVED_80 0x80 /* Reserved for future use */
158 * Flag bits in connection-oriented PDU header.
160 #define PFC_FIRST_FRAG 0x01 /* First fragment */
161 #define PFC_LAST_FRAG 0x02 /* Last fragment */
162 #define PFC_PENDING_CANCEL 0x04 /* Cancel was pending at sender */
163 #define PFC_RESERVED_1 0x08
164 #define PFC_CONC_MPX 0x10 /* suports concurrent multiplexing
165 * of a single connection. */
166 #define PFC_DID_NOT_EXECUTE 0x20 /* only meaningful on `fault' packet;
167 * if true, guaranteed call did not
169 #define PFC_MAYBE 0x40 /* `maybe' call semantics requested */
170 #define PFC_OBJECT_UUID 0x80 /* if true, a non-nil object UUID
171 * was specified in the handle, and
172 * is present in the optional object
173 * field. If false, the object field
177 * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
178 * it's not fragmented (i.e., this is both the first *and* last fragment),
179 * and FALSE otherwise.
181 #define PFC_NOT_FRAGMENTED(hdr) \
182 ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
185 * Presentation context negotiation result.
187 static const value_string p_cont_result_vals[] = {
189 { 1, "User rejection" },
190 { 2, "Provider rejection" },
195 * Presentation context negotiation rejection reasons.
197 static const value_string p_provider_reason_vals[] = {
198 { 0, "Reason not specified" },
199 { 1, "Abstract syntax not supported" },
200 { 2, "Proposed transfer syntaxes not supported" },
201 { 3, "Local limit exceeded" },
208 #define REASON_NOT_SPECIFIED 0
209 #define TEMPORARY_CONGESTION 1
210 #define LOCAL_LIMIT_EXCEEDED 2
211 #define CALLED_PADDR_UNKNOWN 3 /* not used */
212 #define PROTOCOL_VERSION_NOT_SUPPORTED 4
213 #define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */
214 #define USER_DATA_NOT_READABLE 6 /* not used */
215 #define NO_PSAP_AVAILABLE 7 /* not used */
217 static const value_string reject_reason_vals[] = {
218 { REASON_NOT_SPECIFIED, "Reason not specified" },
219 { TEMPORARY_CONGESTION, "Temporary congestion" },
220 { LOCAL_LIMIT_EXCEEDED, "Local limit exceeded" },
221 { CALLED_PADDR_UNKNOWN, "Called paddr unknown" },
222 { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
223 { DEFAULT_CONTEXT_NOT_SUPPORTED, "Default context not supported" },
224 { USER_DATA_NOT_READABLE, "User data not readable" },
225 { NO_PSAP_AVAILABLE, "No PSAP available" },
230 * Reject status codes.
232 static const value_string reject_status_vals[] = {
233 { 0, "Stub-defined exception" },
234 { 0x1c000001, "nca_s_fault_int_div_by_zero" },
235 { 0x1c000002, "nca_s_fault_addr_error" },
236 { 0x1c000003, "nca_s_fault_fp_div_zero" },
237 { 0x1c000004, "nca_s_fault_fp_underflow" },
238 { 0x1c000005, "nca_s_fault_fp_overflow" },
239 { 0x1c000006, "nca_s_fault_invalid_tag" },
240 { 0x1c000007, "nca_s_fault_invalid_bound" },
241 { 0x1c000008, "nca_rpc_version_mismatch" },
242 { 0x1c000009, "nca_unspec_reject" },
243 { 0x1c00000a, "nca_s_bad_actid" },
244 { 0x1c00000b, "nca_who_are_you_failed" },
245 { 0x1c00000c, "nca_manager_not_entered" },
246 { 0x1c00000d, "nca_s_fault_cancel" },
247 { 0x1c00000e, "nca_s_fault_ill_inst" },
248 { 0x1c00000f, "nca_s_fault_fp_error" },
249 { 0x1c000010, "nca_s_fault_int_overflow" },
250 { 0x1c000014, "nca_s_fault_pipe_empty" },
251 { 0x1c000015, "nca_s_fault_pipe_closed" },
252 { 0x1c000016, "nca_s_fault_pipe_order" },
253 { 0x1c000017, "nca_s_fault_pipe_discipline" },
254 { 0x1c000018, "nca_s_fault_pipe_comm_error" },
255 { 0x1c000019, "nca_s_fault_pipe_memory" },
256 { 0x1c00001a, "nca_s_fault_context_mismatch" },
257 { 0x1c00001b, "nca_s_fault_remote_no_memory" },
258 { 0x1c00001c, "nca_invalid_pres_context_id" },
259 { 0x1c00001d, "nca_unsupported_authn_level" },
260 { 0x1c00001f, "nca_invalid_checksum" },
261 { 0x1c000020, "nca_invalid_crc" },
262 { 0x1c000021, "ncs_s_fault_user_defined" },
263 { 0x1c000022, "nca_s_fault_tx_open_failed" },
264 { 0x1c000023, "nca_s_fault_codeset_conv_error" },
265 { 0x1c000024, "nca_s_fault_object_not_found" },
266 { 0x1c000025, "nca_s_fault_no_client_stub" },
267 { 0x1c010002, "nca_op_rng_error" },
268 { 0x1c010003, "nca_unk_if"},
269 { 0x1c010006, "nca_wrong_boot_time" },
270 { 0x1c010009, "nca_s_you_crashed" },
271 { 0x1c01000b, "nca_proto_error" },
272 { 0x1c010013, "nca_out_args_too_big" },
273 { 0x1c010014, "nca_server_too_busy" },
274 { 0x1c010017, "nca_unsupported_type" },
278 static int proto_dcerpc = -1;
281 static int hf_dcerpc_request_in = -1;
282 static int hf_dcerpc_response_in = -1;
283 static int hf_dcerpc_ver = -1;
284 static int hf_dcerpc_ver_minor = -1;
285 static int hf_dcerpc_packet_type = -1;
286 static int hf_dcerpc_cn_flags = -1;
287 static int hf_dcerpc_cn_flags_first_frag = -1;
288 static int hf_dcerpc_cn_flags_last_frag = -1;
289 static int hf_dcerpc_cn_flags_cancel_pending = -1;
290 static int hf_dcerpc_cn_flags_reserved = -1;
291 static int hf_dcerpc_cn_flags_mpx = -1;
292 static int hf_dcerpc_cn_flags_dne = -1;
293 static int hf_dcerpc_cn_flags_maybe = -1;
294 static int hf_dcerpc_cn_flags_object = -1;
295 static int hf_dcerpc_drep = -1;
296 static int hf_dcerpc_drep_byteorder = -1;
297 static int hf_dcerpc_drep_character = -1;
298 static int hf_dcerpc_drep_fp = -1;
299 static int hf_dcerpc_cn_frag_len = -1;
300 static int hf_dcerpc_cn_auth_len = -1;
301 static int hf_dcerpc_cn_call_id = -1;
302 static int hf_dcerpc_cn_max_xmit = -1;
303 static int hf_dcerpc_cn_max_recv = -1;
304 static int hf_dcerpc_cn_assoc_group = -1;
305 static int hf_dcerpc_cn_num_ctx_items = -1;
306 static int hf_dcerpc_cn_ctx_id = -1;
307 static int hf_dcerpc_cn_num_trans_items = -1;
308 static int hf_dcerpc_cn_bind_if_id = -1;
309 static int hf_dcerpc_cn_bind_if_ver = -1;
310 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
311 static int hf_dcerpc_cn_bind_trans_id = -1;
312 static int hf_dcerpc_cn_bind_trans_ver = -1;
313 static int hf_dcerpc_cn_alloc_hint = -1;
314 static int hf_dcerpc_cn_sec_addr_len = -1;
315 static int hf_dcerpc_cn_sec_addr = -1;
316 static int hf_dcerpc_cn_num_results = -1;
317 static int hf_dcerpc_cn_ack_result = -1;
318 static int hf_dcerpc_cn_ack_reason = -1;
319 static int hf_dcerpc_cn_ack_trans_id = -1;
320 static int hf_dcerpc_cn_ack_trans_ver = -1;
321 static int hf_dcerpc_cn_reject_reason = -1;
322 static int hf_dcerpc_cn_num_protocols = -1;
323 static int hf_dcerpc_cn_protocol_ver_major = -1;
324 static int hf_dcerpc_cn_protocol_ver_minor = -1;
325 static int hf_dcerpc_cn_cancel_count = -1;
326 static int hf_dcerpc_cn_status = -1;
327 static int hf_dcerpc_auth_type = -1;
328 static int hf_dcerpc_auth_level = -1;
329 static int hf_dcerpc_auth_pad_len = -1;
330 static int hf_dcerpc_auth_rsrvd = -1;
331 static int hf_dcerpc_auth_ctx_id = -1;
332 static int hf_dcerpc_dg_flags1 = -1;
333 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
334 static int hf_dcerpc_dg_flags1_last_frag = -1;
335 static int hf_dcerpc_dg_flags1_frag = -1;
336 static int hf_dcerpc_dg_flags1_nofack = -1;
337 static int hf_dcerpc_dg_flags1_maybe = -1;
338 static int hf_dcerpc_dg_flags1_idempotent = -1;
339 static int hf_dcerpc_dg_flags1_broadcast = -1;
340 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
341 static int hf_dcerpc_dg_flags2 = -1;
342 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
343 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
344 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
345 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
346 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
347 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
348 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
349 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
350 static int hf_dcerpc_dg_serial_hi = -1;
351 static int hf_dcerpc_obj_id = -1;
352 static int hf_dcerpc_dg_if_id = -1;
353 static int hf_dcerpc_dg_act_id = -1;
354 static int hf_dcerpc_dg_serial_lo = -1;
355 static int hf_dcerpc_dg_ahint = -1;
356 static int hf_dcerpc_dg_ihint = -1;
357 static int hf_dcerpc_dg_frag_len = -1;
358 static int hf_dcerpc_dg_frag_num = -1;
359 static int hf_dcerpc_dg_auth_proto = -1;
360 static int hf_dcerpc_opnum = -1;
361 static int hf_dcerpc_dg_seqnum = -1;
362 static int hf_dcerpc_dg_server_boot = -1;
363 static int hf_dcerpc_dg_if_ver = -1;
364 static int hf_dcerpc_dg_cancel_vers = -1;
365 static int hf_dcerpc_dg_cancel_id = -1;
366 static int hf_dcerpc_dg_server_accepting_cancels = -1;
367 static int hf_dcerpc_dg_fack_vers = -1;
368 static int hf_dcerpc_dg_fack_window_size = -1;
369 static int hf_dcerpc_dg_fack_max_tsdu = -1;
370 static int hf_dcerpc_dg_fack_max_frag_size = -1;
371 static int hf_dcerpc_dg_fack_serial_num = -1;
372 static int hf_dcerpc_dg_fack_selack_len = -1;
373 static int hf_dcerpc_dg_fack_selack = -1;
374 static int hf_dcerpc_dg_status = -1;
375 static int hf_dcerpc_array_max_count = -1;
376 static int hf_dcerpc_array_offset = -1;
377 static int hf_dcerpc_array_actual_count = -1;
378 static int hf_dcerpc_op = -1;
379 static int hf_dcerpc_referent_id = -1;
380 static int hf_dcerpc_fragments = -1;
381 static int hf_dcerpc_fragment = -1;
382 static int hf_dcerpc_fragment_overlap = -1;
383 static int hf_dcerpc_fragment_overlap_conflict = -1;
384 static int hf_dcerpc_fragment_multiple_tails = -1;
385 static int hf_dcerpc_fragment_too_long_fragment = -1;
386 static int hf_dcerpc_fragment_error = -1;
388 static gint ett_dcerpc = -1;
389 static gint ett_dcerpc_cn_flags = -1;
390 static gint ett_dcerpc_drep = -1;
391 static gint ett_dcerpc_dg_flags1 = -1;
392 static gint ett_dcerpc_dg_flags2 = -1;
393 static gint ett_dcerpc_pointer_data = -1;
394 static gint ett_dcerpc_fragments = -1;
395 static gint ett_dcerpc_fragment = -1;
397 static dissector_handle_t ntlmssp_handle=NULL;
399 fragment_items dcerpc_frag_items = {
400 &ett_dcerpc_fragments,
401 &ett_dcerpc_fragment,
403 &hf_dcerpc_fragments,
405 &hf_dcerpc_fragment_overlap,
406 &hf_dcerpc_fragment_overlap_conflict,
407 &hf_dcerpc_fragment_multiple_tails,
408 &hf_dcerpc_fragment_too_long_fragment,
409 &hf_dcerpc_fragment_error,
414 /* try to desegment big DCE/RPC packets over TCP? */
415 static gboolean dcerpc_cn_desegment = TRUE;
417 /* reassemble DCE/RPC fragments */
418 /* reassembly of dcerpc fragments will not work for the case where ONE frame
419 might contain multiple dcerpc fragments for different PDUs.
420 this case would be so unusual/weird so if you got captures like that:
423 static gboolean dcerpc_reassemble = FALSE;
424 static GHashTable *dcerpc_co_reassemble_table = NULL;
425 static GHashTable *dcerpc_cl_reassemble_table = NULL;
428 dcerpc_reassemble_init(void)
430 fragment_table_init(&dcerpc_co_reassemble_table);
431 fragment_table_init(&dcerpc_cl_reassemble_table);
438 /* the registered subdissectors */
439 static GHashTable *dcerpc_uuids;
441 typedef struct _dcerpc_uuid_key {
446 typedef struct _dcerpc_uuid_value {
450 dcerpc_sub_dissector *procs;
455 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
457 dcerpc_uuid_key *key1 = (dcerpc_uuid_key *)k1;
458 dcerpc_uuid_key *key2 = (dcerpc_uuid_key *)k2;
459 return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
460 && (key1->ver == key2->ver));
464 dcerpc_uuid_hash (gconstpointer k)
466 dcerpc_uuid_key *key = (dcerpc_uuid_key *)k;
467 /* This isn't perfect, but the Data1 part of these is almost always
469 return key->uuid.Data1;
473 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
474 dcerpc_sub_dissector *procs, int opnum_hf)
476 dcerpc_uuid_key *key = g_malloc (sizeof (*key));
477 dcerpc_uuid_value *value = g_malloc (sizeof (*value));
482 value->proto = proto;
484 value->name = proto_get_protocol_short_name (proto);
485 value->procs = procs;
486 value->opnum_hf = opnum_hf;
488 g_hash_table_insert (dcerpc_uuids, key, value);
493 * To keep track of ctx_id mappings.
495 * Everytime we see a bind call we update this table.
496 * Note that we always specify a SMB FID. For non-SMB transports this
499 static GHashTable *dcerpc_binds=NULL;
501 typedef struct _dcerpc_bind_key {
502 conversation_t *conv;
507 typedef struct _dcerpc_bind_value {
512 static GMemChunk *dcerpc_bind_key_chunk=NULL;
513 static GMemChunk *dcerpc_bind_value_chunk=NULL;
516 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
518 dcerpc_bind_key *key1 = (dcerpc_bind_key *)k1;
519 dcerpc_bind_key *key2 = (dcerpc_bind_key *)k2;
520 return (key1->conv == key2->conv
521 && key1->ctx_id == key2->ctx_id
522 && key1->smb_fid == key2->smb_fid);
526 dcerpc_bind_hash (gconstpointer k)
528 dcerpc_bind_key *key = (dcerpc_bind_key *)k;
529 return ((guint)key->conv) + key->ctx_id + key->smb_fid;
533 * To keep track of callid mappings. Should really use some generic
534 * conversation support instead.
536 static GHashTable *dcerpc_calls=NULL;
538 typedef struct _dcerpc_call_key {
539 conversation_t *conv;
544 static GMemChunk *dcerpc_call_key_chunk=NULL;
546 static GMemChunk *dcerpc_call_value_chunk=NULL;
549 dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
551 dcerpc_call_key *key1 = (dcerpc_call_key *)k1;
552 dcerpc_call_key *key2 = (dcerpc_call_key *)k2;
553 return (key1->conv == key2->conv
554 && key1->call_id == key2->call_id
555 && key1->smb_fid == key2->smb_fid);
559 dcerpc_call_hash (gconstpointer k)
561 dcerpc_call_key *key = (dcerpc_call_key *)k;
562 return ((guint32)key->conv) + key->call_id + key->smb_fid;
566 /* to keep track of matched calls/responses
567 this one uses the same value struct as calls, but the key is the frame id
569 static GHashTable *dcerpc_matched=NULL;
571 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
573 return (guint32)k1 == (guint32)k2;
577 dcerpc_matched_hash (gconstpointer k)
585 * Utility functions. Modeled after packet-rpc.c
589 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
590 proto_tree *tree, char *drep,
591 int hfindex, guint8 *pdata)
595 data = tvb_get_guint8 (tvb, offset);
597 proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
605 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
606 proto_tree *tree, char *drep,
607 int hfindex, guint16 *pdata)
611 data = ((drep[0] & 0x10)
612 ? tvb_get_letohs (tvb, offset)
613 : tvb_get_ntohs (tvb, offset));
616 proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
624 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
625 proto_tree *tree, char *drep,
626 int hfindex, guint32 *pdata)
630 data = ((drep[0] & 0x10)
631 ? tvb_get_letohl (tvb, offset)
632 : tvb_get_ntohl (tvb, offset));
635 proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
643 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
644 proto_tree *tree, char *drep,
645 int hfindex, unsigned char *pdata)
648 tvb_memcpy(tvb, pdata, offset, 8);
649 if(drep[0] & 0x10){/* XXX this might be the wrong way around */
651 data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
652 data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
653 data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
654 data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
659 proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
666 * a couple simpler things
669 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
671 if (drep[0] & 0x10) {
672 return tvb_get_letohs (tvb, offset);
674 return tvb_get_ntohs (tvb, offset);
679 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
681 if (drep[0] & 0x10) {
682 return tvb_get_letohl (tvb, offset);
684 return tvb_get_ntohl (tvb, offset);
689 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
692 uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
693 uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
694 uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
696 for (i=0; i<sizeof (uuid->Data4); i++) {
697 uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
704 /* function to dissect a unidimensional conformant array */
706 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
707 proto_tree *tree, char *drep,
708 dcerpc_dissect_fnct_t *fnct)
714 di=pinfo->private_data;
715 if(di->conformant_run){
716 /* conformant run, just dissect the max_count header */
718 di->conformant_run=0;
719 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
720 hf_dcerpc_array_max_count, &di->array_max_count);
721 di->array_max_count_offset=offset-4;
722 di->conformant_run=1;
723 di->conformant_eaten=offset-old_offset;
725 /* we dont dont remember where in the bytestream this fields was */
726 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
728 /* real run, dissect the elements */
729 for(i=0;i<di->array_max_count;i++){
730 offset = (*fnct)(tvb, offset, pinfo, tree, drep);
736 /* function to dissect a unidimensional conformant and varying array */
738 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
739 proto_tree *tree, char *drep,
740 dcerpc_dissect_fnct_t *fnct)
746 di=pinfo->private_data;
747 if(di->conformant_run){
748 /* conformant run, just dissect the max_count header */
750 di->conformant_run=0;
751 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
752 hf_dcerpc_array_max_count, &di->array_max_count);
753 di->array_max_count_offset=offset-4;
754 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
755 hf_dcerpc_array_offset, &di->array_offset);
756 di->array_offset_offset=offset-4;
757 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
758 hf_dcerpc_array_actual_count, &di->array_actual_count);
759 di->array_actual_count_offset=offset-4;
760 di->conformant_run=1;
761 di->conformant_eaten=offset-old_offset;
763 /* we dont dont remember where in the bytestream these fields were */
764 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
765 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
766 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
768 /* real run, dissect the elements */
769 for(i=0;i<di->array_actual_count;i++){
770 offset = (*fnct)(tvb, offset, pinfo, tree, drep);
778 /* ndr pointer handling */
779 /* list of pointers encountered so far */
780 static GSList *ndr_pointer_list = NULL;
782 /* position where in the list to insert newly encountered pointers */
783 static int ndr_pointer_list_pos=0;
785 /* boolean controlling whether pointers are top-level or embedded */
786 static gboolean pointers_are_top_level = TRUE;
788 /* as a kludge, we represent all embedded reference pointers as id==-1
789 hoping that his will not collide with any non-ref pointers */
790 typedef struct ndr_pointer_data {
793 dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
796 } ndr_pointer_data_t;
799 init_ndr_pointer_list(packet_info *pinfo)
803 di=pinfo->private_data;
804 di->conformant_run=0;
806 while(ndr_pointer_list){
807 ndr_pointer_data_t *npd;
809 npd=g_slist_nth_data(ndr_pointer_list, 0);
810 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
816 ndr_pointer_list=NULL;
817 ndr_pointer_list_pos=0;
818 pointers_are_top_level=TRUE;
822 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, char *drep)
824 int found_new_pointer;
828 di=pinfo->private_data;
833 len=g_slist_length(ndr_pointer_list);
835 ndr_pointer_data_t *tnpd;
836 tnpd=g_slist_nth_data(ndr_pointer_list, i);
838 dcerpc_dissect_fnct_t *fnct;
843 ndr_pointer_list_pos=i+1;
844 di->hf_index=tnpd->hf_index;
845 di->levels=tnpd->levels;
846 /* first a run to handle any conformant
848 di->conformant_run=1;
849 di->conformant_eaten=0;
851 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
853 g_assert((offset-old_offset)==di->conformant_eaten);
854 /* This is to check for any bugs in the dissectors.
856 * Basically, the NDR representation will store all
857 * arrays in two blocks, one block with the dimension
858 * discreption, like size, number of elements and such,
859 * and another block that contains the actual data stored
861 * If the array is embedded directly inside another,
862 * encapsulating aggregate type, like a union or struct,
863 * then these two blocks will be stored at different places
864 * in the bytestream, with other data between the blocks.
866 * For this reason, all pointers to types (both aggregate
867 * and scalar, for simplicity no distinction is made)
868 * will have its dissector called twice.
869 * The dissector will first be called with conformant_run==1
870 * in which mode the dissector MUST NOT consume any data from
871 * the tvbuff (i.e. may not dissect anything) except the
872 * initial control block for arrays.
873 * The second time the dissector is called, with
874 * conformant_run==0, all other data for the type will be
877 * All dissect_ndr_<type> dissectors are already prepared
878 * for this and knows when it should eat data from the tvb
879 * and when not to, so implementors of dissectors will
880 * normally not need to worry about this or even know about
881 * it. However, if a dissector for an aggregate type calls
882 * a subdissector from outside packet-dcerpc.c, such as
883 * the dissector in packet-smb.c for NT Security Descriptors
884 * as an example, then it is VERY important to encapsulate
885 * this call to an external subdissector with the appropriate
886 * test for conformant_run, i.e. it will need something like
890 * di=pinfo->private_data;
891 * if(di->conformant_run){
895 * to make sure it makes the right thing.
896 * This assert will signal when someone has forgotten to
897 * make the dissector aware of this requirement.
900 /* now we dissect the actual pointer */
901 di->conformant_run=0;
902 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
906 } while(found_new_pointer);
913 add_pointer_to_list(packet_info *pinfo, proto_tree *tree,
914 dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index, int levels)
916 ndr_pointer_data_t *npd;
918 /* check if this pointer is valid */
921 dcerpc_call_value *value;
923 di=pinfo->private_data;
927 if(!(pinfo->fd->flags.visited)){
928 if(id>value->max_ptr){
933 /* if we havent seen the request bail out since we cant
934 know whether this is the first non-NULL instance
936 if(value->req_frame==0){
937 /* XXX THROW EXCEPTION */
940 /* We saw this one in the request frame, nothing to
942 if(id<=value->max_ptr){
948 npd=g_malloc(sizeof(ndr_pointer_data_t));
952 npd->hf_index=hf_index;
954 ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
955 ndr_pointer_list_pos);
956 ndr_pointer_list_pos++;
961 find_pointer_index(guint32 id)
963 ndr_pointer_data_t *npd;
966 len=g_slist_length(ndr_pointer_list);
968 npd=g_slist_nth_data(ndr_pointer_list, i);
979 /* This function dissects an NDR pointer and stores the callback for later
980 * deferred dissection.
982 * fnct is the callback function for when we have reached this object in
985 * type is what type of pointer.
987 * this is text is what text we should put in any created tree node.
989 * hf_index is what hf value we want to pass to the callback function when
990 * it is called, the callback can later pich this one up from di->hf_index.
992 * levels is a generic int we want to pass to teh callback function. the
993 * callback can later pick it up from di->levels
995 * See packet-dcerpc-samr.c for examples
998 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
999 proto_tree *tree, char *drep, dcerpc_dissect_fnct_t *fnct,
1000 int type, char *text, int hf_index, int levels)
1004 di=pinfo->private_data;
1005 if(di->conformant_run){
1006 /* this call was only for dissecting the header for any
1007 embedded conformant array. we will not parse any
1008 pointers in this mode.
1013 /*TOP LEVEL REFERENCE POINTER*/
1014 if( pointers_are_top_level
1015 &&(type==NDR_POINTER_REF) ){
1019 /* we must find out a nice way to do the length here */
1020 item=proto_tree_add_text(tree, tvb, offset, 0,
1022 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1024 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1028 /*TOP LEVEL FULL POINTER*/
1029 if( pointers_are_top_level
1030 && (type==NDR_POINTER_PTR) ){
1036 /* get the referent id */
1037 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1039 /* we got a NULL pointer */
1041 proto_tree_add_text(tree, tvb, offset-4, 4,
1042 "(NULL pointer) %s",text);
1046 /* see if we have seen this pointer before */
1047 idx=find_pointer_index(id);
1049 /* we have seen this pointer before */
1051 proto_tree_add_text(tree, tvb, offset-4, 4,
1052 "(duplicate PTR) %s",text);
1057 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1059 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1060 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1061 add_pointer_to_list(pinfo, tr, fnct, id, hf_index, levels);
1064 /*TOP LEVEL UNIQUE POINTER*/
1065 if( pointers_are_top_level
1066 && (type==NDR_POINTER_UNIQUE) ){
1071 /* get the referent id */
1072 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1074 /* we got a NULL pointer */
1076 proto_tree_add_text(tree, tvb, offset-4, 4,
1077 "(NULL pointer) %s",text);
1082 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1084 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1085 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1086 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1090 /*EMBEDDED REFERENCE POINTER*/
1091 if( (!pointers_are_top_level)
1092 && (type==NDR_POINTER_REF) ){
1097 /* get the referent id */
1098 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1101 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1103 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1104 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1105 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1109 /*EMBEDDED UNIQUE POINTER*/
1110 if( (!pointers_are_top_level)
1111 && (type==NDR_POINTER_UNIQUE) ){
1116 /* get the referent id */
1117 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1119 /* we got a NULL pointer */
1121 proto_tree_add_text(tree, tvb, offset-4, 4,
1122 "(NULL pointer) %s", text);
1127 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1129 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1130 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1131 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1135 /*EMBEDDED FULL POINTER*/
1136 if( (!pointers_are_top_level)
1137 && (type==NDR_POINTER_PTR) ){
1143 /* get the referent id */
1144 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1146 /* we got a NULL pointer */
1148 proto_tree_add_text(tree, tvb, offset-4, 4,
1149 "(NULL pointer) %s",text);
1153 /* see if we have seen this pointer before */
1154 idx=find_pointer_index(id);
1156 /* we have seen this pointer before */
1158 proto_tree_add_text(tree, tvb, offset-4, 4,
1159 "(duplicate PTR) %s",text);
1164 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1166 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1167 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1168 add_pointer_to_list(pinfo, tr, fnct, id, hf_index, levels);
1174 /* After each top level pointer we have dissected we have to
1175 dissect all deferrals before we move on to the next top level
1177 if(pointers_are_top_level==TRUE){
1178 pointers_are_top_level=FALSE;
1179 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
1180 pointers_are_top_level=TRUE;
1189 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
1190 proto_tree *dcerpc_tree,
1191 tvbuff_t *tvb, gint offset,
1192 char *drep, dcerpc_info *info,
1195 dcerpc_uuid_key key;
1196 dcerpc_uuid_value *sub_proto;
1198 proto_tree *sub_tree = NULL;
1199 dcerpc_sub_dissector *proc;
1201 dcerpc_dissect_fnct_t *sub_dissect;
1202 const char *saved_proto;
1203 void *saved_private_data;
1205 key.uuid = info->call_data->uuid;
1206 key.ver = info->call_data->ver;
1209 if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
1210 || !proto_is_protocol_enabled(sub_proto->proto)) {
1212 * We don't have a dissector for this UUID, or the protocol
1213 * for that UUID is disabled.
1215 length = tvb_length_remaining (tvb, offset);
1217 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1218 "Stub data (%d byte%s)", length,
1219 plurality(length, "", "s"));
1224 for (proc = sub_proto->procs; proc->name; proc++) {
1225 if (proc->num == info->call_data->opnum) {
1234 if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
1235 col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
1238 if (check_col (pinfo->cinfo, COL_INFO)) {
1239 col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
1240 name, info->request ? "request" : "reply");
1244 proto_item *sub_item;
1245 sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
1249 sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
1253 * Put the operation number into the tree along with
1254 * the operation's name.
1257 if (sub_proto->opnum_hf != -1)
1258 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
1259 tvb, 0, 0, info->call_data->opnum,
1260 "Operation: %s (%u)",
1261 name, info->call_data->opnum);
1263 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
1264 0, 0, info->call_data->opnum,
1265 "Operation: %s (%u)",
1266 name, info->call_data->opnum);
1270 * If the authentication level is DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
1271 * the stub data is encrypted, and we can't dissect it.
1273 if (auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
1274 length = tvb_length_remaining (tvb, offset);
1276 proto_tree_add_text(sub_tree, tvb, offset, length,
1277 "Encrypted stub data (%d byte%s)",
1278 length, plurality(length, "", "s"));
1281 sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp;
1283 saved_proto = pinfo->current_proto;
1284 saved_private_data = pinfo->private_data;
1285 pinfo->current_proto = sub_proto->name;
1286 pinfo->private_data = (void *)info;
1288 init_ndr_pointer_list(pinfo);
1289 offset = sub_dissect (tvb, offset, pinfo, sub_tree, drep);
1291 pinfo->current_proto = saved_proto;
1292 pinfo->private_data = saved_private_data;
1294 length = tvb_length_remaining (tvb, offset);
1296 proto_tree_add_text (sub_tree, tvb, offset, length,
1297 "Stub data (%d byte%s)", length,
1298 plurality(length, "", "s"));
1306 dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1307 e_dce_cn_common_hdr_t *hdr, int *auth_level_p)
1310 guint8 auth_pad_len;
1315 * Initially set "*auth_level_p" to -1 to indicate that we haven't
1316 * yet seen any authentication level information.
1318 if (auth_level_p != NULL)
1322 * The authentication information is at the *end* of the PDU; in
1323 * request and response PDUs, the request and response stub data
1326 * If the full packet is here, and we've got an auth len, and it's
1327 * valid, then dissect the auth info.
1329 if (tvb_length (tvb) >= hdr->frag_len
1331 && (hdr->auth_len + 8 <= hdr->frag_len)) {
1333 offset = hdr->frag_len - (hdr->auth_len + 8);
1335 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1336 hf_dcerpc_auth_type, &auth_type);
1337 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1338 hf_dcerpc_auth_level, &auth_level);
1339 if (auth_level_p != NULL)
1340 *auth_level_p = auth_level;
1341 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1342 hf_dcerpc_auth_pad_len, &auth_pad_len);
1343 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1344 hf_dcerpc_auth_rsrvd, NULL);
1345 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1346 hf_dcerpc_auth_ctx_id, NULL);
1348 /* Dissect the authentication data as NTLMSSP Parameters if the
1349 auth_type is DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP and this is a
1350 BIND request, BIND response, or AUTH3.
1351 Otherwise just show it as "Auth Data".
1352 XXX - dissect it for other authentication types?
1354 if ((auth_type == DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP) &&
1355 ((hdr->ptype == PDU_BIND) || (hdr->ptype == PDU_BIND_ACK) ||
1356 (hdr->ptype == PDU_AUTH3))) {
1357 tvbuff_t *ntlmssp_tvb;
1358 ntlmssp_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
1360 call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, dcerpc_tree);
1362 proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
1366 /* figure out where the auth padding starts */
1367 offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len);
1368 if (offset > 0 && auth_pad_len) {
1369 proto_tree_add_text (dcerpc_tree, tvb, offset,
1370 auth_pad_len, "Auth padding");
1371 return hdr->auth_len + 8 + auth_pad_len;
1373 return hdr->auth_len + 8;
1381 /* We need to hash in the SMB fid number to generate a unique hash table
1382 key as DCERPC over SMB allows several pipes over the same TCP/IP
1385 static guint16 get_smb_fid (void *private_data)
1387 dcerpc_private_info *priv = (dcerpc_private_info *)private_data;
1390 return 0; /* Nothing to see here */
1392 /* DCERPC over smb */
1394 if (priv->transport_type == DCERPC_TRANSPORT_SMB)
1395 return priv->data.smb.fid;
1397 /* Some other transport... */
1403 * Connection oriented packet types
1407 dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1408 e_dce_cn_common_hdr_t *hdr)
1410 conversation_t *conv = NULL;
1411 guint8 num_ctx_items;
1413 gboolean saw_ctx_item = FALSE;
1415 guint16 num_trans_items;
1420 guint16 if_ver, if_ver_minor;
1423 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1424 hf_dcerpc_cn_max_xmit, NULL);
1426 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1427 hf_dcerpc_cn_max_recv, NULL);
1429 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1430 hf_dcerpc_cn_assoc_group, NULL);
1432 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1433 hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
1438 for (i = 0; i < num_ctx_items; i++) {
1439 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1440 hf_dcerpc_cn_ctx_id, &ctx_id);
1442 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1443 hf_dcerpc_cn_num_trans_items, &num_trans_items);
1445 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
1447 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
1449 "Interface UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1450 if_id.Data1, if_id.Data2, if_id.Data3,
1451 if_id.Data4[0], if_id.Data4[1],
1452 if_id.Data4[2], if_id.Data4[3],
1453 if_id.Data4[4], if_id.Data4[5],
1454 if_id.Data4[6], if_id.Data4[7]);
1458 if (hdr->drep[0] & 0x10) {
1459 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1460 hf_dcerpc_cn_bind_if_ver, &if_ver);
1461 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1462 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
1464 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1465 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
1466 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1467 hf_dcerpc_cn_bind_if_ver, &if_ver);
1470 if (!saw_ctx_item) {
1471 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1472 pinfo->srcport, pinfo->destport, 0);
1474 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
1475 pinfo->srcport, pinfo->destport, 0);
1478 /* if this is the first time we see this packet, we need to
1479 update the dcerpc_binds table so that any later calls can
1480 match to the interface.
1481 XXX We assume that BINDs will NEVER be fragmented.
1483 if(!(pinfo->fd->flags.visited)){
1484 dcerpc_bind_key *key;
1485 dcerpc_bind_value *value;
1487 key = g_mem_chunk_alloc (dcerpc_bind_key_chunk);
1489 key->ctx_id = ctx_id;
1490 key->smb_fid = get_smb_fid(pinfo->private_data);
1492 value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
1493 value->uuid = if_id;
1494 value->ver = if_ver;
1496 /* add this entry to the bind table, first removing any
1497 previous ones that are identical
1499 if(g_hash_table_lookup(dcerpc_binds, key)){
1500 g_hash_table_remove(dcerpc_binds, key);
1502 g_hash_table_insert (dcerpc_binds, key, value);
1505 if (check_col (pinfo->cinfo, COL_INFO)) {
1506 dcerpc_uuid_key key;
1507 dcerpc_uuid_value *value;
1512 if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
1513 col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
1515 col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
1516 if_id.Data1, if_id.Data2, if_id.Data3,
1517 if_id.Data4[0], if_id.Data4[1],
1518 if_id.Data4[2], if_id.Data4[3],
1519 if_id.Data4[4], if_id.Data4[5],
1520 if_id.Data4[6], if_id.Data4[7],
1521 if_ver, if_ver_minor);
1523 saw_ctx_item = TRUE;
1526 for (j = 0; j < num_trans_items; j++) {
1527 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
1529 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
1531 "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1532 trans_id.Data1, trans_id.Data2, trans_id.Data3,
1533 trans_id.Data4[0], trans_id.Data4[1],
1534 trans_id.Data4[2], trans_id.Data4[3],
1535 trans_id.Data4[4], trans_id.Data4[5],
1536 trans_id.Data4[6], trans_id.Data4[7]);
1540 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1541 hf_dcerpc_cn_bind_trans_ver, &trans_ver);
1546 * XXX - we should save the authentication type *if* we have
1547 * an authentication header, and associate it with an authentication
1548 * context, so subsequent PDUs can use that context.
1550 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL);
1554 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1555 e_dce_cn_common_hdr_t *hdr)
1557 guint16 max_xmit, max_recv;
1558 guint16 sec_addr_len;
1568 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1569 hf_dcerpc_cn_max_xmit, &max_xmit);
1571 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1572 hf_dcerpc_cn_max_recv, &max_recv);
1574 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1575 hf_dcerpc_cn_assoc_group, NULL);
1577 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1578 hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
1579 if (sec_addr_len != 0) {
1580 proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
1581 sec_addr_len, FALSE);
1582 offset += sec_addr_len;
1586 offset += 4 - offset % 4;
1589 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1590 hf_dcerpc_cn_num_results, &num_results);
1595 for (i = 0; i < num_results; i++) {
1596 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1597 hdr->drep, hf_dcerpc_cn_ack_result,
1600 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1601 hdr->drep, hf_dcerpc_cn_ack_reason,
1605 * The reason for rejection isn't meaningful, and often isn't
1606 * set, when the syntax was accepted.
1611 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
1613 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
1615 "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1616 trans_id.Data1, trans_id.Data2, trans_id.Data3,
1617 trans_id.Data4[0], trans_id.Data4[1],
1618 trans_id.Data4[2], trans_id.Data4[3],
1619 trans_id.Data4[4], trans_id.Data4[5],
1620 trans_id.Data4[6], trans_id.Data4[7]);
1624 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1625 hf_dcerpc_cn_ack_trans_ver, &trans_ver);
1629 * XXX - do we need to do anything with the authentication level
1630 * we get back from this?
1632 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL);
1634 if (check_col (pinfo->cinfo, COL_INFO)) {
1635 if (num_results != 0 && result == 0) {
1636 /* XXX - only checks the last result */
1637 col_append_fstr (pinfo->cinfo, COL_INFO,
1638 " accept max_xmit: %u max_recv: %u",
1639 max_xmit, max_recv);
1641 /* XXX - only shows the last result and reason */
1642 col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
1643 val_to_str(result, p_cont_result_vals,
1644 "Unknown result (%u)"),
1645 val_to_str(reason, p_provider_reason_vals,
1652 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1653 e_dce_cn_common_hdr_t *hdr)
1656 guint8 num_protocols;
1661 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1662 hdr->drep, hf_dcerpc_cn_reject_reason,
1665 if (check_col (pinfo->cinfo, COL_INFO)) {
1666 col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
1667 val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
1670 if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
1671 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1672 hf_dcerpc_cn_num_protocols,
1675 for (i = 0; i < num_protocols; i++) {
1676 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
1677 hdr->drep, hf_dcerpc_cn_protocol_ver_major,
1679 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
1680 hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
1687 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
1688 proto_tree *dcerpc_tree, proto_tree *tree,
1689 e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
1690 int auth_sz, int auth_level, guint32 alloc_hint,
1693 int length, reported_length, stub_length;
1694 gboolean save_fragmented;
1696 length = tvb_length_remaining(tvb, offset);
1697 reported_length = tvb_reported_length_remaining(tvb, offset);
1698 stub_length = hdr->frag_len - offset - auth_sz;
1699 if (length > stub_length)
1700 length = stub_length;
1701 if (reported_length > stub_length)
1702 reported_length = stub_length;
1704 save_fragmented = pinfo->fragmented;
1706 /* If we don't have reassembly enabled, or this packet contains
1707 the entire PDU, or if this is a short frame (or a frame
1708 not reassembled at a lower layer) that doesn't include all
1709 the data in the fragment, just call the handoff directly if
1710 this is the first fragment or the PDU isn't fragmented. */
1711 if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
1712 stub_length > length ){
1713 if(hdr->flags&PFC_FIRST_FRAG){
1714 /* First fragment, possibly the only fragment */
1715 pinfo->fragmented = !PFC_NOT_FRAGMENTED(hdr);
1716 dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
1717 tvb_new_subset (tvb, offset, length,
1719 0, hdr->drep, di, auth_level);
1721 /* PDU is fragmented and this isn't the first fragment */
1722 if (check_col(pinfo->cinfo, COL_INFO)) {
1723 col_append_fstr(pinfo->cinfo, COL_INFO,
1724 " [DCE/RPC fragment]");
1728 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1729 "Fragment data (%d byte%s)", length,
1730 plurality(length, "", "s"));
1735 /* Reassembly is enabled, the PDU is fragmented, and
1736 we have all the data in the fragment; the first two
1737 of those mean we should attempt reassembly, and the
1738 third means we can attempt reassembly. */
1741 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1742 "Fragment data (%d byte%s)", length,
1743 plurality(length, "", "s"));
1746 if(hdr->flags&PFC_FIRST_FRAG){ /* FIRST fragment */
1747 if( (!pinfo->fd->flags.visited) && frame){
1748 fragment_add(tvb, offset, pinfo, frame,
1749 dcerpc_co_reassemble_table,
1753 fragment_set_tot_len(pinfo, frame,
1754 dcerpc_co_reassemble_table, alloc_hint);
1756 if (check_col(pinfo->cinfo, COL_INFO)) {
1757 col_append_fstr(pinfo->cinfo, COL_INFO,
1758 " [DCE/RPC fragment]");
1760 } else if(hdr->flags&PFC_LAST_FRAG){ /* LAST fragment */
1762 fragment_data *fd_head;
1765 tot_len = fragment_get_tot_len(pinfo, frame,
1766 dcerpc_co_reassemble_table);
1767 fd_head = fragment_add(tvb, offset, pinfo,
1769 dcerpc_co_reassemble_table,
1775 /* We completed reassembly */
1778 next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
1779 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1780 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
1781 show_fragment_tree(fd_head, &dcerpc_frag_items,
1782 dcerpc_tree, pinfo, next_tvb);
1784 pinfo->fragmented = FALSE;
1785 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
1786 0, hdr->drep, di, auth_level);
1788 /* Reassembly not complete - some fragments
1790 if (check_col(pinfo->cinfo, COL_INFO)) {
1791 col_append_fstr(pinfo->cinfo, COL_INFO,
1792 " [DCE/RPC fragment]");
1796 } else { /* MIDDLE fragment(s) */
1797 if( (!pinfo->fd->flags.visited) && frame ){
1799 tot_len = fragment_get_tot_len(pinfo, frame,
1800 dcerpc_co_reassemble_table);
1801 fragment_add(tvb, offset, pinfo, frame,
1802 dcerpc_co_reassemble_table,
1807 if (check_col(pinfo->cinfo, COL_INFO)) {
1808 col_append_fstr(pinfo->cinfo, COL_INFO,
1809 " [DCE/RPC fragment]");
1813 pinfo->fragmented = save_fragmented;
1817 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1818 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
1820 conversation_t *conv;
1830 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1831 hf_dcerpc_cn_alloc_hint, &alloc_hint);
1833 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1834 hf_dcerpc_cn_ctx_id, &ctx_id);
1836 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1837 hf_dcerpc_opnum, &opnum);
1839 if (check_col (pinfo->cinfo, COL_INFO)) {
1840 col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
1844 if (hdr->flags & PFC_OBJECT_UUID) {
1845 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
1847 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
1849 "Object UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1850 obj_id.Data1, obj_id.Data2, obj_id.Data3,
1864 * XXX - what if this was set when the connection was set up,
1865 * and we just have a security context?
1867 auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
1870 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1871 pinfo->srcport, pinfo->destport, 0);
1875 dcerpc_call_value *value;
1877 /* !!! we can NOT check flags.visited here since this will interact
1878 badly with when SMB handles (i.e. calls the subdissector)
1879 and desegmented pdu's .
1880 Instead we check if this pdu is already in the matched table or not
1882 if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
1883 dcerpc_bind_key bind_key;
1884 dcerpc_bind_value *bind_value;
1887 bind_key.ctx_id=ctx_id;
1888 bind_key.smb_fid=get_smb_fid(pinfo->private_data);
1890 if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key))){
1891 dcerpc_call_key *call_key;
1892 dcerpc_call_value *call_value;
1894 /* We found the binding so just add the call
1895 to both the call table and the matched table
1897 call_key=g_mem_chunk_alloc (dcerpc_call_key_chunk);
1898 call_key->conv=conv;
1899 call_key->call_id=hdr->call_id;
1900 call_key->smb_fid=get_smb_fid(pinfo->private_data);
1902 /* if there is already a matching call in the table
1903 remove it so it is replaced with the new one */
1904 if(g_hash_table_lookup(dcerpc_calls, call_key)){
1905 g_hash_table_remove(dcerpc_calls, call_key);
1908 call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
1909 call_value->uuid = bind_value->uuid;
1910 call_value->ver = bind_value->ver;
1911 call_value->opnum = opnum;
1912 call_value->req_frame=pinfo->fd->num;
1913 call_value->rep_frame=0;
1914 call_value->max_ptr=0;
1915 call_value->private_data = NULL;
1916 g_hash_table_insert (dcerpc_calls, call_key, call_value);
1918 g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
1922 value=g_hash_table_lookup (dcerpc_matched, (void *)pinfo->fd->num);
1927 /* handoff this call */
1929 di.call_id = hdr->call_id;
1930 di.smb_fid = get_smb_fid(pinfo->private_data);
1932 di.call_data = value;
1934 if(value->rep_frame!=0){
1935 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
1936 tvb, 0, 0, value->rep_frame);
1939 dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
1940 hdr, &di, auth_sz, auth_level, alloc_hint,
1943 length = tvb_length_remaining (tvb, offset);
1945 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1946 "Stub data (%d byte%s)", length,
1947 plurality(length, "", "s"));
1954 dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1955 proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
1957 dcerpc_call_value *value = NULL;
1958 conversation_t *conv;
1966 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1967 hf_dcerpc_cn_alloc_hint, &alloc_hint);
1969 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1970 hf_dcerpc_cn_ctx_id, &ctx_id);
1972 if (check_col (pinfo->cinfo, COL_INFO)) {
1973 col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
1976 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1977 hf_dcerpc_cn_cancel_count, NULL);
1982 * XXX - what if this was set when the connection was set up,
1983 * and we just have a security context?
1985 auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
1988 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1989 pinfo->srcport, pinfo->destport, 0);
1991 /* no point in creating one here, really */
1994 /* !!! we can NOT check flags.visited here since this will interact
1995 badly with when SMB handles (i.e. calls the subdissector)
1996 and desegmented pdu's .
1997 Instead we check if this pdu is already in the matched table or not
1999 if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
2000 dcerpc_call_key call_key;
2001 dcerpc_call_value *call_value;
2004 call_key.call_id=hdr->call_id;
2005 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2007 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2008 g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2009 if(call_value->rep_frame==0){
2010 call_value->rep_frame=pinfo->fd->num;
2016 value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2021 /* handoff this call */
2023 di.call_id = hdr->call_id;
2024 di.smb_fid = get_smb_fid(pinfo->private_data);
2026 di.call_data = value;
2028 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2029 if(value->req_frame!=0){
2030 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2031 tvb, 0, 0, value->req_frame);
2034 dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
2035 hdr, &di, auth_sz, auth_level, alloc_hint,
2038 length = tvb_length_remaining (tvb, offset);
2040 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2041 "Stub data (%d byte%s)", length,
2042 plurality(length, "", "s"));
2049 dissect_dcerpc_cn_fault (tvbuff_t *tvb, packet_info *pinfo,
2050 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2052 dcerpc_call_value *value = NULL;
2053 conversation_t *conv;
2061 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2062 hf_dcerpc_cn_alloc_hint, &alloc_hint);
2064 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2065 hf_dcerpc_cn_ctx_id, &ctx_id);
2067 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2068 hf_dcerpc_cn_cancel_count, NULL);
2072 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2073 hf_dcerpc_cn_status, &status);
2075 if (check_col (pinfo->cinfo, COL_INFO)) {
2076 col_append_fstr (pinfo->cinfo, COL_INFO,
2077 " ctx_id: %u status: %s", ctx_id,
2078 val_to_str(status, reject_status_vals,
2079 "Unknown (0x%08x)"));
2086 * XXX - what if this was set when the connection was set up,
2087 * and we just have a security context?
2089 auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
2092 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2093 pinfo->srcport, pinfo->destport, 0);
2095 /* no point in creating one here, really */
2098 /* !!! we can NOT check flags.visited here since this will interact
2099 badly with when SMB handles (i.e. calls the subdissector)
2100 and desegmented pdu's .
2101 Instead we check if this pdu is already in the matched table or not
2103 if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
2104 dcerpc_call_key call_key;
2105 dcerpc_call_value *call_value;
2108 call_key.call_id=hdr->call_id;
2109 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2111 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2112 g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2113 if(call_value->rep_frame==0){
2114 call_value->rep_frame=pinfo->fd->num;
2120 value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2123 int length, reported_length, stub_length;
2126 /* handoff this call */
2128 di.call_id = hdr->call_id;
2129 di.smb_fid = get_smb_fid(pinfo->private_data);
2131 di.call_data = value;
2133 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2134 if(value->req_frame!=0){
2135 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2136 tvb, 0, 0, value->req_frame);
2139 length = tvb_length_remaining(tvb, offset);
2140 reported_length = tvb_reported_length_remaining(tvb, offset);
2141 stub_length = hdr->frag_len - offset - auth_sz;
2142 if (length > stub_length)
2143 length = stub_length;
2144 if (reported_length > stub_length)
2145 reported_length = stub_length;
2147 /* If we don't have reassembly enabled, or this packet contains
2148 the entire PDU, or if this is a short frame (or a frame
2149 not reassembled at a lower layer) that doesn't include all
2150 the data in the fragment, just call the handoff directly if
2151 this is the first fragment or the PDU isn't fragmented. */
2152 if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
2153 stub_length > length ){
2154 if(hdr->flags&PFC_FIRST_FRAG){
2155 /* First fragment, possibly the only fragment */
2157 * XXX - should there be a third routine for each
2158 * function in an RPC subdissector, to handle
2159 * fault responses? The DCE RPC 1.1 spec says
2160 * three's "stub data" here, which I infer means
2161 * that it's protocol-specific and call-specific.
2163 * It should probably get passed the status code
2164 * as well, as that might be protocol-specific.
2168 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2169 "Fault stub data (%d byte%s)", length,
2170 plurality(length, "", "s"));
2174 /* PDU is fragmented and this isn't the first fragment */
2175 if (check_col(pinfo->cinfo, COL_INFO)) {
2176 col_append_fstr(pinfo->cinfo, COL_INFO,
2177 " [DCE/RPC fragment]");
2181 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2182 "Fragment data (%d byte%s)", length,
2183 plurality(length, "", "s"));
2188 /* Reassembly is enabled, the PDU is fragmented, and
2189 we have all the data in the fragment; the first two
2190 of those mean we should attempt reassembly, and the
2191 third means we can attempt reassembly. */
2194 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2195 "Fragment data (%d byte%s)", length,
2196 plurality(length, "", "s"));
2199 if(hdr->flags&PFC_FIRST_FRAG){ /* FIRST fragment */
2200 if( (!pinfo->fd->flags.visited) && value->rep_frame ){
2201 fragment_add(tvb, offset, pinfo, value->rep_frame,
2202 dcerpc_co_reassemble_table,
2206 fragment_set_tot_len(pinfo, value->rep_frame,
2207 dcerpc_co_reassemble_table, alloc_hint);
2209 if (check_col(pinfo->cinfo, COL_INFO)) {
2210 col_append_fstr(pinfo->cinfo, COL_INFO,
2211 " [DCE/RPC fragment]");
2213 } else if(hdr->flags&PFC_LAST_FRAG){ /* LAST fragment */
2214 if( value->rep_frame ){
2215 fragment_data *fd_head;
2218 tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
2219 dcerpc_co_reassemble_table);
2220 fd_head = fragment_add(tvb, offset, pinfo,
2222 dcerpc_co_reassemble_table,
2228 /* We completed reassembly */
2231 next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
2232 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2233 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2234 show_fragment_tree(fd_head, &dcerpc_frag_items,
2235 dcerpc_tree, pinfo, next_tvb);
2238 * XXX - should there be a third routine for each
2239 * function in an RPC subdissector, to handle
2240 * fault responses? The DCE RPC 1.1 spec says
2241 * three's "stub data" here, which I infer means
2242 * that it's protocol-specific and call-specific.
2244 * It should probably get passed the status code
2245 * as well, as that might be protocol-specific.
2249 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2250 "Fault stub data (%d byte%s)", length,
2251 plurality(length, "", "s"));
2255 /* Reassembly not complete - some fragments
2257 if (check_col(pinfo->cinfo, COL_INFO)) {
2258 col_append_fstr(pinfo->cinfo, COL_INFO,
2259 " [DCE/RPC fragment]");
2263 } else { /* MIDDLE fragment(s) */
2264 if( (!pinfo->fd->flags.visited) && value->rep_frame ){
2266 tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
2267 dcerpc_co_reassemble_table);
2268 fragment_add(tvb, offset, pinfo, value->rep_frame,
2269 dcerpc_co_reassemble_table,
2274 if (check_col(pinfo->cinfo, COL_INFO)) {
2275 col_append_fstr(pinfo->cinfo, COL_INFO,
2276 " [DCE/RPC fragment]");
2285 * DCERPC dissector for connection oriented calls
2288 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
2289 proto_tree *tree, gboolean can_desegment)
2291 static char nulls[4] = { 0 };
2294 proto_item *ti = NULL;
2295 proto_item *tf = NULL;
2296 proto_tree *dcerpc_tree = NULL;
2297 proto_tree *cn_flags_tree = NULL;
2298 proto_tree *drep_tree = NULL;
2299 e_dce_cn_common_hdr_t hdr;
2302 * when done over nbt, dcerpc requests are padded with 4 bytes of null
2303 * data for some reason.
2305 * XXX - if that's always the case, the right way to do this would
2306 * be to have a "dissect_dcerpc_cn_nb" routine which strips off
2307 * the 4 bytes of null padding, and make that the dissector
2308 * used for "netbios".
2310 if (tvb_bytes_exist (tvb, offset, 4) &&
2311 tvb_memeql (tvb, offset, nulls, 4) == 0) {
2321 * Check if this looks like a C/O DCERPC call
2323 if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
2326 start_offset = offset;
2327 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
2328 if (hdr.rpc_ver != 5)
2330 hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
2331 if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
2333 hdr.ptype = tvb_get_guint8 (tvb, offset++);
2337 if (check_col (pinfo->cinfo, COL_PROTOCOL))
2338 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
2339 if (check_col (pinfo->cinfo, COL_INFO))
2340 col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
2342 hdr.flags = tvb_get_guint8 (tvb, offset++);
2343 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
2344 offset += sizeof (hdr.drep);
2346 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2348 hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2350 hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
2353 offset = start_offset;
2354 if (can_desegment && pinfo->can_desegment
2355 && hdr.frag_len > tvb_length_remaining (tvb, offset)) {
2356 pinfo->desegment_offset = offset;
2357 pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, offset);
2358 return 0; /* desegmentation required */
2361 if (check_col (pinfo->cinfo, COL_INFO))
2362 col_append_fstr (pinfo->cinfo, COL_INFO, ": call_id: %u", hdr.call_id);
2364 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
2366 dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
2368 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
2369 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
2370 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
2371 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
2372 cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
2373 if (cn_flags_tree) {
2374 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
2375 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
2376 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
2377 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
2378 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
2379 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
2380 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
2381 proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
2385 tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
2386 drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
2388 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
2389 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
2390 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
2392 offset += sizeof (hdr.drep);
2394 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
2397 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
2400 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
2406 * Packet type specific stuff is next.
2408 switch (hdr.ptype) {
2411 dissect_dcerpc_cn_bind (tvb, pinfo, dcerpc_tree, &hdr);
2416 dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
2420 dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
2424 dissect_dcerpc_cn_resp (tvb, pinfo, dcerpc_tree, tree, &hdr);
2428 dissect_dcerpc_cn_fault (tvb, pinfo, dcerpc_tree, &hdr);
2432 dissect_dcerpc_cn_bind_nak (tvb, pinfo, dcerpc_tree, &hdr);
2438 * Nothing after the common header other than an authentication
2441 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL);
2446 * Nothing after the common header, not even an authentication
2452 /* might as well dissect the auth info */
2453 dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL);
2456 return hdr.frag_len + padding;
2460 * DCERPC dissector for connection oriented calls over packet-oriented
2464 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2467 * Only one PDU per transport packet, and only one transport
2470 if (dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE) == -1) {
2472 * It wasn't a DCERPC PDU.
2484 * DCERPC dissector for connection oriented calls over byte-stream
2488 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2492 gboolean ret = FALSE;
2495 * There may be multiple PDUs per transport packet; keep
2498 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2499 pdu_len = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
2500 dcerpc_cn_desegment);
2501 if (pdu_len == -1) {
2509 * Well, we've seen at least one DCERPC PDU.
2515 * Desegmentation required - bail now.
2521 * Step to the next PDU.
2529 dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
2530 e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
2533 * Initially set "*auth_level_p" to -1 to indicate that we haven't
2534 * yet seen any authentication level information.
2536 if (auth_level_p != NULL)
2540 * The authentication information is at the *end* of the PDU; in
2541 * request and response PDUs, the request and response stub data
2544 * If the full packet is here, and there's data past the end of the
2545 * packet body, then dissect the auth info.
2547 offset += hdr->frag_len;
2548 if (tvb_length_remaining(tvb, offset) > 0)
2549 proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Auth data");
2553 dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
2554 proto_tree *dcerpc_tree,
2555 e_dce_dg_common_hdr_t *hdr)
2559 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2560 hdr->drep, hf_dcerpc_dg_cancel_vers,
2566 /* The only version we know about */
2567 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2568 hdr->drep, hf_dcerpc_dg_cancel_id,
2570 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2571 hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
2578 dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
2579 proto_tree *dcerpc_tree,
2580 e_dce_dg_common_hdr_t *hdr)
2584 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2585 hdr->drep, hf_dcerpc_dg_cancel_vers,
2591 /* The only version we know about */
2592 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2593 hdr->drep, hf_dcerpc_dg_cancel_id,
2595 /* XXX - are NDR booleans 32 bits? */
2596 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2597 hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
2604 dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
2605 proto_tree *dcerpc_tree,
2606 e_dce_dg_common_hdr_t *hdr)
2613 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2614 hdr->drep, hf_dcerpc_dg_fack_vers,
2621 case 0: /* The only version documented in the DCE RPC 1.1 spec */
2622 case 1: /* This appears to be the same */
2623 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2624 hdr->drep, hf_dcerpc_dg_fack_window_size,
2626 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2627 hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
2629 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2630 hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
2632 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2633 hdr->drep, hf_dcerpc_dg_fack_serial_num,
2635 if (check_col (pinfo->cinfo, COL_INFO)) {
2636 col_append_fstr (pinfo->cinfo, COL_INFO, " serial_num: %u",
2639 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2640 hdr->drep, hf_dcerpc_dg_fack_selack_len,
2642 for (i = 0; i < selack_len; i++) {
2643 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2644 hdr->drep, hf_dcerpc_dg_fack_selack,
2653 dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
2654 proto_tree *dcerpc_tree,
2655 e_dce_dg_common_hdr_t *hdr)
2659 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2660 hdr->drep, hf_dcerpc_dg_status,
2663 if (check_col (pinfo->cinfo, COL_INFO)) {
2664 col_append_fstr (pinfo->cinfo, COL_INFO,
2666 val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
2671 dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2672 proto_tree *dcerpc_tree, proto_tree *tree,
2673 e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
2675 int length, reported_length, stub_length;
2676 gboolean save_fragmented;
2677 fragment_data *fd_head;
2679 if (check_col (pinfo->cinfo, COL_INFO)) {
2680 col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u",
2681 di->call_data->opnum);
2684 length = tvb_length_remaining (tvb, offset);
2685 reported_length = tvb_reported_length_remaining (tvb, offset);
2686 stub_length = hdr->frag_len;
2687 if (length > stub_length)
2688 length = stub_length;
2689 if (reported_length > stub_length)
2690 reported_length = stub_length;
2692 save_fragmented = pinfo->fragmented;
2694 /* If we don't have reassembly enabled, or this packet contains
2695 the entire PDU, or if this is a short frame (or a frame
2696 not reassembled at a lower layer) that doesn't include all
2697 the data in the fragment, just call the handoff directly if
2698 this is the first fragment or the PDU isn't fragmented. */
2699 if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
2700 stub_length > length ) {
2701 if(hdr->frag_num == 0) {
2702 /* First fragment, possibly the only fragment */
2705 * XXX - authentication level?
2707 pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
2708 dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
2709 tvb_new_subset (tvb, offset, length,
2711 0, hdr->drep, di, 0);
2713 /* PDU is fragmented and this isn't the first fragment */
2714 if (check_col(pinfo->cinfo, COL_INFO)) {
2715 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
2719 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2720 "Fragment data (%d byte%s)", length,
2721 plurality(length, "", "s"));
2726 /* Reassembly is enabled, the PDU is fragmented, and
2727 we have all the data in the fragment; the first two
2728 of those mean we should attempt reassembly, and the
2729 third means we can attempt reassembly. */
2732 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2733 "Fragment data (%d byte%s)", length,
2734 plurality(length, "", "s"));
2738 fd_head = fragment_add_seq(tvb, offset, pinfo,
2739 hdr->seqnum, dcerpc_cl_reassemble_table,
2740 hdr->frag_num, length, !(hdr->flags1 & PFCL1_LASTFRAG));
2741 if (fd_head != NULL) {
2742 /* We completed reassembly */
2745 next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
2746 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2747 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2748 show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
2749 dcerpc_tree, pinfo, next_tvb);
2752 * XXX - authentication level?
2754 pinfo->fragmented = FALSE;
2755 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
2756 0, hdr->drep, di, 0);
2758 /* Reassembly isn't completed yet */
2759 if (check_col(pinfo->cinfo, COL_INFO)) {
2760 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
2764 pinfo->fragmented = save_fragmented;
2768 dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
2769 proto_tree *dcerpc_tree, proto_tree *tree,
2770 e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
2773 dcerpc_call_value *value, v;
2775 if(!(pinfo->fd->flags.visited)){
2776 dcerpc_call_value *call_value;
2777 dcerpc_call_key *call_key;
2779 call_key=g_mem_chunk_alloc (dcerpc_call_key_chunk);
2780 call_key->conv=conv;
2781 call_key->call_id=hdr->seqnum;
2782 call_key->smb_fid=get_smb_fid(pinfo->private_data);
2784 call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
2785 call_value->uuid = hdr->if_id;
2786 call_value->ver = hdr->if_ver;
2787 call_value->opnum = hdr->opnum;
2788 call_value->req_frame=pinfo->fd->num;
2789 call_value->rep_frame=0;
2790 call_value->max_ptr=0;
2791 call_value->private_data = NULL;
2792 g_hash_table_insert (dcerpc_calls, call_key, call_value);
2794 g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2797 value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2799 v.uuid = hdr->if_id;
2800 v.ver = hdr->if_ver;
2801 v.opnum = hdr->opnum;
2802 v.req_frame = pinfo->fd->num;
2805 v.private_data=NULL;
2810 di.call_id = hdr->seqnum;
2813 di.call_data = value;
2815 dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
2819 dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
2820 proto_tree *dcerpc_tree, proto_tree *tree,
2821 e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
2824 dcerpc_call_value *value, v;
2826 if(!(pinfo->fd->flags.visited)){
2827 dcerpc_call_value *call_value;
2828 dcerpc_call_key call_key;
2831 call_key.call_id=hdr->seqnum;
2832 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2834 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2835 g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2836 if(call_value->rep_frame==0){
2837 call_value->rep_frame=pinfo->fd->num;
2842 value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2844 v.uuid = hdr->if_id;
2845 v.ver = hdr->if_ver;
2846 v.opnum = hdr->opnum;
2848 v.rep_frame=pinfo->fd->num;
2849 v.private_data=NULL;
2857 di.call_data = value;
2859 dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
2863 * DCERPC dissector for connectionless calls
2866 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2868 proto_item *ti = NULL;
2869 proto_item *tf = NULL;
2870 proto_tree *dcerpc_tree = NULL;
2871 proto_tree *dg_flags1_tree = NULL;
2872 proto_tree *dg_flags2_tree = NULL;
2873 proto_tree *drep_tree = NULL;
2874 e_dce_dg_common_hdr_t hdr;
2876 conversation_t *conv;
2879 * Check if this looks like a CL DCERPC call. All dg packets
2880 * have an 80 byte header on them. Which starts with
2881 * version (4), pkt_type.
2883 if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
2886 hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
2887 if (hdr.rpc_ver != 4)
2889 hdr.ptype = tvb_get_guint8 (tvb, offset++);
2893 if (check_col (pinfo->cinfo, COL_PROTOCOL))
2894 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
2895 if (check_col (pinfo->cinfo, COL_INFO))
2896 col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
2898 hdr.flags1 = tvb_get_guint8 (tvb, offset++);
2899 hdr.flags2 = tvb_get_guint8 (tvb, offset++);
2900 tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
2901 offset += sizeof (hdr.drep);
2902 hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
2903 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
2905 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
2907 dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
2909 hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
2911 hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
2913 hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
2915 hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2917 hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2919 hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2921 hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2923 hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2925 hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
2926 hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
2929 ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
2931 dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
2937 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
2941 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
2945 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
2946 dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
2947 if (dg_flags1_tree) {
2948 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
2949 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
2950 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
2951 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
2952 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
2953 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
2954 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
2955 proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
2961 tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
2962 dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
2963 if (dg_flags2_tree) {
2964 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
2965 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
2966 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
2967 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
2968 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
2969 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
2970 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
2971 proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
2977 tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
2978 drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
2980 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
2981 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
2982 proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
2985 offset += sizeof (hdr.drep);
2988 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
2992 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
2994 "Object: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2995 hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
2996 hdr.obj_id.Data4[0],
2997 hdr.obj_id.Data4[1],
2998 hdr.obj_id.Data4[2],
2999 hdr.obj_id.Data4[3],
3000 hdr.obj_id.Data4[4],
3001 hdr.obj_id.Data4[5],
3002 hdr.obj_id.Data4[6],
3003 hdr.obj_id.Data4[7]);
3008 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
3010 "Interface: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3011 hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
3019 hdr.if_id.Data4[7]);
3024 proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
3026 "Activity: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3027 hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
3028 hdr.act_id.Data4[0],
3029 hdr.act_id.Data4[1],
3030 hdr.act_id.Data4[2],
3031 hdr.act_id.Data4[3],
3032 hdr.act_id.Data4[4],
3033 hdr.act_id.Data4[5],
3034 hdr.act_id.Data4[6],
3035 hdr.act_id.Data4[7]);
3040 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_server_boot, tvb, offset, 4, hdr.server_boot);
3044 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
3048 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
3049 if (check_col (pinfo->cinfo, COL_INFO)) {
3050 col_append_fstr (pinfo->cinfo, COL_INFO, ": seq_num: %u", hdr.seqnum);
3055 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
3059 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
3063 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
3067 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
3071 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
3072 if (check_col (pinfo->cinfo, COL_INFO)) {
3073 if (hdr.flags1 & PFCL1_FRAG) {
3074 /* Fragmented - put the fragment number into the Info column */
3075 col_append_fstr (pinfo->cinfo, COL_INFO, " frag_num: %u",
3082 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
3086 proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
3087 if (check_col (pinfo->cinfo, COL_INFO)) {
3088 if (hdr.flags1 & PFCL1_FRAG) {
3089 /* Fragmented - put the serial number into the Info column */
3090 col_append_fstr (pinfo->cinfo, COL_INFO, " serial_num: %u",
3091 (hdr.serial_hi << 8) | hdr.serial_lo);
3098 * XXX - for Kerberos, we can get a protection level; if it's
3099 * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
3102 dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr, NULL);
3106 * keeping track of the conversation shouldn't really be necessary
3107 * for connectionless packets, because everything we need to know
3108 * to dissect is in the header for each packet. Unfortunately,
3109 * Microsoft's implementation is buggy and often puts the
3110 * completely wrong if_id in the header. go figure. So, keep
3111 * track of the seqnum and use that if possible. Note: that's not
3112 * completely correct. It should really be done based on both the
3113 * activity_id and seqnum. I haven't seen anywhere that it would
3114 * make a difference, but for future reference...
3116 conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
3117 pinfo->srcport, pinfo->destport, 0);
3119 conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
3120 pinfo->srcport, pinfo->destport, 0);
3124 * Packet type specific stuff is next.
3127 switch (hdr.ptype) {
3129 case PDU_CANCEL_ACK:
3130 /* Body is optional */
3131 /* XXX - we assume "frag_len" is the length of the body */
3132 if (hdr.frag_len != 0)
3133 dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3138 * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
3139 * but in at least one capture none of the Cl_cancel PDUs had a
3142 /* XXX - we assume "frag_len" is the length of the body */
3143 if (hdr.frag_len != 0)
3144 dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
3148 /* Body is optional; if present, it's the same as PDU_FACK */
3149 /* XXX - we assume "frag_len" is the length of the body */
3150 if (hdr.frag_len != 0)
3151 dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3155 dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3160 dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
3164 dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
3168 dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
3171 /* these requests have no body */
3183 dcerpc_init_protocol (void)
3185 /* structures and data for BIND */
3187 g_hash_table_destroy (dcerpc_binds);
3189 dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
3191 if (dcerpc_bind_key_chunk){
3192 g_mem_chunk_destroy (dcerpc_bind_key_chunk);
3194 dcerpc_bind_key_chunk = g_mem_chunk_new ("dcerpc_bind_key_chunk",
3195 sizeof (dcerpc_bind_key),
3196 200 * sizeof (dcerpc_bind_key),
3198 if (dcerpc_bind_value_chunk){
3199 g_mem_chunk_destroy (dcerpc_bind_value_chunk);
3201 dcerpc_bind_value_chunk = g_mem_chunk_new ("dcerpc_bind_value_chunk",
3202 sizeof (dcerpc_bind_value),
3203 200 * sizeof (dcerpc_bind_value),
3205 /* structures and data for CALL */
3207 g_hash_table_destroy (dcerpc_calls);
3209 dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
3210 if (dcerpc_call_key_chunk){
3211 g_mem_chunk_destroy (dcerpc_call_key_chunk);
3213 dcerpc_call_key_chunk = g_mem_chunk_new ("dcerpc_call_key_chunk",
3214 sizeof (dcerpc_call_key),
3215 200 * sizeof (dcerpc_call_key),
3217 if (dcerpc_call_value_chunk){
3218 g_mem_chunk_destroy (dcerpc_call_value_chunk);
3220 dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
3221 sizeof (dcerpc_call_value),
3222 200 * sizeof (dcerpc_call_value),
3225 /* structure and data for MATCHED */
3226 if (dcerpc_matched){
3227 g_hash_table_destroy (dcerpc_matched);
3229 dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
3234 proto_register_dcerpc (void)
3236 static hf_register_info hf[] = {
3237 { &hf_dcerpc_request_in,
3238 { "Request in", "dcerpc.request_in", FT_UINT32, BASE_DEC,
3239 NULL, 0, "This packet is a response to the packet in this frame", HFILL }},
3240 { &hf_dcerpc_response_in,
3241 { "Response in", "dcerpc.response_in", FT_UINT32, BASE_DEC,
3242 NULL, 0, "The response to this packet is in this packet", HFILL }},
3243 { &hf_dcerpc_referent_id,
3244 { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
3245 NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
3247 { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3248 { &hf_dcerpc_ver_minor,
3249 { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3250 { &hf_dcerpc_packet_type,
3251 { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, "", HFILL }},
3252 { &hf_dcerpc_cn_flags,
3253 { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3254 { &hf_dcerpc_cn_flags_first_frag,
3255 { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_FIRST_FRAG, "", HFILL }},
3256 { &hf_dcerpc_cn_flags_last_frag,
3257 { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_LAST_FRAG, "", HFILL }},
3258 { &hf_dcerpc_cn_flags_cancel_pending,
3259 { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_PENDING_CANCEL, "", HFILL }},
3260 { &hf_dcerpc_cn_flags_reserved,
3261 { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_RESERVED_1, "", HFILL }},
3262 { &hf_dcerpc_cn_flags_mpx,
3263 { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_CONC_MPX, "", HFILL }},
3264 { &hf_dcerpc_cn_flags_dne,
3265 { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_DID_NOT_EXECUTE, "", HFILL }},
3266 { &hf_dcerpc_cn_flags_maybe,
3267 { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_MAYBE, "", HFILL }},
3268 { &hf_dcerpc_cn_flags_object,
3269 { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_OBJECT_UUID, "", HFILL }},
3271 { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
3272 { &hf_dcerpc_drep_byteorder,
3273 { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, "", HFILL }},
3274 { &hf_dcerpc_drep_character,
3275 { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, "", HFILL }},
3276 { &hf_dcerpc_drep_fp,
3277 { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, "", HFILL }},
3278 { &hf_dcerpc_cn_frag_len,
3279 { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3280 { &hf_dcerpc_cn_auth_len,
3281 { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3282 { &hf_dcerpc_cn_call_id,
3283 { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3284 { &hf_dcerpc_cn_max_xmit,
3285 { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3286 { &hf_dcerpc_cn_max_recv,
3287 { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3288 { &hf_dcerpc_cn_assoc_group,
3289 { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3290 { &hf_dcerpc_cn_num_ctx_items,
3291 { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3292 { &hf_dcerpc_cn_ctx_id,
3293 { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3294 { &hf_dcerpc_cn_num_trans_items,
3295 { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3296 { &hf_dcerpc_cn_bind_if_id,
3297 { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3298 { &hf_dcerpc_cn_bind_if_ver,
3299 { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3300 { &hf_dcerpc_cn_bind_if_ver_minor,
3301 { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3302 { &hf_dcerpc_cn_bind_trans_id,
3303 { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3304 { &hf_dcerpc_cn_bind_trans_ver,
3305 { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3306 { &hf_dcerpc_cn_alloc_hint,
3307 { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3308 { &hf_dcerpc_cn_sec_addr_len,
3309 { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3310 { &hf_dcerpc_cn_sec_addr,
3311 { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, "", HFILL }},
3312 { &hf_dcerpc_cn_num_results,
3313 { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3314 { &hf_dcerpc_cn_ack_result,
3315 { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, "", HFILL }},
3316 { &hf_dcerpc_cn_ack_reason,
3317 { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, "", HFILL }},
3318 { &hf_dcerpc_cn_ack_trans_id,
3319 { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3320 { &hf_dcerpc_cn_ack_trans_ver,
3321 { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3322 { &hf_dcerpc_cn_reject_reason,
3323 { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, "", HFILL }},
3324 { &hf_dcerpc_cn_num_protocols,
3325 { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3326 { &hf_dcerpc_cn_protocol_ver_major,
3327 { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3328 { &hf_dcerpc_cn_protocol_ver_minor,
3329 { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3330 { &hf_dcerpc_cn_cancel_count,
3331 { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3332 { &hf_dcerpc_cn_status,
3333 { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
3334 { &hf_dcerpc_auth_type,
3335 { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
3336 { &hf_dcerpc_auth_level,
3337 { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, "", HFILL }},
3338 { &hf_dcerpc_auth_pad_len,
3339 { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3340 { &hf_dcerpc_auth_rsrvd,
3341 { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3342 { &hf_dcerpc_auth_ctx_id,
3343 { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3344 { &hf_dcerpc_dg_flags1,
3345 { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3346 { &hf_dcerpc_dg_flags1_rsrvd_01,
3347 { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_01, "", HFILL }},
3348 { &hf_dcerpc_dg_flags1_last_frag,
3349 { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_LASTFRAG, "", HFILL }},
3350 { &hf_dcerpc_dg_flags1_frag,
3351 { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_FRAG, "", HFILL }},
3352 { &hf_dcerpc_dg_flags1_nofack,
3353 { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_NOFACK, "", HFILL }},
3354 { &hf_dcerpc_dg_flags1_maybe,
3355 { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_MAYBE, "", HFILL }},
3356 { &hf_dcerpc_dg_flags1_idempotent,
3357 { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_IDEMPOTENT, "", HFILL }},
3358 { &hf_dcerpc_dg_flags1_broadcast,
3359 { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_BROADCAST, "", HFILL }},
3360 { &hf_dcerpc_dg_flags1_rsrvd_80,
3361 { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_80, "", HFILL }},
3362 { &hf_dcerpc_dg_flags2,
3363 { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3364 { &hf_dcerpc_dg_flags2_rsrvd_01,
3365 { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_01, "", HFILL }},
3366 { &hf_dcerpc_dg_flags2_cancel_pending,
3367 { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_CANCEL_PENDING, "", HFILL }},
3368 { &hf_dcerpc_dg_flags2_rsrvd_04,
3369 { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_04, "", HFILL }},
3370 { &hf_dcerpc_dg_flags2_rsrvd_08,
3371 { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_08, "", HFILL }},
3372 { &hf_dcerpc_dg_flags2_rsrvd_10,
3373 { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_10, "", HFILL }},
3374 { &hf_dcerpc_dg_flags2_rsrvd_20,
3375 { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_20, "", HFILL }},
3376 { &hf_dcerpc_dg_flags2_rsrvd_40,
3377 { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_40, "", HFILL }},
3378 { &hf_dcerpc_dg_flags2_rsrvd_80,
3379 { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_80, "", HFILL }},
3380 { &hf_dcerpc_dg_serial_lo,
3381 { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3382 { &hf_dcerpc_dg_serial_hi,
3383 { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3384 { &hf_dcerpc_dg_ahint,
3385 { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
3386 { &hf_dcerpc_dg_ihint,
3387 { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
3388 { &hf_dcerpc_dg_frag_len,
3389 { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3390 { &hf_dcerpc_dg_frag_num,
3391 { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3392 { &hf_dcerpc_dg_auth_proto,
3393 { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
3394 { &hf_dcerpc_dg_seqnum,
3395 { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3396 { &hf_dcerpc_dg_server_boot,
3397 { "Server boot time", "dcerpc.dg_server_boot", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3398 { &hf_dcerpc_dg_if_ver,
3399 { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3400 { &hf_dcerpc_obj_id,
3401 { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3402 { &hf_dcerpc_dg_if_id,
3403 { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3404 { &hf_dcerpc_dg_act_id,
3405 { "Activitiy", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3407 { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3409 { &hf_dcerpc_dg_cancel_vers,
3410 { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3412 { &hf_dcerpc_dg_cancel_id,
3413 { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3415 { &hf_dcerpc_dg_server_accepting_cancels,
3416 { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
3418 { &hf_dcerpc_dg_fack_vers,
3419 { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3421 { &hf_dcerpc_dg_fack_window_size,
3422 { "Window Size", "dcerpc.fack_window size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3424 { &hf_dcerpc_dg_fack_max_tsdu,
3425 { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3427 { &hf_dcerpc_dg_fack_max_frag_size,
3428 { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3430 { &hf_dcerpc_dg_fack_serial_num,
3431 { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3433 { &hf_dcerpc_dg_fack_selack_len,
3434 { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3436 { &hf_dcerpc_dg_fack_selack,
3437 { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3439 { &hf_dcerpc_dg_status,
3440 { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
3442 { &hf_dcerpc_array_max_count,
3443 { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
3445 { &hf_dcerpc_array_offset,
3446 { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
3448 { &hf_dcerpc_array_actual_count,
3449 { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
3452 { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3454 { &hf_dcerpc_fragments,
3455 { "DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
3456 NULL, 0x0, "DCE/RPC Fragments", HFILL }},
3458 { &hf_dcerpc_fragment,
3459 { "DCE/RPC Fragment", "dcerpc.fragment", FT_NONE, BASE_NONE,
3460 NULL, 0x0, "DCE/RPC Fragment", HFILL }},
3462 { &hf_dcerpc_fragment_overlap,
3463 { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
3465 { &hf_dcerpc_fragment_overlap_conflict,
3466 { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
3468 { &hf_dcerpc_fragment_multiple_tails,
3469 { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
3471 { &hf_dcerpc_fragment_too_long_fragment,
3472 { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
3474 { &hf_dcerpc_fragment_error,
3475 { "Defragmentation error", "dcerpc.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
3478 static gint *ett[] = {
3480 &ett_dcerpc_cn_flags,
3482 &ett_dcerpc_dg_flags1,
3483 &ett_dcerpc_dg_flags2,
3484 &ett_dcerpc_pointer_data,
3485 &ett_dcerpc_fragments,
3486 &ett_dcerpc_fragment,
3488 module_t *dcerpc_module;
3490 proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
3491 proto_register_field_array (proto_dcerpc, hf, array_length (hf));
3492 proto_register_subtree_array (ett, array_length (ett));
3493 register_init_routine (dcerpc_init_protocol);
3494 dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
3495 prefs_register_bool_preference (dcerpc_module,
3497 "Desegment all DCE/RPC over TCP",
3498 "Whether the DCE/RPC dissector should desegment all DCE/RPC over TCP",
3499 &dcerpc_cn_desegment);
3500 prefs_register_bool_preference (dcerpc_module,
3501 "reassemble_dcerpc",
3502 "Reassemble DCE/RPC fragments",
3503 "Whether the DCE/RPC dissector should reassemble all fragmented PDUs",
3504 &dcerpc_reassemble);
3505 register_init_routine(dcerpc_reassemble_init);
3506 dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
3510 proto_reg_handoff_dcerpc (void)
3512 heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
3513 heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
3514 heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
3515 heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc);
3516 ntlmssp_handle = find_dissector("ntlmssp");