patch_netlogon_260709
[metze/wireshark/wip.git] / epan / dissectors / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  * Copyright 2003, Tim Potter <tpot@samba.org>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /* The DCE RPC specification can be found at:
28  * http://www.opengroup.org/dce/
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38
39 #include <glib.h>
40 #include <epan/packet.h>
41 #include <epan/dissectors/packet-dcerpc.h>
42 #include <epan/conversation.h>
43 #include <epan/prefs.h>
44 #include <epan/reassemble.h>
45 #include <epan/tap.h>
46 #include <epan/emem.h>
47 #include <epan/dissectors/packet-frame.h>
48 #include <epan/dissectors/packet-dcerpc-nt.h>
49 #include <epan/expert.h>
50 #include <epan/strutil.h>
51
52 static int dcerpc_tap = -1;
53
54
55 static const value_string pckt_vals[] = {
56     { PDU_REQ,        "Request"},
57     { PDU_PING,       "Ping"},
58     { PDU_RESP,       "Response"},
59     { PDU_FAULT,      "Fault"},
60     { PDU_WORKING,    "Working"},
61     { PDU_NOCALL,     "Nocall"},
62     { PDU_REJECT,     "Reject"},
63     { PDU_ACK,        "Ack"},
64     { PDU_CL_CANCEL,  "Cl_cancel"},
65     { PDU_FACK,       "Fack"},
66     { PDU_CANCEL_ACK, "Cancel_ack"},
67     { PDU_BIND,       "Bind"},
68     { PDU_BIND_ACK,   "Bind_ack"},
69     { PDU_BIND_NAK,   "Bind_nak"},
70     { PDU_ALTER,      "Alter_context"},
71     { PDU_ALTER_ACK,  "Alter_context_resp"},
72     { PDU_AUTH3,      "AUTH3"},
73     { PDU_SHUTDOWN,   "Shutdown"},
74     { PDU_CO_CANCEL,  "Co_cancel"},
75     { PDU_ORPHANED,   "Orphaned"},
76     { 0,              NULL }
77 };
78
79 static const value_string drep_byteorder_vals[] = {
80     { 0, "Big-endian" },
81     { 1, "Little-endian" },
82     { 0,  NULL }
83 };
84
85 static const value_string drep_character_vals[] = {
86     { 0, "ASCII" },
87     { 1, "EBCDIC" },
88     { 0,  NULL }
89 };
90
91 #define DCE_RPC_DREP_FP_IEEE 0
92 #define DCE_RPC_DREP_FP_VAX  1
93 #define DCE_RPC_DREP_FP_CRAY 2
94 #define DCE_RPC_DREP_FP_IBM  3
95
96 static const value_string drep_fp_vals[] = {
97     { DCE_RPC_DREP_FP_IEEE, "IEEE" },
98     { DCE_RPC_DREP_FP_VAX,  "VAX"  },
99     { DCE_RPC_DREP_FP_CRAY, "Cray" },
100     { DCE_RPC_DREP_FP_IBM,  "IBM"  },
101     { 0,  NULL }
102 };
103
104 /*
105  * Authentication services.
106  */
107 static const value_string authn_protocol_vals[] = {
108         { DCE_C_RPC_AUTHN_PROTOCOL_NONE,    "None" },
109         { DCE_C_RPC_AUTHN_PROTOCOL_KRB5,    "Kerberos 5" },
110         { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,  "SPNEGO" },
111         { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
112         { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
113         { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
114         { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
115                 "Distributed Password Authentication SSP"},
116         { DCE_C_RPC_AUTHN_PROTOCOL_MSN, "MSN SSP"},
117         { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST, "Digest SSP"},
118         { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
119         { DCE_C_RPC_AUTHN_PROTOCOL_MQ, "MSMQ SSP"},
120         { 0, NULL }
121 };
122
123 /*
124  * Protection levels.
125  */
126 static const value_string authn_level_vals[] = {
127         { DCE_C_AUTHN_LEVEL_NONE,          "None" },
128         { DCE_C_AUTHN_LEVEL_CONNECT,       "Connect" },
129         { DCE_C_AUTHN_LEVEL_CALL,          "Call" },
130         { DCE_C_AUTHN_LEVEL_PKT,           "Packet" },
131         { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
132         { DCE_C_AUTHN_LEVEL_PKT_PRIVACY,   "Packet privacy" },
133         { 0,                               NULL }
134 };
135
136 /*
137  * Flag bits in first flag field in connectionless PDU header.
138  */
139 #define PFCL1_RESERVED_01       0x01    /* Reserved for use by implementations */
140 #define PFCL1_LASTFRAG          0x02    /* If set, the PDU is the last
141                                          * fragment of a multi-PDU
142                                          * transmission */
143 #define PFCL1_FRAG              0x04    /* If set, the PDU is a fragment of
144                                            a multi-PDU transmission */
145 #define PFCL1_NOFACK            0x08    /* If set, the receiver is not
146                                          * requested to send a `fack' PDU
147                                          * for the fragment */
148 #define PFCL1_MAYBE             0x10    /* If set, the PDU is for a `maybe'
149                                          * request */
150 #define PFCL1_IDEMPOTENT        0x20    /* If set, the PDU is for an idempotent
151                                          * request */
152 #define PFCL1_BROADCAST         0x40    /* If set, the PDU is for a broadcast
153                                          * request */
154 #define PFCL1_RESERVED_80       0x80    /* Reserved for use by implementations */
155
156 /*
157  * Flag bits in second flag field in connectionless PDU header.
158  */
159 #define PFCL2_RESERVED_01       0x01    /* Reserved for use by implementations */
160 #define PFCL2_CANCEL_PENDING    0x02    /* Cancel pending at the call end */
161 #define PFCL2_RESERVED_04       0x04    /* Reserved for future use */
162 #define PFCL2_RESERVED_08       0x08    /* Reserved for future use */
163 #define PFCL2_RESERVED_10       0x10    /* Reserved for future use */
164 #define PFCL2_RESERVED_20       0x20    /* Reserved for future use */
165 #define PFCL2_RESERVED_40       0x40    /* Reserved for future use */
166 #define PFCL2_RESERVED_80       0x80    /* Reserved for future use */
167
168 /*
169  * Flag bits in connection-oriented PDU header.
170  */
171 #define PFC_FIRST_FRAG          0x01    /* First fragment */
172 #define PFC_LAST_FRAG           0x02    /* Last fragment */
173 #define PFC_PENDING_CANCEL      0x04    /* Cancel was pending at sender */
174 #define PFC_RESERVED_1          0x08
175 #define PFC_CONC_MPX            0x10    /* suports concurrent multiplexing
176                                          * of a single connection. */
177 #define PFC_DID_NOT_EXECUTE     0x20    /* only meaningful on `fault' packet;
178                                          * if true, guaranteed call did not
179                                          * execute. */
180 #define PFC_MAYBE               0x40    /* `maybe' call semantics requested */
181 #define PFC_OBJECT_UUID         0x80    /* if true, a non-nil object UUID
182                                          * was specified in the handle, and
183                                          * is present in the optional object
184                                          * field. If false, the object field
185                                          * is omitted. */
186
187 /*
188  * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
189  * it's not fragmented (i.e., this is both the first *and* last fragment),
190  * and FALSE otherwise.
191  */
192 #define PFC_NOT_FRAGMENTED(hdr) \
193   ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
194
195 /*
196  * Presentation context negotiation result.
197  */
198 static const value_string p_cont_result_vals[] = {
199         { 0, "Acceptance" },
200         { 1, "User rejection" },
201         { 2, "Provider rejection" },
202         { 0, NULL }
203 };
204
205 /*
206  * Presentation context negotiation rejection reasons.
207  */
208 static const value_string p_provider_reason_vals[] = {
209         { 0, "Reason not specified" },
210         { 1, "Abstract syntax not supported" },
211         { 2, "Proposed transfer syntaxes not supported" },
212         { 3, "Local limit exceeded" },
213         { 0, NULL }
214 };
215
216 /*
217  * Reject reasons.
218  */
219 #define REASON_NOT_SPECIFIED            0
220 #define TEMPORARY_CONGESTION            1
221 #define LOCAL_LIMIT_EXCEEDED            2
222 #define CALLED_PADDR_UNKNOWN            3 /* not used */
223 #define PROTOCOL_VERSION_NOT_SUPPORTED  4
224 #define DEFAULT_CONTEXT_NOT_SUPPORTED   5 /* not used */
225 #define USER_DATA_NOT_READABLE          6 /* not used */
226 #define NO_PSAP_AVAILABLE               7 /* not used */
227 #define AUTH_TYPE_NOT_RECOGNIZED        8
228 #define INVALID_CHECKSUM                        9
229
230 static const value_string reject_reason_vals[] = {
231         { REASON_NOT_SPECIFIED,           "Reason not specified" },
232         { TEMPORARY_CONGESTION,           "Temporary congestion" },
233         { LOCAL_LIMIT_EXCEEDED,           "Local limit exceeded" },
234         { CALLED_PADDR_UNKNOWN,           "Called paddr unknown" },
235         { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
236         { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
237         { USER_DATA_NOT_READABLE,         "User data not readable" },
238         { NO_PSAP_AVAILABLE,              "No PSAP available" },
239         { AUTH_TYPE_NOT_RECOGNIZED,       "Authentication type not recognized" },
240         { INVALID_CHECKSUM,               "Invalid checksum" },
241         { 0,                              NULL }
242 };
243
244 /*
245  * Reject status codes.
246  */
247 static const value_string reject_status_vals[] = {
248         { 0,          "Stub-defined exception" },
249         { 0x00000001, "nca_s_fault_other" },
250         { 0x00000005, "nca_s_fault_access_denied" },
251         { 0x000006f7, "nca_s_fault_ndr" },
252         { 0x000006d8, "nca_s_fault_cant_perform" },
253         { 0x1c000001, "nca_s_fault_int_div_by_zero" },
254         { 0x1c000002, "nca_s_fault_addr_error" },
255         { 0x1c000003, "nca_s_fault_fp_div_zero" },
256         { 0x1c000004, "nca_s_fault_fp_underflow" },
257         { 0x1c000005, "nca_s_fault_fp_overflow" },
258         { 0x1c000006, "nca_s_fault_invalid_tag" },
259         { 0x1c000007, "nca_s_fault_invalid_bound" },
260         { 0x1c000008, "nca_rpc_version_mismatch" },
261         { 0x1c000009, "nca_unspec_reject" },
262         { 0x1c00000a, "nca_s_bad_actid" },
263         { 0x1c00000b, "nca_who_are_you_failed" },
264         { 0x1c00000c, "nca_manager_not_entered" },
265         { 0x1c00000d, "nca_s_fault_cancel" },
266         { 0x1c00000e, "nca_s_fault_ill_inst" },
267         { 0x1c00000f, "nca_s_fault_fp_error" },
268         { 0x1c000010, "nca_s_fault_int_overflow" },
269         { 0x1c000014, "nca_s_fault_pipe_empty" },
270         { 0x1c000015, "nca_s_fault_pipe_closed" },
271         { 0x1c000016, "nca_s_fault_pipe_order" },
272         { 0x1c000017, "nca_s_fault_pipe_discipline" },
273         { 0x1c000018, "nca_s_fault_pipe_comm_error" },
274         { 0x1c000019, "nca_s_fault_pipe_memory" },
275         { 0x1c00001a, "nca_s_fault_context_mismatch" },
276         { 0x1c00001b, "nca_s_fault_remote_no_memory" },
277         { 0x1c00001c, "nca_invalid_pres_context_id" },
278         { 0x1c00001d, "nca_unsupported_authn_level" },
279         { 0x1c00001f, "nca_invalid_checksum" },
280         { 0x1c000020, "nca_invalid_crc" },
281         { 0x1c000021, "ncs_s_fault_user_defined" },
282         { 0x1c000022, "nca_s_fault_tx_open_failed" },
283         { 0x1c000023, "nca_s_fault_codeset_conv_error" },
284         { 0x1c000024, "nca_s_fault_object_not_found" },
285         { 0x1c000025, "nca_s_fault_no_client_stub" },
286         { 0x1c010002, "nca_op_rng_error" },
287         { 0x1c010003, "nca_unk_if"},
288         { 0x1c010006, "nca_wrong_boot_time" },
289         { 0x1c010009, "nca_s_you_crashed" },
290         { 0x1c01000b, "nca_proto_error" },
291         { 0x1c010013, "nca_out_args_too_big" },
292         { 0x1c010014, "nca_server_too_busy" },
293         { 0x1c010017, "nca_unsupported_type" },
294         /* MS Windows specific values
295          * see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
296          * and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
297          * and: http://www.megos.ch/support/doserrors.txt
298          *
299          * XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
300          * at least MS protocols (like DCOM) do it that way ... */
301         { 0x80004001, "E_NOTIMPL" },
302         { 0x80004003, "E_POINTER" },
303         { 0x80004004, "E_ABORT" },
304         { 0x8000FFFF, "E_UNEXPECTED" },
305         { 0x80010105, "RPC_E_SERVERFAULT" },
306         { 0x80010108, "RPC_E_DISCONNECTED" },
307         { 0x80010113, "RPC_E_INVALID_IPID" },
308         { 0x8001011F, "RPC_E_TIMEOUT" },
309         { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
310         { 0x80020006, "DISP_E_UNKNOWNNAME" },
311         { 0x8002000E, "DISP_E_BADPARAMCOUNT" },
312         { 0x8004CB00, "CBA_E_MALFORMED" },
313         { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
314         { 0x8004CB05, "CBA_E_INVALIDID" },
315         { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
316         { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
317         { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
318         { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
319         { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
320         { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
321         { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
322         { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
323         { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
324         { 0x8004CB25, "CBA_E_MODECHANGE" },
325         { 0x8007000E, "E_OUTOFMEMORY" },
326         { 0x80070057, "E_INVALIDARG" },
327         { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
328         { 0x80070776, "OR_INVALID_OXID" },
329         { 0,          NULL }
330 };
331
332
333 /* we need to keep track of what transport were used, ie what handle we came
334  * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
335  */
336 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
337 #define DCE_TRANSPORT_UNKNOWN           0
338 #define DCE_CN_TRANSPORT_SMBPIPE        1
339
340
341 static int proto_dcerpc = -1;
342
343 /* field defines */
344 static int hf_dcerpc_request_in = -1;
345 static int hf_dcerpc_time = -1;
346 static int hf_dcerpc_response_in = -1;
347 static int hf_dcerpc_ver = -1;
348 static int hf_dcerpc_ver_minor = -1;
349 static int hf_dcerpc_packet_type = -1;
350 static int hf_dcerpc_cn_flags = -1;
351 static int hf_dcerpc_cn_flags_first_frag = -1;
352 static int hf_dcerpc_cn_flags_last_frag = -1;
353 static int hf_dcerpc_cn_flags_cancel_pending = -1;
354 static int hf_dcerpc_cn_flags_reserved = -1;
355 static int hf_dcerpc_cn_flags_mpx = -1;
356 static int hf_dcerpc_cn_flags_dne = -1;
357 static int hf_dcerpc_cn_flags_maybe = -1;
358 static int hf_dcerpc_cn_flags_object = -1;
359 static int hf_dcerpc_drep = -1;
360        int hf_dcerpc_drep_byteorder = -1;
361 static int hf_dcerpc_drep_character = -1;
362 static int hf_dcerpc_drep_fp = -1;
363 static int hf_dcerpc_cn_frag_len = -1;
364 static int hf_dcerpc_cn_auth_len = -1;
365 static int hf_dcerpc_cn_call_id = -1;
366 static int hf_dcerpc_cn_max_xmit = -1;
367 static int hf_dcerpc_cn_max_recv = -1;
368 static int hf_dcerpc_cn_assoc_group = -1;
369 static int hf_dcerpc_cn_num_ctx_items = -1;
370 static int hf_dcerpc_cn_ctx_item = -1;
371 static int hf_dcerpc_cn_ctx_id = -1;
372 static int hf_dcerpc_cn_num_trans_items = -1;
373 static int hf_dcerpc_cn_bind_abstract_syntax = -1;
374 static int hf_dcerpc_cn_bind_if_id = -1;
375 static int hf_dcerpc_cn_bind_if_ver = -1;
376 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
377 static int hf_dcerpc_cn_bind_trans_syntax = -1;
378 static int hf_dcerpc_cn_bind_trans_id = -1;
379 static int hf_dcerpc_cn_bind_trans_ver = -1;
380 static int hf_dcerpc_cn_alloc_hint = -1;
381 static int hf_dcerpc_cn_sec_addr_len = -1;
382 static int hf_dcerpc_cn_sec_addr = -1;
383 static int hf_dcerpc_cn_num_results = -1;
384 static int hf_dcerpc_cn_ack_result = -1;
385 static int hf_dcerpc_cn_ack_reason = -1;
386 static int hf_dcerpc_cn_ack_trans_id = -1;
387 static int hf_dcerpc_cn_ack_trans_ver = -1;
388 static int hf_dcerpc_cn_reject_reason = -1;
389 static int hf_dcerpc_cn_num_protocols = -1;
390 static int hf_dcerpc_cn_protocol_ver_major = -1;
391 static int hf_dcerpc_cn_protocol_ver_minor = -1;
392 static int hf_dcerpc_cn_cancel_count = -1;
393 static int hf_dcerpc_cn_status = -1;
394 static int hf_dcerpc_cn_deseg_req = -1;
395 static int hf_dcerpc_auth_type = -1;
396 static int hf_dcerpc_auth_level = -1;
397 static int hf_dcerpc_auth_pad_len = -1;
398 static int hf_dcerpc_auth_rsrvd = -1;
399 static int hf_dcerpc_auth_ctx_id = -1;
400 static int hf_dcerpc_dg_flags1 = -1;
401 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
402 static int hf_dcerpc_dg_flags1_last_frag = -1;
403 static int hf_dcerpc_dg_flags1_frag = -1;
404 static int hf_dcerpc_dg_flags1_nofack = -1;
405 static int hf_dcerpc_dg_flags1_maybe = -1;
406 static int hf_dcerpc_dg_flags1_idempotent = -1;
407 static int hf_dcerpc_dg_flags1_broadcast = -1;
408 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
409 static int hf_dcerpc_dg_flags2 = -1;
410 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
411 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
412 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
413 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
414 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
415 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
416 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
417 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
418 static int hf_dcerpc_dg_serial_hi = -1;
419 static int hf_dcerpc_obj_id = -1;
420 static int hf_dcerpc_dg_if_id = -1;
421 static int hf_dcerpc_dg_act_id = -1;
422 static int hf_dcerpc_dg_serial_lo = -1;
423 static int hf_dcerpc_dg_ahint = -1;
424 static int hf_dcerpc_dg_ihint = -1;
425 static int hf_dcerpc_dg_frag_len = -1;
426 static int hf_dcerpc_dg_frag_num = -1;
427 static int hf_dcerpc_dg_auth_proto = -1;
428 static int hf_dcerpc_opnum = -1;
429 static int hf_dcerpc_dg_seqnum = -1;
430 static int hf_dcerpc_dg_server_boot = -1;
431 static int hf_dcerpc_dg_if_ver = -1;
432 static int hf_dcerpc_krb5_av_prot_level = -1;
433 static int hf_dcerpc_krb5_av_key_vers_num = -1;
434 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
435 static int hf_dcerpc_dg_cancel_vers = -1;
436 static int hf_dcerpc_dg_cancel_id = -1;
437 static int hf_dcerpc_dg_server_accepting_cancels = -1;
438 static int hf_dcerpc_dg_fack_vers = -1;
439 static int hf_dcerpc_dg_fack_window_size = -1;
440 static int hf_dcerpc_dg_fack_max_tsdu = -1;
441 static int hf_dcerpc_dg_fack_max_frag_size = -1;
442 static int hf_dcerpc_dg_fack_serial_num = -1;
443 static int hf_dcerpc_dg_fack_selack_len = -1;
444 static int hf_dcerpc_dg_fack_selack = -1;
445 static int hf_dcerpc_dg_status = -1;
446 static int hf_dcerpc_array_max_count = -1;
447 static int hf_dcerpc_array_offset = -1;
448 static int hf_dcerpc_array_actual_count = -1;
449 static int hf_dcerpc_array_buffer = -1;
450 static int hf_dcerpc_op = -1;
451 static int hf_dcerpc_referent_id = -1;
452 static int hf_dcerpc_fragments = -1;
453 static int hf_dcerpc_fragment = -1;
454 static int hf_dcerpc_fragment_overlap = -1;
455 static int hf_dcerpc_fragment_overlap_conflict = -1;
456 static int hf_dcerpc_fragment_multiple_tails = -1;
457 static int hf_dcerpc_fragment_too_long_fragment = -1;
458 static int hf_dcerpc_fragment_error = -1;
459 static int hf_dcerpc_reassembled_in = -1;
460 static int hf_dcerpc_unknown_if_id = -1;
461
462 static gint ett_dcerpc = -1;
463 static gint ett_dcerpc_cn_flags = -1;
464 static gint ett_dcerpc_cn_ctx = -1;
465 static gint ett_dcerpc_cn_iface = -1;
466 static gint ett_dcerpc_cn_trans_syntax = -1;
467 static gint ett_dcerpc_drep = -1;
468 static gint ett_dcerpc_dg_flags1 = -1;
469 static gint ett_dcerpc_dg_flags2 = -1;
470 static gint ett_dcerpc_pointer_data = -1;
471 static gint ett_dcerpc_string = -1;
472 static gint ett_dcerpc_fragments = -1;
473 static gint ett_dcerpc_fragment = -1;
474 static gint ett_dcerpc_krb5_auth_verf = -1;
475
476 static const fragment_items dcerpc_frag_items = {
477         &ett_dcerpc_fragments,
478         &ett_dcerpc_fragment,
479
480         &hf_dcerpc_fragments,
481         &hf_dcerpc_fragment,
482         &hf_dcerpc_fragment_overlap,
483         &hf_dcerpc_fragment_overlap_conflict,
484         &hf_dcerpc_fragment_multiple_tails,
485         &hf_dcerpc_fragment_too_long_fragment,
486         &hf_dcerpc_fragment_error,
487         NULL,
488
489         "fragments"
490 };
491
492 /* list of hooks to be called when init_protocols is done */
493 GHookList dcerpc_hooks_init_protos;
494
495 static dcerpc_info *
496 get_next_di(void)
497 {
498         static dcerpc_info di[20];
499         static int di_counter=0;
500
501         di_counter++;
502         if(di_counter>=20){
503                 di_counter=0;
504         }
505         return &di[di_counter];
506 }
507
508 /* try to desegment big DCE/RPC packets over TCP? */
509 static gboolean dcerpc_cn_desegment = TRUE;
510
511 /* reassemble DCE/RPC fragments */
512 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
513    might contain multiple dcerpc fragments for different PDUs.
514    this case would be so unusual/weird so if you got captures like that:
515         too bad
516
517    reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
518    are coming in out of sequence, but that will hurt in a lot of other places as well.
519 */
520 static gboolean dcerpc_reassemble = TRUE;
521 static GHashTable *dcerpc_co_fragment_table = NULL;
522 static GHashTable *dcerpc_co_reassemble_table = NULL;
523 static GHashTable *dcerpc_cl_reassemble_table = NULL;
524
525 static void
526 dcerpc_reassemble_init(void)
527 {
528   fragment_table_init(&dcerpc_co_fragment_table);
529   reassembled_table_init(&dcerpc_co_reassemble_table);
530   dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
531 }
532
533 /*
534  * Authentication subdissectors.  Used to dissect authentication blobs in
535  * DCERPC binds, requests and responses.
536  */
537
538 typedef struct _dcerpc_auth_subdissector {
539         guint8 auth_level;
540         guint8 auth_type;
541         dcerpc_auth_subdissector_fns auth_fns;
542 } dcerpc_auth_subdissector;
543
544 static GSList *dcerpc_auth_subdissector_list;
545
546 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
547         guint8 auth_level, guint8 auth_type)
548 {
549         gpointer data;
550         int i;
551
552         for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
553                 dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
554                 if (asd->auth_level == auth_level &&
555                     asd->auth_type == auth_type)
556                         return &asd->auth_fns;
557         }
558
559         return NULL;
560 }
561
562 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
563                                        dcerpc_auth_subdissector_fns *fns)
564 {
565         dcerpc_auth_subdissector *d;
566
567         if (get_auth_subdissector_fns(auth_level, auth_type))
568                 return;
569
570         d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
571
572         d->auth_level = auth_level;
573         d->auth_type = auth_type;
574         memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
575
576         dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
577 }
578
579 /* Hand off verifier data to a registered dissector */
580
581 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
582                               proto_tree *tree,
583                               dcerpc_auth_subdissector_fns *auth_fns,
584                               e_dce_cn_common_hdr_t *hdr,
585                               dcerpc_auth_info *auth_info)
586 {
587         dcerpc_dissect_fnct_t *volatile fn = NULL;
588
589         switch (hdr->ptype) {
590         case PDU_BIND:
591         case PDU_ALTER:
592                 fn = auth_fns->bind_fn;
593                 break;
594         case PDU_BIND_ACK:
595         case PDU_ALTER_ACK:
596                 fn = auth_fns->bind_ack_fn;
597                 break;
598         case PDU_AUTH3:
599                 fn = auth_fns->auth3_fn;
600                 break;
601         case PDU_REQ:
602                 fn = auth_fns->req_verf_fn;
603                 break;
604         case PDU_RESP:
605                 fn = auth_fns->resp_verf_fn;
606                 break;
607
608                 /* Don't know how to handle authentication data in this
609                    pdu type. */
610
611         default:
612                 g_warning("attempt to dissect %s pdu authentication data",
613                           val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
614                 break;
615         }
616
617         if (fn)
618                 fn(auth_tvb, 0, pinfo, tree, hdr->drep);
619         else {
620                 tvb_ensure_bytes_exist(auth_tvb, 0, hdr->auth_len);
621                 proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
622                                     "%s Verifier",
623                                     val_to_str(auth_info->auth_type,
624                                                authn_protocol_vals,
625                                                "Unknown (%u)"));
626         }
627 }
628
629 /* Hand off payload data to a registered dissector */
630
631 static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
632                                        tvbuff_t *auth_tvb,
633                                        packet_info *pinfo,
634                                        dcerpc_auth_subdissector_fns *auth_fns,
635                                        gboolean is_request,
636                                        dcerpc_auth_info *auth_info)
637 {
638         dcerpc_decode_data_fnct_t *fn;
639
640         if (is_request)
641                 fn = auth_fns->req_data_fn;
642         else
643                 fn = auth_fns->resp_data_fn;
644
645         if (fn)
646                 return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
647
648         return NULL;
649 }
650
651 /*
652  * Subdissectors
653  */
654
655 /* the registered subdissectors */
656 GHashTable *dcerpc_uuids=NULL;
657
658 static gint
659 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
660 {
661     const dcerpc_uuid_key *key1 = (const dcerpc_uuid_key *)k1;
662     const dcerpc_uuid_key *key2 = (const dcerpc_uuid_key *)k2;
663     return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
664             && (key1->ver == key2->ver));
665 }
666
667 static guint
668 dcerpc_uuid_hash (gconstpointer k)
669 {
670     const dcerpc_uuid_key *key = (const dcerpc_uuid_key *)k;
671     /* This isn't perfect, but the Data1 part of these is almost always
672        unique. */
673     return key->uuid.Data1;
674 }
675
676 void
677 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
678                   dcerpc_sub_dissector *procs, int opnum_hf)
679 {
680     dcerpc_uuid_key *key = g_malloc (sizeof (*key));
681     dcerpc_uuid_value *value = g_malloc (sizeof (*value));
682     header_field_info *hf_info;
683     module_t *samr_module;
684     const char *filter_name = proto_get_protocol_filter_name(proto);
685
686     key->uuid = *uuid;
687     key->ver = ver;
688
689     value->proto = find_protocol_by_id(proto);
690     value->proto_id = proto;
691     value->ett = ett;
692     value->name = proto_get_protocol_short_name (value->proto);
693     value->procs = procs;
694     value->opnum_hf = opnum_hf;
695
696     g_hash_table_insert (dcerpc_uuids, key, value);
697
698     hf_info = proto_registrar_get_nth(opnum_hf);
699     hf_info->strings = value_string_from_subdissectors(procs);
700
701     /* add this GUID to the global name resolving */
702     guids_add_uuid(uuid, proto_get_protocol_short_name (value->proto));
703
704     /* Register the samr.nt_password preference as obsolete */
705     /* This should be in packet-dcerpc-samr.c */
706     if (strcmp(filter_name, "samr") == 0) {
707         samr_module = prefs_register_protocol (proto, NULL);
708         prefs_register_obsolete_preference(samr_module, "nt_password");
709     }
710 }
711
712 /* Function to find the name of a registered protocol
713  * or NULL if the protocol/version is not known to wireshark.
714  */
715 const char *
716 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
717 {
718     dcerpc_uuid_key key;
719     dcerpc_uuid_value *sub_proto;
720
721     key.uuid = *uuid;
722     key.ver = ver;
723     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
724         return NULL;
725     }
726     return sub_proto->name;
727 }
728
729 /* Function to find the opnum hf-field of a registered protocol
730  * or -1 if the protocol/version is not known to wireshark.
731  */
732 int
733 dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
734 {
735     dcerpc_uuid_key key;
736     dcerpc_uuid_value *sub_proto;
737
738     key.uuid = *uuid;
739     key.ver = ver;
740     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
741         return -1;
742     }
743     return sub_proto->opnum_hf;
744 }
745
746 /* Create a value_string consisting of DCERPC opnum and name from a
747    subdissector array. */
748
749 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
750 {
751         value_string *vs = NULL;
752         int i, num_sd = 0;
753
754  again:
755         for (i = 0; sd[i].name; i++) {
756                 if (vs) {
757                         vs[i].value = sd[i].num;
758                         vs[i].strptr = sd[i].name;
759                 } else
760                         num_sd++;
761         }
762
763         if (!vs) {
764                 vs = g_malloc((num_sd + 1) * sizeof(value_string));
765                 goto again;
766         }
767
768         vs[num_sd].value = 0;
769         vs[num_sd].strptr = NULL;
770
771         return vs;
772 }
773
774 /* Function to find the subdissector table of a registered protocol
775  * or NULL if the protocol/version is not known to wireshark.
776  */
777 dcerpc_sub_dissector *
778 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
779 {
780     dcerpc_uuid_key key;
781     dcerpc_uuid_value *sub_proto;
782
783     key.uuid = *uuid;
784     key.ver = ver;
785     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
786         return NULL;
787     }
788     return sub_proto->procs;
789 }
790
791
792 /*
793  * To keep track of ctx_id mappings.
794  *
795  * Everytime we see a bind call we update this table.
796  * Note that we always specify a SMB FID. For non-SMB transports this
797  * value is 0.
798  */
799 static GHashTable *dcerpc_binds=NULL;
800
801 typedef struct _dcerpc_bind_key {
802     conversation_t *conv;
803     guint16 ctx_id;
804     guint16 smb_fid;
805 } dcerpc_bind_key;
806
807 typedef struct _dcerpc_bind_value {
808         e_uuid_t uuid;
809         guint16 ver;
810 } dcerpc_bind_value;
811
812 static gint
813 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
814 {
815     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
816     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
817     return (key1->conv == key2->conv
818             && key1->ctx_id == key2->ctx_id
819             && key1->smb_fid == key2->smb_fid);
820 }
821
822 static guint
823 dcerpc_bind_hash (gconstpointer k)
824 {
825     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
826     guint hash;
827
828     hash=GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
829     return hash;
830
831 }
832
833 /*
834  * To keep track of callid mappings.  Should really use some generic
835  * conversation support instead.
836  */
837 static GHashTable *dcerpc_cn_calls=NULL;
838 static GHashTable *dcerpc_dg_calls=NULL;
839
840 typedef struct _dcerpc_cn_call_key {
841     conversation_t *conv;
842     guint32 call_id;
843     guint16 smb_fid;
844 } dcerpc_cn_call_key;
845
846 typedef struct _dcerpc_dg_call_key {
847     conversation_t *conv;
848     guint32 seqnum;
849     e_uuid_t act_id ;
850 } dcerpc_dg_call_key;
851
852
853 static gint
854 dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
855 {
856     const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
857     const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
858     return (key1->conv == key2->conv
859             && key1->call_id == key2->call_id
860             && key1->smb_fid == key2->smb_fid);
861 }
862
863 static gint
864 dcerpc_dg_call_equal (gconstpointer k1, gconstpointer k2)
865 {
866     const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
867     const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
868     return (key1->conv == key2->conv
869             && key1->seqnum == key2->seqnum
870             && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_uuid_t)) == 0));
871 }
872
873 static guint
874 dcerpc_cn_call_hash (gconstpointer k)
875 {
876     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
877     return GPOINTER_TO_UINT(key->conv) + key->call_id + key->smb_fid;
878 }
879
880 static guint
881 dcerpc_dg_call_hash (gconstpointer k)
882 {
883     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
884     return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.Data1
885             + (key->act_id.Data2 << 16) + key->act_id.Data3
886             + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
887             + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
888             + (key->act_id.Data4[4] << 24) + (key->act_id.Data4[5] << 16)
889             + (key->act_id.Data4[6] << 8) + (key->act_id.Data4[7] << 0));
890 }
891
892
893 /* to keep track of matched calls/responses
894    this one uses the same value struct as calls, but the key is the frame id
895    and call id; there can be more than one call in a frame.
896
897    XXX - why not just use the same keys as are used for calls?
898 */
899
900 static GHashTable *dcerpc_matched=NULL;
901
902 typedef struct _dcerpc_matched_key {
903     guint32 frame;
904     guint32 call_id;
905 } dcerpc_matched_key;
906
907 static gint
908 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
909 {
910     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
911     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
912     return (key1->frame == key2->frame
913             && key1->call_id == key2->call_id);
914 }
915
916 static guint
917 dcerpc_matched_hash (gconstpointer k)
918 {
919     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
920     return key->frame;
921 }
922
923
924
925 /*
926  * Utility functions.  Modeled after packet-rpc.c
927  */
928
929 int
930 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
931                       proto_tree *tree, guint8 *drep,
932                       int hfindex, guint8 *pdata)
933 {
934     guint8 data;
935
936     data = tvb_get_guint8 (tvb, offset);
937     if (tree) {
938         proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
939     }
940     if (pdata)
941         *pdata = data;
942     return offset + 1;
943 }
944
945 int
946 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
947                        proto_tree *tree, guint8 *drep,
948                        int hfindex, guint16 *pdata)
949 {
950     guint16 data;
951
952     data = ((drep[0] & 0x10)
953             ? tvb_get_letohs (tvb, offset)
954             : tvb_get_ntohs (tvb, offset));
955
956     if (tree) {
957         proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
958     }
959     if (pdata)
960         *pdata = data;
961     return offset + 2;
962 }
963
964 int
965 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
966                        proto_tree *tree, guint8 *drep,
967                        int hfindex, guint32 *pdata)
968 {
969     guint32 data;
970
971     data = ((drep[0] & 0x10)
972             ? tvb_get_letohl (tvb, offset)
973             : tvb_get_ntohl (tvb, offset));
974
975     if (tree) {
976         proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
977     }
978     if (pdata)
979         *pdata = data;
980     return offset+4;
981 }
982
983 /* handles 32 bit unix time_t */
984 int
985 dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
986                        proto_tree *tree, guint8 *drep,
987                        int hfindex, guint32 *pdata)
988 {
989     guint32 data;
990     nstime_t tv;
991
992     data = ((drep[0] & 0x10)
993             ? tvb_get_letohl (tvb, offset)
994             : tvb_get_ntohl (tvb, offset));
995
996     tv.secs=data;
997     tv.nsecs=0;
998     if (tree) {
999         if(data==0xffffffff){
1000             /* special case,   no time specified */
1001             proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
1002         } else {
1003             proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
1004         }
1005     }
1006     if (pdata)
1007         *pdata = data;
1008
1009     return offset+4;
1010 }
1011
1012 int
1013 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1014                        proto_tree *tree, guint8 *drep,
1015                        int hfindex, guint64 *pdata)
1016 {
1017     guint64 data;
1018
1019     data = ((drep[0] & 0x10)
1020             ? tvb_get_letoh64 (tvb, offset)
1021             : tvb_get_ntoh64 (tvb, offset));
1022
1023     if (tree) {
1024         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
1025     }
1026     if (pdata)
1027         *pdata = data;
1028     return offset+8;
1029 }
1030
1031
1032 int
1033 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1034                     proto_tree *tree, guint8 *drep,
1035                     int hfindex, gfloat *pdata)
1036 {
1037         gfloat data;
1038
1039
1040         switch(drep[1]) {
1041                 case(DCE_RPC_DREP_FP_IEEE):
1042                         data = ((drep[0] & 0x10)
1043                                         ? tvb_get_letohieee_float(tvb, offset)
1044                                         : tvb_get_ntohieee_float(tvb, offset));
1045                         if (tree) {
1046                                 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
1047                         }
1048                         break;
1049                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1050                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1051                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1052                 default:
1053                         /* ToBeDone: non IEEE floating formats */
1054                         /* Set data to a negative infinity value */
1055                         data = -G_MAXFLOAT;
1056                         if (tree) {
1057                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
1058                         }
1059         }
1060     if (pdata)
1061         *pdata = data;
1062     return offset + 4;
1063 }
1064
1065
1066 int
1067 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1068                     proto_tree *tree, guint8 *drep,
1069                     int hfindex, gdouble *pdata)
1070 {
1071     gdouble data;
1072
1073
1074         switch(drep[1]) {
1075                 case(DCE_RPC_DREP_FP_IEEE):
1076                         data = ((drep[0] & 0x10)
1077                                         ? tvb_get_letohieee_double(tvb, offset)
1078                                         : tvb_get_ntohieee_double(tvb, offset));
1079                         if (tree) {
1080                                 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
1081                         }
1082                         break;
1083                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1084                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1085                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1086                 default:
1087                         /* ToBeDone: non IEEE double formats */
1088                         /* Set data to a negative infinity value */
1089                         data = -G_MAXDOUBLE;
1090                         if (tree) {
1091                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
1092                         }
1093         }
1094     if (pdata)
1095         *pdata = data;
1096     return offset + 8;
1097 }
1098
1099
1100 int
1101 dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1102                     proto_tree *tree, guint8 *drep,
1103                     int hfindex, e_uuid_t *pdata)
1104 {
1105     e_uuid_t uuid;
1106
1107
1108     if (drep[0] & 0x10) {
1109         tvb_get_letohguid (tvb, offset, (e_guid_t *) &uuid);
1110     } else {
1111         tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
1112     }
1113     if (tree) {
1114                 proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
1115     }
1116     if (pdata) {
1117         *pdata = uuid;
1118     }
1119     return offset + 16;
1120 }
1121
1122
1123 /*
1124  * a couple simpler things
1125  */
1126 guint16
1127 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep)
1128 {
1129     if (drep[0] & 0x10) {
1130         return tvb_get_letohs (tvb, offset);
1131     } else {
1132         return tvb_get_ntohs (tvb, offset);
1133     }
1134 }
1135
1136 guint32
1137 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
1138 {
1139     if (drep[0] & 0x10) {
1140         return tvb_get_letohl (tvb, offset);
1141     } else {
1142         return tvb_get_ntohl (tvb, offset);
1143     }
1144 }
1145
1146 void
1147 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
1148 {
1149     if (drep[0] & 0x10) {
1150         tvb_get_letohguid (tvb, offset, (e_guid_t *) uuid);
1151     } else {
1152         tvb_get_ntohguid (tvb, offset, (e_guid_t *) uuid);
1153     }
1154 }
1155
1156
1157 /* NDR arrays */
1158 /* function to dissect a unidimensional conformant array */
1159 int
1160 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1161                 proto_tree *tree, guint8 *drep,
1162                 dcerpc_dissect_fnct_t *fnct)
1163 {
1164         guint32 i;
1165         dcerpc_info *di;
1166         int old_offset;
1167
1168         di=pinfo->private_data;
1169         if(di->conformant_run){
1170                 /* conformant run, just dissect the max_count header */
1171                 old_offset=offset;
1172                 di->conformant_run=0;
1173                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1174                                 hf_dcerpc_array_max_count, &di->array_max_count);
1175                 di->array_max_count_offset=offset-4;
1176                 di->conformant_run=1;
1177                 di->conformant_eaten=offset-old_offset;
1178         } else {
1179                 /* we don't remember where in the bytestream this field was */
1180                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1181
1182                 /* real run, dissect the elements */
1183                 for(i=0;i<di->array_max_count;i++){
1184                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1185                 }
1186         }
1187
1188         return offset;
1189 }
1190 /* function to dissect a unidimensional conformant and varying array */
1191 int
1192 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1193                 proto_tree *tree, guint8 *drep,
1194                 dcerpc_dissect_fnct_t *fnct)
1195 {
1196         guint32 i;
1197         dcerpc_info *di;
1198         int old_offset;
1199
1200         di=pinfo->private_data;
1201         if(di->conformant_run){
1202                 /* conformant run, just dissect the max_count header */
1203                 old_offset=offset;
1204                 di->conformant_run=0;
1205                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1206                                 hf_dcerpc_array_max_count, &di->array_max_count);
1207                 di->array_max_count_offset=offset-4;
1208                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1209                                 hf_dcerpc_array_offset, &di->array_offset);
1210                 di->array_offset_offset=offset-4;
1211                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1212                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1213                 di->array_actual_count_offset=offset-4;
1214                 di->conformant_run=1;
1215                 di->conformant_eaten=offset-old_offset;
1216         } else {
1217                 /* we dont dont remember where  in the bytestream these fields were */
1218                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1219                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1220                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1221
1222                 /* real run, dissect the elements */
1223                 for(i=0;i<di->array_actual_count;i++){
1224                         old_offset = offset;
1225                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1226                         if (offset <= old_offset)
1227                                 THROW(ReportedBoundsError);
1228                 }
1229         }
1230
1231         return offset;
1232 }
1233 /* function to dissect a unidimensional varying array */
1234 int
1235 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1236                 proto_tree *tree, guint8 *drep,
1237                 dcerpc_dissect_fnct_t *fnct)
1238 {
1239         guint32 i;
1240         dcerpc_info *di;
1241         int old_offset;
1242
1243         di=pinfo->private_data;
1244         if(di->conformant_run){
1245                 /* conformant run, just dissect the max_count header */
1246                 old_offset=offset;
1247                 di->conformant_run=0;
1248                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1249                                 hf_dcerpc_array_offset, &di->array_offset);
1250                 di->array_offset_offset=offset-4;
1251                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1252                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1253                 di->array_actual_count_offset=offset-4;
1254                 di->conformant_run=1;
1255                 di->conformant_eaten=offset-old_offset;
1256         } else {
1257                 /* we dont dont remember where  in the bytestream these fields were */
1258                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1259                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1260
1261                 /* real run, dissect the elements */
1262                 for(i=0;i<di->array_actual_count;i++){
1263                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1264                 }
1265         }
1266
1267         return offset;
1268 }
1269
1270 /* Dissect an string of bytes.  This corresponds to
1271    IDL of the form '[string] byte *foo'.
1272
1273    It can also be used for a conformant varying array of bytes if
1274    the contents of the array should be shown as a big blob, rather
1275    than showing each byte as an individual element.
1276
1277    XXX - which of those is really the IDL type for, for example,
1278    the encrypted data in some MAPI packets?  (Microsoft haven't
1279    released that IDL.)
1280
1281    XXX - does this need to do all the conformant array stuff that
1282    "dissect_ndr_ucvarray()" does?  These are presumably for strings
1283    that are conformant and varying - they're stored like conformant
1284    varying arrays of bytes.  */
1285 int
1286 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
1287                             proto_tree *tree, guint8 *drep)
1288 {
1289     dcerpc_info *di;
1290     guint32 len;
1291
1292     di=pinfo->private_data;
1293     if(di->conformant_run){
1294       /* just a run to handle conformant arrays, no scalars to dissect */
1295       return offset;
1296     }
1297
1298     /* NDR array header */
1299
1300     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1301                                 hf_dcerpc_array_max_count, NULL);
1302
1303     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1304                                 hf_dcerpc_array_offset, NULL);
1305
1306     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1307                                 hf_dcerpc_array_actual_count, &len);
1308
1309     if (tree && len) {
1310         tvb_ensure_bytes_exist(tvb, offset, len);
1311         proto_tree_add_item(tree, hf_dcerpc_array_buffer,
1312                             tvb, offset, len, drep[0] & 0x10);
1313     }
1314
1315     offset += len;
1316
1317     return offset;
1318 }
1319
1320 /* For dissecting arrays that are to be interpreted as strings.  */
1321
1322 /* Dissect an NDR conformant varying string of elements.
1323    The length of each element is given by the 'size_is' parameter;
1324    the elements are assumed to be characters or wide characters.
1325
1326    XXX - does this need to do all the conformant array stuff that
1327    "dissect_ndr_ucvarray()" does?  */
1328 int
1329 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1330                      proto_tree *tree, guint8 *drep, int size_is,
1331                      int hfindex, gboolean add_subtree, char **data)
1332 {
1333     dcerpc_info *di;
1334     proto_item *string_item;
1335     proto_tree *string_tree;
1336     guint32 len, buffer_len, max;
1337     char *s;
1338     header_field_info *hfinfo;
1339
1340     di=pinfo->private_data;
1341     if(di->conformant_run){
1342       /* just a run to handle conformant arrays, no scalars to dissect */
1343       return offset;
1344     }
1345
1346     if (add_subtree) {
1347         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1348                                           proto_registrar_get_name(hfindex));
1349         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1350     } else {
1351         string_item = NULL;
1352         string_tree = tree;
1353     }
1354
1355     /* NDR array header */
1356
1357     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1358                                 hf_dcerpc_array_max_count, &max);
1359
1360     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1361                                 hf_dcerpc_array_offset, NULL);
1362
1363     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1364                                 hf_dcerpc_array_actual_count, &len);
1365     buffer_len = size_is * len;
1366     /*buffer_len2 = size_is * max;*/
1367     hfinfo = proto_registrar_get_nth(hfindex);
1368
1369     /* Adjust offset */
1370     if (offset % size_is)
1371         offset += size_is - (offset % size_is);
1372     /*if( buffer_len2 != buffer_len && hfinfo->type == FT_STRING && tvb_reported_length_remaining(tvb,offset) > (gint)buffer_len2) {
1373       / * Max can be bigger that len 
1374        * if the packet is comming from windows it normally means that the 
1375        * last two bytes are null terminators. In this case we change the length
1376        * in order to consume them ...
1377        * If it's from samba then it's more unlikely to be terminator so we carefully check if
1378        * it's null terminators or not in order to know if we should consume them * /
1379
1380       buf = ep_alloc(sizeof(guint8)*buffer_len2);
1381       tvb_memcpy(tvb,buf,offset,buffer_len2);
1382       if( buf[buffer_len2-2] == 0x0 && buf[buffer_len2-1] == 0x0) {
1383         buffer_len = buffer_len2;
1384       }
1385     }*/
1386     if (size_is == sizeof(guint16)) {
1387         /* XXX - use drep to determine the byte order? */
1388         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1389         /*
1390          * XXX - we don't support a string type with Unicode
1391          * characters, so if this is a string item, we make
1392          * its value be the "fake Unicode" string.
1393          */
1394         if (tree && buffer_len) {
1395             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1396             if (hfinfo->type == FT_STRING) {
1397                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1398                                       buffer_len, s);
1399             } else {
1400                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1401                                     buffer_len, drep[0] & 0x10);
1402             }
1403         }
1404     } else {
1405         /*
1406          * "tvb_get_ephemeral_string()" throws an exception if the entire string
1407          * isn't in the tvbuff.  If the length is bogus, this should
1408          * keep us from trying to allocate an immensely large buffer.
1409          * (It won't help if the length is *valid* but immensely large,
1410          * but that's another matter; in any case, that would happen only
1411          * if we had an immensely large tvbuff....)
1412          */
1413         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1414         s = tvb_get_ephemeral_string(tvb, offset, buffer_len);
1415         if (tree && buffer_len)
1416             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1417                                 buffer_len, drep[0] & 0x10);
1418     }
1419
1420     if (string_item != NULL)
1421         proto_item_append_text(string_item, ": %s", s);
1422
1423     if (data)
1424             *data = s;
1425
1426     offset += buffer_len;
1427
1428     proto_item_set_end(string_item, tvb, offset);
1429
1430     return offset;
1431 }
1432
1433 /* Dissect an conformant varying string of chars.
1434    This corresponds to IDL of the form '[string] char *foo'.
1435
1436    XXX - at least according to the DCE RPC 1.1 spec, a string has
1437    a null terminator, which isn't necessary as a terminator for
1438    the transfer language (as there's a length), but is presumably
1439    there for the benefit of null-terminated-string languages
1440    such as C.  Is this ever used for purely counted strings?
1441    (Not that it matters if it is.) */
1442 int
1443 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1444                         proto_tree *tree, guint8 *drep)
1445 {
1446     dcerpc_info *di;
1447     di=pinfo->private_data;
1448
1449     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1450                                 sizeof(guint8), di->hf_index,
1451                                 FALSE, NULL);
1452 }
1453
1454 /* Dissect a conformant varying string of wchars (wide characters).
1455    This corresponds to IDL of the form '[string] wchar *foo'
1456
1457    XXX - at least according to the DCE RPC 1.1 spec, a string has
1458    a null terminator, which isn't necessary as a terminator for
1459    the transfer language (as there's a length), but is presumably
1460    there for the benefit of null-terminated-string languages
1461    such as C.  Is this ever used for purely counted strings?
1462    (Not that it matters if it is.) */
1463 /* This function should be duplicated to handle properly null terminated strings*/
1464 int
1465 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1466                         proto_tree *tree, guint8 *drep)
1467 {
1468     dcerpc_info *di;
1469     di=pinfo->private_data;
1470
1471     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1472                                 sizeof(guint16), di->hf_index,
1473                                 FALSE, NULL);
1474 }
1475
1476 /* This function is aimed for PIDL useage and dissects a UNIQUE pointer to
1477  * unicode string.
1478  */
1479 int
1480 PIDL_dissect_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int chsize, int hfindex, guint32 param)
1481 {
1482         dcerpc_info *di;
1483         char *s = NULL;
1484         gint levels = CB_STR_ITEM_LEVELS(param);
1485
1486         di=pinfo->private_data;
1487
1488         offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1489                                 chsize, hfindex,
1490                                 FALSE, &s);
1491
1492         if(!di->conformant_run){
1493                 /* Append string to COL_INFO */
1494                 if (param & PIDL_SET_COL_INFO) {
1495                         if (check_col(pinfo->cinfo, COL_INFO))
1496                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
1497                 }
1498                 /* Save string to dcv->private_data */
1499                 if((param & PIDL_STR_SAVE)
1500                 && (!pinfo->fd->flags.visited)){
1501                         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1502                         dcv->private_data = se_strdup(s);
1503                 }
1504                 /* Append string to upper-level proto_items */
1505                 if (levels > 0 && tree && s && s[0]) {
1506                         proto_item_append_text(tree, ": %s", s);
1507                         tree = tree->parent;
1508                         levels--;
1509                         if (levels > 0) {
1510                                 proto_item_append_text(tree, ": %s", s);
1511                                 tree = tree->parent;
1512                                 levels--;
1513                                 while (levels > 0) {
1514                                         proto_item_append_text(tree, " %s", s);
1515                                         tree = tree->parent;
1516                                         levels--;
1517                                 }
1518                         }
1519                 }
1520
1521         }
1522
1523         g_free(s);
1524         return offset;
1525 }
1526
1527 /* Dissect an NDR varying string of elements.
1528    The length of each element is given by the 'size_is' parameter;
1529    the elements are assumed to be characters or wide characters.
1530 */
1531 int
1532 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1533                      proto_tree *tree, guint8 *drep, int size_is,
1534                      int hfindex, gboolean add_subtree, char **data)
1535 {
1536     dcerpc_info *di;
1537     proto_item *string_item;
1538     proto_tree *string_tree;
1539     guint32 len, buffer_len;
1540     char *s;
1541     header_field_info *hfinfo;
1542
1543     di=pinfo->private_data;
1544     if(di->conformant_run){
1545       /* just a run to handle conformant arrays, no scalars to dissect */
1546       return offset;
1547     }
1548
1549     if (add_subtree) {
1550         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1551                                           proto_registrar_get_name(hfindex));
1552         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1553     } else {
1554         string_item = NULL;
1555         string_tree = tree;
1556     }
1557
1558     /* NDR array header */
1559     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1560                                 hf_dcerpc_array_offset, NULL);
1561
1562     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1563                                 hf_dcerpc_array_actual_count, &len);
1564
1565     buffer_len = size_is * len;
1566
1567     /* Adjust offset */
1568     if (offset % size_is)
1569         offset += size_is - (offset % size_is);
1570
1571     if (size_is == sizeof(guint16)) {
1572         /* XXX - use drep to determine the byte order? */
1573         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1574         /*
1575          * XXX - we don't support a string type with Unicode
1576          * characters, so if this is a string item, we make
1577          * its value be the "fake Unicode" string.
1578          */
1579         if (tree && buffer_len) {
1580             hfinfo = proto_registrar_get_nth(hfindex);
1581             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1582             if (hfinfo->type == FT_STRING) {
1583                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1584                                       buffer_len, s);
1585             } else {
1586                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1587                                     buffer_len, drep[0] & 0x10);
1588             }
1589         }
1590     } else {
1591         /*
1592          * "tvb_get_ephemeral_string()" throws an exception if the entire string
1593          * isn't in the tvbuff.  If the length is bogus, this should
1594          * keep us from trying to allocate an immensely large buffer.
1595          * (It won't help if the length is *valid* but immensely large,
1596          * but that's another matter; in any case, that would happen only
1597          * if we had an immensely large tvbuff....)
1598          */
1599         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1600         s = tvb_get_ephemeral_string(tvb, offset, buffer_len);
1601         if (tree && buffer_len)
1602             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1603                                 buffer_len, drep[0] & 0x10);
1604     }
1605
1606     if (string_item != NULL)
1607         proto_item_append_text(string_item, ": %s", s);
1608
1609     if (data)
1610             *data = s;
1611
1612     offset += buffer_len;
1613
1614     proto_item_set_end(string_item, tvb, offset);
1615
1616     return offset;
1617 }
1618
1619 /* Dissect an varying string of chars.
1620    This corresponds to IDL of the form '[string] char *foo'.
1621
1622    XXX - at least according to the DCE RPC 1.1 spec, a string has
1623    a null terminator, which isn't necessary as a terminator for
1624    the transfer language (as there's a length), but is presumably
1625    there for the benefit of null-terminated-string languages
1626    such as C.  Is this ever used for purely counted strings?
1627    (Not that it matters if it is.) */
1628 int
1629 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1630                         proto_tree *tree, guint8 *drep)
1631 {
1632     dcerpc_info *di;
1633     di=pinfo->private_data;
1634
1635     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1636                                 sizeof(guint8), di->hf_index,
1637                                 FALSE, NULL);
1638 }
1639
1640 /* Dissect a varying string of wchars (wide characters).
1641    This corresponds to IDL of the form '[string] wchar *foo'
1642
1643    XXX - at least according to the DCE RPC 1.1 spec, a string has
1644    a null terminator, which isn't necessary as a terminator for
1645    the transfer language (as there's a length), but is presumably
1646    there for the benefit of null-terminated-string languages
1647    such as C.  Is this ever used for purely counted strings?
1648    (Not that it matters if it is.) */
1649 int
1650 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1651                         proto_tree *tree, guint8 *drep)
1652 {
1653     dcerpc_info *di;
1654     di=pinfo->private_data;
1655
1656     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1657                                 sizeof(guint16), di->hf_index,
1658                                 FALSE, NULL);
1659 }
1660
1661
1662 /* ndr pointer handling */
1663 /* list of pointers encountered so far */
1664 static GSList *ndr_pointer_list = NULL;
1665
1666 /* position where in the list to insert newly encountered pointers */
1667 static int ndr_pointer_list_pos=0;
1668
1669 /* boolean controlling whether pointers are top-level or embedded */
1670 static gboolean pointers_are_top_level = TRUE;
1671
1672 /* as a kludge, we represent all embedded reference pointers as id==-1
1673    hoping that his will not collide with any non-ref pointers */
1674 typedef struct ndr_pointer_data {
1675         guint32 id;
1676         proto_item *item;       /* proto_item for pointer */
1677         proto_tree *tree;       /* subtree of above item */
1678         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1679         int hf_index;
1680         dcerpc_callback_fnct_t *callback;
1681         void *callback_args;
1682 } ndr_pointer_data_t;
1683
1684 void
1685 init_ndr_pointer_list(packet_info *pinfo)
1686 {
1687         dcerpc_info *di;
1688
1689         di=pinfo->private_data;
1690         di->conformant_run=0;
1691
1692         while(ndr_pointer_list){
1693                 ndr_pointer_data_t *npd;
1694
1695                 npd=g_slist_nth_data(ndr_pointer_list, 0);
1696                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1697                 g_free(npd);
1698         }
1699
1700         ndr_pointer_list=NULL;
1701         ndr_pointer_list_pos=0;
1702         pointers_are_top_level=TRUE;
1703 }
1704
1705 int
1706 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
1707 {
1708         int found_new_pointer;
1709         dcerpc_info *di;
1710         int old_offset;
1711         int next_pointer;
1712
1713         next_pointer=0;
1714         di=pinfo->private_data;
1715         do{
1716                 int i, len;
1717
1718                 found_new_pointer=0;
1719                 len=g_slist_length(ndr_pointer_list);
1720                 for(i=next_pointer;i<len;i++){
1721                         ndr_pointer_data_t *tnpd;
1722                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
1723                         if(tnpd->fnct){
1724                                 dcerpc_dissect_fnct_t *fnct;
1725
1726                                 next_pointer=i+1;
1727                                 found_new_pointer=1;
1728                                 fnct=tnpd->fnct;
1729                                 tnpd->fnct=NULL;
1730                                 ndr_pointer_list_pos=i+1;
1731                                 di->hf_index=tnpd->hf_index;
1732                                 /* first a run to handle any conformant
1733                                    array headers */
1734                                 di->conformant_run=1;
1735                                 di->conformant_eaten=0;
1736                                 old_offset = offset;
1737                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1738
1739                                 DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
1740                                 /* This is to check for any bugs in the dissectors.
1741                                  *
1742                                  * Basically, the NDR representation will store all
1743                                  * arrays in two blocks, one block with the dimension
1744                                  * discreption, like size, number of elements and such,
1745                                  * and another block that contains the actual data stored
1746                                  * in the array.
1747                                  * If the array is embedded directly inside another,
1748                                  * encapsulating aggregate type, like a union or struct,
1749                                  * then these two blocks will be stored at different places
1750                                  * in the bytestream, with other data between the blocks.
1751                                  *
1752                                  * For this reason, all pointers to types (both aggregate
1753                                  * and scalar, for simplicity no distinction is made)
1754                                  * will have its dissector called twice.
1755                                  * The dissector will first be called with conformant_run==1
1756                                  * in which mode the dissector MUST NOT consume any data from
1757                                  * the tvbuff (i.e. may not dissect anything) except the
1758                                  * initial control block for arrays.
1759                                  * The second time the dissector is called, with
1760                                  * conformant_run==0, all other data for the type will be
1761                                  * dissected.
1762                                  *
1763                                  * All dissect_ndr_<type> dissectors are already prepared
1764                                  * for this and knows when it should eat data from the tvb
1765                                  * and when not to, so implementors of dissectors will
1766                                  * normally not need to worry about this or even know about
1767                                  * it. However, if a dissector for an aggregate type calls
1768                                  * a subdissector from outside packet-dcerpc.c, such as
1769                                  * the dissector in packet-smb.c for NT Security Descriptors
1770                                  * as an example, then it is VERY important to encapsulate
1771                                  * this call to an external subdissector with the appropriate
1772                                  * test for conformant_run, i.e. it will need something like
1773                                  *
1774                                  *      dcerpc_info *di;
1775                                  *
1776                                  *      di=pinfo->private_data;
1777                                  *      if(di->conformant_run){
1778                                  *              return offset;
1779                                  *      }
1780                                  *
1781                                  * to make sure it makes the right thing.
1782                                  * This assert will signal when someone has forgotten to
1783                                  * make the dissector aware of this requirement.
1784                                  */
1785
1786                                 /* now we dissect the actual pointer */
1787                                 di->conformant_run=0;
1788                                 old_offset = offset;
1789                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1790                                 if (tnpd->callback)
1791                                         tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1792                                 break;
1793                         }
1794                 }
1795         } while(found_new_pointer);
1796
1797         return offset;
1798 }
1799
1800
1801 static void
1802 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1803                     dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
1804                     dcerpc_callback_fnct_t *callback, void *callback_args)
1805 {
1806         ndr_pointer_data_t *npd;
1807
1808         /* check if this pointer is valid */
1809         if(id!=0xffffffff){
1810                 dcerpc_info *di;
1811                 dcerpc_call_value *value;
1812
1813                 di=pinfo->private_data;
1814                 value=di->call_data;
1815
1816                 if(di->ptype == PDU_REQ){
1817                         if(!(pinfo->fd->flags.visited)){
1818                                 if(id>value->max_ptr){
1819                                         value->max_ptr=id;
1820                                 }
1821                         }
1822                 } else {
1823                         /* if we havent seen the request bail out since we cant
1824                            know whether this is the first non-NULL instance
1825                            or not */
1826                         if(value->req_frame==0){
1827                                 /* XXX THROW EXCEPTION */
1828                         }
1829
1830                         /* We saw this one in the request frame, nothing to
1831                            dissect later */
1832                         if(id<=value->max_ptr){
1833                                 return;
1834                         }
1835                 }
1836         }
1837
1838         npd=g_malloc(sizeof(ndr_pointer_data_t));
1839         npd->id=id;
1840         npd->tree=tree;
1841         npd->item=item;
1842         npd->fnct=fnct;
1843         npd->hf_index=hf_index;
1844         npd->callback=callback;
1845         npd->callback_args=callback_args;
1846         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1847                                         ndr_pointer_list_pos);
1848         ndr_pointer_list_pos++;
1849 }
1850
1851
1852 static int
1853 find_pointer_index(guint32 id)
1854 {
1855         ndr_pointer_data_t *npd;
1856         int i,len;
1857
1858         len=g_slist_length(ndr_pointer_list);
1859         for(i=0;i<len;i++){
1860                 npd=g_slist_nth_data(ndr_pointer_list, i);
1861                 if(npd){
1862                         if(npd->id==id){
1863                                 return i;
1864                         }
1865                 }
1866         }
1867
1868         return -1;
1869 }
1870
1871 /* This function dissects an NDR pointer and stores the callback for later
1872  * deferred dissection.
1873  *
1874  *   fnct is the callback function for when we have reached this object in
1875  *   the bytestream.
1876  *
1877  *   type is what type of pointer.
1878  *
1879  *   this is text is what text we should put in any created tree node.
1880  *
1881  *   hf_index is what hf value we want to pass to the callback function when
1882  *   it is called, the callback can later pich this one up from di->hf_index.
1883  *
1884  *   callback is executed after the pointer has been dereferenced.
1885  *
1886  *   callback_args is passed as an argument to the callback function
1887  *
1888  * See packet-dcerpc-samr.c for examples
1889  */
1890 int
1891 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1892                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
1893                     int type, const char *text, int hf_index,
1894                     dcerpc_callback_fnct_t *callback, void *callback_args)
1895 {
1896         dcerpc_info *di;
1897         proto_tree *tr = NULL;
1898         gint start_offset = offset;
1899
1900         di=pinfo->private_data;
1901         if(di->conformant_run){
1902                 /* this call was only for dissecting the header for any
1903                    embedded conformant array. we will not parse any
1904                    pointers in this mode.
1905                 */
1906                 return offset;
1907         }
1908         /*TOP LEVEL REFERENCE POINTER*/
1909         if( pointers_are_top_level
1910         &&(type==NDR_POINTER_REF) ){
1911                 proto_item *item;
1912
1913                 /* we must find out a nice way to do the length here */
1914                 item=proto_tree_add_text(tree, tvb, offset, 0,
1915                         "%s", text);
1916                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1917
1918                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1919                                     hf_index, callback, callback_args);
1920                 goto after_ref_id;
1921         }
1922
1923         /*TOP LEVEL FULL POINTER*/
1924         if( pointers_are_top_level
1925         && (type==NDR_POINTER_PTR) ){
1926                 int idx;
1927                 guint32 id;
1928                 proto_item *item;
1929
1930                 /* get the referent id */
1931                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1932
1933                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1934                 /* we got a NULL pointer */
1935                 if(id==0){
1936                         proto_tree_add_text(tree, tvb, offset-4, 4,
1937                                 "(NULL pointer) %s",text);
1938                         goto after_ref_id;
1939                 }
1940
1941                 /* see if we have seen this pointer before */
1942                 idx=find_pointer_index(id);
1943
1944                 /* we have seen this pointer before */
1945                 if(idx>=0){
1946                         proto_tree_add_text(tree, tvb, offset-4, 4,
1947                                 "(duplicate PTR) %s",text);
1948                         goto after_ref_id;
1949                 }
1950
1951                 /* new pointer */
1952                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1953                         "%s", text);
1954                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1955                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1956                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1957                                     callback, callback_args);
1958                 goto after_ref_id;
1959         }
1960         /*TOP LEVEL UNIQUE POINTER*/
1961         if( pointers_are_top_level
1962         && (type==NDR_POINTER_UNIQUE) ){
1963                 guint32 id;
1964                 proto_item *item;
1965
1966                 /* get the referent id */
1967                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1968
1969                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1970                 /* we got a NULL pointer */
1971                 if(id==0){
1972                         proto_tree_add_text(tree, tvb, offset-4, 4,
1973                                 "(NULL pointer) %s",text);
1974                         goto after_ref_id;
1975                 }
1976
1977                 /* new pointer */
1978                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1979                         "%s", text);
1980                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1981                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1982                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1983                                     hf_index, callback, callback_args);
1984                 goto after_ref_id;
1985         }
1986
1987         /*EMBEDDED REFERENCE POINTER*/
1988         if( (!pointers_are_top_level)
1989         && (type==NDR_POINTER_REF) ){
1990                 guint32 id;
1991                 proto_item *item;
1992
1993                 /* get the referent id */
1994                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1995
1996                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1997                 /* new pointer */
1998                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1999                         "%s",text);
2000                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2001                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2002                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
2003                                     hf_index, callback, callback_args);
2004                 goto after_ref_id;
2005         }
2006
2007         /*EMBEDDED UNIQUE POINTER*/
2008         if( (!pointers_are_top_level)
2009         && (type==NDR_POINTER_UNIQUE) ){
2010                 guint32 id;
2011                 proto_item *item;
2012
2013                 /* get the referent id */
2014                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2015
2016                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2017                 /* we got a NULL pointer */
2018                 if(id==0){
2019                         proto_tree_add_text(tree, tvb, offset-4, 4,
2020                                 "(NULL pointer) %s", text);
2021                         goto after_ref_id;
2022                 }
2023
2024                 /* new pointer */
2025                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2026                         "%s",text);
2027                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2028                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2029                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
2030                                     hf_index, callback, callback_args);
2031                 goto after_ref_id;
2032         }
2033
2034         /*EMBEDDED FULL POINTER*/
2035         if( (!pointers_are_top_level)
2036         && (type==NDR_POINTER_PTR) ){
2037                 int idx;
2038                 guint32 id;
2039                 proto_item *item;
2040
2041                 /* get the referent id */
2042                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2043                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2044                 /* we got a NULL pointer */
2045                 if(id==0){
2046                         proto_tree_add_text(tree, tvb, offset-4, 4,
2047                                 "(NULL pointer) %s",text);
2048                         goto after_ref_id;
2049                 }
2050
2051                 /* see if we have seen this pointer before */
2052                 idx=find_pointer_index(id);
2053
2054                 /* we have seen this pointer before */
2055                 if(idx>=0){
2056                         proto_tree_add_text(tree, tvb, offset-4, 4,
2057                                 "(duplicate PTR) %s",text);
2058                         goto after_ref_id;
2059                 }
2060
2061                 /* new pointer */
2062                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2063                         "%s", text);
2064                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2065                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2066                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
2067                                     callback, callback_args);
2068                 goto after_ref_id;
2069         }
2070
2071
2072 after_ref_id:
2073         /* After each top level pointer we have dissected we have to
2074            dissect all deferrals before we move on to the next top level
2075            argument */
2076         if(pointers_are_top_level==TRUE){
2077                 pointers_are_top_level=FALSE;
2078                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
2079                 pointers_are_top_level=TRUE;
2080         }
2081
2082         /* Set the length for the new subtree */
2083         if (tr){
2084                 proto_item_set_len(tr, offset-start_offset);
2085         }
2086         return offset;
2087 }
2088
2089 int
2090 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2091                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2092                     int type, const char *text, int hf_index)
2093 {
2094         return dissect_ndr_pointer_cb(
2095                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2096                 NULL, NULL);
2097 }
2098 int
2099 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2100                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2101                     int type, const char *text, int hf_index)
2102 {
2103         int ret;
2104
2105         pointers_are_top_level=TRUE;
2106         ret=dissect_ndr_pointer_cb(
2107                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2108                 NULL, NULL);
2109         return ret;
2110 }
2111 int
2112 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2113                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2114                     int type, const char *text, int hf_index)
2115 {
2116         int ret;
2117
2118         pointers_are_top_level=FALSE;
2119         ret=dissect_ndr_pointer_cb(
2120                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2121                 NULL, NULL);
2122         return ret;
2123 }
2124
2125 static void
2126 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
2127                 dcerpc_auth_info *auth_info, gboolean is_encrypted)
2128 {
2129   int length, plain_length, auth_pad_len;
2130   guint auth_pad_offset;
2131
2132     /*
2133      * We don't show stub data unless we have some in the tvbuff;
2134      * however, in the protocol tree, we show, as the number of
2135      * bytes, the reported number of bytes, not the number of bytes
2136      * that happen to be in the tvbuff.
2137      */
2138   if (tvb_length_remaining (tvb, offset) > 0) {
2139         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
2140     length = tvb_reported_length_remaining (tvb, offset);
2141
2142         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
2143         plain_length = length - auth_pad_len;
2144           if (plain_length < 1) {
2145             plain_length = length;
2146             auth_pad_len = 0;
2147           }
2148           auth_pad_offset = offset + plain_length;
2149     if (auth_info != NULL &&
2150         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2151       if (is_encrypted) {
2152                     tvb_ensure_bytes_exist(tvb, offset, length);
2153                 proto_tree_add_text(dcerpc_tree, tvb, offset, length,
2154                 "Encrypted stub data (%d byte%s)",
2155                 length, plurality(length, "", "s"));
2156                 /* is the padding is still inside the encrypted blob, don't display it explicit */
2157                     auth_pad_len = 0;
2158       } 
2159       else {
2160                     tvb_ensure_bytes_exist(tvb, offset, plain_length);
2161         proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
2162             "Decrypted stub data (%d byte%s)",
2163             plain_length, plurality(plain_length, "", "s"));
2164       }
2165     } 
2166     else {
2167            tvb_ensure_bytes_exist(tvb, offset, plain_length);
2168      proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
2169             "Stub data (%d byte%s)", plain_length,
2170             plurality(plain_length, "", "s"));
2171     }
2172     /* If there is auth padding at the end of the stub, display it */
2173     if (auth_pad_len != 0) {
2174                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2175       proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
2176                            auth_pad_len, "Auth Padding (%u byte%s)",
2177                            auth_pad_len, plurality(auth_pad_len, "", "s"));
2178     }
2179   }
2180 }
2181
2182 static int
2183 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
2184                     proto_tree *dcerpc_tree,
2185                     tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
2186                     guint8 *drep, dcerpc_info *info,
2187                     dcerpc_auth_info *auth_info)
2188 {
2189     volatile gint offset = 0;
2190     dcerpc_uuid_key key;
2191     dcerpc_uuid_value *sub_proto;
2192     proto_tree *volatile sub_tree = NULL;
2193     dcerpc_sub_dissector *proc;
2194     const gchar *name = NULL;
2195     dcerpc_dissect_fnct_t *volatile sub_dissect;
2196     const char *volatile saved_proto;
2197     void *volatile saved_private_data;
2198     guint length = 0, reported_length = 0;
2199     tvbuff_t *volatile stub_tvb;
2200     volatile guint auth_pad_len;
2201     volatile int auth_pad_offset;
2202     proto_item *sub_item=NULL;
2203     proto_item *pi, *hidden_item;
2204
2205     key.uuid = info->call_data->uuid;
2206     key.ver = info->call_data->ver;
2207
2208
2209     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
2210          || !proto_is_protocol_enabled(sub_proto->proto)) {
2211         /*
2212          * We don't have a dissector for this UUID, or the protocol
2213          * for that UUID is disabled.
2214          */
2215
2216         hidden_item = proto_tree_add_boolean(dcerpc_tree, hf_dcerpc_unknown_if_id,
2217                                                   tvb, offset, 0, TRUE);
2218         PROTO_ITEM_SET_HIDDEN(hidden_item);
2219         if (check_col (pinfo->cinfo, COL_INFO)) {
2220                 col_append_fstr (pinfo->cinfo, COL_INFO, " %s V%u",
2221                         guids_resolve_uuid_to_str(&info->call_data->uuid), info->call_data->ver);
2222         }
2223
2224         if (decrypted_tvb != NULL) {
2225             show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
2226                             FALSE);
2227         } else
2228             show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
2229         return -1;
2230     }
2231
2232     for (proc = sub_proto->procs; proc->name; proc++) {
2233         if (proc->num == info->call_data->opnum) {
2234             name = proc->name;
2235             break;
2236         }
2237     }
2238
2239     if (!name)
2240         name = "Unknown?!";
2241
2242     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
2243         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
2244     }
2245
2246     if (check_col (pinfo->cinfo, COL_INFO)) {
2247         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
2248                       name, (info->ptype == PDU_REQ) ? "request" : "response");
2249     }
2250
2251     sub_dissect = (info->ptype == PDU_REQ) ?
2252             proc->dissect_rqst : proc->dissect_resp;
2253
2254     if (tree) {
2255         sub_item = proto_tree_add_item (tree, sub_proto->proto_id,
2256                                         (decrypted_tvb != NULL)?decrypted_tvb:tvb,
2257                                         0, -1, FALSE);
2258
2259         if (sub_item) {
2260             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
2261             proto_item_append_text(sub_item, ", %s", name);
2262         }
2263
2264         /*
2265          * Put the operation number into the tree along with
2266          * the operation's name.
2267          */
2268         if (sub_proto->opnum_hf != -1)
2269                 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
2270                                            tvb, 0, 0, info->call_data->opnum,
2271                                            "Operation: %s (%u)",
2272                                            name, info->call_data->opnum);
2273         else
2274                 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
2275                                            0, 0, info->call_data->opnum,
2276                                            "Operation: %s (%u)",
2277                                            name, info->call_data->opnum);
2278
2279         if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
2280             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
2281                                      tvb, 0, 0, info->call_data->rep_frame);
2282             PROTO_ITEM_SET_GENERATED(pi);
2283         }
2284         if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
2285             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
2286                                      tvb, 0, 0, info->call_data->req_frame);
2287             PROTO_ITEM_SET_GENERATED(pi);
2288         }
2289     } /* tree */
2290
2291     if (decrypted_tvb != NULL) {
2292         /* Either there was no encryption or we successfully decrypted
2293            the encrypted payload. */
2294         if (sub_dissect) {
2295             /* We have a subdissector - call it. */
2296             saved_proto = pinfo->current_proto;
2297             saved_private_data = pinfo->private_data;
2298             pinfo->current_proto = sub_proto->name;
2299             pinfo->private_data = (void *)info;
2300
2301             init_ndr_pointer_list(pinfo);
2302
2303             length = tvb_length(decrypted_tvb);
2304             reported_length = tvb_reported_length(decrypted_tvb);
2305
2306             /*
2307              * Remove the authentication padding from the stub data.
2308              */
2309             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
2310                 if (reported_length >= auth_info->auth_pad_len) {
2311                     /*
2312                      * OK, the padding length isn't so big that it
2313                      * exceeds the stub length.  Trim the reported
2314                      * length of the tvbuff.
2315                      */
2316                     reported_length -= auth_info->auth_pad_len;
2317
2318                     /*
2319                      * If that exceeds the actual amount of data in
2320                      * the tvbuff (which means we have at least one
2321                      * byte of authentication padding in the tvbuff),
2322                      * trim the actual amount.
2323                      */
2324                     if (length > reported_length)
2325                         length = reported_length;
2326
2327                     stub_tvb = tvb_new_subset(decrypted_tvb, 0, length, reported_length);
2328                     auth_pad_len = auth_info->auth_pad_len;
2329                     auth_pad_offset = reported_length;
2330                 } else {
2331                     /*
2332                      * The padding length exceeds the stub length.
2333                      * Don't bother dissecting the stub, trim the padding
2334                      * length to what's in the stub data, and show the
2335                      * entire stub as authentication padding.
2336                      */
2337                     stub_tvb = NULL;
2338                     auth_pad_len = reported_length;
2339                     auth_pad_offset = 0;
2340                     length = 0;
2341                     reported_length = 0;
2342                 }
2343             } else {
2344                 /*
2345                  * No authentication padding.
2346                  */
2347                 stub_tvb = decrypted_tvb;
2348                 auth_pad_len = 0;
2349                 auth_pad_offset = 0;
2350             }
2351
2352             if (sub_item) {
2353                 proto_item_set_len(sub_item, length);
2354             }
2355
2356             if (stub_tvb != NULL) {
2357                 /*
2358                  * Catch all exceptions other than BoundsError, so that even
2359                  * if the stub data is bad, we still show the authentication
2360                  * padding, if any.
2361                  *
2362                  * If we get BoundsError, it means the frame was cut short
2363                  * by a snapshot length, so there's nothing more to
2364                  * dissect; just re-throw that exception.
2365                  */
2366                 TRY {
2367                     int remaining;
2368
2369                     offset = sub_dissect (stub_tvb, 0, pinfo, sub_tree,
2370                                           drep);
2371
2372                     /* If we have a subdissector and it didn't dissect all
2373                        data in the tvb, make a note of it. */
2374                     remaining = tvb_reported_length_remaining(stub_tvb, offset);
2375                     if (remaining > 0) {
2376                         proto_tree_add_text(sub_tree, stub_tvb, offset,
2377                                             remaining,
2378                                             "[Long frame (%d byte%s)]",
2379                                             remaining,
2380                                             plurality(remaining, "", "s"));
2381                         if (check_col(pinfo->cinfo, COL_INFO))
2382                             col_append_fstr(pinfo->cinfo, COL_INFO,
2383                                             "[Long frame (%d byte%s)]",
2384                                             remaining,
2385                                             plurality(remaining, "", "s"));
2386
2387                     }
2388                 } CATCH(BoundsError) {
2389                     RETHROW;
2390                 } CATCH_ALL {
2391                     show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2392                 } ENDTRY;
2393             }
2394
2395             /* If there is auth padding at the end of the stub, display it */
2396             if (auth_pad_len != 0) {
2397                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2398                 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
2399                                      auth_pad_len,
2400                                      "Auth Padding (%u byte%s)",
2401                                      auth_pad_len,
2402                                      plurality(auth_pad_len, "", "s"));
2403             }
2404
2405             pinfo->current_proto = saved_proto;
2406             pinfo->private_data = saved_private_data;
2407         } else {
2408             /* No subdissector - show it as stub data. */
2409             if(decrypted_tvb){
2410                show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
2411             } else {
2412                show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2413             }
2414         }
2415     } else
2416         show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2417
2418     tap_queue_packet(dcerpc_tap, pinfo, info);
2419     return 0;
2420 }
2421
2422 static int
2423 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
2424                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2425                          dcerpc_auth_info *auth_info)
2426 {
2427     int auth_offset;
2428
2429     auth_info->auth_data = NULL;
2430
2431     if (auth_info->auth_size != 0) {
2432         dcerpc_auth_subdissector_fns *auth_fns;
2433         tvbuff_t *auth_tvb;
2434
2435         auth_offset = hdr->frag_len - hdr->auth_len;
2436
2437         auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
2438                                   hdr->auth_len);
2439
2440         auth_info->auth_data = auth_tvb;
2441
2442         if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2443                                                   auth_info->auth_type))) {
2444             /*
2445              * Catch all exceptions, so that even if the verifier is bad
2446              * or we don't have all of it, we still show the stub data.
2447              */
2448             TRY {
2449                 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2450                                   hdr, auth_info);
2451             } CATCH_ALL {
2452                 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2453             } ENDTRY;
2454         } else {
2455             tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
2456             proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
2457                                  "Auth Verifier");
2458         }
2459     }
2460
2461     return hdr->auth_len;
2462 }
2463
2464 static void
2465 dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
2466                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2467                         gboolean are_credentials, dcerpc_auth_info *auth_info)
2468 {
2469     volatile int offset;
2470
2471     /*
2472      * Initially set auth_level and auth_type to zero to indicate that we
2473      * haven't yet seen any authentication level information.
2474      */
2475     auth_info->auth_level = 0;
2476     auth_info->auth_type = 0;
2477     auth_info->auth_size = 0;
2478     auth_info->auth_pad_len = 0;
2479
2480     /*
2481      * The authentication information is at the *end* of the PDU; in
2482      * request and response PDUs, the request and response stub data
2483      * come before it.
2484      *
2485      * Is there any authentication data (i.e., is the authentication length
2486      * non-zero), and is the authentication length valid (i.e., is it, plus
2487      * 8 bytes for the type/level/pad length/reserved/context id, less than
2488      * or equal to the fragment length minus the starting offset of the
2489      * stub data?)
2490      */
2491
2492     if (hdr->auth_len
2493         && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
2494
2495         /*
2496          * Yes, there is authentication data, and the length is valid.
2497          * Do we have all the bytes of stub data?
2498          * (If not, we'd throw an exception dissecting *that*, so don't
2499          * bother trying to dissect the authentication information and
2500          * throwing another exception there.)
2501          */
2502         offset = hdr->frag_len - (hdr->auth_len + 8);
2503         if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
2504             /*
2505              * Either there's no stub data, or the last byte of the stub
2506              * data is present in the captured data, so we shouldn't
2507              * get a BoundsError dissecting the stub data.
2508              *
2509              * Try dissecting the authentication data.
2510              * Catch all exceptions, so that even if the auth info is bad
2511              * or we don't have all of it, we still show the stuff we
2512              * dissect after this, such as stub data.
2513              */
2514             TRY {
2515                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2516                                                hf_dcerpc_auth_type,
2517                                                &auth_info->auth_type);
2518                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2519                                                hf_dcerpc_auth_level,
2520                                                &auth_info->auth_level);
2521
2522                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2523                                                hf_dcerpc_auth_pad_len,
2524                                                &auth_info->auth_pad_len);
2525                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2526                                                hf_dcerpc_auth_rsrvd, NULL);
2527                 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2528                                                 hf_dcerpc_auth_ctx_id, NULL);
2529
2530                 /*
2531                  * Dissect the authentication data.
2532                  */
2533                 if (are_credentials) {
2534                     tvbuff_t *auth_tvb;
2535                     dcerpc_auth_subdissector_fns *auth_fns;
2536
2537                     auth_tvb = tvb_new_subset(tvb, offset,
2538                                    MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
2539                                    hdr->auth_len);
2540
2541                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2542                                                               auth_info->auth_type)))
2543                         dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2544                                           hdr, auth_info);
2545                     else
2546                         proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
2547                                              "Auth Credentials");
2548                 }
2549
2550                 /* Compute the size of the auth block.  Note that this should not
2551                    include auth padding, since when NTLMSSP encryption is used, the
2552                    padding is actually inside the encrypted stub */
2553                    auth_info->auth_size = hdr->auth_len + 8;
2554             } CATCH_ALL {
2555                 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2556             } ENDTRY;
2557         }
2558     }
2559 }
2560
2561
2562 /* We need to hash in the SMB fid number to generate a unique hash table
2563  * key as DCERPC over SMB allows several pipes over the same TCP/IP
2564  * socket.
2565  * We pass this function the transport type here to make sure we only look
2566  * at this function if it came across an SMB pipe.
2567  * Other transports might need to mix in their own extra multiplexing data
2568  * as well in the future.
2569  */
2570
2571 guint16 dcerpc_get_transport_salt (packet_info *pinfo)
2572 {
2573     switch(pinfo->dcetransporttype){
2574         case DCE_CN_TRANSPORT_SMBPIPE:
2575             /* DCERPC over smb */
2576             return pinfo->dcetransportsalt;
2577     }
2578
2579     /* Some other transport... */
2580     return 0;
2581 }
2582
2583 /*
2584  * Connection oriented packet types
2585  */
2586
2587 static void
2588 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2589                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2590 {
2591     conversation_t *conv = NULL;
2592     guint8 num_ctx_items = 0;
2593     guint i;
2594     gboolean saw_ctx_item = FALSE;
2595     guint16 ctx_id;
2596     guint8 num_trans_items;
2597     guint j;
2598     e_uuid_t if_id;
2599     e_uuid_t trans_id;
2600     guint32 trans_ver;
2601     guint16 if_ver, if_ver_minor;
2602     dcerpc_auth_info auth_info;
2603     char *uuid_str;
2604     const char *uuid_name = NULL;
2605     proto_item *iface_item = NULL;
2606
2607     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2608                                     hf_dcerpc_cn_max_xmit, NULL);
2609
2610     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2611                                     hf_dcerpc_cn_max_recv, NULL);
2612
2613     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2614                                     hf_dcerpc_cn_assoc_group, NULL);
2615
2616     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2617                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2618
2619     /* padding */
2620     offset += 3;
2621
2622     for (i = 0; i < num_ctx_items; i++) {
2623             proto_item *ctx_item = NULL;
2624             proto_tree *ctx_tree = NULL, *iface_tree = NULL;
2625         gint ctx_offset = offset;
2626
2627       dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
2628                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2629
2630       /* save context ID for use with dcerpc_add_conv_to_bind_table() */
2631       /* (if we have multiple contexts, this might cause "decode as"
2632        *  to behave unpredictably) */
2633       pinfo->dcectxid = ctx_id;
2634
2635       if (dcerpc_tree) {
2636               ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
2637                                              tvb, offset, 0,
2638                                              hdr->drep[0] & 0x10);
2639               ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2640       }
2641
2642       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2643                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2644       offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2645                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
2646
2647       if(dcerpc_tree) {
2648         proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
2649       }
2650
2651       /* padding */
2652       offset += 1;
2653
2654       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2655       if (ctx_tree) {
2656
2657       iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
2658           iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
2659
2660       uuid_str = guid_to_str((e_guid_t*)&if_id);
2661       uuid_name = guids_get_uuid_name(&if_id);
2662       if(uuid_name) {
2663                   proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2664                                         offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
2665           proto_item_append_text(iface_item, ": %s", uuid_name);
2666       } else {
2667           proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2668                                         offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
2669           proto_item_append_text(iface_item, ": %s", uuid_str);
2670       }
2671       }
2672       offset += 16;
2673
2674       if (hdr->drep[0] & 0x10) {
2675           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2676                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2677           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2678                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2679       } else {
2680           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2681                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2682           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2683                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2684       }
2685
2686       if (ctx_tree) {
2687           proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
2688           proto_item_set_len(iface_item, 20);
2689       }
2690
2691       if (!saw_ctx_item) {
2692         conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2693                                   pinfo->srcport, pinfo->destport, 0);
2694         if (conv == NULL) {
2695         fprintf(stderr,"Creating a new conv on packet %d\n",pinfo->fd->num);
2696             conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2697                                      pinfo->srcport, pinfo->destport, 0);
2698         }
2699
2700
2701         /* if this is the first time we see this packet, we need to
2702            update the dcerpc_binds table so that any later calls can
2703            match to the interface.
2704            XXX We assume that BINDs will NEVER be fragmented.
2705         */
2706         if(!(pinfo->fd->flags.visited)){
2707                 dcerpc_bind_key *key;
2708                 dcerpc_bind_value *value;
2709
2710                 key = se_alloc (sizeof (dcerpc_bind_key));
2711                 key->conv = conv;
2712                 key->ctx_id = ctx_id;
2713                 key->smb_fid = dcerpc_get_transport_salt(pinfo);
2714
2715                 value = se_alloc (sizeof (dcerpc_bind_value));
2716                 value->uuid = if_id;
2717                 value->ver = if_ver;
2718
2719                 /* add this entry to the bind table, first removing any
2720                    previous ones that are identical
2721                  */
2722                 if(g_hash_table_lookup(dcerpc_binds, key)){
2723                         g_hash_table_remove(dcerpc_binds, key);
2724                 }
2725                 g_hash_table_insert (dcerpc_binds, key, value);
2726         }
2727
2728         if (check_col (pinfo->cinfo, COL_INFO)) {
2729           if (num_ctx_items > 1)
2730                   col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
2731
2732                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u.%u",
2733                        guids_resolve_uuid_to_str(&if_id), if_ver, if_ver_minor);
2734         }
2735         saw_ctx_item = TRUE;
2736       }
2737
2738       for (j = 0; j < num_trans_items; j++) {
2739             proto_tree *trans_tree = NULL;
2740             proto_item *trans_item = NULL;
2741
2742         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2743         if (ctx_tree) {
2744
2745         trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
2746         trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
2747
2748         uuid_str = guid_to_str((e_guid_t *) &trans_id);
2749             proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2750                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2751             proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
2752         }
2753         offset += 16;
2754
2755         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
2756                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2757         if (ctx_tree) {
2758           proto_item_set_len(trans_item, 20);
2759           proto_item_append_text(trans_item, " V%u", trans_ver);
2760         }
2761       }
2762
2763       if(ctx_tree) {
2764         proto_item_set_len(ctx_item, offset - ctx_offset);
2765       }
2766     }
2767
2768     /*
2769      * XXX - we should save the authentication type *if* we have
2770      * an authentication header, and associate it with an authentication
2771      * context, so subsequent PDUs can use that context.
2772      */
2773     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2774 }
2775
2776 static void
2777 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2778                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2779 {
2780     guint16 max_xmit, max_recv;
2781     guint16 sec_addr_len;
2782     guint8 num_results;
2783     guint i;
2784     guint16 result;
2785     guint16 reason;
2786     e_uuid_t trans_id;
2787     guint32 trans_ver;
2788     dcerpc_auth_info auth_info;
2789
2790     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2791                                     hf_dcerpc_cn_max_xmit, &max_xmit);
2792
2793     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2794                                     hf_dcerpc_cn_max_recv, &max_recv);
2795
2796     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2797                                     hf_dcerpc_cn_assoc_group, NULL);
2798
2799     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2800                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2801     if (sec_addr_len != 0) {
2802         tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
2803         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2804                              sec_addr_len, FALSE);
2805         offset += sec_addr_len;
2806     }
2807
2808     if (offset % 4) {
2809         offset += 4 - offset % 4;
2810     }
2811
2812     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2813                                    hf_dcerpc_cn_num_results, &num_results);
2814
2815     /* padding */
2816     offset += 3;
2817
2818     for (i = 0; i < num_results; i++) {
2819         proto_tree *ctx_tree = NULL;
2820
2821         if(dcerpc_tree){
2822                 proto_item *ctx_item;
2823                 ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
2824                 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2825         }
2826
2827         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2828                                         hdr->drep, hf_dcerpc_cn_ack_result,
2829                                         &result);
2830         if (result != 0) {
2831             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2832                                             hdr->drep, hf_dcerpc_cn_ack_reason,
2833                                             &reason);
2834         } else {
2835             /*
2836              * The reason for rejection isn't meaningful, and often isn't
2837              * set, when the syntax was accepted.
2838              */
2839             offset += 2;
2840         }
2841
2842         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2843         if (ctx_tree) {
2844             proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2845                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s",
2846                                           guid_to_str((e_guid_t *) &trans_id));
2847         }
2848         offset += 16;
2849
2850         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2851                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2852     }
2853
2854     /*
2855      * XXX - do we need to do anything with the authentication level
2856      * we get back from this?
2857      */
2858     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2859
2860     if (check_col (pinfo->cinfo, COL_INFO)) {
2861         if (num_results != 0) {
2862             if (result == 0) {
2863                 /* XXX - only checks the last result */
2864                 col_append_fstr (pinfo->cinfo, COL_INFO,
2865                                  " accept max_xmit: %u max_recv: %u",
2866                                  max_xmit, max_recv);
2867             } else {
2868                 /* XXX - only shows the last result and reason */
2869                 col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2870                                  val_to_str(result, p_cont_result_vals,
2871                                             "Unknown result (%u)"),
2872                                  val_to_str(reason, p_provider_reason_vals,
2873                                             "Unknown (%u)"));
2874             }
2875         }
2876     }
2877 }
2878
2879 static void
2880 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2881                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2882 {
2883     guint16 reason;
2884     guint8 num_protocols;
2885     guint i;
2886
2887     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2888                                     hdr->drep, hf_dcerpc_cn_reject_reason,
2889                                     &reason);
2890
2891     if (check_col (pinfo->cinfo, COL_INFO)) {
2892         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2893                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2894     }
2895
2896     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2897         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2898                                        hf_dcerpc_cn_num_protocols,
2899                                        &num_protocols);
2900
2901         for (i = 0; i < num_protocols; i++) {
2902             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2903                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2904                                         NULL);
2905             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2906                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2907                                         NULL);
2908         }
2909     }
2910 }
2911
2912 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2913    fragment. */
2914
2915 #define PFC_FRAG_MASK  0x03
2916
2917 static const char *
2918 fragment_type(guint8 flags)
2919 {
2920         flags = flags & PFC_FRAG_MASK;
2921
2922         if (flags == PFC_FIRST_FRAG)
2923                 return "first";
2924
2925         if (flags == 0)
2926                 return "middle";
2927
2928         if (flags == PFC_LAST_FRAG)
2929                 return "last";
2930
2931         if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
2932                 return "whole";
2933
2934         return "unknown";
2935 }
2936
2937 /* Dissect stub data (payload) of a DCERPC packet. */
2938
2939 static void
2940 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2941                         proto_tree *dcerpc_tree, proto_tree *tree,
2942                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
2943                         dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
2944                         guint32 frame)
2945 {
2946     gint length, reported_length;
2947     gboolean save_fragmented;
2948     fragment_data *fd_head=NULL;
2949
2950     tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
2951     proto_item *pi;
2952     proto_item *parent_pi;
2953     proto_item *dcerpc_tree_item;
2954
2955     save_fragmented = pinfo->fragmented;
2956     length = tvb_length_remaining(tvb, offset);
2957     reported_length = tvb_reported_length_remaining(tvb, offset);
2958     if (reported_length < 0 ||
2959             (guint32)reported_length < auth_info->auth_size) {
2960         /* We don't even have enough bytes for the authentication
2961            stuff. */
2962             return;
2963     }
2964     reported_length -= auth_info->auth_size;
2965     if (length > reported_length)
2966             length = reported_length;
2967     payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
2968
2969     auth_tvb=NULL;
2970     /*dont bother if we dont have the entire tvb */
2971     /*XXX we should really make sure we calculate auth_info->auth_data
2972            *and use that one instead of this auth_tvb hack
2973      */
2974     if(tvb_length(tvb)==tvb_reported_length(tvb)){
2975         if(tvb_length_remaining(tvb, offset+length)>8){
2976             auth_tvb = tvb_new_subset_remaining(tvb, offset+length+8);
2977         }
2978     }
2979
2980     /* Decrypt the PDU if it is encrypted */
2981
2982     if (auth_info->auth_type &&
2983         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2984             /*
2985              * We know the authentication type, and the authentication
2986              * level is "Packet privacy", meaning the payload is
2987              * encrypted; attempt to decrypt it.
2988              */
2989             dcerpc_auth_subdissector_fns *auth_fns;
2990
2991             /* Start out assuming we won't succeed in decrypting. */
2992             decrypted_tvb = NULL;
2993       /* Schannel needs informations into the footer (verifier) in order to setup decryptions keys 
2994        * so we call it in order to have a chance to decypher the data 
2995        */
2996       if (DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN == auth_info->auth_type) {
2997         dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, auth_info);
2998       }
2999
3000             if ((auth_fns = get_auth_subdissector_fns(
3001                          auth_info->auth_level, auth_info->auth_type))) {
3002                     tvbuff_t *result;
3003                     result = decode_encrypted_data( payload_tvb, auth_tvb, pinfo, auth_fns,
3004                              hdr->ptype == PDU_REQ, auth_info);
3005                     if (result) {
3006                             if (dcerpc_tree) {
3007                                     proto_tree_add_text(dcerpc_tree, payload_tvb, 0, -1,
3008                                             "Encrypted stub data (%d byte%s)",
3009                                             tvb_reported_length(payload_tvb),
3010                                 plurality(tvb_length(payload_tvb), "", "s"));
3011           }
3012                             add_new_data_source(pinfo, result, "Decrypted stub data");
3013                             /* We succeeded. */
3014                             decrypted_tvb = result;
3015                     }
3016             }
3017     } 
3018     else
3019             decrypted_tvb = payload_tvb;
3020
3021     /* if this packet is not fragmented, just dissect it and exit */
3022     if(PFC_NOT_FRAGMENTED(hdr)) {
3023             pinfo->fragmented = FALSE;
3024
3025             dcerpc_try_handoff( pinfo, tree, dcerpc_tree, payload_tvb, 
3026           decrypted_tvb, hdr->drep, di, auth_info);
3027
3028            pinfo->fragmented = save_fragmented;
3029            return;
3030     }
3031
3032     /* The packet is fragmented. */
3033     pinfo->fragmented = TRUE;
3034
3035           /* debug output of essential fragment data. */
3036           /* leave it here for future debugging sessions */
3037           /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
3038                    pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
3039
3040     /* if we are not doing reassembly and this is the first fragment
3041        then just dissect it and exit
3042        XXX - if we're not doing reassembly, can we decrypt an
3043        encrypted stub?
3044     */
3045     if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
3046
3047         dcerpc_try_handoff(
3048                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
3049                 hdr->drep, di, auth_info);
3050
3051         if (check_col(pinfo->cinfo, COL_INFO)) {
3052             col_append_fstr(pinfo->cinfo, COL_INFO,
3053                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3054         }
3055                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3056                         "%s fragment", fragment_type(hdr->flags));
3057         pinfo->fragmented = save_fragmented;
3058         return;
3059     }
3060
3061     /* if we have already seen this packet, see if it was reassembled
3062        and if so dissect the full pdu.
3063        then exit
3064     */
3065     if(pinfo->fd->flags.visited){
3066         fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
3067         goto end_cn_stub;
3068     }
3069
3070     /* if we are not doing reassembly and it was neither a complete PDU
3071        nor the first fragment then there is nothing more we can do
3072        so we just have to exit
3073     */
3074     if( !dcerpc_reassemble || (tvb_length(tvb)!=tvb_reported_length(tvb)) )
3075         goto end_cn_stub;
3076
3077     /* if we didnt get 'frame' we dont know where the PDU started and thus
3078        it is pointless to continue
3079     */
3080     if(!frame)
3081         goto end_cn_stub;
3082
3083     /* from now on we must attempt to reassemble the PDU
3084     */
3085
3086     /* if we get here we know it is the first time we see the packet
3087        and we also know it is only a fragment and not a full PDU,
3088        thus we must reassemble it.
3089     */
3090
3091     /* Do we have any non-encrypted data to reassemble? */
3092     if (decrypted_tvb == NULL) {
3093       /* No.  We can't even try to reassemble.  */
3094       goto end_cn_stub;
3095     }
3096
3097     /* defragmentation is a bit tricky, as there's no offset of the fragment
3098      * in the protocol data.
3099      *
3100      * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
3101      * in with the correct sequence.
3102      */
3103     fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
3104                 dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3105                 tvb_length(decrypted_tvb),
3106                 hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
3107
3108 end_cn_stub:
3109
3110     /* if reassembly is complete and this is the last fragment
3111          * (multiple fragments in one PDU are possible!)
3112          * dissect the full PDU
3113      */
3114     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
3115
3116         if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
3117             tvbuff_t *next_tvb;
3118         proto_item *frag_tree_item;
3119
3120             next_tvb = tvb_new_child_real_data((decrypted_tvb)?decrypted_tvb:payload_tvb,
3121                                  fd_head->data, fd_head->len, fd_head->len);
3122
3123             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3124             show_fragment_tree(fd_head, &dcerpc_frag_items,
3125                         tree, pinfo, next_tvb, &frag_tree_item);
3126                 /* the toplevel fragment subtree is now behind all desegmented data,
3127                  * move it right behind the DCE/RPC tree */
3128                 dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
3129                 if(frag_tree_item && dcerpc_tree_item) {
3130                         proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
3131                 }
3132
3133             pinfo->fragmented = FALSE;
3134
3135                 expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
3136                         "%s fragment, reassembled",
3137                         fragment_type(hdr->flags));
3138
3139             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
3140                 next_tvb, hdr->drep, di, auth_info);
3141
3142         } else {
3143             if(decrypted_tvb){
3144                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3145                                 decrypted_tvb, 0, 0, fd_head->reassembled_in);
3146             } else {
3147                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3148                                 payload_tvb, 0, 0, fd_head->reassembled_in);
3149             }
3150         PROTO_ITEM_SET_GENERATED(pi);
3151         parent_pi = proto_tree_get_parent(dcerpc_tree);
3152         if(parent_pi != NULL) {
3153             proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
3154         }
3155             if (check_col(pinfo->cinfo, COL_INFO)) {
3156                 col_append_fstr(pinfo->cinfo, COL_INFO,
3157                         " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
3158             }
3159                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3160                         "%s fragment, reassembled in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
3161         }
3162     } else {
3163         /* Reassembly not complete - some fragments
3164            are missing.  Just show the stub data. */
3165         if (check_col(pinfo->cinfo, COL_INFO)) {
3166             col_append_fstr(pinfo->cinfo, COL_INFO,
3167                         " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3168         }
3169         expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3170                 "%s fragment", fragment_type(hdr->flags));
3171
3172         if(decrypted_tvb){
3173                 show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
3174         } else {
3175                 show_stub_data (payload_tvb, 0, tree, auth_info, TRUE);
3176         }
3177     }
3178
3179     pinfo->fragmented = save_fragmented;
3180 }
3181
3182 /**
3183  *  Registers a conversation/UUID binding association, so that
3184  *  we can invoke the proper sub-dissector for a given DCERPC
3185  *  conversation.
3186  *
3187  *  @param binding all values needed to create and bind a new conversation
3188  *
3189  *  @return Pointer to newly-added UUID/conversation binding.
3190  */
3191 struct _dcerpc_bind_value *
3192 dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
3193 {
3194     dcerpc_bind_value *bind_value;
3195     dcerpc_bind_key *key;
3196     conversation_t *conv;
3197
3198     conv = find_conversation (
3199         0,
3200         &binding->addr_a,
3201         &binding->addr_b,
3202         binding->ptype,
3203         binding->port_a,
3204         binding->port_b,
3205         0);
3206
3207     if (!conv) {
3208         fprintf(stderr,"Creating a new conv on this bind packet \n");
3209         conv = conversation_new (
3210             0,
3211             &binding->addr_a,
3212             &binding->addr_b,
3213             binding->ptype,
3214             binding->port_a,
3215             binding->port_b,
3216             0);
3217     }
3218
3219     bind_value = se_alloc (sizeof (dcerpc_bind_value));
3220     bind_value->uuid = binding->uuid;
3221     bind_value->ver = binding->ver;
3222
3223     key = se_alloc(sizeof (dcerpc_bind_key));
3224     key->conv = conv;
3225     key->ctx_id = binding->ctx_id;
3226     key->smb_fid = binding->smb_fid;
3227
3228     /* add this entry to the bind table, first removing any
3229        previous ones that are identical
3230      */
3231     if(g_hash_table_lookup(dcerpc_binds, key)){
3232             g_hash_table_remove(dcerpc_binds, key);
3233     }
3234     g_hash_table_insert(dcerpc_binds, key, bind_value);
3235
3236     return bind_value;
3237
3238 }
3239
3240 static void
3241 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3242                         proto_tree *dcerpc_tree, proto_tree *tree,
3243                         e_dce_cn_common_hdr_t *hdr)
3244 {
3245     conversation_t *conv;
3246     guint16 ctx_id;
3247     guint16 opnum;
3248     e_uuid_t obj_id = DCERPC_UUID_NULL;
3249     dcerpc_auth_info auth_info;
3250     guint32 alloc_hint;
3251     proto_item *pi;
3252     proto_item *parent_pi;
3253     dcerpc_matched_key matched_key, *new_matched_key;
3254     dcerpc_call_value *value;
3255
3256     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3257                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3258
3259     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3260                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3261     parent_pi = proto_tree_get_parent(dcerpc_tree);
3262     if(parent_pi != NULL) {
3263         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3264     }
3265
3266     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3267                 if(pinfo->dcectxid == 0) {
3268                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3269                 } else {
3270                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3271                          * prepend a delimiter */
3272                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3273                 }
3274     }
3275
3276     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3277                                     hf_dcerpc_opnum, &opnum);
3278
3279     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3280     pinfo->dcectxid = ctx_id;
3281
3282     if (check_col (pinfo->cinfo, COL_INFO)) {
3283         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
3284                          opnum, ctx_id);
3285     }
3286
3287     if (hdr->flags & PFC_OBJECT_UUID) {
3288         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
3289         if (dcerpc_tree) {
3290             proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3291                                           offset, 16, (e_guid_t *) &obj_id, "Object UUID: %s",
3292                                           guid_to_str((e_guid_t *) &obj_id));
3293         }
3294         offset += 16;
3295     }
3296
3297     /*
3298      * XXX - what if this was set when the connection was set up,
3299      * and we just have a security context?
3300      */
3301     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3302     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3303                               pinfo->srcport, pinfo->destport, 0);
3304     if (!conv) {
3305       /*conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3306                       pinfo->srcport, pinfo->destport, 0);*/
3307        fprintf(stderr,"No conv showing raw stuf %d \n",pinfo->fd->num);
3308        show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3309     }
3310     else {
3311     /* !!! we can NOT check flags.visited here since this will interact
3312        badly with when SMB handles (i.e. calls the subdissector)
3313        and desegmented pdu's .
3314        Instead we check if this pdu is already in the matched table or not
3315     */
3316       matched_key.frame = pinfo->fd->num;
3317       matched_key.call_id = hdr->call_id;
3318       value = g_hash_table_lookup(dcerpc_matched, &matched_key);
3319       if(!value) {
3320         dcerpc_bind_key bind_key;
3321         dcerpc_bind_value *bind_value;
3322
3323         bind_key.conv=conv;
3324         bind_key.ctx_id=ctx_id;
3325         bind_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3326         if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
3327         if(!(hdr->flags&PFC_FIRST_FRAG)){
3328           dcerpc_cn_call_key call_key;
3329           dcerpc_call_value *call_value;
3330
3331           call_key.conv=conv;
3332           call_key.call_id=hdr->call_id;
3333           call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3334           if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3335             new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3336             *new_matched_key = matched_key;
3337             g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3338             value = call_value;
3339           }
3340         } 
3341         else {
3342           dcerpc_cn_call_key *call_key;
3343           dcerpc_call_value *call_value;
3344
3345           /* We found the binding and it is the first fragment
3346              (or a complete PDU) of a dcerpc pdu so just add
3347              the call to both the call table and the
3348              matched table
3349           */
3350           call_key=se_alloc (sizeof (dcerpc_cn_call_key));
3351           call_key->conv=conv;
3352           call_key->call_id=hdr->call_id;
3353           call_key->smb_fid=dcerpc_get_transport_salt(pinfo);
3354
3355           /* if there is already a matching call in the table
3356              remove it so it is replaced with the new one */
3357           if(g_hash_table_lookup(dcerpc_cn_calls, call_key)){
3358             g_hash_table_remove(dcerpc_cn_calls, call_key);
3359           }
3360
3361           call_value=se_alloc (sizeof (dcerpc_call_value));
3362           call_value->uuid = bind_value->uuid;
3363           call_value->ver = bind_value->ver;
3364           call_value->object_uuid = obj_id;
3365           call_value->opnum = opnum;
3366           call_value->req_frame=pinfo->fd->num;
3367           call_value->req_time=pinfo->fd->abs_ts;
3368           call_value->rep_frame=0;
3369           call_value->max_ptr=0;
3370           call_value->se_data = NULL;
3371           call_value->private_data = NULL;
3372           call_value->pol = NULL;
3373           g_hash_table_insert (dcerpc_cn_calls, call_key, call_value);
3374
3375           new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3376           *new_matched_key = matched_key;
3377           g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3378           value = call_value;   
3379         } 
3380       }
3381     }
3382     if (value) {
3383       dcerpc_info *di;
3384       di=get_next_di();
3385       /* handoff this call */
3386       di->conv = conv;
3387       di->call_id = hdr->call_id;
3388       di->smb_fid = dcerpc_get_transport_salt(pinfo);
3389       di->ptype = PDU_REQ;
3390       di->call_data = value;
3391       di->hf_index = -1;
3392
3393       if(value->rep_frame!=0){
3394         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
3395             tvb, 0, 0, value->rep_frame);
3396         PROTO_ITEM_SET_GENERATED(pi);
3397         if(parent_pi != NULL) {
3398             proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
3399         }
3400       }
3401       dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3402             hdr, di, &auth_info, alloc_hint,
3403             value->req_frame);
3404     } 
3405     else {
3406       /* no bind information, simply show stub data */
3407       pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3408       PROTO_ITEM_SET_GENERATED(pi);
3409       expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",
3410           ctx_id);
3411       show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3412     }
3413   }
3414   /* Dissect the verifier */
3415   dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3416
3417 }
3418
3419 static void
3420 dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3421                         proto_tree *dcerpc_tree, proto_tree *tree,
3422                         e_dce_cn_common_hdr_t *hdr)
3423 {
3424     dcerpc_call_value *value = NULL;
3425     conversation_t *conv;
3426     guint16 ctx_id;
3427     dcerpc_auth_info auth_info;
3428     guint32 alloc_hint;
3429     proto_item *pi;
3430     proto_item *parent_pi;
3431     e_uuid_t obj_id_null = DCERPC_UUID_NULL;
3432
3433     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3434                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3435
3436     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3437                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3438     parent_pi = proto_tree_get_parent(dcerpc_tree);
3439     if(parent_pi != NULL) {
3440         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3441     }
3442
3443     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3444                   if(pinfo->dcectxid == 0) {
3445                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3446                 } else {
3447                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3448                          * prepend a delimiter */
3449                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3450                 }
3451     }
3452
3453     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3454     pinfo->dcectxid = ctx_id;
3455
3456     if (check_col (pinfo->cinfo, COL_INFO)) {
3457         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
3458     }
3459
3460     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3461                                    hf_dcerpc_cn_cancel_count, NULL);
3462     /* padding */
3463     offset++;
3464
3465     /*
3466      * XXX - what if this was set when the connection was set up,
3467      * and we just have a security context?
3468      */
3469     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3470
3471     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3472                               pinfo->srcport, pinfo->destport, 0);
3473
3474     if (!conv) {
3475         /* no point in creating one here, really */
3476         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3477     } else {
3478             dcerpc_matched_key matched_key, *new_matched_key;
3479
3480         /* !!! we can NOT check flags.visited here since this will interact
3481            badly with when SMB handles (i.e. calls the subdissector)
3482            and desegmented pdu's .
3483            Instead we check if this pdu is already in the matched table or not
3484         */
3485             matched_key.frame = pinfo->fd->num;
3486             matched_key.call_id = hdr->call_id;
3487             value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3488             if(!value){
3489                     dcerpc_cn_call_key call_key;
3490                     dcerpc_call_value *call_value;
3491
3492                     call_key.conv=conv;
3493                     call_key.call_id=hdr->call_id;
3494                     call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3495
3496                     if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3497                         /* extra sanity check,  only match them if the reply
3498                            came after the request */
3499                             if(call_value->req_frame<pinfo->fd->num){
3500                                     new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3501                                     *new_matched_key = matched_key;
3502                                     g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3503                                     value = call_value;
3504                                     if(call_value->rep_frame==0) {
3505                                             call_value->rep_frame=pinfo->fd->num;
3506                                     }
3507                             }
3508                     }
3509             }
3510
3511       if (value) {
3512         dcerpc_info *di;
3513
3514         di=get_next_di();
3515         /* handoff this call */
3516               di->conv = conv;
3517               di->call_id = hdr->call_id;
3518               di->smb_fid = dcerpc_get_transport_salt(pinfo);
3519               di->ptype = PDU_RESP;
3520               di->call_data = value;
3521
3522               proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3523
3524         /* (optional) "Object UUID" from request */
3525         if (value && dcerpc_tree && memcmp(&value->object_uuid, &obj_id_null, sizeof(obj_id_null)) != 0) {
3526           pi = proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3527                 offset, 0, (e_guid_t *) &value->object_uuid, "Object UUID: %s",
3528                 guid_to_str((e_guid_t *) &value->object_uuid));
3529           PROTO_ITEM_SET_GENERATED(pi);
3530         }
3531
3532         /* request in */
3533               if(value->req_frame!=0) {
3534                       nstime_t delta_ts;
3535                       pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3536                                     tvb, 0, 0, value->req_frame);
3537           PROTO_ITEM_SET_GENERATED(pi);
3538           if(parent_pi != NULL) {
3539             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3540           }
3541                       nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3542                       pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3543           PROTO_ITEM_SET_GENERATED(pi);
3544         } else {
3545                       pi = proto_tree_add_text(dcerpc_tree,
3546                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3547                       expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3548                             "No request to this DCE/RPC call found");
3549               }
3550
3551               dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3552                                     hdr, di, &auth_info, alloc_hint,value->rep_frame);
3553       } else {
3554             /* no bind information, simply show stub data */
3555         pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3556         PROTO_ITEM_SET_GENERATED(pi);
3557               expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",ctx_id);
3558         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3559       }
3560     }
3561     /* Dissect the verifier */
3562     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3563 }
3564
3565 static void
3566 dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3567                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
3568 {
3569     dcerpc_call_value *value = NULL;
3570     conversation_t *conv;
3571     guint16 ctx_id;
3572     guint32 status;
3573     guint32 alloc_hint;
3574     dcerpc_auth_info auth_info;
3575     proto_item *pi = NULL;
3576
3577     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3578                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3579
3580     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3581                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3582
3583     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3584                                    hf_dcerpc_cn_cancel_count, NULL);
3585     /* padding */
3586     offset++;
3587
3588     /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3589                                     hf_dcerpc_cn_status, &status);*/
3590     status = ((hdr->drep[0] & 0x10)
3591             ? tvb_get_letohl (tvb, offset)
3592             : tvb_get_ntohl (tvb, offset));
3593
3594     if (dcerpc_tree) {
3595         pi = proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_status, tvb, offset, 4, (hdr->drep[0] & 0x10));
3596     }
3597         offset+=4;
3598
3599         expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "Fault: %s",
3600                 val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
3601
3602     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3603     pinfo->dcectxid = ctx_id;
3604
3605     if (check_col (pinfo->cinfo, COL_INFO)) {
3606         col_append_fstr (pinfo->cinfo, COL_INFO,
3607                       " ctx_id: %u status: %s", ctx_id,
3608                       val_to_str(status, reject_status_vals,
3609                                  "Unknown (0x%08x)"));
3610     }
3611
3612     /* padding */
3613     offset += 4;
3614
3615     /*
3616      * XXX - what if this was set when the connection was set up,
3617      * and we just have a security context?
3618      */
3619     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3620
3621     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3622                               pinfo->srcport, pinfo->destport, 0);
3623     if (!conv) {
3624         /* no point in creating one here, really */
3625     } else {
3626         dcerpc_matched_key matched_key, *new_matched_key;
3627
3628         /* !!! we can NOT check flags.visited here since this will interact
3629            badly with when SMB handles (i.e. calls the subdissector)
3630            and desegmented pdu's .
3631            Instead we check if this pdu is already in the matched table or not
3632         */
3633         matched_key.frame = pinfo->fd->num;
3634         matched_key.call_id = hdr->call_id;
3635         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3636         if(!value){
3637                 dcerpc_cn_call_key call_key;
3638                 dcerpc_call_value *call_value;
3639
3640                 call_key.conv=conv;
3641                 call_key.call_id=hdr->call_id;
3642                 call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3643
3644                 if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3645                         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3646                         *new_matched_key = matched_key;
3647                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3648                         value = call_value;
3649                         if(call_value->rep_frame==0){
3650                                 call_value->rep_frame=pinfo->fd->num;
3651                         }
3652
3653                 }
3654         }
3655
3656         if (value) {
3657             int length, reported_length, stub_length;
3658             dcerpc_info *di;
3659             proto_item *parent_pi;
3660
3661             di=get_next_di();
3662             /* handoff this call */
3663             di->conv = conv;
3664             di->call_id = hdr->call_id;
3665             di->smb_fid = dcerpc_get_transport_salt(pinfo);
3666             di->ptype = PDU_FAULT;
3667             di->call_data = value;
3668
3669             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3670             if(value->req_frame!=0){
3671                 nstime_t delta_ts;
3672                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3673                                     tvb, 0, 0, value->req_frame);
3674         PROTO_ITEM_SET_GENERATED(pi);
3675         parent_pi = proto_tree_get_parent(dcerpc_tree);
3676         if(parent_pi != NULL) {
3677             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3678         }
3679                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3680                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3681         PROTO_ITEM_SET_GENERATED(pi);
3682         } else {
3683                     pi = proto_tree_add_text(dcerpc_tree,
3684                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3685                     expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3686                             "No request to this DCE/RPC call found");
3687             }
3688
3689             length = tvb_length_remaining(tvb, offset);
3690             reported_length = tvb_reported_length_remaining(tvb, offset);
3691                 /* as we now create a tvb in dissect_dcerpc_cn() containing only the
3692                  * stub_data, the following calculation is no longer valid:
3693              * stub_length = hdr->frag_len - offset - auth_info.auth_size;
3694                  * simply use the remaining length of the tvb instead.
3695                  * XXX - or better use the reported_length?!?
3696                  */
3697             stub_length = length;
3698             if (length > stub_length)
3699               length = stub_length;
3700             if (reported_length > stub_length)
3701               reported_length = stub_length;
3702
3703             /* If we don't have reassembly enabled, or this packet contains
3704                the entire PDU, or if we don't have all the data in this
3705                fragment, just call the handoff directly if this is the
3706                first fragment or the PDU isn't fragmented. */
3707             if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
3708                         !tvb_bytes_exist(tvb, offset, stub_length) ){
3709                 if(hdr->flags&PFC_FIRST_FRAG){
3710                     /* First fragment, possibly the only fragment */
3711                     /*
3712                      * XXX - should there be a third routine for each
3713                      * function in an RPC subdissector, to handle
3714                      * fault responses?  The DCE RPC 1.1 spec says
3715                      * three's "stub data" here, which I infer means
3716                      * that it's protocol-specific and call-specific.
3717                      *
3718                      * It should probably get passed the status code
3719                      * as well, as that might be protocol-specific.
3720                      */
3721                     if (dcerpc_tree) {
3722                         if (stub_length > 0) {
3723                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3724                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3725                                                  "Fault stub data (%d byte%s)",
3726                                                  stub_length,
3727                                                  plurality(stub_length, "", "s"));
3728                         }
3729                     }
3730                 } else {
3731                     /* PDU is fragmented and this isn't the first fragment */
3732                     col_append_str(pinfo->cinfo, COL_INFO,
3733                                         " [DCE/RPC fragment]");
3734                     if (dcerpc_tree) {
3735                         if (stub_length > 0) {
3736                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3737                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3738                                                  "Fragment data (%d byte%s)",
3739                                                  stub_length,
3740                                                  plurality(stub_length, "", "s"));
3741                         }
3742                     }
3743                 }
3744             } else {
3745                 /* Reassembly is enabled, the PDU is fragmented, and
3746                    we have all the data in the fragment; the first two
3747                    of those mean we should attempt reassembly, and the
3748                    third means we can attempt reassembly. */
3749                 if (dcerpc_tree) {
3750                     if (length > 0) {
3751                         tvb_ensure_bytes_exist(tvb, offset, stub_length);
3752                         proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3753                                              "Fragment data (%d byte%s)",
3754                                              stub_length,
3755                                              plurality(stub_length, "", "s"));
3756                     }
3757                 }
3758                 if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
3759                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3760                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3761                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3762                              stub_length,
3763                              TRUE);
3764                     }
3765                     col_append_str(pinfo->cinfo, COL_INFO,
3766                                         " [DCE/RPC fragment]");
3767                 } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
3768                     if( value->rep_frame ){
3769                         fragment_data *fd_head;
3770
3771                         fd_head = fragment_add_seq_next(tvb, offset, pinfo,
3772                              value->rep_frame,
3773                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3774                              stub_length,
3775                              TRUE);
3776
3777                         if(fd_head){
3778                             /* We completed reassembly */
3779                             tvbuff_t *next_tvb;
3780                 proto_item *frag_tree_item;
3781
3782                             next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->len, fd_head->len);
3783                             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3784                             show_fragment_tree(fd_head, &dcerpc_frag_items,
3785                                 dcerpc_tree, pinfo, next_tvb, &frag_tree_item);
3786
3787                             /*
3788                              * XXX - should there be a third routine for each
3789                              * function in an RPC subdissector, to handle
3790                              * fault responses?  The DCE RPC 1.1 spec says
3791                              * three's "stub data" here, which I infer means
3792                              * that it's protocol-specific and call-specific.
3793                              *
3794                              * It should probably get passed the status code
3795                              * as well, as that might be protocol-specific.
3796                              */
3797                             if (dcerpc_tree) {
3798                                 if (length > 0) {
3799                                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
3800                                      proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3801                                                           "Fault stub data (%d byte%s)",
3802                                                           stub_length,
3803                                                           plurality(stub_length, "", "s"));
3804                                 }
3805                             }
3806                         } else {
3807                             /* Reassembly not complete - some fragments
3808                                are missing */
3809                             col_append_str(pinfo->cinfo, COL_INFO,
3810                                                 " [DCE/RPC fragment]");
3811                         }
3812                     }
3813                 } else {  /* MIDDLE fragment(s) */
3814                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3815                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3816                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3817                              stub_length,
3818                              TRUE);
3819                     }
3820                     col_append_str(pinfo->cinfo, COL_INFO,
3821                                         " [DCE/RPC fragment]");
3822                 }
3823             }
3824         }
3825     }
3826 }
3827
3828 /*
3829  * DCERPC dissector for connection oriented calls.
3830  * We use transport type to later multiplex between what kind of
3831  * pinfo->private_data structure to expect.
3832  */
3833 static gboolean
3834 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
3835                    proto_tree *tree, gboolean can_desegment, int *pkt_len)
3836 {
3837     static const guint8 nulls[4] = { 0 };
3838     int start_offset;
3839     int padding = 0;
3840     proto_item *ti = NULL;
3841     proto_item *tf = NULL;
3842     proto_tree *dcerpc_tree = NULL;
3843     proto_tree *cn_flags_tree = NULL;
3844     proto_tree *drep_tree = NULL;
3845     e_dce_cn_common_hdr_t hdr;
3846     dcerpc_auth_info auth_info;
3847         tvbuff_t *fragment_tvb;
3848
3849     /*
3850      * when done over nbt, dcerpc requests are padded with 4 bytes of null
3851      * data for some reason.
3852      *
3853      * XXX - if that's always the case, the right way to do this would
3854      * be to have a "dissect_dcerpc_cn_nb" routine which strips off
3855      * the 4 bytes of null padding, and make that the dissector
3856      * used for "netbios".
3857      */
3858     if (tvb_memeql (tvb, offset, nulls, 4) == 0) {
3859
3860         /*
3861          * Skip the padding.
3862          */
3863         offset += 4;
3864         padding += 4;
3865     }
3866     /*
3867      * Check if this looks like a C/O DCERPC call
3868      */
3869     if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
3870         return FALSE;   /* not enough information to check */
3871     }
3872     start_offset = offset;
3873     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
3874     if (hdr.rpc_ver != 5)
3875         return FALSE;
3876     hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
3877     if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
3878         return FALSE;
3879     hdr.ptype = tvb_get_guint8 (tvb, offset++);
3880     if (hdr.ptype > 19)
3881         return FALSE;
3882
3883     hdr.flags = tvb_get_guint8 (tvb, offset++);
3884     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
3885     offset += sizeof (hdr.drep);
3886
3887     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3888     offset += 2;
3889     hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3890     offset += 2;
3891     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3892     offset += 4;
3893
3894     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
3895                 if(pinfo->dcectxid == 0) {
3896                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.call_id);
3897                 } else {
3898                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3899                          * prepend a delimiter */
3900                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "#%u", hdr.call_id);
3901                 }
3902     }
3903
3904     if (can_desegment && pinfo->can_desegment
3905         && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
3906         pinfo->desegment_offset = start_offset;
3907         pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
3908         *pkt_len = 0;   /* desegmentation required */
3909         return TRUE;
3910     }
3911
3912     col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
3913
3914     if (check_col (pinfo->cinfo, COL_INFO)) {
3915         if(pinfo->dcectxid != 0) {
3916             /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3917              * append a delimiter and set a column fence */
3918             col_append_str (pinfo->cinfo, COL_INFO, " # ");
3919             col_set_fence(pinfo->cinfo,COL_INFO);
3920         }
3921         col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
3922                 pckt_vals[hdr.ptype].strptr, hdr.call_id);
3923     }
3924
3925     if(pinfo->dcectxid != 0) {
3926         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU */
3927                 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_CHAT, "Multiple DCE/RPC fragments/PDU's in one packet");
3928         }
3929
3930     offset = start_offset;
3931     tvb_ensure_bytes_exist(tvb, offset, 16);
3932     if (tree) {
3933         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
3934         dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
3935     }
3936
3937     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
3938     offset++;
3939
3940     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset, 1, hdr.rpc_ver_minor);
3941     offset++;
3942
3943     tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
3944     offset++;
3945
3946     /* XXX - too much "output noise", removed for now
3947     if(hdr.ptype == PDU_BIND || hdr.ptype == PDU_ALTER ||
3948         hdr.ptype == PDU_BIND_ACK || hdr.ptype == PDU_ALTER_ACK)
3949         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_CHAT, "Context change: %s",
3950             val_to_str(hdr.ptype, pckt_vals, "(0x%x)"));*/
3951     if(hdr.ptype == PDU_BIND_NAK)
3952         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_WARN, "Bind not acknowledged");
3953
3954     if (tree) {
3955         proto_item_append_text(ti, " %s, Fragment:", val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"));
3956
3957         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
3958         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
3959     }
3960     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
3961     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
3962     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
3963     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
3964     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
3965     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
3966     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
3967     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
3968     if( (hdr.flags & PFC_FIRST_FRAG) && (hdr.flags & PFC_LAST_FRAG) ) {
3969         proto_item_append_text(ti, " Single");
3970     } else {
3971         if(hdr.flags & PFC_FIRST_FRAG) {
3972              proto_item_append_text(ti, " 1st");
3973         }
3974         if(hdr.flags & PFC_LAST_FRAG) {
3975             proto_item_append_text(ti, " Last");
3976         }
3977         if( !(hdr.flags & PFC_FIRST_FRAG) && !(hdr.flags & PFC_LAST_FRAG) ) {
3978             proto_item_append_text(ti, " Mid");
3979         }
3980     }
3981     offset++;
3982
3983     if(dcerpc_tree){
3984         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
3985         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
3986     }
3987     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
3988     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
3989     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
3990     offset += sizeof (hdr.drep);
3991
3992     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
3993     offset += 2;
3994
3995     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
3996     offset += 2;
3997
3998     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
3999     offset += 4;
4000
4001     if(ti){
4002         proto_item_append_text(ti, ", FragLen: %u, Call: %u", hdr.frag_len, hdr.call_id);
4003     }
4004
4005     /*
4006      * None of the stuff done above should throw an exception, because
4007      * we would have rejected this as "not DCE RPC" if we didn't have all
4008      * of it.  (XXX - perhaps we should request reassembly if we have
4009      * enough of the header to consider it DCE RPC but not enough to
4010      * get the fragment length; in that case the stuff still wouldn't
4011      * throw an exception.)
4012      *
4013      * The rest of the stuff might, so return the PDU length to our caller.
4014      * XXX - should we construct a tvbuff containing only the PDU and
4015      * use that?  Or should we have separate "is this a DCE RPC PDU",
4016      * "how long is it", and "dissect it" routines - which might let us
4017      * do most of the work in "tcp_dissect_pdus()"?
4018      */
4019     if (pkt_len != NULL)
4020         *pkt_len = hdr.frag_len + padding;
4021
4022     /* The remaining bytes in the current tvb might contain multiple
4023      * DCE/RPC fragments, so create a new tvb subset for this fragment.
4024      * Only limit the end of the fragment, but not the offset start,
4025      * as the authentication function dissect_dcerpc_cn_auth() will fail
4026      * (and other functions might fail as well) computing the right start
4027      * offset otherwise.
4028      */
4029     fragment_tvb = tvb_new_subset(tvb, 0,
4030         MIN((hdr.frag_len + (guint) start_offset), tvb_length(tvb)) /* length */,
4031         hdr.frag_len + start_offset /* reported_length */);
4032
4033     /*
4034      * Packet type specific stuff is next.
4035      */
4036     switch (hdr.ptype) {
4037     case PDU_BIND:
4038     case PDU_ALTER:
4039         dissect_dcerpc_cn_bind (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4040         break;
4041
4042     case PDU_BIND_ACK:
4043     case PDU_ALTER_ACK:
4044         dissect_dcerpc_cn_bind_ack (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4045         break;
4046
4047     case PDU_AUTH3:
4048         /*
4049          * Nothing after the common header other than credentials.
4050          */
4051         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
4052                                 &auth_info);
4053         break;
4054
4055     case PDU_REQ:
4056         dissect_dcerpc_cn_rqst (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4057         break;
4058
4059     case PDU_RESP:
4060         dissect_dcerpc_cn_resp (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4061         break;
4062
4063     case PDU_FAULT:
4064         dissect_dcerpc_cn_fault (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4065         break;
4066
4067     case PDU_BIND_NAK:
4068         dissect_dcerpc_cn_bind_nak (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4069         break;
4070
4071     case PDU_CO_CANCEL:
4072     case PDU_ORPHANED:
4073         /*
4074          * Nothing after the common header other than an authentication
4075          * verifier.
4076          */
4077         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4078                                 &auth_info);
4079         break;
4080
4081     case PDU_SHUTDOWN:
4082         /*
4083          * Nothing after the common header, not even an authentication
4084          * verifier.
4085          */
4086         break;
4087
4088     default:
4089         /* might as well dissect the auth info */
4090         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4091                                 &auth_info);
4092         break;
4093     }
4094     return TRUE;
4095 }
4096
4097 /*
4098  * DCERPC dissector for connection oriented calls over packet-oriented
4099  * transports
4100  */
4101 static gboolean
4102 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4103 {
4104     /*
4105      * Only one PDU per transport packet, and only one transport
4106      * packet per PDU.
4107      */
4108     pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4109     if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL)) {
4110         /*
4111          * It wasn't a DCERPC PDU.
4112          */
4113         return FALSE;
4114     } else {
4115         /*
4116          * It was.
4117          */
4118         return TRUE;
4119     }
4120 }
4121
4122 /*
4123  * DCERPC dissector for connection oriented calls over byte-stream
4124  * transports.
4125  * we need to distinguish here between SMB and non-TCP (more in the future?)
4126  * to be able to know what kind of private_data structure to expect.
4127  */
4128 static gboolean
4129 dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4130 {
4131     volatile int offset = 0;
4132     int pdu_len;
4133     volatile gboolean dcerpc_pdus = 0;
4134     volatile gboolean ret = FALSE;
4135
4136     /*
4137      * There may be multiple PDUs per transport packet; keep
4138      * processing them.
4139      */
4140     while (tvb_reported_length_remaining(tvb, offset) != 0) {
4141         /*
4142          * Catch ReportedBoundsError, so that even if the stub data is bad,
4143          * we don't abort the full DCE RPC dissection - there might be more
4144          * than one DCE RPC PDU in the data being dissected.
4145          *
4146          * If we get BoundsError, it means the frame was cut short by a
4147          * snapshot length, so there's nothing more to dissect; just
4148          * re-throw that exception.
4149          */
4150         TRY {
4151             pdu_len = 0;
4152             if(dissect_dcerpc_cn (tvb, offset, pinfo, tree,
4153                 dcerpc_cn_desegment, &pdu_len)) {
4154                 dcerpc_pdus++;
4155             }
4156         } CATCH(BoundsError) {
4157             RETHROW;
4158         } CATCH(ReportedBoundsError) {
4159             show_reported_bounds_error(tvb, pinfo, tree);
4160             /*
4161              * Presumably it looked enough like a DCE RPC PDU that we
4162              * dissected enough of it to throw an exception.
4163              */
4164             dcerpc_pdus++;
4165         } ENDTRY;
4166
4167         if (!dcerpc_pdus) {
4168             /*
4169              * Not a DCERPC PDU.
4170              */
4171             break;
4172         }
4173
4174         /*
4175          * Well, we've seen at least one DCERPC PDU.
4176          */
4177         ret = TRUE;
4178
4179         /* if we had more than one Req/Resp in this PDU change the protocol column */
4180         /* this will formerly contain the last interface name, which may not be the same for all Req/Resp */
4181         if (dcerpc_pdus >= 2 && check_col (pinfo->cinfo, COL_PROTOCOL))
4182             col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%u*DCERPC", dcerpc_pdus);
4183
4184         if (pdu_len == 0) {
4185             /*
4186              * Desegmentation required - bail now, but give the user a hint that desegmentation might be done later.
4187              */
4188             proto_tree_add_uint_format(tree, hf_dcerpc_cn_deseg_req, tvb, offset,
4189                 0,
4190                 tvb_reported_length_remaining(tvb, offset),
4191                 "[DCE RPC: %u byte%s left, desegmentation might follow]",
4192                 tvb_reported_length_remaining(tvb, offset),
4193                 plurality(tvb_reported_length_remaining(tvb, offset), "", "s"));
4194             break;
4195         }
4196
4197         /*
4198          * Step to the next PDU.
4199          */
4200         offset += pdu_len;
4201     }
4202     return ret;
4203 }
4204
4205 static gboolean
4206 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4207 {
4208         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4209         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4210 }
4211
4212 static gboolean
4213 dissect_dcerpc_cn_smbpipe (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4214 {
4215         pinfo->dcetransporttype=DCE_CN_TRANSPORT_SMBPIPE;
4216         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4217 }
4218
4219 static gboolean
4220 dissect_dcerpc_cn_smb2 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4221 {
4222         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4223         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4224 }
4225
4226
4227
4228 static void
4229 dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
4230                         e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
4231 {
4232     proto_item *ti = NULL;
4233     proto_tree *auth_tree = NULL;
4234     guint8 protection_level;
4235
4236     /*
4237      * Initially set "*auth_level_p" to -1 to indicate that we haven't
4238      * yet seen any authentication level information.
4239      */
4240     if (auth_level_p != NULL)
4241         *auth_level_p = -1;
4242
4243     /*
4244      * The authentication information is at the *end* of the PDU; in
4245      * request and response PDUs, the request and response stub data
4246      * come before it.
4247      *
4248      * If the full packet is here, and there's data past the end of the
4249      * packet body, then dissect the auth info.
4250      */
4251     offset += hdr->frag_len;
4252     if (tvb_length_remaining(tvb, offset) > 0) {
4253         switch (hdr->auth_proto) {
4254
4255         case DCE_C_RPC_AUTHN_PROTOCOL_KRB5:
4256             ti = proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Kerberos authentication verifier");
4257             auth_tree = proto_item_add_subtree (ti, ett_dcerpc_krb5_auth_verf);
4258             protection_level = tvb_get_guint8 (tvb, offset);
4259             if (auth_level_p != NULL)
4260                 *auth_level_p = protection_level;
4261             proto_tree_add_uint (auth_tree, hf_dcerpc_krb5_av_prot_level, tvb, offset, 1, protection_level);
4262             offset++;
4263             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_vers_num, tvb, offset, 1, FALSE);
4264             offset++;
4265             if (protection_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)
4266                 offset += 6;    /* 6 bytes of padding */
4267             else
4268                 offset += 2;    /* 6 bytes of padding */
4269             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_auth_verifier, tvb, offset, 16, FALSE);
4270             offset += 16;
4271             break;
4272
4273         default:
4274             proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Authentication verifier");
4275             break;
4276         }
4277     }
4278 }
4279
4280 static void
4281 dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4282                               proto_tree *dcerpc_tree,
4283                               e_dce_dg_common_hdr_t *hdr)
4284 {
4285     guint32 version;
4286
4287     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4288                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4289                                     &version);
4290
4291     switch (version) {
4292
4293     case 0:
4294         /* The only version we know about */
4295         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4296                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4297                                         NULL);
4298         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4299                                        hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4300                                        NULL);
4301         break;
4302     }
4303 }
4304
4305 static void
4306 dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
4307                           proto_tree *dcerpc_tree,
4308                           e_dce_dg_common_hdr_t *hdr)
4309 {
4310     guint32 version;
4311
4312     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4313                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4314                                     &version);
4315
4316     switch (version) {
4317
4318     case 0:
4319         /* The only version we know about */
4320         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4321                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4322                                         NULL);
4323         /* XXX - are NDR booleans 32 bits? */
4324
4325         /* XXX - the RPC reference in chapter: "the cancel PDU" doesn't mention
4326            the accepting_cancels field (it's only in the cancel_ack PDU)! */
4327         /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4328                                         hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4329                                         NULL);*/
4330         break;
4331     }
4332 }
4333
4334 static void
4335 dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4336                         proto_tree *dcerpc_tree,
4337                         e_dce_dg_common_hdr_t *hdr)
4338 {
4339     guint8 version;
4340     guint16 serial_num;
4341     guint16 selack_len;
4342     guint i;
4343
4344     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4345                                   hdr->drep, hf_dcerpc_dg_fack_vers,
4346                                   &version);
4347     /* padding */
4348     offset++;
4349
4350     switch (version) {
4351
4352     case 0:     /* The only version documented in the DCE RPC 1.1 spec */
4353     case 1:     /* This appears to be the same */
4354         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4355                                         hdr->drep, hf_dcerpc_dg_fack_window_size,
4356                                         NULL);
4357         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4358                                         hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
4359                                         NULL);
4360         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4361                                         hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
4362                                         NULL);
4363         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4364                                         hdr->drep, hf_dcerpc_dg_fack_serial_num,
4365                                         &serial_num);
4366         if (check_col (pinfo->cinfo, COL_INFO)) {
4367             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
4368                              serial_num);
4369         }
4370         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4371                                         hdr->drep, hf_dcerpc_dg_fack_selack_len,
4372                                         &selack_len);
4373         for (i = 0; i < selack_len; i++) {
4374             offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4375                                             hdr->drep, hf_dcerpc_dg_fack_selack,
4376                                             NULL);
4377         }
4378
4379         break;
4380     }
4381 }
4382
4383 static void
4384 dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
4385                         proto_tree *dcerpc_tree,
4386                         e_dce_dg_common_hdr_t *hdr)
4387 {
4388     guint32 status;
4389
4390     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4391                                     hdr->drep, hf_dcerpc_dg_status,
4392                                     &status);
4393
4394     if (check_col (pinfo->cinfo, COL_INFO)) {
4395         col_append_fstr (pinfo->cinfo, COL_INFO,
4396                       ": status: %s",
4397                       val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
4398     }
4399 }
4400
4401 static void
4402 dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
4403                         proto_tree *dcerpc_tree, proto_tree *tree,
4404                         e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
4405 {
4406     int length, reported_length, stub_length;
4407     gboolean save_fragmented;
4408     fragment_data *fd_head;
4409     tvbuff_t *next_tvb;
4410     proto_item *pi;
4411     proto_item *parent_pi;
4412
4413     if (check_col (pinfo->cinfo, COL_INFO))
4414         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u",
4415             di->call_data->opnum, hdr->frag_len );
4416
4417     length = tvb_length_remaining (tvb, offset);
4418     reported_length = tvb_reported_length_remaining (tvb, offset);
4419     stub_length = hdr->frag_len;
4420     if (length > stub_length)
4421         length = stub_length;
4422     if (reported_length > stub_length)
4423         reported_length = stub_length;
4424
4425     save_fragmented = pinfo->fragmented;
4426
4427     /* If we don't have reassembly enabled, or this packet contains
4428        the entire PDU, or if this is a short frame (or a frame
4429        not reassembled at a lower layer) that doesn't include all
4430        the data in the fragment, just call the handoff directly if
4431        this is the first fragment or the PDU isn't fragmented. */
4432     if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
4433                 !tvb_bytes_exist(tvb, offset, stub_length) ){
4434         if(hdr->frag_num == 0) {
4435
4436
4437             /* First fragment, possibly the only fragment */
4438
4439             /*
4440              * XXX - authentication info?
4441              */
4442             pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
4443             next_tvb = tvb_new_subset (tvb, offset, length,
4444                                        reported_length);
4445             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4446                                 next_tvb, hdr->drep, di, NULL);
4447         } else {
4448             /* PDU is fragmented and this isn't the first fragment */
4449             col_append_str(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4450             if (dcerpc_tree) {
4451                 if (length > 0) {
4452                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
4453                     proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4454                                          "Fragment data (%d byte%s)",
4455                                          stub_length,
4456                                          plurality(stub_length, "", "s"));
4457                 }
4458             }
4459         }
4460     } else {
4461         /* Reassembly is enabled, the PDU is fragmented, and
4462            we have all the data in the fragment; the first two
4463            of those mean we should attempt reassembly, and the
4464            third means we can attempt reassembly. */
4465         if (dcerpc_tree) {
4466             if (length > 0) {
4467                 tvb_ensure_bytes_exist(tvb, offset, stub_length);
4468                 proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4469                                      "Fragment data (%d byte%s)", stub_length,
4470                                      plurality(stub_length, "", "s"));
4471             }
4472         }
4473
4474         fd_head = fragment_add_dcerpc_dg(tvb, offset, pinfo,
4475                         hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table,
4476                         hdr->frag_num, stub_length,
4477                         !(hdr->flags1 & PFCL1_LASTFRAG));
4478     if (fd_head != NULL) {
4479             /* We completed reassembly... */
4480         if(pinfo->fd->num==fd_head->reassembled_in) {
4481             /* ...and this is the reassembled RPC PDU */
4482                 next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->len, fd_head->len);
4483                 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
4484                 show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
4485                                            tree, pinfo, next_tvb, &pi);
4486
4487                 /*
4488                  * XXX - authentication info?
4489                  */
4490                 pinfo->fragmented = FALSE;
4491                 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4492                                         next_tvb, hdr->drep, di, NULL);
4493                 } else {
4494             /* ...and this isn't the reassembled RPC PDU */
4495                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
4496                                     tvb, 0, 0, fd_head->reassembled_in);
4497             PROTO_ITEM_SET_GENERATED(pi);
4498             parent_pi = proto_tree_get_parent(dcerpc_tree);
4499             if(parent_pi != NULL) {
4500                 proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
4501             }
4502                 if (check_col(pinfo->cinfo, COL_INFO)) {
4503                     col_append_fstr(pinfo->cinfo, COL_INFO,
4504                             " [DCE/RPC fragment, reas: #%u]", fd_head->reassembled_in);
4505                 }
4506         }
4507         } else {
4508             /* Reassembly isn't completed yet */
4509             col_append_str(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4510         }
4511     }
4512     pinfo->fragmented = save_fragmented;
4513 }
4514
4515 static void
4516 dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
4517                         proto_tree *dcerpc_tree, proto_tree *tree,
4518                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4519 {
4520     dcerpc_info *di;
4521     dcerpc_call_value *value, v;
4522     dcerpc_matched_key matched_key, *new_matched_key;
4523     proto_item *pi;
4524     proto_item *parent_pi;
4525
4526     di=get_next_di();
4527     if(!(pinfo->fd->flags.visited)){
4528         dcerpc_call_value *call_value;
4529         dcerpc_dg_call_key *call_key;
4530
4531         call_key=se_alloc (sizeof (dcerpc_dg_call_key));
4532         call_key->conv=conv;
4533         call_key->seqnum=hdr->seqnum;
4534         call_key->act_id=hdr->act_id;
4535
4536         call_value=se_alloc (sizeof (dcerpc_call_value));
4537         call_value->uuid = hdr->if_id;
4538         call_value->ver = hdr->if_ver;
4539         call_value->object_uuid = hdr->obj_id;
4540         call_value->opnum = hdr->opnum;
4541         call_value->req_frame=pinfo->fd->num;
4542         call_value->req_time=pinfo->fd->abs_ts;
4543         call_value->rep_frame=0;
4544         call_value->max_ptr=0;
4545         call_value->se_data = NULL;
4546         call_value->private_data = NULL;
4547         call_value->pol = NULL;
4548         g_hash_table_insert (dcerpc_dg_calls, call_key, call_value);
4549
4550         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4551         new_matched_key->frame = pinfo->fd->num;
4552         new_matched_key->call_id = hdr->seqnum;
4553         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4554     }
4555
4556     matched_key.frame = pinfo->fd->num;
4557     matched_key.call_id = hdr->seqnum;
4558     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4559     if (!value) {
4560         v.uuid = hdr->if_id;
4561         v.ver = hdr->if_ver;
4562         v.object_uuid = hdr->obj_id;
4563         v.opnum = hdr->opnum;
4564         v.req_frame = pinfo->fd->num;
4565         v.rep_frame = 0;
4566         v.max_ptr = 0;
4567         v.se_data=NULL;
4568         v.private_data=NULL;
4569         value = &v;
4570     }
4571
4572     di->conv = conv;
4573     di->call_id = hdr->seqnum;
4574     di->smb_fid = -1;
4575     di->ptype = PDU_REQ;
4576     di->call_data = value;
4577
4578     if(value->rep_frame!=0){
4579         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
4580                             tvb, 0, 0, value->rep_frame);
4581     PROTO_ITEM_SET_GENERATED(pi);
4582     parent_pi = proto_tree_get_parent(dcerpc_tree);
4583     if(parent_pi != NULL) {
4584         proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
4585     }
4586     }
4587     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4588 }
4589
4590 static void
4591 dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
4592                         proto_tree *dcerpc_tree, proto_tree *tree,
4593                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4594 {
4595     dcerpc_info *di;
4596     dcerpc_call_value *value, v;
4597     dcerpc_matched_key matched_key, *new_matched_key;
4598     proto_item *pi;
4599     proto_item *parent_pi;
4600
4601     di=get_next_di();
4602     if(!(pinfo->fd->flags.visited)){
4603         dcerpc_call_value *call_value;
4604         dcerpc_dg_call_key call_key;
4605
4606         call_key.conv=conv;
4607         call_key.seqnum=hdr->seqnum;
4608         call_key.act_id=hdr->act_id;
4609
4610         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4611             new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4612             new_matched_key->frame = pinfo->fd->num;
4613             new_matched_key->call_id = hdr->seqnum;
4614             g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4615             if(call_value->rep_frame==0){
4616                 call_value->rep_frame=pinfo->fd->num;
4617             }
4618         }
4619     }
4620
4621     matched_key.frame = pinfo->fd->num;
4622     matched_key.call_id = hdr->seqnum;
4623     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4624     if (!value) {
4625         v.uuid = hdr->if_id;
4626         v.ver = hdr->if_ver;
4627         v.object_uuid = hdr->obj_id;
4628         v.opnum = hdr->opnum;
4629         v.req_frame=0;
4630         v.rep_frame=pinfo->fd->num;
4631         v.se_data=NULL;
4632         v.private_data=NULL;
4633         value = &v;
4634     }
4635
4636     di->conv = conv;
4637     di->call_id = 0;
4638     di->smb_fid = -1;
4639     di->ptype = PDU_RESP;
4640     di->call_data = value;
4641
4642     if(value->req_frame!=0){
4643         nstime_t delta_ts;
4644         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4645                             tvb, 0, 0, value->req_frame);
4646     PROTO_ITEM_SET_GENERATED(pi);
4647     parent_pi = proto_tree_get_parent(dcerpc_tree);
4648     if(parent_pi != NULL) {
4649         proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
4650     }
4651         nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
4652         pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4653     PROTO_ITEM_SET_GENERATED(pi);
4654     } else {
4655                 pi = proto_tree_add_text(dcerpc_tree,
4656                                     tvb, 0, 0, "No request to this DCE/RPC call found");
4657                 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
4658                         "No request to this DCE/RPC call found");
4659     }
4660     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4661 }
4662
4663 static void
4664 dissect_dcerpc_dg_ping_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4665                         proto_tree *dcerpc_tree,
4666                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4667 {
4668     proto_item *parent_pi;
4669 /*    if(!(pinfo->fd->flags.visited)){*/
4670         dcerpc_call_value *call_value;
4671         dcerpc_dg_call_key call_key;
4672
4673         call_key.conv=conv;
4674         call_key.seqnum=hdr->seqnum;
4675         call_key.act_id=hdr->act_id;
4676
4677         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4678         proto_item *pi;
4679                 nstime_t delta_ts;
4680
4681                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4682                                     tvb, 0, 0, call_value->req_frame);
4683         PROTO_ITEM_SET_GENERATED(pi);
4684         parent_pi = proto_tree_get_parent(dcerpc_tree);
4685         if(parent_pi != NULL) {
4686             proto_item_append_text(parent_pi, ", [Req: #%u]", call_value->req_frame);
4687         }
4688
4689         if (check_col (pinfo->cinfo, COL_INFO))
4690             col_append_fstr(pinfo->cinfo, COL_INFO, " [req: #%u]", call_value->req_frame);
4691
4692                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &call_value->req_time);
4693                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4694         PROTO_ITEM_SET_GENERATED(pi);
4695 /*    }*/
4696     }
4697 }
4698
4699 /*
4700  * DCERPC dissector for connectionless calls
4701  */
4702 static gboolean
4703 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4704 {
4705     proto_item *ti = NULL;
4706     proto_item *tf = NULL;
4707     proto_tree *dcerpc_tree = NULL;
4708     proto_tree *dg_flags1_tree = NULL;
4709     proto_tree *dg_flags2_tree = NULL;
4710     proto_tree *drep_tree = NULL;
4711     e_dce_dg_common_hdr_t hdr;
4712     int offset = 0;
4713     conversation_t *conv;
4714     int auth_level;
4715     char *uuid_str;
4716     const char *uuid_name = NULL;
4717
4718     /*
4719      * Check if this looks like a CL DCERPC call.  All dg packets
4720      * have an 80 byte header on them.  Which starts with
4721      * version (4), pkt_type.
4722      */
4723     if (tvb_length (tvb) < sizeof (hdr)) {
4724         return FALSE;
4725     }
4726
4727     /* Version must be 4 */
4728     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
4729     if (hdr.rpc_ver != 4)
4730         return FALSE;
4731
4732     /* Type must be <=19 or its not DCE/RPC */
4733     hdr.ptype = tvb_get_guint8 (tvb, offset++);
4734     if (hdr.ptype > 19)
4735         return FALSE;
4736
4737     /* flags1 has bit 1 and 8 as reserved so if any of them are set, it is
4738        probably not a DCE/RPC packet
4739      */
4740     hdr.flags1 = tvb_get_guint8 (tvb, offset++);
4741     if(hdr.flags1&0x81)
4742         return FALSE;
4743
4744     /* flags2 has all bits except bit 2 as reserved so if any of them are set
4745        it is probably not DCE/RPC.
4746      */
4747     hdr.flags2 = tvb_get_guint8 (tvb, offset++);
4748     if(hdr.flags2&0xfd)
4749         return FALSE;
4750
4751
4752     col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
4753     if (check_col (pinfo->cinfo, COL_INFO))
4754         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
4755
4756     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
4757     offset += sizeof (hdr.drep);
4758     hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
4759     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
4760     offset += 16;
4761     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
4762     offset += 16;
4763     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
4764     offset += 16;
4765     hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4766     offset += 4;
4767     hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4768     offset += 4;
4769     hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4770     offset += 4;
4771     hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4772     offset += 2;
4773     hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4774     offset += 2;
4775     hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4776     offset += 2;
4777     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4778     offset += 2;
4779     hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4780     offset += 2;
4781     hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
4782     hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
4783
4784     if (tree) {
4785         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
4786         if (ti) {
4787             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
4788                     proto_item_append_text(ti, " %s, Seq: %u, Serial: %u, Frag: %u, FragLen: %u",
4789                 val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"),
4790                 hdr.seqnum, hdr.serial_hi*256+hdr.serial_lo,
4791                 hdr.frag_num, hdr.frag_len);
4792         }
4793     }
4794     offset = 0;
4795
4796     if (tree)
4797         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
4798     offset++;
4799
4800     if (tree)
4801         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
4802     offset++;
4803
4804     if (tree) {
4805         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
4806         dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
4807         if (dg_flags1_tree) {
4808             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
4809             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
4810             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
4811             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
4812             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
4813             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
4814             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
4815             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
4816             if(hdr.flags1) {
4817                         proto_item_append_text(tf, " %s%s%s%s%s%s",
4818                     (hdr.flags1 & PFCL1_BROADCAST) ? "\"Broadcast\" " : "",
4819                     (hdr.flags1 & PFCL1_IDEMPOTENT) ? "\"Idempotent\" " : "",
4820                     (hdr.flags1 & PFCL1_MAYBE) ? "\"Maybe\" " : "",
4821                     (hdr.flags1 & PFCL1_NOFACK) ? "\"No Fack\" " : "",
4822                     (hdr.flags1 & PFCL1_FRAG) ? "\"Fragment\" " : "",
4823                     (hdr.flags1 & PFCL1_LASTFRAG) ? "\"Last Fragment\" " : "");
4824             }
4825         }
4826     }
4827     offset++;
4828
4829     if (tree) {
4830         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
4831         dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
4832         if (dg_flags2_tree) {
4833             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
4834             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
4835             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
4836             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
4837             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
4838             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
4839             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
4840             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
4841             if(hdr.flags2) {
4842                         proto_item_append_text(tf, " %s",
4843                     (hdr.flags2 & PFCL2_CANCEL_PENDING) ? "\"Cancel Pending\" " : "");
4844             }
4845         }
4846     }
4847     offset++;
4848
4849     if (tree) {
4850         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
4851         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
4852         if (drep_tree) {
4853             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
4854             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
4855             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
4856                     proto_item_append_text(tf, " (Order: %s, Char: %s, Float: %s)",
4857                 val_to_str(hdr.drep[0] >> 4, drep_byteorder_vals, "Unknown"),
4858                 val_to_str(hdr.drep[0] & 0x0f, drep_character_vals, "Unknown"),
4859                 val_to_str(hdr.drep[1], drep_fp_vals, "Unknown"));
4860         }
4861     }
4862     offset += sizeof (hdr.drep);
4863
4864     if (tree)
4865         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
4866     offset++;
4867
4868     if (tree) {
4869         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
4870             offset, 16, (e_guid_t *) &hdr.obj_id, "Object UUID: %s",
4871             guid_to_str((e_guid_t *) &hdr.obj_id));
4872     }
4873     offset += 16;
4874
4875     if (tree) {
4876         uuid_str = guid_to_str((e_guid_t*)&hdr.if_id);
4877         uuid_name = guids_get_uuid_name(&hdr.if_id);
4878         if(uuid_name) {
4879                   proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
4880                                         offset, 16, (e_guid_t *) &hdr.if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
4881         } else {
4882           proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
4883                                         offset, 16, (e_guid_t *) &hdr.if_id, "Interface UUID: %s", uuid_str);
4884         }
4885     }
4886     offset += 16;
4887
4888     if (tree) {
4889         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
4890                                       offset, 16, (e_guid_t *) &hdr.act_id, "Activity: %s",
4891                                       guid_to_str((e_guid_t *) &hdr.act_id));
4892     }
4893     offset += 16;
4894
4895     if (tree) {
4896         nstime_t server_boot;
4897
4898         server_boot.secs  = hdr.server_boot;
4899         server_boot.nsecs = 0;
4900
4901         if (hdr.server_boot == 0)
4902             proto_tree_add_time_format (dcerpc_tree, hf_dcerpc_dg_server_boot,
4903                                         tvb, offset, 4, &server_boot,
4904                                         "Server boot time: Unknown (0)");
4905         else
4906             proto_tree_add_time (dcerpc_tree, hf_dcerpc_dg_server_boot,
4907                                  tvb, offset, 4, &server_boot);
4908     }
4909     offset += 4;
4910
4911     if (tree)
4912         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
4913     offset += 4;
4914
4915     if (tree)
4916         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
4917     if (check_col (pinfo->cinfo, COL_INFO)) {
4918         col_append_fstr (pinfo->cinfo, COL_INFO, ": seq: %u", hdr.seqnum);
4919     }
4920     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
4921         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.seqnum);
4922     }
4923     offset += 4;
4924
4925     if (tree)
4926         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
4927     offset += 2;
4928
4929     if (tree)
4930         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
4931     offset += 2;
4932
4933     if (tree)
4934         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
4935     offset += 2;
4936
4937     if (tree)
4938         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
4939     offset += 2;
4940
4941     if (tree)
4942         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
4943     if (check_col (pinfo->cinfo, COL_INFO)) {
4944         if (hdr.flags1 & PFCL1_FRAG) {
4945             /* Fragmented - put the fragment number into the Info column */
4946             col_append_fstr (pinfo->cinfo, COL_INFO, " frag: %u",
4947                              hdr.frag_num);
4948         }
4949     }
4950     offset += 2;
4951
4952     if (tree)
4953         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
4954     offset++;
4955
4956     if (tree)
4957         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
4958     if (check_col (pinfo->cinfo, COL_INFO)) {
4959         if (hdr.flags1 & PFCL1_FRAG) {
4960             /* Fragmented - put the serial number into the Info column */
4961             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
4962                              (hdr.serial_hi << 8) | hdr.serial_lo);
4963         }
4964     }
4965     offset++;
4966
4967     if (tree) {
4968         /*
4969          * XXX - for Kerberos, we get a protection level; if it's
4970          * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
4971          * stub data.
4972          */
4973         dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr,
4974                                 &auth_level);
4975     }
4976
4977     /*
4978      * keeping track of the conversation shouldn't really be necessary
4979      * for connectionless packets, because everything we need to know
4980      * to dissect is in the header for each packet.  Unfortunately,
4981      * Microsoft's implementation is buggy and often puts the
4982      * completely wrong if_id in the header.  go figure.  So, keep
4983      * track of the seqnum and use that if possible.  Note: that's not
4984      * completely correct.  It should really be done based on both the
4985      * activity_id and seqnum.  I haven't seen anywhere that it would
4986      * make a difference, but for future reference...
4987      */
4988     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
4989                               pinfo->srcport, pinfo->destport, 0);
4990     if (!conv) {
4991         fprintf(stderr,"Creating a new conv on packet %d\n",pinfo->fd->num);
4992         conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
4993                                  pinfo->srcport, pinfo->destport, 0);
4994     }
4995
4996     /*
4997      * Packet type specific stuff is next.
4998      */
4999
5000     switch (hdr.ptype) {
5001
5002     case PDU_CANCEL_ACK:
5003         /* Body is optional */
5004         /* XXX - we assume "frag_len" is the length of the body */
5005         if (hdr.frag_len != 0)
5006             dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5007         break;
5008
5009     case PDU_CL_CANCEL:
5010         /*
5011          * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
5012          * but in at least one capture none of the Cl_cancel PDUs had a
5013          * body.
5014          */
5015         /* XXX - we assume "frag_len" is the length of the body */
5016         if (hdr.frag_len != 0)
5017             dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
5018         break;
5019
5020     case PDU_NOCALL:
5021         /* Body is optional; if present, it's the same as PDU_FACK */
5022         /* XXX - we assume "frag_len" is the length of the body */
5023         if (hdr.frag_len != 0)
5024             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5025         break;
5026
5027     case PDU_FACK:
5028         /* Body is optional */
5029         /* XXX - we assume "frag_len" is the length of the body */
5030         if (hdr.frag_len != 0)
5031             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5032         break;
5033
5034     case PDU_REJECT:
5035     case PDU_FAULT:
5036         dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
5037         break;
5038
5039     case PDU_REQ:
5040         dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5041         break;
5042
5043     case PDU_RESP:
5044         dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5045         break;
5046
5047     /* these requests have no body */
5048     case PDU_ACK:
5049     case PDU_PING:
5050         dissect_dcerpc_dg_ping_ack (tvb, offset, pinfo, dcerpc_tree, &hdr, conv);
5051         break;
5052     case PDU_WORKING:
5053     default:
5054         break;
5055     }
5056
5057     return TRUE;
5058 }
5059
5060 static void
5061 dcerpc_init_protocol (void)
5062 {
5063         /* structures and data for BIND */
5064         if (dcerpc_binds){
5065                 g_hash_table_destroy (dcerpc_binds);
5066                 dcerpc_binds=NULL;
5067         }
5068         if(!dcerpc_binds){
5069                 dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
5070         }
5071
5072         /* structures and data for CALL */
5073         if (dcerpc_cn_calls){
5074                 g_hash_table_destroy (dcerpc_cn_calls);
5075         }
5076         dcerpc_cn_calls = g_hash_table_new (dcerpc_cn_call_hash, dcerpc_cn_call_equal);
5077         if (dcerpc_dg_calls){
5078                 g_hash_table_destroy (dcerpc_dg_calls);
5079         }
5080         dcerpc_dg_calls = g_hash_table_new (dcerpc_dg_call_hash, dcerpc_dg_call_equal);
5081
5082         /* structure and data for MATCHED */
5083         if (dcerpc_matched){
5084                 g_hash_table_destroy (dcerpc_matched);
5085         }
5086         dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
5087
5088     /* call the registered hooks */
5089     g_hook_list_invoke(&dcerpc_hooks_init_protos, FALSE /* not may_recurse */);
5090 }
5091
5092 void
5093 proto_register_dcerpc (void)
5094 {
5095     static hf_register_info hf[] = {
5096         { &hf_dcerpc_request_in,
5097                 { "Request in frame", "dcerpc.request_in", FT_FRAMENUM, BASE_NONE,
5098                 NULL, 0, "This packet is a response to the packet with this number", HFILL }},
5099         { &hf_dcerpc_response_in,
5100                 { "Response in frame", "dcerpc.response_in", FT_FRAMENUM, BASE_NONE,
5101                 NULL, 0, "This packet will be responded in the packet with this number", HFILL }},
5102         { &hf_dcerpc_referent_id,
5103                 { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
5104                 NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
5105         { &hf_dcerpc_ver,
5106           { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5107         { &hf_dcerpc_ver_minor,
5108           { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5109         { &hf_dcerpc_packet_type,
5110           { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, NULL, HFILL }},
5111         { &hf_dcerpc_cn_flags,
5112           { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5113         { &hf_dcerpc_cn_flags_first_frag,
5114           { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_FIRST_FRAG, NULL, HFILL }},
5115         { &hf_dcerpc_cn_flags_last_frag,
5116           { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_LAST_FRAG, NULL, HFILL }},
5117         { &hf_dcerpc_cn_flags_cancel_pending,
5118           { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_PENDING_CANCEL, NULL, HFILL }},
5119         { &hf_dcerpc_cn_flags_reserved,
5120           { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_RESERVED_1, NULL, HFILL }},
5121         { &hf_dcerpc_cn_flags_mpx,
5122           { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_CONC_MPX, NULL, HFILL }},
5123         { &hf_dcerpc_cn_flags_dne,
5124           { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_DID_NOT_EXECUTE, NULL, HFILL }},
5125         { &hf_dcerpc_cn_flags_maybe,
5126           { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_MAYBE, NULL, HFILL }},
5127         { &hf_dcerpc_cn_flags_object,
5128           { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_OBJECT_UUID, NULL, HFILL }},
5129         { &hf_dcerpc_drep,
5130           { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5131         { &hf_dcerpc_drep_byteorder,
5132           { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, NULL, HFILL }},
5133         { &hf_dcerpc_drep_character,
5134           { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, NULL, HFILL }},
5135         { &hf_dcerpc_drep_fp,
5136           { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, NULL, HFILL }},
5137         { &hf_dcerpc_cn_frag_len,
5138           { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5139         { &hf_dcerpc_cn_auth_len,
5140           { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5141         { &hf_dcerpc_cn_call_id,
5142           { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5143         { &hf_dcerpc_cn_max_xmit,
5144           { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5145         { &hf_dcerpc_cn_max_recv,
5146           { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5147         { &hf_dcerpc_cn_assoc_group,
5148           { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5149         { &hf_dcerpc_cn_num_ctx_items,
5150           { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5151         { &hf_dcerpc_cn_ctx_item,
5152           { "Ctx Item", "dcerpc.cn_ctx_item", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5153         { &hf_dcerpc_cn_ctx_id,
5154           { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5155         { &hf_dcerpc_cn_num_trans_items,
5156           { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5157         { &hf_dcerpc_cn_bind_abstract_syntax,
5158           { "Abstract Syntax", "dcerpc.cn_bind_abstract_syntax", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5159         { &hf_dcerpc_cn_bind_if_id,
5160           { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5161         { &hf_dcerpc_cn_bind_if_ver,
5162           { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5163         { &hf_dcerpc_cn_bind_if_ver_minor,
5164           { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5165         { &hf_dcerpc_cn_bind_trans_syntax,
5166           { "Transfer Syntax", "dcerpc.cn_bind_trans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5167         { &hf_dcerpc_cn_bind_trans_id,
5168           { "ID", "dcerpc.cn_bind_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5169         { &hf_dcerpc_cn_bind_trans_ver,
5170           { "ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5171         { &hf_dcerpc_cn_alloc_hint,
5172           { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5173         { &hf_dcerpc_cn_sec_addr_len,
5174           { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5175         { &hf_dcerpc_cn_sec_addr,
5176           { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5177         { &hf_dcerpc_cn_num_results,
5178           { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5179         { &hf_dcerpc_cn_ack_result,
5180           { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, NULL, HFILL }},
5181         { &hf_dcerpc_cn_ack_reason,
5182           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, NULL, HFILL }},
5183         { &hf_dcerpc_cn_ack_trans_id,
5184           { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5185         { &hf_dcerpc_cn_ack_trans_ver,
5186           { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5187         { &hf_dcerpc_cn_reject_reason,
5188           { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, NULL, HFILL }},
5189         { &hf_dcerpc_cn_num_protocols,
5190           { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5191         { &hf_dcerpc_cn_protocol_ver_major,
5192           { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5193         { &hf_dcerpc_cn_protocol_ver_minor,
5194           { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5195         { &hf_dcerpc_cn_cancel_count,
5196           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5197         { &hf_dcerpc_cn_status,
5198           { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, NULL, HFILL }},
5199         { &hf_dcerpc_cn_deseg_req,
5200           { "Desegmentation Required", "dcerpc.cn_deseg_req", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5201         { &hf_dcerpc_auth_type,
5202           { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, NULL, HFILL }},
5203         { &hf_dcerpc_auth_level,
5204           { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, NULL, HFILL }},
5205         { &hf_dcerpc_auth_pad_len,
5206           { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5207         { &hf_dcerpc_auth_rsrvd,
5208           { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5209         { &hf_dcerpc_auth_ctx_id,
5210           { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5211         { &hf_dcerpc_dg_flags1,
5212           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5213         { &hf_dcerpc_dg_flags1_rsrvd_01,
5214           { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_RESERVED_01, NULL, HFILL }},
5215         { &hf_dcerpc_dg_flags1_last_frag,
5216           { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_LASTFRAG, NULL, HFILL }},
5217         { &hf_dcerpc_dg_flags1_frag,
5218           { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_FRAG, NULL, HFILL }},
5219         { &hf_dcerpc_dg_flags1_nofack,
5220           { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_NOFACK, NULL, HFILL }},
5221         { &hf_dcerpc_dg_flags1_maybe,
5222           { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_MAYBE, NULL, HFILL }},
5223         { &hf_dcerpc_dg_flags1_idempotent,
5224           { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_IDEMPOTENT, NULL, HFILL }},
5225         { &hf_dcerpc_dg_flags1_broadcast,
5226           { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_BROADCAST, NULL, HFILL }},
5227         { &hf_dcerpc_dg_flags1_rsrvd_80,
5228           { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_RESERVED_80, NULL, HFILL }},
5229         { &hf_dcerpc_dg_flags2,
5230           { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5231         { &hf_dcerpc_dg_flags2_rsrvd_01,
5232           { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_01, NULL, HFILL }},
5233         { &hf_dcerpc_dg_flags2_cancel_pending,
5234           { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_CANCEL_PENDING, NULL, HFILL }},
5235         { &hf_dcerpc_dg_flags2_rsrvd_04,
5236           { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_04, NULL, HFILL }},
5237         { &hf_dcerpc_dg_flags2_rsrvd_08,
5238           { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_08, NULL, HFILL }},
5239         { &hf_dcerpc_dg_flags2_rsrvd_10,
5240           { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_10, NULL, HFILL }},
5241         { &hf_dcerpc_dg_flags2_rsrvd_20,
5242           { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_20, NULL, HFILL }},
5243         { &hf_dcerpc_dg_flags2_rsrvd_40,
5244           { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_40, NULL, HFILL }},
5245         { &hf_dcerpc_dg_flags2_rsrvd_80,
5246           { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_80, NULL, HFILL }},
5247         { &hf_dcerpc_dg_serial_lo,
5248           { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5249         { &hf_dcerpc_dg_serial_hi,
5250           { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5251         { &hf_dcerpc_dg_ahint,
5252           { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5253         { &hf_dcerpc_dg_ihint,
5254           { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5255         { &hf_dcerpc_dg_frag_len,
5256           { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5257         { &hf_dcerpc_dg_frag_num,
5258           { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5259         { &hf_dcerpc_dg_auth_proto,
5260           { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, NULL, HFILL }},
5261         { &hf_dcerpc_dg_seqnum,
5262           { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5263         { &hf_dcerpc_dg_server_boot,
5264           { "Server boot time", "dcerpc.dg_server_boot", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5265         { &hf_dcerpc_dg_if_ver,
5266           { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5267         { &hf_dcerpc_krb5_av_prot_level,
5268           { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, NULL, HFILL }},
5269         { &hf_dcerpc_krb5_av_key_vers_num,
5270           { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5271         { &hf_dcerpc_krb5_av_key_auth_verifier,
5272           { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5273         { &hf_dcerpc_obj_id,
5274           { "Object", "dcerpc.obj_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5275         { &hf_dcerpc_dg_if_id,
5276           { "Interface", "dcerpc.dg_if_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5277         { &hf_dcerpc_dg_act_id,
5278           { "Activity", "dcerpc.dg_act_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5279         { &hf_dcerpc_opnum,
5280           { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5281
5282         { &hf_dcerpc_dg_cancel_vers,
5283           { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5284
5285         { &hf_dcerpc_dg_cancel_id,
5286           { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5287
5288         { &hf_dcerpc_dg_server_accepting_cancels,
5289           { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5290
5291         { &hf_dcerpc_dg_fack_vers,
5292           { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5293
5294         { &hf_dcerpc_dg_fack_window_size,
5295           { "Window Size", "dcerpc.fack_window_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5296
5297         { &hf_dcerpc_dg_fack_max_tsdu,
5298           { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5299
5300         { &hf_dcerpc_dg_fack_max_frag_size,
5301           { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5302
5303         { &hf_dcerpc_dg_fack_serial_num,
5304           { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5305
5306         { &hf_dcerpc_dg_fack_selack_len,
5307           { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5308
5309         { &hf_dcerpc_dg_fack_selack,
5310           { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5311
5312         { &hf_dcerpc_dg_status,
5313           { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, NULL, HFILL }},
5314
5315         { &hf_dcerpc_array_max_count,
5316           { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
5317
5318         { &hf_dcerpc_array_offset,
5319           { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
5320
5321         { &hf_dcerpc_array_actual_count,
5322           { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
5323
5324         { &hf_dcerpc_array_buffer,
5325           { "Buffer", "dcerpc.array.buffer", FT_BYTES, BASE_NONE, NULL, 0x0, "Buffer: Buffer containing elements of the array", HFILL }},
5326
5327         { &hf_dcerpc_op,
5328           { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5329
5330         { &hf_dcerpc_fragments,
5331           { "Reassembled DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
5332           NULL, 0x0, "DCE/RPC Fragments", HFILL }},
5333
5334         { &hf_dcerpc_fragment,
5335           { "DCE/RPC Fragment", "dcerpc.fragment", FT_FRAMENUM, BASE_NONE,
5336           NULL, 0x0, NULL, HFILL }},
5337
5338         { &hf_dcerpc_fragment_overlap,
5339           { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE,
5340       NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
5341
5342         { &hf_dcerpc_fragment_overlap_conflict,
5343           { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE,
5344       NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
5345
5346         { &hf_dcerpc_fragment_multiple_tails,
5347           { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE,
5348       NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
5349
5350         { &hf_dcerpc_fragment_too_long_fragment,
5351           { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
5352       NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
5353
5354         { &hf_dcerpc_fragment_error,
5355           { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE,
5356       NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
5357
5358         { &hf_dcerpc_time,
5359           { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE,
5360       NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }},
5361
5362         { &hf_dcerpc_reassembled_in,
5363       { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE,
5364       NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }},
5365
5366         { &hf_dcerpc_unknown_if_id,
5367           { "Unknown DCERPC interface id", "dcerpc.unknown_if_id", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5368    };
5369     static gint *ett[] = {
5370         &ett_dcerpc,
5371         &ett_dcerpc_cn_flags,
5372         &ett_dcerpc_cn_ctx,
5373         &ett_dcerpc_cn_iface,
5374         &ett_dcerpc_cn_trans_syntax,
5375         &ett_dcerpc_drep,
5376         &ett_dcerpc_dg_flags1,
5377         &ett_dcerpc_dg_flags2,
5378         &ett_dcerpc_pointer_data,
5379         &ett_dcerpc_string,
5380         &ett_dcerpc_fragments,
5381         &ett_dcerpc_fragment,
5382         &ett_dcerpc_krb5_auth_verf,
5383     };
5384     module_t *dcerpc_module;
5385
5386     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
5387     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
5388     proto_register_subtree_array (ett, array_length (ett));
5389     register_init_routine (dcerpc_init_protocol);
5390     dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
5391     prefs_register_bool_preference (dcerpc_module,
5392                                     "desegment_dcerpc",
5393                                     "Reassemble DCE/RPC messages spanning multiple TCP segments",
5394                                     "Whether the DCE/RPC dissector should reassemble messages spanning multiple TCP segments."
5395                                     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5396                                     &dcerpc_cn_desegment);
5397     prefs_register_bool_preference (dcerpc_module,
5398                                     "reassemble_dcerpc",
5399                                     "Reassemble DCE/RPC fragments",
5400                                     "Whether the DCE/RPC dissector should reassemble fragmented DCE/RPC PDUs",
5401                                     &dcerpc_reassemble);
5402     register_init_routine(dcerpc_reassemble_init);
5403     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
5404     dcerpc_tap=register_tap("dcerpc");
5405
5406     g_hook_list_init(&dcerpc_hooks_init_protos, sizeof(GHook));
5407 }
5408
5409 void
5410 proto_reg_handoff_dcerpc (void)
5411 {
5412     heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
5413     heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
5414     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
5415     heur_dissector_add ("smb_transact", dissect_dcerpc_cn_smbpipe, proto_dcerpc);
5416     heur_dissector_add ("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, proto_dcerpc);
5417     heur_dissector_add ("http", dissect_dcerpc_cn_bs, proto_dcerpc);
5418     dcerpc_smb_init(proto_dcerpc);
5419 }