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