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