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