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