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