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