Dissect the autentication verifier for Kerberos 5 authentication in
[metze/wireshark/wip.git] / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  *
5  * $Id: packet-dcerpc.c,v 1.78 2002/09/09 22:11:33 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include "packet-dcerpc.h"
36 #include <epan/conversation.h>
37 #include "prefs.h"
38 #include "reassemble.h"
39
40 static const value_string pckt_vals[] = {
41     { PDU_REQ,        "Request"},
42     { PDU_PING,       "Ping"},
43     { PDU_RESP,       "Response"},
44     { PDU_FAULT,      "Fault"},
45     { PDU_WORKING,    "Working"},
46     { PDU_NOCALL,     "Nocall"},
47     { PDU_REJECT,     "Reject"},
48     { PDU_ACK,        "Ack"},
49     { PDU_CL_CANCEL,  "Cl_cancel"},
50     { PDU_FACK,       "Fack"},
51     { PDU_CANCEL_ACK, "Cancel_ack"},
52     { PDU_BIND,       "Bind"},
53     { PDU_BIND_ACK,   "Bind_ack"},
54     { PDU_BIND_NAK,   "Bind_nak"},
55     { PDU_ALTER,      "Alter_context"},
56     { PDU_ALTER_ACK,  "Alter_context_resp"},
57     { PDU_AUTH3,      "AUTH3?"},
58     { PDU_SHUTDOWN,   "Shutdown"},
59     { PDU_CO_CANCEL,  "Co_cancel"},
60     { PDU_ORPHANED,   "Orphaned"},
61     { 0,              NULL }
62 };
63
64 static const value_string drep_byteorder_vals[] = {
65     { 0, "Big-endian" },
66     { 1, "Little-endian" },
67     { 0,  NULL }
68 };
69
70 static const value_string drep_character_vals[] = {
71     { 0, "ASCII" },
72     { 1, "EBCDIC" },
73     { 0,  NULL }
74 };
75
76 #define DCE_RPC_DREP_FP_IEEE 0
77 #define DCE_RPC_DREP_FP_VAX  1
78 #define DCE_RPC_DREP_FP_CRAY 2
79 #define DCE_RPC_DREP_FP_IBM  3
80
81 static const value_string drep_fp_vals[] = {
82     { DCE_RPC_DREP_FP_IEEE, "IEEE" },
83     { DCE_RPC_DREP_FP_VAX,  "VAX"  },
84     { DCE_RPC_DREP_FP_CRAY, "Cray" },
85     { DCE_RPC_DREP_FP_IBM,  "IBM"  },
86     { 0,  NULL }
87 };
88
89 /*
90  * Authentication services.
91  */
92 #define DCE_C_RPC_AUTHN_PROTOCOL_NONE           0
93 #define DCE_C_RPC_AUTHN_PROTOCOL_KRB5           1
94 #define DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO         9
95 #define DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP        10
96 #define DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN       68
97
98 static const value_string authn_protocol_vals[] = {
99         { DCE_C_RPC_AUTHN_PROTOCOL_NONE,    "None" },
100         { DCE_C_RPC_AUTHN_PROTOCOL_KRB5,    "Kerberos 5" },
101         { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,  "SPNEGO" },
102         { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
103         { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
104         { 0, NULL }
105 };
106
107 /*
108  * Protection levels.
109  */
110 #define DCE_C_AUTHN_LEVEL_NONE          1
111 #define DCE_C_AUTHN_LEVEL_CONNECT       2
112 #define DCE_C_AUTHN_LEVEL_CALL          3
113 #define DCE_C_AUTHN_LEVEL_PKT           4
114 #define DCE_C_AUTHN_LEVEL_PKT_INTEGRITY 5
115 #define DCE_C_AUTHN_LEVEL_PKT_PRIVACY   6
116
117 static const value_string authn_level_vals[] = {
118         { DCE_C_AUTHN_LEVEL_NONE,          "None" },
119         { DCE_C_AUTHN_LEVEL_CONNECT,       "Connect" },
120         { DCE_C_AUTHN_LEVEL_CALL,          "Call" },
121         { DCE_C_AUTHN_LEVEL_PKT,           "Packet" },
122         { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
123         { DCE_C_AUTHN_LEVEL_PKT_PRIVACY,   "Packet privacy" },
124         { 0,                               NULL }
125 };
126
127 /*
128  * Flag bits in first flag field in connectionless PDU header.
129  */
130 #define PFCL1_RESERVED_01       0x01    /* Reserved for use by implementations */
131 #define PFCL1_LASTFRAG          0x02    /* If set, the PDU is the last
132                                          * fragment of a multi-PDU
133                                          * transmission */
134 #define PFCL1_FRAG              0x04    /* If set, the PDU is a fragment of
135                                            a multi-PDU transmission */
136 #define PFCL1_NOFACK            0x08    /* If set, the receiver is not
137                                          * requested to send a `fack' PDU
138                                          * for the fragment */
139 #define PFCL1_MAYBE             0x10    /* If set, the PDU is for a `maybe'
140                                          * request */
141 #define PFCL1_IDEMPOTENT        0x20    /* If set, the PDU is for an idempotent
142                                          * request */
143 #define PFCL1_BROADCAST         0x40    /* If set, the PDU is for a broadcast
144                                          * request */
145 #define PFCL1_RESERVED_80       0x80    /* Reserved for use by implementations */
146
147 /*
148  * Flag bits in second flag field in connectionless PDU header.
149  */
150 #define PFCL2_RESERVED_01       0x01    /* Reserved for use by implementations */
151 #define PFCL2_CANCEL_PENDING    0x02    /* Cancel pending at the call end */
152 #define PFCL2_RESERVED_04       0x04    /* Reserved for future use */
153 #define PFCL2_RESERVED_08       0x08    /* Reserved for future use */
154 #define PFCL2_RESERVED_10       0x10    /* Reserved for future use */
155 #define PFCL2_RESERVED_20       0x20    /* Reserved for future use */
156 #define PFCL2_RESERVED_40       0x40    /* Reserved for future use */
157 #define PFCL2_RESERVED_80       0x80    /* Reserved for future use */
158
159 /*
160  * Flag bits in connection-oriented PDU header.
161  */
162 #define PFC_FIRST_FRAG          0x01    /* First fragment */
163 #define PFC_LAST_FRAG           0x02    /* Last fragment */
164 #define PFC_PENDING_CANCEL      0x04    /* Cancel was pending at sender */
165 #define PFC_RESERVED_1          0x08
166 #define PFC_CONC_MPX            0x10    /* suports concurrent multiplexing
167                                          * of a single connection. */
168 #define PFC_DID_NOT_EXECUTE     0x20    /* only meaningful on `fault' packet;
169                                          * if true, guaranteed call did not
170                                          * execute. */
171 #define PFC_MAYBE               0x40    /* `maybe' call semantics requested */
172 #define PFC_OBJECT_UUID         0x80    /* if true, a non-nil object UUID
173                                          * was specified in the handle, and
174                                          * is present in the optional object
175                                          * field. If false, the object field
176                                          * is omitted. */
177
178 /*
179  * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
180  * it's not fragmented (i.e., this is both the first *and* last fragment),
181  * and FALSE otherwise.
182  */
183 #define PFC_NOT_FRAGMENTED(hdr) \
184   ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
185
186 /*
187  * Presentation context negotiation result.
188  */
189 static const value_string p_cont_result_vals[] = {
190         { 0, "Acceptance" },
191         { 1, "User rejection" },
192         { 2, "Provider rejection" },
193         { 0, NULL }
194 };
195
196 /*
197  * Presentation context negotiation rejection reasons.
198  */
199 static const value_string p_provider_reason_vals[] = {
200         { 0, "Reason not specified" },
201         { 1, "Abstract syntax not supported" },
202         { 2, "Proposed transfer syntaxes not supported" },
203         { 3, "Local limit exceeded" },
204         { 0, NULL }
205 };
206
207 /*
208  * Reject reasons.
209  */
210 #define REASON_NOT_SPECIFIED            0
211 #define TEMPORARY_CONGESTION            1
212 #define LOCAL_LIMIT_EXCEEDED            2
213 #define CALLED_PADDR_UNKNOWN            3 /* not used */
214 #define PROTOCOL_VERSION_NOT_SUPPORTED  4
215 #define DEFAULT_CONTEXT_NOT_SUPPORTED   5 /* not used */
216 #define USER_DATA_NOT_READABLE          6 /* not used */
217 #define NO_PSAP_AVAILABLE               7 /* not used */
218
219 static const value_string reject_reason_vals[] = {
220         { REASON_NOT_SPECIFIED,           "Reason not specified" },
221         { TEMPORARY_CONGESTION,           "Temporary congestion" },
222         { LOCAL_LIMIT_EXCEEDED,           "Local limit exceeded" },
223         { CALLED_PADDR_UNKNOWN,           "Called paddr unknown" },
224         { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
225         { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
226         { USER_DATA_NOT_READABLE,         "User data not readable" },
227         { NO_PSAP_AVAILABLE,              "No PSAP available" },
228         { 0,                              NULL }
229 };
230
231 /*
232  * Reject status codes.
233  */
234 static const value_string reject_status_vals[] = {
235         { 0,          "Stub-defined exception" },
236         { 0x1c000001, "nca_s_fault_int_div_by_zero" },
237         { 0x1c000002, "nca_s_fault_addr_error" },
238         { 0x1c000003, "nca_s_fault_fp_div_zero" },
239         { 0x1c000004, "nca_s_fault_fp_underflow" },
240         { 0x1c000005, "nca_s_fault_fp_overflow" },
241         { 0x1c000006, "nca_s_fault_invalid_tag" },
242         { 0x1c000007, "nca_s_fault_invalid_bound" },
243         { 0x1c000008, "nca_rpc_version_mismatch" },
244         { 0x1c000009, "nca_unspec_reject" },
245         { 0x1c00000a, "nca_s_bad_actid" },
246         { 0x1c00000b, "nca_who_are_you_failed" },
247         { 0x1c00000c, "nca_manager_not_entered" },
248         { 0x1c00000d, "nca_s_fault_cancel" },
249         { 0x1c00000e, "nca_s_fault_ill_inst" },
250         { 0x1c00000f, "nca_s_fault_fp_error" },
251         { 0x1c000010, "nca_s_fault_int_overflow" },
252         { 0x1c000014, "nca_s_fault_pipe_empty" },
253         { 0x1c000015, "nca_s_fault_pipe_closed" },
254         { 0x1c000016, "nca_s_fault_pipe_order" },
255         { 0x1c000017, "nca_s_fault_pipe_discipline" },
256         { 0x1c000018, "nca_s_fault_pipe_comm_error" },
257         { 0x1c000019, "nca_s_fault_pipe_memory" },
258         { 0x1c00001a, "nca_s_fault_context_mismatch" },
259         { 0x1c00001b, "nca_s_fault_remote_no_memory" },
260         { 0x1c00001c, "nca_invalid_pres_context_id" },
261         { 0x1c00001d, "nca_unsupported_authn_level" },
262         { 0x1c00001f, "nca_invalid_checksum" },
263         { 0x1c000020, "nca_invalid_crc" },
264         { 0x1c000021, "ncs_s_fault_user_defined" },
265         { 0x1c000022, "nca_s_fault_tx_open_failed" },
266         { 0x1c000023, "nca_s_fault_codeset_conv_error" },
267         { 0x1c000024, "nca_s_fault_object_not_found" },
268         { 0x1c000025, "nca_s_fault_no_client_stub" },
269         { 0x1c010002, "nca_op_rng_error" },
270         { 0x1c010003, "nca_unk_if"},
271         { 0x1c010006, "nca_wrong_boot_time" },
272         { 0x1c010009, "nca_s_you_crashed" },
273         { 0x1c01000b, "nca_proto_error" },
274         { 0x1c010013, "nca_out_args_too_big" },
275         { 0x1c010014, "nca_server_too_busy" },
276         { 0x1c010017, "nca_unsupported_type" },
277         { 0,          NULL }
278 };
279
280 static int proto_dcerpc = -1;
281
282 /* field defines */
283 static int hf_dcerpc_request_in = -1;
284 static int hf_dcerpc_response_in = -1;
285 static int hf_dcerpc_ver = -1;
286 static int hf_dcerpc_ver_minor = -1;
287 static int hf_dcerpc_packet_type = -1;
288 static int hf_dcerpc_cn_flags = -1;
289 static int hf_dcerpc_cn_flags_first_frag = -1;
290 static int hf_dcerpc_cn_flags_last_frag = -1;
291 static int hf_dcerpc_cn_flags_cancel_pending = -1;
292 static int hf_dcerpc_cn_flags_reserved = -1;
293 static int hf_dcerpc_cn_flags_mpx = -1;
294 static int hf_dcerpc_cn_flags_dne = -1;
295 static int hf_dcerpc_cn_flags_maybe = -1;
296 static int hf_dcerpc_cn_flags_object = -1;
297 static int hf_dcerpc_drep = -1;
298 static int hf_dcerpc_drep_byteorder = -1;
299 static int hf_dcerpc_drep_character = -1;
300 static int hf_dcerpc_drep_fp = -1;
301 static int hf_dcerpc_cn_frag_len = -1;
302 static int hf_dcerpc_cn_auth_len = -1;
303 static int hf_dcerpc_cn_call_id = -1;
304 static int hf_dcerpc_cn_max_xmit = -1;
305 static int hf_dcerpc_cn_max_recv = -1;
306 static int hf_dcerpc_cn_assoc_group = -1;
307 static int hf_dcerpc_cn_num_ctx_items = -1;
308 static int hf_dcerpc_cn_ctx_id = -1;
309 static int hf_dcerpc_cn_num_trans_items = -1;
310 static int hf_dcerpc_cn_bind_if_id = -1;
311 static int hf_dcerpc_cn_bind_if_ver = -1;
312 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
313 static int hf_dcerpc_cn_bind_trans_id = -1;
314 static int hf_dcerpc_cn_bind_trans_ver = -1;
315 static int hf_dcerpc_cn_alloc_hint = -1;
316 static int hf_dcerpc_cn_sec_addr_len = -1;
317 static int hf_dcerpc_cn_sec_addr = -1;
318 static int hf_dcerpc_cn_num_results = -1;
319 static int hf_dcerpc_cn_ack_result = -1;
320 static int hf_dcerpc_cn_ack_reason = -1;
321 static int hf_dcerpc_cn_ack_trans_id = -1;
322 static int hf_dcerpc_cn_ack_trans_ver = -1;
323 static int hf_dcerpc_cn_reject_reason = -1;
324 static int hf_dcerpc_cn_num_protocols = -1;
325 static int hf_dcerpc_cn_protocol_ver_major = -1;
326 static int hf_dcerpc_cn_protocol_ver_minor = -1;
327 static int hf_dcerpc_cn_cancel_count = -1;
328 static int hf_dcerpc_cn_status = -1;
329 static int hf_dcerpc_auth_type = -1;
330 static int hf_dcerpc_auth_level = -1;
331 static int hf_dcerpc_auth_pad_len = -1;
332 static int hf_dcerpc_auth_rsrvd = -1;
333 static int hf_dcerpc_auth_ctx_id = -1;
334 static int hf_dcerpc_dg_flags1 = -1;
335 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
336 static int hf_dcerpc_dg_flags1_last_frag = -1;
337 static int hf_dcerpc_dg_flags1_frag = -1;
338 static int hf_dcerpc_dg_flags1_nofack = -1;
339 static int hf_dcerpc_dg_flags1_maybe = -1;
340 static int hf_dcerpc_dg_flags1_idempotent = -1;
341 static int hf_dcerpc_dg_flags1_broadcast = -1;
342 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
343 static int hf_dcerpc_dg_flags2 = -1;
344 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
345 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
346 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
347 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
348 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
349 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
350 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
351 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
352 static int hf_dcerpc_dg_serial_hi = -1;
353 static int hf_dcerpc_obj_id = -1;
354 static int hf_dcerpc_dg_if_id = -1;
355 static int hf_dcerpc_dg_act_id = -1;
356 static int hf_dcerpc_dg_serial_lo = -1;
357 static int hf_dcerpc_dg_ahint = -1;
358 static int hf_dcerpc_dg_ihint = -1;
359 static int hf_dcerpc_dg_frag_len = -1;
360 static int hf_dcerpc_dg_frag_num = -1;
361 static int hf_dcerpc_dg_auth_proto = -1;
362 static int hf_dcerpc_opnum = -1;
363 static int hf_dcerpc_dg_seqnum = -1;
364 static int hf_dcerpc_dg_server_boot = -1;
365 static int hf_dcerpc_dg_if_ver = -1;
366 static int hf_dcerpc_krb5_av_prot_level = -1;
367 static int hf_dcerpc_krb5_av_key_vers_num = -1;
368 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
369 static int hf_dcerpc_dg_cancel_vers = -1;
370 static int hf_dcerpc_dg_cancel_id = -1;
371 static int hf_dcerpc_dg_server_accepting_cancels = -1;
372 static int hf_dcerpc_dg_fack_vers = -1;
373 static int hf_dcerpc_dg_fack_window_size = -1;
374 static int hf_dcerpc_dg_fack_max_tsdu = -1;
375 static int hf_dcerpc_dg_fack_max_frag_size = -1;
376 static int hf_dcerpc_dg_fack_serial_num = -1;
377 static int hf_dcerpc_dg_fack_selack_len = -1;
378 static int hf_dcerpc_dg_fack_selack = -1;
379 static int hf_dcerpc_dg_status = -1;
380 static int hf_dcerpc_array_max_count = -1;
381 static int hf_dcerpc_array_offset = -1;
382 static int hf_dcerpc_array_actual_count = -1;
383 static int hf_dcerpc_op = -1;
384 static int hf_dcerpc_referent_id = -1;
385 static int hf_dcerpc_fragments = -1;
386 static int hf_dcerpc_fragment = -1;
387 static int hf_dcerpc_fragment_overlap = -1;
388 static int hf_dcerpc_fragment_overlap_conflict = -1;
389 static int hf_dcerpc_fragment_multiple_tails = -1;
390 static int hf_dcerpc_fragment_too_long_fragment = -1;
391 static int hf_dcerpc_fragment_error = -1;
392
393 static gint ett_dcerpc = -1;
394 static gint ett_dcerpc_cn_flags = -1;
395 static gint ett_dcerpc_drep = -1;
396 static gint ett_dcerpc_dg_flags1 = -1;
397 static gint ett_dcerpc_dg_flags2 = -1;
398 static gint ett_dcerpc_pointer_data = -1;
399 static gint ett_dcerpc_fragments = -1;
400 static gint ett_dcerpc_fragment = -1;
401 static gint ett_decrpc_krb5_auth_verf = -1;
402
403 static dissector_handle_t ntlmssp_handle, gssapi_handle;
404
405 fragment_items dcerpc_frag_items = {
406         &ett_dcerpc_fragments,
407         &ett_dcerpc_fragment,
408
409         &hf_dcerpc_fragments,
410         &hf_dcerpc_fragment,
411         &hf_dcerpc_fragment_overlap,
412         &hf_dcerpc_fragment_overlap_conflict,
413         &hf_dcerpc_fragment_multiple_tails,
414         &hf_dcerpc_fragment_too_long_fragment,
415         &hf_dcerpc_fragment_error,
416
417         "fragments"
418 };
419
420 /* try to desegment big DCE/RPC packets over TCP? */
421 static gboolean dcerpc_cn_desegment = TRUE;
422
423 /* reassemble DCE/RPC fragments */
424 /* reassembly of dcerpc fragments will not work for the case where ONE frame
425    might contain multiple dcerpc fragments for different PDUs.
426    this case would be so unusual/weird so if you got captures like that:
427         too bad
428 */
429 static gboolean dcerpc_reassemble = FALSE;
430 static GHashTable *dcerpc_co_reassemble_table = NULL;
431 static GHashTable *dcerpc_cl_reassemble_table = NULL;
432
433 static void
434 dcerpc_reassemble_init(void)
435 {
436   fragment_table_init(&dcerpc_co_reassemble_table);
437   fragment_table_init(&dcerpc_cl_reassemble_table);
438 }
439
440 /*
441  * Subdissectors
442  */
443
444 /* the registered subdissectors */
445 static GHashTable *dcerpc_uuids;
446
447 typedef struct _dcerpc_uuid_key {
448     e_uuid_t uuid;
449     guint16 ver;
450 } dcerpc_uuid_key;
451
452 typedef struct _dcerpc_uuid_value {
453     int proto;
454     int ett;
455     gchar *name;
456     dcerpc_sub_dissector *procs;
457     int opnum_hf;
458 } dcerpc_uuid_value;
459
460 static gint
461 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
462 {
463     dcerpc_uuid_key *key1 = (dcerpc_uuid_key *)k1;
464     dcerpc_uuid_key *key2 = (dcerpc_uuid_key *)k2;
465     return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
466             && (key1->ver == key2->ver));
467 }
468
469 static guint
470 dcerpc_uuid_hash (gconstpointer k)
471 {
472     dcerpc_uuid_key *key = (dcerpc_uuid_key *)k;
473     /* This isn't perfect, but the Data1 part of these is almost always
474        unique. */
475     return key->uuid.Data1;
476 }
477
478 void
479 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
480                   dcerpc_sub_dissector *procs, int opnum_hf)
481 {
482     dcerpc_uuid_key *key = g_malloc (sizeof (*key));
483     dcerpc_uuid_value *value = g_malloc (sizeof (*value));
484
485     key->uuid = *uuid;
486     key->ver = ver;
487
488     value->proto = proto;
489     value->ett = ett;
490     value->name = proto_get_protocol_short_name (proto);
491     value->procs = procs;
492     value->opnum_hf = opnum_hf;
493
494     g_hash_table_insert (dcerpc_uuids, key, value);
495 }
496
497
498 /*
499  * To keep track of ctx_id mappings.
500  *
501  * Everytime we see a bind call we update this table.
502  * Note that we always specify a SMB FID. For non-SMB transports this
503  * value is 0.
504  */
505 static GHashTable *dcerpc_binds=NULL;
506
507 typedef struct _dcerpc_bind_key {
508     conversation_t *conv;
509     guint16 ctx_id;
510     guint16 smb_fid;
511 } dcerpc_bind_key;
512
513 typedef struct _dcerpc_bind_value {
514         e_uuid_t uuid;
515         guint16 ver;
516 } dcerpc_bind_value;
517
518 static GMemChunk *dcerpc_bind_key_chunk=NULL;
519 static GMemChunk *dcerpc_bind_value_chunk=NULL;
520
521 static gint
522 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
523 {
524     dcerpc_bind_key *key1 = (dcerpc_bind_key *)k1;
525     dcerpc_bind_key *key2 = (dcerpc_bind_key *)k2;
526     return (key1->conv == key2->conv
527             && key1->ctx_id == key2->ctx_id
528             && key1->smb_fid == key2->smb_fid);
529 }
530
531 static guint
532 dcerpc_bind_hash (gconstpointer k)
533 {
534     dcerpc_bind_key *key = (dcerpc_bind_key *)k;
535     return ((guint)key->conv) + key->ctx_id + key->smb_fid;
536 }
537
538 /*
539  * To keep track of callid mappings.  Should really use some generic
540  * conversation support instead.
541  */
542 static GHashTable *dcerpc_calls=NULL;
543
544 typedef struct _dcerpc_call_key {
545     conversation_t *conv;
546     guint32 call_id;
547     guint16 smb_fid;
548 } dcerpc_call_key;
549
550 static GMemChunk *dcerpc_call_key_chunk=NULL;
551
552 static GMemChunk *dcerpc_call_value_chunk=NULL;
553
554 static gint
555 dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
556 {
557     dcerpc_call_key *key1 = (dcerpc_call_key *)k1;
558     dcerpc_call_key *key2 = (dcerpc_call_key *)k2;
559     return (key1->conv == key2->conv
560             && key1->call_id == key2->call_id
561             && key1->smb_fid == key2->smb_fid);
562 }
563
564 static guint
565 dcerpc_call_hash (gconstpointer k)
566 {
567     dcerpc_call_key *key = (dcerpc_call_key *)k;
568     return ((guint32)key->conv) + key->call_id + key->smb_fid;
569 }
570
571
572 /* to keep track of matched calls/responses
573    this one uses the same value struct as calls, but the key is the frame id
574 */
575 static GHashTable *dcerpc_matched=NULL;
576 static gint
577 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
578 {
579         return (guint32)k1 == (guint32)k2;
580 }
581
582 static guint
583 dcerpc_matched_hash (gconstpointer k)
584 {
585         return (guint32)k;
586 }
587
588
589
590 /*
591  * Utility functions.  Modeled after packet-rpc.c
592  */
593
594 int
595 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
596                       proto_tree *tree, char *drep,
597                       int hfindex, guint8 *pdata)
598 {
599     guint8 data;
600
601     data = tvb_get_guint8 (tvb, offset);
602     if (tree) {
603         proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
604     }
605     if (pdata)
606         *pdata = data;
607     return offset + 1;
608 }
609
610 int
611 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
612                        proto_tree *tree, char *drep,
613                        int hfindex, guint16 *pdata)
614 {
615     guint16 data;
616
617     data = ((drep[0] & 0x10)
618             ? tvb_get_letohs (tvb, offset)
619             : tvb_get_ntohs (tvb, offset));
620
621     if (tree) {
622         proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
623     }
624     if (pdata)
625         *pdata = data;
626     return offset + 2;
627 }
628
629 int
630 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
631                        proto_tree *tree, char *drep,
632                        int hfindex, guint32 *pdata)
633 {
634     guint32 data;
635
636     data = ((drep[0] & 0x10)
637             ? tvb_get_letohl (tvb, offset)
638             : tvb_get_ntohl (tvb, offset));
639
640     if (tree) {
641         proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
642     }
643     if (pdata)
644         *pdata = data;
645     return offset+4;
646 }
647
648 int
649 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
650                        proto_tree *tree, char *drep,
651                        int hfindex, unsigned char *pdata)
652 {
653     if(pdata){
654       tvb_memcpy(tvb, pdata, offset, 8);
655       if(drep[0] & 0x10){/* XXX this might be the wrong way around */
656         unsigned char data;
657         data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
658         data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
659         data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
660         data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
661       }
662     }
663
664     if (tree) {
665         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
666     }
667
668     return offset+8;
669 }
670
671
672 int
673 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
674                     proto_tree *tree, char *drep, 
675                     int hfindex, gfloat *pdata)
676 {
677         gfloat data;
678
679
680         switch(drep[1]) {
681                 case(DCE_RPC_DREP_FP_IEEE):
682                         data = ((drep[0] & 0x10)
683                                         ? tvb_get_letohieee_float(tvb, offset)
684                                         : tvb_get_ntohieee_float(tvb, offset));
685                         if (tree) {
686                                 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
687                         }
688                         break;
689                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
690                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
691                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
692                 default:
693                         /* ToBeDone: non IEEE floating formats */
694                         /* Set data to a negative infinity value */
695                         data = -1.0 * 1e100 * 1e100;
696                         if (tree) {
697                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
698                         }
699         }
700     if (pdata)
701         *pdata = data;
702     return offset + 4;
703 }
704
705
706 int
707 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
708                     proto_tree *tree, char *drep, 
709                     int hfindex, gdouble *pdata)
710 {
711     gdouble data;
712
713
714         switch(drep[1]) {
715                 case(DCE_RPC_DREP_FP_IEEE):
716                         data = ((drep[0] & 0x10)
717                                         ? tvb_get_letohieee_double(tvb, offset)
718                                         : tvb_get_ntohieee_double(tvb, offset));
719                         if (tree) {
720                                 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
721                         }
722                         break;
723                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
724                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
725                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
726                 default:
727                         /* ToBeDone: non IEEE double formats */
728                         /* Set data to a negative infinity value */
729                         data = -1.0 * 1e100 * 1e100;
730                         if (tree) {
731                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
732                         }
733         }
734     if (pdata)
735         *pdata = data;
736     return offset + 8;
737 }
738
739
740 /*
741  * a couple simpler things
742  */
743 guint16
744 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
745 {
746     if (drep[0] & 0x10) {
747         return tvb_get_letohs (tvb, offset);
748     } else {
749         return tvb_get_ntohs (tvb, offset);
750     }
751 }
752
753 guint32
754 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
755 {
756     if (drep[0] & 0x10) {
757         return tvb_get_letohl (tvb, offset);
758     } else {
759         return tvb_get_ntohl (tvb, offset);
760     }
761 }
762
763 void
764 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
765 {
766     unsigned int i;
767     uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
768     uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
769     uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
770
771     for (i=0; i<sizeof (uuid->Data4); i++) {
772         uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
773     }
774 }
775
776
777
778 /* NDR arrays */
779 /* function to dissect a unidimensional conformant array */
780 int
781 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
782                 proto_tree *tree, char *drep,
783                 dcerpc_dissect_fnct_t *fnct)
784 {
785         guint32 i;
786         dcerpc_info *di;
787         int old_offset;
788
789         di=pinfo->private_data;
790         if(di->conformant_run){
791                 /* conformant run, just dissect the max_count header */
792                 old_offset=offset;
793                 di->conformant_run=0;
794                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
795                                 hf_dcerpc_array_max_count, &di->array_max_count);
796                 di->array_max_count_offset=offset-4;
797                 di->conformant_run=1;
798                 di->conformant_eaten=offset-old_offset;
799         } else {
800                 /* we dont dont remember where  in the bytestream this fields was */
801                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
802
803                 /* real run, dissect the elements */
804                 for(i=0;i<di->array_max_count;i++){
805                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
806                 }
807         }
808
809         return offset;
810 }
811 /* function to dissect a unidimensional conformant and varying array */
812 int
813 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
814                 proto_tree *tree, char *drep,
815                 dcerpc_dissect_fnct_t *fnct)
816 {
817         guint32 i;
818         dcerpc_info *di;
819         int old_offset;
820
821         di=pinfo->private_data;
822         if(di->conformant_run){
823                 /* conformant run, just dissect the max_count header */
824                 old_offset=offset;
825                 di->conformant_run=0;
826                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
827                                 hf_dcerpc_array_max_count, &di->array_max_count);
828                 di->array_max_count_offset=offset-4;
829                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
830                                 hf_dcerpc_array_offset, &di->array_offset);
831                 di->array_offset_offset=offset-4;
832                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
833                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
834                 di->array_actual_count_offset=offset-4;
835                 di->conformant_run=1;
836                 di->conformant_eaten=offset-old_offset;
837         } else {
838                 /* we dont dont remember where  in the bytestream these fields were */
839                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
840                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
841                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
842
843                 /* real run, dissect the elements */
844                 for(i=0;i<di->array_actual_count;i++){
845                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
846                 }
847         }
848
849         return offset;
850 }
851
852
853 /* ndr pointer handling */
854 /* list of pointers encountered so far */
855 static GSList *ndr_pointer_list = NULL;
856
857 /* position where in the list to insert newly encountered pointers */
858 static int ndr_pointer_list_pos=0;
859
860 /* boolean controlling whether pointers are top-level or embedded */
861 static gboolean pointers_are_top_level = TRUE;
862
863 /* as a kludge, we represent all embedded reference pointers as id==-1
864    hoping that his will not collide with any non-ref pointers */
865 typedef struct ndr_pointer_data {
866         guint32 id;
867         proto_tree *tree;
868         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
869         int hf_index;
870         int levels;
871 } ndr_pointer_data_t;
872
873 static void
874 init_ndr_pointer_list(packet_info *pinfo)
875 {
876         dcerpc_info *di;
877
878         di=pinfo->private_data;
879         di->conformant_run=0;
880
881         while(ndr_pointer_list){
882                 ndr_pointer_data_t *npd;
883
884                 npd=g_slist_nth_data(ndr_pointer_list, 0);
885                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
886                 if(npd){
887                         g_free(npd);
888                 }
889         }
890
891         ndr_pointer_list=NULL;
892         ndr_pointer_list_pos=0;
893         pointers_are_top_level=TRUE;
894 }
895
896 static int
897 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, char *drep)
898 {
899         int found_new_pointer;
900         dcerpc_info *di;
901         int old_offset;
902
903         di=pinfo->private_data;
904         do{
905                 int i, len;
906
907                 found_new_pointer=0;
908                 len=g_slist_length(ndr_pointer_list);
909                 for(i=0;i<len;i++){
910                         ndr_pointer_data_t *tnpd;
911                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
912                         if(tnpd->fnct){
913                                 dcerpc_dissect_fnct_t *fnct;
914
915                                 found_new_pointer=1;
916                                 fnct=tnpd->fnct;
917                                 tnpd->fnct=NULL;
918                                 ndr_pointer_list_pos=i+1;
919                                 di->hf_index=tnpd->hf_index;
920                                 di->levels=tnpd->levels;
921                                 /* first a run to handle any conformant
922                                    array headers */
923                                 di->conformant_run=1;
924                                 di->conformant_eaten=0;
925                                 old_offset = offset;
926                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
927
928                                 g_assert((offset-old_offset)==di->conformant_eaten);
929                                 /* This is to check for any bugs in the dissectors.
930                                  *
931                                  * Basically, the NDR representation will store all
932                                  * arrays in two blocks, one block with the dimension
933                                  * discreption, like size, number of elements and such,
934                                  * and another block that contains the actual data stored
935                                  * in the array.
936                                  * If the array is embedded directly inside another,
937                                  * encapsulating aggregate type, like a union or struct,
938                                  * then these two blocks will be stored at different places
939                                  * in the bytestream, with other data between the blocks.
940                                  *
941                                  * For this reason, all pointers to types (both aggregate
942                                  * and scalar, for simplicity no distinction is made)
943                                  * will have its dissector called twice.
944                                  * The dissector will first be called with conformant_run==1
945                                  * in which mode the dissector MUST NOT consume any data from
946                                  * the tvbuff (i.e. may not dissect anything) except the
947                                  * initial control block for arrays.
948                                  * The second time the dissector is called, with
949                                  * conformant_run==0, all other data for the type will be
950                                  * dissected.
951                                  *
952                                  * All dissect_ndr_<type> dissectors are already prepared
953                                  * for this and knows when it should eat data from the tvb
954                                  * and when not to, so implementors of dissectors will
955                                  * normally not need to worry about this or even know about
956                                  * it. However, if a dissector for an aggregate type calls
957                                  * a subdissector from outside packet-dcerpc.c, such as
958                                  * the dissector in packet-smb.c for NT Security Descriptors
959                                  * as an example, then it is VERY important to encapsulate
960                                  * this call to an external subdissector with the appropriate
961                                  * test for conformant_run, i.e. it will need something like
962                                  *
963                                  *      dcerpc_info *di;
964                                  *
965                                  *      di=pinfo->private_data;
966                                  *      if(di->conformant_run){
967                                  *              return offset;
968                                  *      }
969                                  *
970                                  * to make sure it makes the right thing.
971                                  * This assert will signal when someone has forgotten to
972                                  * make the dissector aware of this requirement.
973                                  */
974
975                                 /* now we dissect the actual pointer */
976                                 di->conformant_run=0;
977                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
978                                 break;
979                         }
980                 }
981         } while(found_new_pointer);
982
983         return offset;
984 }
985
986
987 static void
988 add_pointer_to_list(packet_info *pinfo, proto_tree *tree,
989                 dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index, int levels)
990 {
991         ndr_pointer_data_t *npd;
992
993         /* check if this pointer is valid */
994         if(id!=0xffffffff){
995                 dcerpc_info *di;
996                 dcerpc_call_value *value;
997
998                 di=pinfo->private_data;
999                 value=di->call_data;
1000
1001                 if(di->request){
1002                         if(!(pinfo->fd->flags.visited)){
1003                                 if(id>value->max_ptr){
1004                                         value->max_ptr=id;
1005                                 }
1006                         }
1007                 } else {
1008                         /* if we havent seen the request bail out since we cant
1009                            know whether this is the first non-NULL instance
1010                            or not */
1011                         if(value->req_frame==0){
1012                                 /* XXX THROW EXCEPTION */
1013                         }
1014
1015                         /* We saw this one in the request frame, nothing to
1016                            dissect later */
1017                         if(id<=value->max_ptr){
1018                                 return;
1019                         }
1020                 }
1021         }
1022
1023         npd=g_malloc(sizeof(ndr_pointer_data_t));
1024         npd->id=id;
1025         npd->tree=tree;
1026         npd->fnct=fnct;
1027         npd->hf_index=hf_index;
1028         npd->levels=levels;
1029         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1030                                         ndr_pointer_list_pos);
1031         ndr_pointer_list_pos++;
1032 }
1033
1034
1035 static int
1036 find_pointer_index(guint32 id)
1037 {
1038         ndr_pointer_data_t *npd;
1039         int i,len;
1040
1041         len=g_slist_length(ndr_pointer_list);
1042         for(i=0;i<len;i++){
1043                 npd=g_slist_nth_data(ndr_pointer_list, i);
1044                 if(npd){
1045                         if(npd->id==id){
1046                                 return i;
1047                         }
1048                 }
1049         }
1050
1051         return -1;
1052 }
1053
1054 /* This function dissects an NDR pointer and stores the callback for later
1055  * deferred dissection.
1056  *
1057  *   fnct is the callback function for when we have reached this object in
1058  *   the bytestream.
1059  *
1060  *   type is what type of pointer.
1061  *
1062  *   this is text is what text we should put in any created tree node.
1063  *
1064  *   hf_index is what hf value we want to pass to the callback function when
1065  *   it is called, the callback can later pich this one up from di->hf_index.
1066  *
1067  *   levels is a generic int we want to pass to teh callback function.  the
1068  *   callback can later pick it up from di->levels
1069  *
1070  * See packet-dcerpc-samr.c for examples
1071  */
1072 int
1073 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1074                     proto_tree *tree, char *drep, dcerpc_dissect_fnct_t *fnct,
1075                     int type, char *text, int hf_index, int levels)
1076 {
1077         dcerpc_info *di;
1078
1079         di=pinfo->private_data;
1080         if(di->conformant_run){
1081                 /* this call was only for dissecting the header for any
1082                    embedded conformant array. we will not parse any
1083                    pointers in this mode.
1084                 */
1085                 return offset;
1086         }
1087
1088         /*TOP LEVEL REFERENCE POINTER*/
1089         if( pointers_are_top_level
1090         &&(type==NDR_POINTER_REF) ){
1091                 proto_item *item;
1092                 proto_tree *tr;
1093
1094                 /* we must find out a nice way to do the length here */
1095                 item=proto_tree_add_text(tree, tvb, offset, 0,
1096                         "%s", text);
1097                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1098
1099                 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1100                 goto after_ref_id;
1101         }
1102
1103         /*TOP LEVEL FULL POINTER*/
1104         if( pointers_are_top_level
1105         && (type==NDR_POINTER_PTR) ){
1106                 int idx;
1107                 guint32 id;
1108                 proto_item *item;
1109                 proto_tree *tr;
1110
1111                 /* get the referent id */
1112                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1113
1114                 /* we got a NULL pointer */
1115                 if(id==0){
1116                         proto_tree_add_text(tree, tvb, offset-4, 4,
1117                                 "(NULL pointer) %s",text);
1118                         goto after_ref_id;
1119                 }
1120
1121                 /* see if we have seen this pointer before */
1122                 idx=find_pointer_index(id);
1123
1124                 /* we have seen this pointer before */
1125                 if(idx>=0){
1126                         proto_tree_add_text(tree, tvb, offset-4, 4,
1127                                 "(duplicate PTR) %s",text);
1128                         goto after_ref_id;
1129                 }
1130
1131                 /* new pointer */
1132                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1133                         "%s", text);
1134                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1135                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1136                 add_pointer_to_list(pinfo, tr, fnct, id, hf_index, levels);
1137                 goto after_ref_id;
1138         }
1139         /*TOP LEVEL UNIQUE POINTER*/
1140         if( pointers_are_top_level
1141         && (type==NDR_POINTER_UNIQUE) ){
1142                 guint32 id;
1143                 proto_item *item;
1144                 proto_tree *tr;
1145
1146                 /* get the referent id */
1147                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1148
1149                 /* we got a NULL pointer */
1150                 if(id==0){
1151                         proto_tree_add_text(tree, tvb, offset-4, 4,
1152                                 "(NULL pointer) %s",text);
1153                         goto after_ref_id;
1154                 }
1155
1156                 /* new pointer */
1157                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1158                         "%s", text);
1159                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1160                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1161                 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1162                 goto after_ref_id;
1163         }
1164
1165         /*EMBEDDED REFERENCE POINTER*/
1166         if( (!pointers_are_top_level)
1167         && (type==NDR_POINTER_REF) ){
1168                 guint32 id;
1169                 proto_item *item;
1170                 proto_tree *tr;
1171
1172                 /* get the referent id */
1173                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1174
1175                 /* new pointer */
1176                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1177                         "%s",text);
1178                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1179                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1180                 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1181                 goto after_ref_id;
1182         }
1183
1184         /*EMBEDDED UNIQUE POINTER*/
1185         if( (!pointers_are_top_level)
1186         && (type==NDR_POINTER_UNIQUE) ){
1187                 guint32 id;
1188                 proto_item *item;
1189                 proto_tree *tr;
1190
1191                 /* get the referent id */
1192                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1193
1194                 /* we got a NULL pointer */
1195                 if(id==0){
1196                         proto_tree_add_text(tree, tvb, offset-4, 4,
1197                                 "(NULL pointer) %s", text);
1198                         goto after_ref_id;
1199                 }
1200
1201                 /* new pointer */
1202                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1203                         "%s",text);
1204                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1205                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1206                 add_pointer_to_list(pinfo, tr, fnct, 0xffffffff, hf_index, levels);
1207                 goto after_ref_id;
1208         }
1209
1210         /*EMBEDDED FULL POINTER*/
1211         if( (!pointers_are_top_level)
1212         && (type==NDR_POINTER_PTR) ){
1213                 int idx;
1214                 guint32 id;
1215                 proto_item *item;
1216                 proto_tree *tr;
1217
1218                 /* get the referent id */
1219                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1220
1221                 /* we got a NULL pointer */
1222                 if(id==0){
1223                         proto_tree_add_text(tree, tvb, offset-4, 4,
1224                                 "(NULL pointer) %s",text);
1225                         goto after_ref_id;
1226                 }
1227
1228                 /* see if we have seen this pointer before */
1229                 idx=find_pointer_index(id);
1230
1231                 /* we have seen this pointer before */
1232                 if(idx>=0){
1233                         proto_tree_add_text(tree, tvb, offset-4, 4,
1234                                 "(duplicate PTR) %s",text);
1235                         goto after_ref_id;
1236                 }
1237
1238                 /* new pointer */
1239                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1240                         "%s", text);
1241                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1242                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1243                 add_pointer_to_list(pinfo, tr, fnct, id, hf_index, levels);
1244                 goto after_ref_id;
1245         }
1246
1247
1248 after_ref_id:
1249         /* After each top level pointer we have dissected we have to
1250            dissect all deferrals before we move on to the next top level
1251            argument */
1252         if(pointers_are_top_level==TRUE){
1253                 pointers_are_top_level=FALSE;
1254                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
1255                 pointers_are_top_level=TRUE;
1256         }
1257
1258         return offset;
1259 }
1260
1261
1262
1263 static int
1264 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
1265                     proto_tree *dcerpc_tree,
1266                     tvbuff_t *tvb, gint offset,
1267                     char *drep, dcerpc_info *info,
1268                     int auth_level)
1269 {
1270     dcerpc_uuid_key key;
1271     dcerpc_uuid_value *sub_proto;
1272     int length;
1273     proto_tree *sub_tree = NULL;
1274     dcerpc_sub_dissector *proc;
1275     gchar *name = NULL;
1276     dcerpc_dissect_fnct_t *sub_dissect;
1277     const char *saved_proto;
1278     void *saved_private_data;
1279
1280     key.uuid = info->call_data->uuid;
1281     key.ver = info->call_data->ver;
1282
1283
1284     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
1285          || !proto_is_protocol_enabled(sub_proto->proto)) {
1286         /*
1287          * We don't have a dissector for this UUID, or the protocol
1288          * for that UUID is disabled.
1289          */
1290         length = tvb_length_remaining (tvb, offset);
1291         if (length > 0) {
1292             proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1293                                  "Stub data (%d byte%s)", length,
1294                                  plurality(length, "", "s"));
1295         }
1296         return -1;
1297     }
1298
1299     for (proc = sub_proto->procs; proc->name; proc++) {
1300         if (proc->num == info->call_data->opnum) {
1301             name = proc->name;
1302             break;
1303         }
1304     }
1305
1306     if (!name)
1307         name = "Unknown?!";
1308
1309     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
1310         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
1311     }
1312
1313     if (check_col (pinfo->cinfo, COL_INFO)) {
1314         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
1315                       name, info->request ? "request" : "reply");
1316     }
1317
1318     if (tree) {
1319         proto_item *sub_item;
1320         sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
1321                                         -1, FALSE);
1322
1323         if (sub_item) {
1324             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
1325         }
1326
1327         /*
1328          * Put the operation number into the tree along with
1329          * the operation's name.
1330          */
1331
1332         if (sub_proto->opnum_hf != -1)
1333                 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
1334                                            tvb, 0, 0, info->call_data->opnum,
1335                                            "Operation: %s (%u)",
1336                                            name, info->call_data->opnum);
1337         else
1338                 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
1339                                            0, 0, info->call_data->opnum,
1340                                            "Operation: %s (%u)",
1341                                            name, info->call_data->opnum);
1342     }
1343
1344     /*
1345      * If the authentication level is DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
1346      * the stub data is encrypted, and we can't dissect it.
1347      */
1348     if (auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
1349         length = tvb_length_remaining (tvb, offset);
1350         if (length > 0) {
1351             proto_tree_add_text(sub_tree, tvb, offset, length,
1352                                 "Encrypted stub data (%d byte%s)",
1353                                 length, plurality(length, "", "s"));
1354         }
1355     } else {
1356         sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp;
1357         if (sub_dissect) {
1358             saved_proto = pinfo->current_proto;
1359             saved_private_data = pinfo->private_data;
1360             pinfo->current_proto = sub_proto->name;
1361             pinfo->private_data = (void *)info;
1362
1363             init_ndr_pointer_list(pinfo);
1364             offset = sub_dissect (tvb, offset, pinfo, sub_tree, drep);
1365
1366             pinfo->current_proto = saved_proto;
1367             pinfo->private_data = saved_private_data;
1368         } else {
1369             length = tvb_length_remaining (tvb, offset);
1370             if (length > 0) {
1371                 proto_tree_add_text (sub_tree, tvb, offset, length,
1372                                      "Stub data (%d byte%s)", length,
1373                                      plurality(length, "", "s"));
1374             }
1375         }
1376     }
1377     return 0;
1378 }
1379
1380 static int
1381 dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1382                         e_dce_cn_common_hdr_t *hdr, int *auth_level_p)
1383 {
1384     int offset;
1385     guint8 auth_pad_len;
1386     guint8 auth_level;
1387     guint8 auth_type;
1388
1389     /*
1390      * Initially set "*auth_level_p" to -1 to indicate that we haven't
1391      * yet seen any authentication level information.
1392      */
1393     if (auth_level_p != NULL)
1394         *auth_level_p = -1;
1395
1396     /*
1397      * The authentication information is at the *end* of the PDU; in
1398      * request and response PDUs, the request and response stub data
1399      * come before it.
1400      *
1401      * If the full packet is here, and we've got an auth len, and it's
1402      * valid, then dissect the auth info.
1403      */
1404     if (tvb_length (tvb) >= hdr->frag_len
1405         && hdr->auth_len
1406         && (hdr->auth_len + 8 <= hdr->frag_len)) {
1407
1408         offset = hdr->frag_len - (hdr->auth_len + 8);
1409
1410         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1411                                        hf_dcerpc_auth_type, &auth_type);
1412         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1413                                        hf_dcerpc_auth_level, &auth_level);
1414         if (auth_level_p != NULL)
1415             *auth_level_p = auth_level;
1416         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1417                                        hf_dcerpc_auth_pad_len, &auth_pad_len);
1418         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1419                                        hf_dcerpc_auth_rsrvd, NULL);
1420         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1421                                         hf_dcerpc_auth_ctx_id, NULL);
1422
1423         /* Dissect the authentication data */
1424
1425         switch(auth_type) {
1426
1427                 /* NTLMSSP */
1428
1429         case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: {
1430                 tvbuff_t *ntlmssp_tvb;
1431
1432                 ntlmssp_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
1433                                              hdr->auth_len);
1434
1435                 call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo,
1436                                dcerpc_tree);
1437
1438                 break;
1439         }
1440
1441                 /* SPNEGO (rfc2478) */
1442
1443         case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: {
1444                 tvbuff_t *gssapi_tvb;
1445
1446                 gssapi_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
1447                                             hdr->auth_len);
1448
1449                 call_dissector(gssapi_handle, gssapi_tvb, pinfo, dcerpc_tree);
1450
1451                 break;
1452         }
1453
1454         default:
1455                 proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
1456                                      "Auth Data");
1457         }
1458
1459         /* figure out where the auth padding starts */
1460         offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len);
1461         if (offset > 0 && auth_pad_len) {
1462             proto_tree_add_text (dcerpc_tree, tvb, offset,
1463                                  auth_pad_len, "Auth padding");
1464             return hdr->auth_len + 8 + auth_pad_len;
1465         } else {
1466             return hdr->auth_len + 8;
1467         }
1468     } else {
1469         return 0;
1470     }
1471 }
1472
1473
1474 /* We need to hash in the SMB fid number to generate a unique hash table
1475    key as DCERPC over SMB allows several pipes over the same TCP/IP
1476    socket. */
1477
1478 static guint16 get_smb_fid (void *private_data)
1479 {
1480     dcerpc_private_info *priv = (dcerpc_private_info *)private_data;
1481
1482     if (!priv)
1483         return 0;       /* Nothing to see here */
1484
1485     /* DCERPC over smb */
1486
1487     if (priv->transport_type == DCERPC_TRANSPORT_SMB)
1488         return priv->data.smb.fid;
1489
1490     /* Some other transport... */
1491
1492     return 0;
1493 }
1494
1495 /*
1496  * Connection oriented packet types
1497  */
1498
1499 static void
1500 dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1501                         e_dce_cn_common_hdr_t *hdr)
1502 {
1503     conversation_t *conv = NULL;
1504     guint8 num_ctx_items;
1505     guint i;
1506     gboolean saw_ctx_item = FALSE;
1507     guint16 ctx_id;
1508     guint16 num_trans_items;
1509     guint j;
1510     e_uuid_t if_id;
1511     e_uuid_t trans_id;
1512     guint32 trans_ver;
1513     guint16 if_ver, if_ver_minor;
1514     int offset = 16;
1515
1516     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1517                                     hf_dcerpc_cn_max_xmit, NULL);
1518
1519     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1520                                     hf_dcerpc_cn_max_recv, NULL);
1521
1522     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1523                                     hf_dcerpc_cn_assoc_group, NULL);
1524
1525     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1526                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
1527
1528     /* padding */
1529     offset += 3;
1530
1531     for (i = 0; i < num_ctx_items; i++) {
1532       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1533                                       hf_dcerpc_cn_ctx_id, &ctx_id);
1534
1535       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1536                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
1537
1538       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
1539       if (dcerpc_tree) {
1540           proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
1541                                         offset, 16, "HMMM",
1542                                         "Interface UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1543                                         if_id.Data1, if_id.Data2, if_id.Data3,
1544                                         if_id.Data4[0], if_id.Data4[1],
1545                                         if_id.Data4[2], if_id.Data4[3],
1546                                         if_id.Data4[4], if_id.Data4[5],
1547                                         if_id.Data4[6], if_id.Data4[7]);
1548       }
1549       offset += 16;
1550
1551       if (hdr->drep[0] & 0x10) {
1552           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1553                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
1554           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1555                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
1556       } else {
1557           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1558                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
1559           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1560                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
1561       }
1562
1563       if (!saw_ctx_item) {
1564         conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1565                                   pinfo->srcport, pinfo->destport, 0);
1566         if (conv == NULL) {
1567             conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
1568                                      pinfo->srcport, pinfo->destport, 0);
1569         }
1570
1571         /* if this is the first time we see this packet, we need to
1572            update the dcerpc_binds table so that any later calls can
1573            match to the interface.
1574            XXX We assume that BINDs will NEVER be fragmented.
1575         */
1576         if(!(pinfo->fd->flags.visited)){
1577                 dcerpc_bind_key *key;
1578                 dcerpc_bind_value *value;
1579
1580                 key = g_mem_chunk_alloc (dcerpc_bind_key_chunk);
1581                 key->conv = conv;
1582                 key->ctx_id = ctx_id;
1583                 key->smb_fid = get_smb_fid(pinfo->private_data);
1584
1585                 value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
1586                 value->uuid = if_id;
1587                 value->ver = if_ver;
1588
1589                 /* add this entry to the bind table, first removing any
1590                    previous ones that are identical
1591                  */
1592                 if(g_hash_table_lookup(dcerpc_binds, key)){
1593                         g_hash_table_remove(dcerpc_binds, key);
1594                 }
1595                 g_hash_table_insert (dcerpc_binds, key, value);
1596         }
1597
1598         if (check_col (pinfo->cinfo, COL_INFO)) {
1599           dcerpc_uuid_key key;
1600           dcerpc_uuid_value *value;
1601
1602           key.uuid = if_id;
1603           key.ver = if_ver;
1604
1605           if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
1606                   col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
1607           else
1608                   col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
1609                            if_id.Data1, if_id.Data2, if_id.Data3,
1610                            if_id.Data4[0], if_id.Data4[1],
1611                            if_id.Data4[2], if_id.Data4[3],
1612                            if_id.Data4[4], if_id.Data4[5],
1613                            if_id.Data4[6], if_id.Data4[7],
1614                            if_ver, if_ver_minor);
1615         }
1616         saw_ctx_item = TRUE;
1617       }
1618
1619       for (j = 0; j < num_trans_items; j++) {
1620         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
1621         if (dcerpc_tree) {
1622             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
1623                                           offset, 16, "HMMM",
1624                                           "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1625                                           trans_id.Data1, trans_id.Data2, trans_id.Data3,
1626                                           trans_id.Data4[0], trans_id.Data4[1],
1627                                           trans_id.Data4[2], trans_id.Data4[3],
1628                                           trans_id.Data4[4], trans_id.Data4[5],
1629                                           trans_id.Data4[6], trans_id.Data4[7]);
1630         }
1631         offset += 16;
1632
1633         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1634                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
1635       }
1636     }
1637
1638     /*
1639      * XXX - we should save the authentication type *if* we have
1640      * an authentication header, and associate it with an authentication
1641      * context, so subsequent PDUs can use that context.
1642      */
1643     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL);
1644 }
1645
1646 static void
1647 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1648                             e_dce_cn_common_hdr_t *hdr)
1649 {
1650     guint16 max_xmit, max_recv;
1651     guint16 sec_addr_len;
1652     guint8 num_results;
1653     guint i;
1654     guint16 result;
1655     guint16 reason;
1656     e_uuid_t trans_id;
1657     guint32 trans_ver;
1658
1659     int offset = 16;
1660
1661     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1662                                     hf_dcerpc_cn_max_xmit, &max_xmit);
1663
1664     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1665                                     hf_dcerpc_cn_max_recv, &max_recv);
1666
1667     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1668                                     hf_dcerpc_cn_assoc_group, NULL);
1669
1670     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1671                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
1672     if (sec_addr_len != 0) {
1673         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
1674                              sec_addr_len, FALSE);
1675         offset += sec_addr_len;
1676     }
1677
1678     if (offset % 4) {
1679         offset += 4 - offset % 4;
1680     }
1681
1682     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1683                                    hf_dcerpc_cn_num_results, &num_results);
1684
1685     /* padding */
1686     offset += 3;
1687
1688     for (i = 0; i < num_results; i++) {
1689         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1690                                         hdr->drep, hf_dcerpc_cn_ack_result,
1691                                         &result);
1692         if (result != 0) {
1693             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1694                                             hdr->drep, hf_dcerpc_cn_ack_reason,
1695                                             &reason);
1696         } else {
1697             /*
1698              * The reason for rejection isn't meaningful, and often isn't
1699              * set, when the syntax was accepted.
1700              */
1701             offset += 2;
1702         }
1703
1704         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
1705         if (dcerpc_tree) {
1706             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
1707                                           offset, 16, "HMMM",
1708                                           "Transfer Syntax: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1709                                           trans_id.Data1, trans_id.Data2, trans_id.Data3,
1710                                           trans_id.Data4[0], trans_id.Data4[1],
1711                                           trans_id.Data4[2], trans_id.Data4[3],
1712                                           trans_id.Data4[4], trans_id.Data4[5],
1713                                           trans_id.Data4[6], trans_id.Data4[7]);
1714         }
1715         offset += 16;
1716
1717         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1718                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
1719     }
1720
1721     /*
1722      * XXX - do we need to do anything with the authentication level
1723      * we get back from this?
1724      */
1725     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL);
1726
1727     if (check_col (pinfo->cinfo, COL_INFO)) {
1728         if (num_results != 0 && result == 0) {
1729             /* XXX - only checks the last result */
1730             col_append_fstr (pinfo->cinfo, COL_INFO,
1731                              " accept max_xmit: %u max_recv: %u",
1732                              max_xmit, max_recv);
1733         } else {
1734             /* XXX - only shows the last result and reason */
1735             col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
1736                              val_to_str(result, p_cont_result_vals,
1737                                         "Unknown result (%u)"),
1738                              val_to_str(reason, p_provider_reason_vals,
1739                                         "Unknown (%u)"));
1740         }
1741     }
1742 }
1743
1744 static void
1745 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1746                             e_dce_cn_common_hdr_t *hdr)
1747 {
1748     guint16 reason;
1749     guint8 num_protocols;
1750     guint i;
1751
1752     int offset = 16;
1753
1754     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
1755                                     hdr->drep, hf_dcerpc_cn_reject_reason,
1756                                     &reason);
1757
1758     if (check_col (pinfo->cinfo, COL_INFO)) {
1759         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
1760                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
1761     }
1762
1763     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
1764         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1765                                        hf_dcerpc_cn_num_protocols,
1766                                        &num_protocols);
1767
1768         for (i = 0; i < num_protocols; i++) {
1769             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
1770                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
1771                                         NULL);
1772             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
1773                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
1774                                         NULL);
1775         }
1776     }
1777 }
1778
1779 static void
1780 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
1781                         proto_tree *dcerpc_tree, proto_tree *tree,
1782                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
1783                         int auth_sz, int auth_level, guint32 alloc_hint,
1784                         guint32 frame)
1785 {
1786     int length, reported_length, stub_length;
1787     gboolean save_fragmented;
1788
1789     length = tvb_length_remaining(tvb, offset);
1790     reported_length = tvb_reported_length_remaining(tvb, offset);
1791     stub_length = hdr->frag_len - offset - auth_sz;
1792     if (length > stub_length)
1793       length = stub_length;
1794     if (reported_length > stub_length)
1795       reported_length = stub_length;
1796
1797     save_fragmented = pinfo->fragmented;
1798
1799     /* If we don't have reassembly enabled, or this packet contains
1800        the entire PDU, or if this is a short frame (or a frame
1801        not reassembled at a lower layer) that doesn't include all
1802        the data in the fragment, just call the handoff directly if
1803        this is the first fragment or the PDU isn't fragmented. */
1804     if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
1805                 stub_length > length ){
1806         if(hdr->flags&PFC_FIRST_FRAG){
1807             /* First fragment, possibly the only fragment */
1808             pinfo->fragmented = !PFC_NOT_FRAGMENTED(hdr);
1809             dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
1810                                 tvb_new_subset (tvb, offset, length,
1811                                                 reported_length),
1812                                 0, hdr->drep, di, auth_level);
1813         } else {
1814             /* PDU is fragmented and this isn't the first fragment */
1815             if (check_col(pinfo->cinfo, COL_INFO)) {
1816                 col_append_fstr(pinfo->cinfo, COL_INFO,
1817                                 " [DCE/RPC fragment]");
1818             }
1819             if (dcerpc_tree) {
1820                 if (length > 0) {
1821                     proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1822                                 "Fragment data (%d byte%s)", length,
1823                                 plurality(length, "", "s"));
1824                 }
1825             }
1826         }
1827     } else {
1828         /* Reassembly is enabled, the PDU is fragmented, and
1829            we have all the data in the fragment; the first two
1830            of those mean we should attempt reassembly, and the
1831            third means we can attempt reassembly. */
1832         if (dcerpc_tree) {
1833             if (length > 0) {
1834                 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
1835                                 "Fragment data (%d byte%s)", length,
1836                                 plurality(length, "", "s"));
1837             }
1838         }
1839         if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
1840             if( (!pinfo->fd->flags.visited) && frame){
1841                 fragment_add(tvb, offset, pinfo, frame,
1842                              dcerpc_co_reassemble_table,
1843                              0,
1844                              length,
1845                              TRUE);
1846                 fragment_set_tot_len(pinfo, frame,
1847                              dcerpc_co_reassemble_table, alloc_hint);
1848             }
1849             if (check_col(pinfo->cinfo, COL_INFO)) {
1850                 col_append_fstr(pinfo->cinfo, COL_INFO,
1851                                 " [DCE/RPC fragment]");
1852             }
1853         } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
1854             if( frame ){
1855                 fragment_data *fd_head;
1856                 guint32 tot_len;
1857
1858                 tot_len = fragment_get_tot_len(pinfo, frame,
1859                                dcerpc_co_reassemble_table);
1860                 fd_head = fragment_add(tvb, offset, pinfo,
1861                      frame,
1862                      dcerpc_co_reassemble_table,
1863                      tot_len-alloc_hint,
1864                      length,
1865                      TRUE);
1866
1867                 if(fd_head){
1868                     /* We completed reassembly */
1869                     tvbuff_t *next_tvb;
1870
1871                     next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
1872                     tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1873                     add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
1874                     show_fragment_tree(fd_head, &dcerpc_frag_items,
1875                         dcerpc_tree, pinfo, next_tvb);
1876
1877                     pinfo->fragmented = FALSE;
1878                     dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
1879                                 0, hdr->drep, di, auth_level);
1880                 } else {
1881                     /* Reassembly not complete - some fragments
1882                        are missing */
1883                     if (check_col(pinfo->cinfo, COL_INFO)) {
1884                         col_append_fstr(pinfo->cinfo, COL_INFO,
1885                                     " [DCE/RPC fragment]");
1886                     }
1887                 }
1888             }
1889         } else {  /* MIDDLE fragment(s) */
1890             if( (!pinfo->fd->flags.visited) && frame ){
1891                 guint32 tot_len;
1892                 tot_len = fragment_get_tot_len(pinfo, frame,
1893                                        dcerpc_co_reassemble_table);
1894                 fragment_add(tvb, offset, pinfo, frame,
1895                              dcerpc_co_reassemble_table,
1896                              tot_len-alloc_hint,
1897                              length,
1898                              TRUE);
1899             }
1900             if (check_col(pinfo->cinfo, COL_INFO)) {
1901                 col_append_fstr(pinfo->cinfo, COL_INFO,
1902                                 " [DCE/RPC fragment]");
1903             }
1904         }
1905     }
1906     pinfo->fragmented = save_fragmented;
1907 }
1908
1909 static void
1910 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1911                         proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
1912 {
1913     conversation_t *conv;
1914     guint16 ctx_id;
1915     guint16 opnum;
1916     e_uuid_t obj_id;
1917     int auth_sz = 0;
1918     int auth_level;
1919     int offset = 16;
1920     guint32 alloc_hint;
1921     int length;
1922
1923     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1924                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
1925
1926     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1927                                     hf_dcerpc_cn_ctx_id, &ctx_id);
1928
1929     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1930                                     hf_dcerpc_opnum, &opnum);
1931
1932     if (check_col (pinfo->cinfo, COL_INFO)) {
1933         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
1934                          opnum, ctx_id);
1935     }
1936
1937     if (hdr->flags & PFC_OBJECT_UUID) {
1938         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
1939         if (dcerpc_tree) {
1940             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
1941                                           offset, 16, "HMMM",
1942                                           "Object UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1943                                           obj_id.Data1, obj_id.Data2, obj_id.Data3,
1944                                           obj_id.Data4[0],
1945                                           obj_id.Data4[1],
1946                                           obj_id.Data4[2],
1947                                           obj_id.Data4[3],
1948                                           obj_id.Data4[4],
1949                                           obj_id.Data4[5],
1950                                           obj_id.Data4[6],
1951                                           obj_id.Data4[7]);
1952         }
1953         offset += 16;
1954     }
1955
1956     /*
1957      * XXX - what if this was set when the connection was set up,
1958      * and we just have a security context?
1959      */
1960     auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
1961                                       &auth_level);
1962
1963     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
1964                               pinfo->srcport, pinfo->destport, 0);
1965     if (!conv) {
1966
1967     } else {
1968         dcerpc_call_value *value;
1969
1970         /* !!! we can NOT check flags.visited here since this will interact
1971            badly with when SMB handles (i.e. calls the subdissector)
1972            and desegmented pdu's .
1973            Instead we check if this pdu is already in the matched table or not
1974         */
1975         if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
1976                 dcerpc_bind_key bind_key;
1977                 dcerpc_bind_value *bind_value;
1978
1979                 bind_key.conv=conv;
1980                 bind_key.ctx_id=ctx_id;
1981                 bind_key.smb_fid=get_smb_fid(pinfo->private_data);
1982
1983                 if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key))){
1984                         dcerpc_call_key *call_key;
1985                         dcerpc_call_value *call_value;
1986
1987                         /* We found the binding so just add the call
1988                            to both the call table and the matched table
1989                         */
1990                         call_key=g_mem_chunk_alloc (dcerpc_call_key_chunk);
1991                         call_key->conv=conv;
1992                         call_key->call_id=hdr->call_id;
1993                         call_key->smb_fid=get_smb_fid(pinfo->private_data);
1994
1995                         /* if there is already a matching call in the table
1996                            remove it so it is replaced with the new one */
1997                         if(g_hash_table_lookup(dcerpc_calls, call_key)){
1998                                 g_hash_table_remove(dcerpc_calls, call_key);
1999                         }
2000
2001                         call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
2002                         call_value->uuid = bind_value->uuid;
2003                         call_value->ver = bind_value->ver;
2004                         call_value->opnum = opnum;
2005                         call_value->req_frame=pinfo->fd->num;
2006                         call_value->rep_frame=0;
2007                         call_value->max_ptr=0;
2008                         call_value->private_data = NULL;
2009                         g_hash_table_insert (dcerpc_calls, call_key, call_value);
2010
2011                         g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2012                 }
2013         }
2014
2015         value=g_hash_table_lookup (dcerpc_matched, (void *)pinfo->fd->num);
2016
2017         if (value) {
2018             dcerpc_info di;
2019
2020             /* handoff this call */
2021             di.conv = conv;
2022             di.call_id = hdr->call_id;
2023             di.smb_fid = get_smb_fid(pinfo->private_data);
2024             di.request = TRUE;
2025             di.call_data = value;
2026
2027             if(value->rep_frame!=0){
2028                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
2029                                     tvb, 0, 0, value->rep_frame);
2030             }
2031
2032             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
2033                                     hdr, &di, auth_sz, auth_level, alloc_hint,
2034                                     value->req_frame);
2035         } else {
2036             length = tvb_length_remaining (tvb, offset);
2037             if (length > 0) {
2038                 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2039                                      "Stub data (%d byte%s)", length,
2040                                      plurality(length, "", "s"));
2041             }
2042         }
2043     }
2044 }
2045
2046 static void
2047 dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
2048                         proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
2049 {
2050     dcerpc_call_value *value = NULL;
2051     conversation_t *conv;
2052     guint16 ctx_id;
2053     int auth_sz = 0;
2054     int offset = 16;
2055     int auth_level;
2056     guint32 alloc_hint;
2057     int length;
2058
2059     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2060                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
2061
2062     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2063                                     hf_dcerpc_cn_ctx_id, &ctx_id);
2064
2065     if (check_col (pinfo->cinfo, COL_INFO)) {
2066         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
2067     }
2068
2069     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2070                                    hf_dcerpc_cn_cancel_count, NULL);
2071     /* padding */
2072     offset++;
2073
2074     /*
2075      * XXX - what if this was set when the connection was set up,
2076      * and we just have a security context?
2077      */
2078     auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
2079                                       &auth_level);
2080
2081     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2082                               pinfo->srcport, pinfo->destport, 0);
2083     if (!conv) {
2084         /* no point in creating one here, really */
2085     } else {
2086
2087         /* !!! we can NOT check flags.visited here since this will interact
2088            badly with when SMB handles (i.e. calls the subdissector)
2089            and desegmented pdu's .
2090            Instead we check if this pdu is already in the matched table or not
2091         */
2092         if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
2093                 dcerpc_call_key call_key;
2094                 dcerpc_call_value *call_value;
2095
2096                 call_key.conv=conv;
2097                 call_key.call_id=hdr->call_id;
2098                 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2099
2100                 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2101                         g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2102                         if(call_value->rep_frame==0){
2103                                 call_value->rep_frame=pinfo->fd->num;
2104                         }
2105
2106                 }
2107         }
2108
2109         value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2110
2111         if (value) {
2112             dcerpc_info di;
2113
2114             /* handoff this call */
2115             di.conv = conv;
2116             di.call_id = hdr->call_id;
2117             di.smb_fid = get_smb_fid(pinfo->private_data);
2118             di.request = FALSE;
2119             di.call_data = value;
2120
2121             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2122             if(value->req_frame!=0){
2123                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2124                                     tvb, 0, 0, value->req_frame);
2125             }
2126
2127             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
2128                                     hdr, &di, auth_sz, auth_level, alloc_hint,
2129                                     value->rep_frame);
2130         } else {
2131             length = tvb_length_remaining (tvb, offset);
2132             if (length > 0) {
2133                 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2134                                      "Stub data (%d byte%s)", length,
2135                                      plurality(length, "", "s"));
2136             }
2137         }
2138     }
2139 }
2140
2141 static void
2142 dissect_dcerpc_cn_fault (tvbuff_t *tvb, packet_info *pinfo,
2143                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2144 {
2145     dcerpc_call_value *value = NULL;
2146     conversation_t *conv;
2147     guint16 ctx_id;
2148     guint32 status;
2149     int auth_sz = 0;
2150     int offset = 16;
2151     int auth_level;
2152     guint32 alloc_hint;
2153
2154     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2155                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
2156
2157     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2158                                     hf_dcerpc_cn_ctx_id, &ctx_id);
2159
2160     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2161                                    hf_dcerpc_cn_cancel_count, NULL);
2162     /* padding */
2163     offset++;
2164
2165     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2166                                     hf_dcerpc_cn_status, &status);
2167
2168     if (check_col (pinfo->cinfo, COL_INFO)) {
2169         col_append_fstr (pinfo->cinfo, COL_INFO,
2170                       " ctx_id: %u status: %s", ctx_id,
2171                       val_to_str(status, reject_status_vals,
2172                                  "Unknown (0x%08x)"));
2173     }
2174
2175     /* padding */
2176     offset += 4;
2177
2178     /*
2179      * XXX - what if this was set when the connection was set up,
2180      * and we just have a security context?
2181      */
2182     auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
2183                                       &auth_level);
2184
2185     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2186                               pinfo->srcport, pinfo->destport, 0);
2187     if (!conv) {
2188         /* no point in creating one here, really */
2189     } else {
2190
2191         /* !!! we can NOT check flags.visited here since this will interact
2192            badly with when SMB handles (i.e. calls the subdissector)
2193            and desegmented pdu's .
2194            Instead we check if this pdu is already in the matched table or not
2195         */
2196         if(!g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num)){
2197                 dcerpc_call_key call_key;
2198                 dcerpc_call_value *call_value;
2199
2200                 call_key.conv=conv;
2201                 call_key.call_id=hdr->call_id;
2202                 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2203
2204                 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2205                         g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2206                         if(call_value->rep_frame==0){
2207                                 call_value->rep_frame=pinfo->fd->num;
2208                         }
2209
2210                 }
2211         }
2212
2213         value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2214
2215         if (value) {
2216             int length, reported_length, stub_length;
2217             dcerpc_info di;
2218
2219             /* handoff this call */
2220             di.conv = conv;
2221             di.call_id = hdr->call_id;
2222             di.smb_fid = get_smb_fid(pinfo->private_data);
2223             di.request = FALSE;
2224             di.call_data = value;
2225
2226             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2227             if(value->req_frame!=0){
2228                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2229                                     tvb, 0, 0, value->req_frame);
2230             }
2231
2232             length = tvb_length_remaining(tvb, offset);
2233             reported_length = tvb_reported_length_remaining(tvb, offset);
2234             stub_length = hdr->frag_len - offset - auth_sz;
2235             if (length > stub_length)
2236               length = stub_length;
2237             if (reported_length > stub_length)
2238               reported_length = stub_length;
2239
2240             /* If we don't have reassembly enabled, or this packet contains
2241                the entire PDU, or if this is a short frame (or a frame
2242                not reassembled at a lower layer) that doesn't include all
2243                the data in the fragment, just call the handoff directly if
2244                this is the first fragment or the PDU isn't fragmented. */
2245             if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
2246                         stub_length > length ){
2247                 if(hdr->flags&PFC_FIRST_FRAG){
2248                     /* First fragment, possibly the only fragment */
2249                     /*
2250                      * XXX - should there be a third routine for each
2251                      * function in an RPC subdissector, to handle
2252                      * fault responses?  The DCE RPC 1.1 spec says
2253                      * three's "stub data" here, which I infer means
2254                      * that it's protocol-specific and call-specific.
2255                      *
2256                      * It should probably get passed the status code
2257                      * as well, as that might be protocol-specific.
2258                      */
2259                     if (dcerpc_tree) {
2260                         if (length > 0) {
2261                             proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2262                                         "Fault stub data (%d byte%s)", length,
2263                                         plurality(length, "", "s"));
2264                         }
2265                     }
2266                 } else {
2267                     /* PDU is fragmented and this isn't the first fragment */
2268                     if (check_col(pinfo->cinfo, COL_INFO)) {
2269                         col_append_fstr(pinfo->cinfo, COL_INFO,
2270                                         " [DCE/RPC fragment]");
2271                     }
2272                     if (dcerpc_tree) {
2273                         if (length > 0) {
2274                             proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2275                                         "Fragment data (%d byte%s)", length,
2276                                         plurality(length, "", "s"));
2277                         }
2278                     }
2279                 }
2280             } else {
2281                 /* Reassembly is enabled, the PDU is fragmented, and
2282                    we have all the data in the fragment; the first two
2283                    of those mean we should attempt reassembly, and the
2284                    third means we can attempt reassembly. */
2285                 if (dcerpc_tree) {
2286                     if (length > 0) {
2287                         proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2288                                         "Fragment data (%d byte%s)", length,
2289                                         plurality(length, "", "s"));
2290                     }
2291                 }
2292                 if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
2293                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
2294                         fragment_add(tvb, offset, pinfo, value->rep_frame,
2295                              dcerpc_co_reassemble_table,
2296                              0,
2297                              length,
2298                              TRUE);
2299                         fragment_set_tot_len(pinfo, value->rep_frame,
2300                              dcerpc_co_reassemble_table, alloc_hint);
2301                     }
2302                     if (check_col(pinfo->cinfo, COL_INFO)) {
2303                         col_append_fstr(pinfo->cinfo, COL_INFO,
2304                                         " [DCE/RPC fragment]");
2305                     }
2306                 } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
2307                     if( value->rep_frame ){
2308                         fragment_data *fd_head;
2309                         guint32 tot_len;
2310
2311                         tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
2312                                        dcerpc_co_reassemble_table);
2313                         fd_head = fragment_add(tvb, offset, pinfo,
2314                              value->rep_frame,
2315                              dcerpc_co_reassemble_table,
2316                              tot_len-alloc_hint,
2317                              length,
2318                              TRUE);
2319
2320                         if(fd_head){
2321                             /* We completed reassembly */
2322                             tvbuff_t *next_tvb;
2323
2324                             next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
2325                             tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2326                             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2327                             show_fragment_tree(fd_head, &dcerpc_frag_items,
2328                                 dcerpc_tree, pinfo, next_tvb);
2329
2330                             /*
2331                              * XXX - should there be a third routine for each
2332                              * function in an RPC subdissector, to handle
2333                              * fault responses?  The DCE RPC 1.1 spec says
2334                              * three's "stub data" here, which I infer means
2335                              * that it's protocol-specific and call-specific.
2336                              *
2337                              * It should probably get passed the status code
2338                              * as well, as that might be protocol-specific.
2339                              */
2340                             if (dcerpc_tree) {
2341                                 if (length > 0) {
2342                                     proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2343                                                 "Fault stub data (%d byte%s)", length,
2344                                                 plurality(length, "", "s"));
2345                                 }
2346                             }
2347                         } else {
2348                             /* Reassembly not complete - some fragments
2349                                are missing */
2350                             if (check_col(pinfo->cinfo, COL_INFO)) {
2351                                 col_append_fstr(pinfo->cinfo, COL_INFO,
2352                                                 " [DCE/RPC fragment]");
2353                             }
2354                         }
2355                     }
2356                 } else {  /* MIDDLE fragment(s) */
2357                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
2358                         guint32 tot_len;
2359                         tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
2360                                        dcerpc_co_reassemble_table);
2361                         fragment_add(tvb, offset, pinfo, value->rep_frame,
2362                              dcerpc_co_reassemble_table,
2363                              tot_len-alloc_hint,
2364                              length,
2365                              TRUE);
2366                     }
2367                     if (check_col(pinfo->cinfo, COL_INFO)) {
2368                         col_append_fstr(pinfo->cinfo, COL_INFO,
2369                                         " [DCE/RPC fragment]");
2370                     }
2371                 }
2372             }
2373         }
2374     }
2375 }
2376
2377 /*
2378  * DCERPC dissector for connection oriented calls
2379  */
2380 static int
2381 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
2382                    proto_tree *tree, gboolean can_desegment)
2383 {
2384     static char nulls[4] = { 0 };
2385     int start_offset;
2386     int padding = 0;
2387     proto_item *ti = NULL;
2388     proto_item *tf = NULL;
2389     proto_tree *dcerpc_tree = NULL;
2390     proto_tree *cn_flags_tree = NULL;
2391     proto_tree *drep_tree = NULL;
2392     e_dce_cn_common_hdr_t hdr;
2393
2394     /*
2395      * when done over nbt, dcerpc requests are padded with 4 bytes of null
2396      * data for some reason.
2397      *
2398      * XXX - if that's always the case, the right way to do this would
2399      * be to have a "dissect_dcerpc_cn_nb" routine which strips off
2400      * the 4 bytes of null padding, and make that the dissector
2401      * used for "netbios".
2402      */
2403     if (tvb_bytes_exist (tvb, offset, 4) &&
2404         tvb_memeql (tvb, offset, nulls, 4) == 0) {
2405
2406         /*
2407          * Skip the padding.
2408          */
2409         offset += 4;
2410         padding += 4;
2411     }
2412
2413     /*
2414      * Check if this looks like a C/O DCERPC call
2415      */
2416     if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
2417         return -1;
2418     }
2419     start_offset = offset;
2420     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
2421     if (hdr.rpc_ver != 5)
2422         return -1;
2423     hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
2424     if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
2425         return -1;
2426     hdr.ptype = tvb_get_guint8 (tvb, offset++);
2427     if (hdr.ptype > 19)
2428         return -1;
2429
2430     if (check_col (pinfo->cinfo, COL_PROTOCOL))
2431         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
2432     if (check_col (pinfo->cinfo, COL_INFO))
2433         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
2434
2435     hdr.flags = tvb_get_guint8 (tvb, offset++);
2436     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
2437     offset += sizeof (hdr.drep);
2438
2439     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2440     offset += 2;
2441     hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
2442     offset += 2;
2443     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
2444     offset += 4;
2445
2446     offset = start_offset;
2447     if (can_desegment && pinfo->can_desegment
2448         && hdr.frag_len > tvb_length_remaining (tvb, offset)) {
2449         pinfo->desegment_offset = offset;
2450         pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, offset);
2451         return 0;       /* desegmentation required */
2452     }
2453
2454     if (check_col (pinfo->cinfo, COL_INFO))
2455         col_append_fstr (pinfo->cinfo, COL_INFO, ": call_id: %u", hdr.call_id);
2456     if (tree) {
2457         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
2458         if (ti) {
2459             dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
2460         }
2461         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
2462         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
2463         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
2464         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
2465         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
2466         if (cn_flags_tree) {
2467             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
2468             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
2469             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
2470             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
2471             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
2472             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
2473             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
2474             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
2475         }
2476         offset++;
2477
2478         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
2479         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
2480         if (drep_tree) {
2481             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
2482             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
2483             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
2484         }
2485         offset += sizeof (hdr.drep);
2486
2487         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
2488         offset += 2;
2489
2490         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
2491         offset += 2;
2492
2493         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
2494         offset += 4;
2495     }
2496
2497
2498     /*
2499      * Packet type specific stuff is next.
2500      */
2501     switch (hdr.ptype) {
2502     case PDU_BIND:
2503     case PDU_ALTER:
2504         dissect_dcerpc_cn_bind (tvb, pinfo, dcerpc_tree, &hdr);
2505         break;
2506
2507     case PDU_BIND_ACK:
2508     case PDU_ALTER_ACK:
2509         dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
2510         break;
2511
2512     case PDU_REQ:
2513         dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
2514         break;
2515
2516     case PDU_RESP:
2517         dissect_dcerpc_cn_resp (tvb, pinfo, dcerpc_tree, tree, &hdr);
2518         break;
2519
2520     case PDU_FAULT:
2521         dissect_dcerpc_cn_fault (tvb, pinfo, dcerpc_tree, &hdr);
2522         break;
2523
2524     case PDU_BIND_NAK:
2525         dissect_dcerpc_cn_bind_nak (tvb, pinfo, dcerpc_tree, &hdr);
2526         break;
2527
2528     case PDU_CO_CANCEL:
2529     case PDU_ORPHANED:
2530         /*
2531          * Nothing after the common header other than an authentication
2532          * verifier.
2533          */
2534         dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL);
2535         break;
2536
2537     case PDU_SHUTDOWN:
2538         /*
2539          * Nothing after the common header, not even an authentication
2540          * verifier.
2541          */
2542         break;
2543
2544     default:
2545         /* might as well dissect the auth info */
2546         dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL);
2547         break;
2548     }
2549     return hdr.frag_len + padding;
2550 }
2551
2552 /*
2553  * DCERPC dissector for connection oriented calls over packet-oriented
2554  * transports
2555  */
2556 static gboolean
2557 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2558 {
2559     /*
2560      * Only one PDU per transport packet, and only one transport
2561      * packet per PDU.
2562      */
2563     if (dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE) == -1) {
2564         /*
2565          * It wasn't a DCERPC PDU.
2566          */
2567         return FALSE;
2568     } else {
2569         /*
2570          * It was.
2571          */
2572         return TRUE;
2573     }
2574 }
2575
2576 /*
2577  * DCERPC dissector for connection oriented calls over byte-stream
2578  * transports
2579  */
2580 static gboolean
2581 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2582 {
2583     int offset = 0;
2584     int pdu_len;
2585     gboolean ret = FALSE;
2586
2587     /*
2588      * There may be multiple PDUs per transport packet; keep
2589      * processing them.
2590      */
2591     while (tvb_reported_length_remaining(tvb, offset) != 0) {
2592         pdu_len = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
2593                                      dcerpc_cn_desegment);
2594         if (pdu_len == -1) {
2595             /*
2596              * Not a DCERPC PDU.
2597              */
2598             break;
2599         }
2600
2601         /*
2602          * Well, we've seen at least one DCERPC PDU.
2603          */
2604         ret = TRUE;
2605
2606         if (pdu_len == 0) {
2607             /*
2608              * Desegmentation required - bail now.
2609              */
2610             break;
2611         }
2612
2613         /*
2614          * Step to the next PDU.
2615          */
2616         offset += pdu_len;
2617     }
2618     return ret;
2619 }
2620
2621 static void
2622 dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
2623                         e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
2624 {
2625     proto_item *ti = NULL;
2626     proto_tree *auth_tree = NULL;
2627     guint8 protection_level;
2628
2629     /*
2630      * Initially set "*auth_level_p" to -1 to indicate that we haven't
2631      * yet seen any authentication level information.
2632      */
2633     if (auth_level_p != NULL)
2634         *auth_level_p = -1;
2635
2636     /*
2637      * The authentication information is at the *end* of the PDU; in
2638      * request and response PDUs, the request and response stub data
2639      * come before it.
2640      *
2641      * If the full packet is here, and there's data past the end of the
2642      * packet body, then dissect the auth info.
2643      */
2644     offset += hdr->frag_len;
2645     if (tvb_length_remaining(tvb, offset) > 0) {
2646         switch (hdr->auth_proto) {
2647
2648         case DCE_C_RPC_AUTHN_PROTOCOL_KRB5:
2649             ti = proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Kerberos authentication verifier");
2650             auth_tree = proto_item_add_subtree (ti, ett_decrpc_krb5_auth_verf);
2651             protection_level = tvb_get_guint8 (tvb, offset);
2652             if (auth_level_p != NULL)
2653                 *auth_level_p = protection_level;
2654             proto_tree_add_uint (auth_tree, hf_dcerpc_krb5_av_prot_level, tvb, offset, 1, protection_level);
2655             offset++;
2656             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_vers_num, tvb, offset, 1, FALSE);
2657             offset++;
2658             if (protection_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)
2659                 offset += 6;    /* 6 bytes of padding */
2660             else
2661                 offset += 2;    /* 6 bytes of padding */
2662             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_auth_verifier, tvb, offset, 16, FALSE);
2663             offset += 16;
2664             break;
2665
2666         default:
2667             proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Authentication verifier");
2668             break;
2669         }
2670     }
2671 }
2672
2673 static void
2674 dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
2675                               proto_tree *dcerpc_tree,
2676                               e_dce_dg_common_hdr_t *hdr)
2677 {
2678     guint32 version;
2679
2680     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2681                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
2682                                     &version);
2683
2684     switch (version) {
2685
2686     case 0:
2687         /* The only version we know about */
2688         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2689                                         hdr->drep, hf_dcerpc_dg_cancel_id,
2690                                         NULL);
2691         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2692                                        hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
2693                                        NULL);
2694         break;
2695     }
2696 }
2697
2698 static void
2699 dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
2700                           proto_tree *dcerpc_tree,
2701                           e_dce_dg_common_hdr_t *hdr)
2702 {
2703     guint32 version;
2704
2705     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2706                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
2707                                     &version);
2708
2709     switch (version) {
2710
2711     case 0:
2712         /* The only version we know about */
2713         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2714                                         hdr->drep, hf_dcerpc_dg_cancel_id,
2715                                         NULL);
2716         /* XXX - are NDR booleans 32 bits? */
2717         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2718                                         hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
2719                                         NULL);
2720         break;
2721     }
2722 }
2723
2724 static void
2725 dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
2726                         proto_tree *dcerpc_tree,
2727                         e_dce_dg_common_hdr_t *hdr)
2728 {
2729     guint8 version;
2730     guint16 serial_num;
2731     guint16 selack_len;
2732     guint i;
2733
2734     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2735                                   hdr->drep, hf_dcerpc_dg_fack_vers,
2736                                   &version);
2737     /* padding */
2738     offset++;
2739
2740     switch (version) {
2741
2742     case 0:     /* The only version documented in the DCE RPC 1.1 spec */
2743     case 1:     /* This appears to be the same */
2744         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2745                                         hdr->drep, hf_dcerpc_dg_fack_window_size,
2746                                         NULL);
2747         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2748                                         hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
2749                                         NULL);
2750         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2751                                         hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
2752                                         NULL);
2753         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2754                                         hdr->drep, hf_dcerpc_dg_fack_serial_num,
2755                                         &serial_num);
2756         if (check_col (pinfo->cinfo, COL_INFO)) {
2757             col_append_fstr (pinfo->cinfo, COL_INFO, " serial_num: %u",
2758                              serial_num);
2759         }
2760         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2761                                         hdr->drep, hf_dcerpc_dg_fack_selack_len,
2762                                         &selack_len);
2763         for (i = 0; i < selack_len; i++) {
2764             offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2765                                             hdr->drep, hf_dcerpc_dg_fack_selack,
2766                                             NULL);
2767         }
2768
2769         break;
2770     }
2771 }
2772
2773 static void
2774 dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
2775                         proto_tree *dcerpc_tree,
2776                         e_dce_dg_common_hdr_t *hdr)
2777 {
2778     guint32 status;
2779
2780     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
2781                                     hdr->drep, hf_dcerpc_dg_status,
2782                                     &status);
2783
2784     if (check_col (pinfo->cinfo, COL_INFO)) {
2785         col_append_fstr (pinfo->cinfo, COL_INFO,
2786                       ": status: %s",
2787                       val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
2788     }
2789 }
2790
2791 static void
2792 dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2793                         proto_tree *dcerpc_tree, proto_tree *tree,
2794                         e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
2795 {
2796     int length, reported_length, stub_length;
2797     gboolean save_fragmented;
2798     fragment_data *fd_head;
2799
2800     if (check_col (pinfo->cinfo, COL_INFO)) {
2801         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u",
2802                          di->call_data->opnum);
2803     }
2804
2805     length = tvb_length_remaining (tvb, offset);
2806     reported_length = tvb_reported_length_remaining (tvb, offset);
2807     stub_length = hdr->frag_len;
2808     if (length > stub_length)
2809         length = stub_length;
2810     if (reported_length > stub_length)
2811         reported_length = stub_length;
2812
2813     save_fragmented = pinfo->fragmented;
2814
2815     /* If we don't have reassembly enabled, or this packet contains
2816        the entire PDU, or if this is a short frame (or a frame
2817        not reassembled at a lower layer) that doesn't include all
2818        the data in the fragment, just call the handoff directly if
2819        this is the first fragment or the PDU isn't fragmented. */
2820     if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
2821                 stub_length > length ) {
2822         if(hdr->frag_num == 0) {
2823             /* First fragment, possibly the only fragment */
2824
2825             /*
2826              * XXX - authentication level?
2827              */
2828             pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
2829             dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
2830                                 tvb_new_subset (tvb, offset, length,
2831                                                 reported_length),
2832                                 0, hdr->drep, di, 0);
2833         } else {
2834             /* PDU is fragmented and this isn't the first fragment */
2835             if (check_col(pinfo->cinfo, COL_INFO)) {
2836                 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
2837             }
2838             if (dcerpc_tree) {
2839                 if (length > 0) {
2840                     proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2841                                          "Fragment data (%d byte%s)", length,
2842                                          plurality(length, "", "s"));
2843                 }
2844             }
2845         }
2846     } else {
2847         /* Reassembly is enabled, the PDU is fragmented, and
2848            we have all the data in the fragment; the first two
2849            of those mean we should attempt reassembly, and the
2850            third means we can attempt reassembly. */
2851         if (dcerpc_tree) {
2852             if (length > 0) {
2853                 proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2854                                      "Fragment data (%d byte%s)", length,
2855                                      plurality(length, "", "s"));
2856             }
2857         }
2858
2859         fd_head = fragment_add_seq(tvb, offset, pinfo,
2860                         hdr->seqnum, dcerpc_cl_reassemble_table,
2861                         hdr->frag_num, length, !(hdr->flags1 & PFCL1_LASTFRAG));
2862         if (fd_head != NULL) {
2863             /* We completed reassembly */
2864             tvbuff_t *next_tvb;
2865
2866             next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
2867             tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2868             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2869             show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
2870                                    dcerpc_tree, pinfo, next_tvb);
2871
2872             /*
2873              * XXX - authentication level?
2874              */
2875             pinfo->fragmented = FALSE;
2876             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
2877                                 0, hdr->drep, di, 0);
2878         } else {
2879             /* Reassembly isn't completed yet */
2880             if (check_col(pinfo->cinfo, COL_INFO)) {
2881                 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
2882             }
2883         }
2884     }
2885     pinfo->fragmented = save_fragmented;
2886 }
2887
2888 static void
2889 dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
2890                         proto_tree *dcerpc_tree, proto_tree *tree,
2891                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
2892 {
2893     dcerpc_info di;
2894     dcerpc_call_value *value, v;
2895
2896     if(!(pinfo->fd->flags.visited)){
2897         dcerpc_call_value *call_value;
2898         dcerpc_call_key *call_key;
2899
2900         call_key=g_mem_chunk_alloc (dcerpc_call_key_chunk);
2901         call_key->conv=conv;
2902         call_key->call_id=hdr->seqnum;
2903         call_key->smb_fid=get_smb_fid(pinfo->private_data);
2904
2905         call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
2906         call_value->uuid = hdr->if_id;
2907         call_value->ver = hdr->if_ver;
2908         call_value->opnum = hdr->opnum;
2909         call_value->req_frame=pinfo->fd->num;
2910         call_value->rep_frame=0;
2911         call_value->max_ptr=0;
2912         call_value->private_data = NULL;
2913         g_hash_table_insert (dcerpc_calls, call_key, call_value);
2914
2915         g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2916     }
2917
2918     value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2919     if (!value) {
2920         v.uuid = hdr->if_id;
2921         v.ver = hdr->if_ver;
2922         v.opnum = hdr->opnum;
2923         v.req_frame = pinfo->fd->num;
2924         v.rep_frame = 0;
2925         v.max_ptr = 0;
2926         v.private_data=NULL;
2927         value = &v;
2928     }
2929
2930     di.conv = conv;
2931     di.call_id = hdr->seqnum;
2932     di.smb_fid = -1;
2933     di.request = TRUE;
2934     di.call_data = value;
2935
2936     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
2937 }
2938
2939 static void
2940 dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
2941                         proto_tree *dcerpc_tree, proto_tree *tree,
2942                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
2943 {
2944     dcerpc_info di;
2945     dcerpc_call_value *value, v;
2946
2947     if(!(pinfo->fd->flags.visited)){
2948         dcerpc_call_value *call_value;
2949         dcerpc_call_key call_key;
2950
2951         call_key.conv=conv;
2952         call_key.call_id=hdr->seqnum;
2953         call_key.smb_fid=get_smb_fid(pinfo->private_data);
2954
2955         if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2956             g_hash_table_insert (dcerpc_matched, (void *)pinfo->fd->num, call_value);
2957             if(call_value->rep_frame==0){
2958                 call_value->rep_frame=pinfo->fd->num;
2959             }
2960         }
2961     }
2962
2963     value=g_hash_table_lookup(dcerpc_matched, (void *)pinfo->fd->num);
2964     if (!value) {
2965         v.uuid = hdr->if_id;
2966         v.ver = hdr->if_ver;
2967         v.opnum = hdr->opnum;
2968         v.req_frame=0;
2969         v.rep_frame=pinfo->fd->num;
2970         v.private_data=NULL;
2971         value = &v;
2972     }
2973
2974     di.conv = conv;
2975     di.call_id = 0;
2976     di.smb_fid = -1;
2977     di.request = FALSE;
2978     di.call_data = value;
2979
2980     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
2981 }
2982
2983 /*
2984  * DCERPC dissector for connectionless calls
2985  */
2986 static gboolean
2987 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2988 {
2989     proto_item *ti = NULL;
2990     proto_item *tf = NULL;
2991     proto_tree *dcerpc_tree = NULL;
2992     proto_tree *dg_flags1_tree = NULL;
2993     proto_tree *dg_flags2_tree = NULL;
2994     proto_tree *drep_tree = NULL;
2995     e_dce_dg_common_hdr_t hdr;
2996     int offset = 0;
2997     conversation_t *conv;
2998     int auth_level;
2999
3000     /*
3001      * Check if this looks like a CL DCERPC call.  All dg packets
3002      * have an 80 byte header on them.  Which starts with
3003      * version (4), pkt_type.
3004      */
3005     if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
3006         return FALSE;
3007     }
3008     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
3009     if (hdr.rpc_ver != 4)
3010         return FALSE;
3011     hdr.ptype = tvb_get_guint8 (tvb, offset++);
3012     if (hdr.ptype > 19)
3013         return FALSE;
3014
3015     if (check_col (pinfo->cinfo, COL_PROTOCOL))
3016         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
3017     if (check_col (pinfo->cinfo, COL_INFO))
3018         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
3019
3020     hdr.flags1 = tvb_get_guint8 (tvb, offset++);
3021     hdr.flags2 = tvb_get_guint8 (tvb, offset++);
3022     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
3023     offset += sizeof (hdr.drep);
3024     hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
3025     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
3026     offset += 16;
3027     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
3028     offset += 16;
3029     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
3030     offset += 16;
3031     hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3032     offset += 4;
3033     hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3034     offset += 4;
3035     hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3036     offset += 4;
3037     hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3038     offset += 2;
3039     hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3040     offset += 2;
3041     hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3042     offset += 2;
3043     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3044     offset += 2;
3045     hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3046     offset += 2;
3047     hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
3048     hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
3049
3050     if (tree) {
3051         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
3052         if (ti) {
3053             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
3054         }
3055     }
3056     offset = 0;
3057
3058     if (tree)
3059         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
3060     offset++;
3061
3062     if (tree)
3063         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
3064     offset++;
3065
3066     if (tree) {
3067         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
3068         dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
3069         if (dg_flags1_tree) {
3070             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
3071             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
3072             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
3073             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
3074             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
3075             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
3076             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
3077             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
3078         }
3079     }
3080     offset++;
3081
3082     if (tree) {
3083         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
3084         dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
3085         if (dg_flags2_tree) {
3086             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
3087             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
3088             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
3089             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
3090             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
3091             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
3092             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
3093             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
3094         }
3095     }
3096     offset++;
3097
3098     if (tree) {
3099         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
3100         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
3101         if (drep_tree) {
3102             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
3103             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
3104             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
3105         }
3106     }
3107     offset += sizeof (hdr.drep);
3108
3109     if (tree)
3110         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
3111     offset++;
3112
3113     if (tree) {
3114         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3115                                       offset, 16, "HMMM",
3116                                       "Object: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3117                                       hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
3118                                       hdr.obj_id.Data4[0],
3119                                       hdr.obj_id.Data4[1],
3120                                       hdr.obj_id.Data4[2],
3121                                       hdr.obj_id.Data4[3],
3122                                       hdr.obj_id.Data4[4],
3123                                       hdr.obj_id.Data4[5],
3124                                       hdr.obj_id.Data4[6],
3125                                       hdr.obj_id.Data4[7]);
3126     }
3127     offset += 16;
3128
3129     if (tree) {
3130         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
3131                                       offset, 16, "HMMM",
3132                                       "Interface: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3133                                       hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
3134                                       hdr.if_id.Data4[0],
3135                                       hdr.if_id.Data4[1],
3136                                       hdr.if_id.Data4[2],
3137                                       hdr.if_id.Data4[3],
3138                                       hdr.if_id.Data4[4],
3139                                       hdr.if_id.Data4[5],
3140                                       hdr.if_id.Data4[6],
3141                                       hdr.if_id.Data4[7]);
3142     }
3143     offset += 16;
3144
3145     if (tree) {
3146         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
3147                                       offset, 16, "HMMM",
3148                                       "Activity: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3149                                       hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
3150                                       hdr.act_id.Data4[0],
3151                                       hdr.act_id.Data4[1],
3152                                       hdr.act_id.Data4[2],
3153                                       hdr.act_id.Data4[3],
3154                                       hdr.act_id.Data4[4],
3155                                       hdr.act_id.Data4[5],
3156                                       hdr.act_id.Data4[6],
3157                                       hdr.act_id.Data4[7]);
3158     }
3159     offset += 16;
3160
3161     if (tree)
3162         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_server_boot, tvb, offset, 4, hdr.server_boot);
3163     offset += 4;
3164
3165     if (tree)
3166         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
3167     offset += 4;
3168
3169     if (tree)
3170         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
3171     if (check_col (pinfo->cinfo, COL_INFO)) {
3172         col_append_fstr (pinfo->cinfo, COL_INFO, ": seq_num: %u", hdr.seqnum);
3173     }
3174     offset += 4;
3175
3176     if (tree)
3177         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
3178     offset += 2;
3179
3180     if (tree)
3181         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
3182     offset += 2;
3183
3184     if (tree)
3185         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
3186     offset += 2;
3187
3188     if (tree)
3189         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
3190     offset += 2;
3191
3192     if (tree)
3193         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
3194     if (check_col (pinfo->cinfo, COL_INFO)) {
3195         if (hdr.flags1 & PFCL1_FRAG) {
3196             /* Fragmented - put the fragment number into the Info column */
3197             col_append_fstr (pinfo->cinfo, COL_INFO, " frag_num: %u",
3198                              hdr.frag_num);
3199         }
3200     }
3201     offset += 2;
3202
3203     if (tree)
3204         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
3205     offset++;
3206
3207     if (tree)
3208         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
3209     if (check_col (pinfo->cinfo, COL_INFO)) {
3210         if (hdr.flags1 & PFCL1_FRAG) {
3211             /* Fragmented - put the serial number into the Info column */
3212             col_append_fstr (pinfo->cinfo, COL_INFO, " serial_num: %u",
3213                              (hdr.serial_hi << 8) | hdr.serial_lo);
3214         }
3215     }
3216     offset++;
3217
3218     if (tree) {
3219         /*
3220          * XXX - for Kerberos, we get a protection level; if it's
3221          * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
3222          * stub data.
3223          */
3224         dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr,
3225                                 &auth_level);
3226     }
3227
3228     /*
3229      * keeping track of the conversation shouldn't really be necessary
3230      * for connectionless packets, because everything we need to know
3231      * to dissect is in the header for each packet.  Unfortunately,
3232      * Microsoft's implementation is buggy and often puts the
3233      * completely wrong if_id in the header.  go figure.  So, keep
3234      * track of the seqnum and use that if possible.  Note: that's not
3235      * completely correct.  It should really be done based on both the
3236      * activity_id and seqnum.  I haven't seen anywhere that it would
3237      * make a difference, but for future reference...
3238      */
3239     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
3240                               pinfo->srcport, pinfo->destport, 0);
3241     if (!conv) {
3242         conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
3243                                  pinfo->srcport, pinfo->destport, 0);
3244     }
3245
3246     /*
3247      * Packet type specific stuff is next.
3248      */
3249
3250     switch (hdr.ptype) {
3251
3252     case PDU_CANCEL_ACK:
3253         /* Body is optional */
3254         /* XXX - we assume "frag_len" is the length of the body */
3255         if (hdr.frag_len != 0)
3256             dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3257         break;
3258
3259     case PDU_CL_CANCEL:
3260         /*
3261          * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
3262          * but in at least one capture none of the Cl_cancel PDUs had a
3263          * body.
3264          */
3265         /* XXX - we assume "frag_len" is the length of the body */
3266         if (hdr.frag_len != 0)
3267             dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
3268         break;
3269
3270     case PDU_NOCALL:
3271         /* Body is optional; if present, it's the same as PDU_FACK */
3272         /* XXX - we assume "frag_len" is the length of the body */
3273         if (hdr.frag_len != 0)
3274             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3275         break;
3276
3277     case PDU_FACK:
3278         dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3279         break;
3280
3281     case PDU_REJECT:
3282     case PDU_FAULT:
3283         dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
3284         break;
3285
3286     case PDU_REQ:
3287         dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
3288         break;
3289
3290     case PDU_RESP:
3291         dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
3292         break;
3293
3294     /* these requests have no body */
3295     case PDU_ACK:
3296     case PDU_PING:
3297     case PDU_WORKING:
3298     default:
3299         break;
3300     }
3301
3302     return TRUE;
3303 }
3304
3305 static void
3306 dcerpc_init_protocol (void)
3307 {
3308         /* structures and data for BIND */
3309         if (dcerpc_binds){
3310                 g_hash_table_destroy (dcerpc_binds);
3311         }
3312         dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
3313
3314         if (dcerpc_bind_key_chunk){
3315                 g_mem_chunk_destroy (dcerpc_bind_key_chunk);
3316         }
3317         dcerpc_bind_key_chunk = g_mem_chunk_new ("dcerpc_bind_key_chunk",
3318                                              sizeof (dcerpc_bind_key),
3319                                              200 * sizeof (dcerpc_bind_key),
3320                                              G_ALLOC_ONLY);
3321         if (dcerpc_bind_value_chunk){
3322                 g_mem_chunk_destroy (dcerpc_bind_value_chunk);
3323         }
3324         dcerpc_bind_value_chunk = g_mem_chunk_new ("dcerpc_bind_value_chunk",
3325                                              sizeof (dcerpc_bind_value),
3326                                              200 * sizeof (dcerpc_bind_value),
3327                                              G_ALLOC_ONLY);
3328         /* structures and data for CALL */
3329         if (dcerpc_calls){
3330                 g_hash_table_destroy (dcerpc_calls);
3331         }
3332         dcerpc_calls = g_hash_table_new (dcerpc_call_hash, dcerpc_call_equal);
3333         if (dcerpc_call_key_chunk){
3334                 g_mem_chunk_destroy (dcerpc_call_key_chunk);
3335         }
3336         dcerpc_call_key_chunk = g_mem_chunk_new ("dcerpc_call_key_chunk",
3337                                              sizeof (dcerpc_call_key),
3338                                              200 * sizeof (dcerpc_call_key),
3339                                              G_ALLOC_ONLY);
3340         if (dcerpc_call_value_chunk){
3341                 g_mem_chunk_destroy (dcerpc_call_value_chunk);
3342         }
3343         dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
3344                                              sizeof (dcerpc_call_value),
3345                                              200 * sizeof (dcerpc_call_value),
3346                                              G_ALLOC_ONLY);
3347
3348         /* structure and data for MATCHED */
3349         if (dcerpc_matched){
3350                 g_hash_table_destroy (dcerpc_matched);
3351         }
3352         dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
3353
3354 }
3355
3356 void
3357 proto_register_dcerpc (void)
3358 {
3359     static hf_register_info hf[] = {
3360         { &hf_dcerpc_request_in,
3361                 { "Request in", "dcerpc.request_in", FT_UINT32, BASE_DEC,
3362                 NULL, 0, "This packet is a response to the packet in this frame", HFILL }},
3363         { &hf_dcerpc_response_in,
3364                 { "Response in", "dcerpc.response_in", FT_UINT32, BASE_DEC,
3365                 NULL, 0, "The response to this packet is in this packet", HFILL }},
3366         { &hf_dcerpc_referent_id,
3367                 { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
3368                 NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
3369         { &hf_dcerpc_ver,
3370           { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3371         { &hf_dcerpc_ver_minor,
3372           { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3373         { &hf_dcerpc_packet_type,
3374           { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, "", HFILL }},
3375         { &hf_dcerpc_cn_flags,
3376           { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3377         { &hf_dcerpc_cn_flags_first_frag,
3378           { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_FIRST_FRAG, "", HFILL }},
3379         { &hf_dcerpc_cn_flags_last_frag,
3380           { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_LAST_FRAG, "", HFILL }},
3381         { &hf_dcerpc_cn_flags_cancel_pending,
3382           { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_PENDING_CANCEL, "", HFILL }},
3383         { &hf_dcerpc_cn_flags_reserved,
3384           { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_RESERVED_1, "", HFILL }},
3385         { &hf_dcerpc_cn_flags_mpx,
3386           { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_CONC_MPX, "", HFILL }},
3387         { &hf_dcerpc_cn_flags_dne,
3388           { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_DID_NOT_EXECUTE, "", HFILL }},
3389         { &hf_dcerpc_cn_flags_maybe,
3390           { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_MAYBE, "", HFILL }},
3391         { &hf_dcerpc_cn_flags_object,
3392           { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_OBJECT_UUID, "", HFILL }},
3393         { &hf_dcerpc_drep,
3394           { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
3395         { &hf_dcerpc_drep_byteorder,
3396           { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, "", HFILL }},
3397         { &hf_dcerpc_drep_character,
3398           { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, "", HFILL }},
3399         { &hf_dcerpc_drep_fp,
3400           { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, "", HFILL }},
3401         { &hf_dcerpc_cn_frag_len,
3402           { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3403         { &hf_dcerpc_cn_auth_len,
3404           { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3405         { &hf_dcerpc_cn_call_id,
3406           { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3407         { &hf_dcerpc_cn_max_xmit,
3408           { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3409         { &hf_dcerpc_cn_max_recv,
3410           { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3411         { &hf_dcerpc_cn_assoc_group,
3412           { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3413         { &hf_dcerpc_cn_num_ctx_items,
3414           { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3415         { &hf_dcerpc_cn_ctx_id,
3416           { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3417         { &hf_dcerpc_cn_num_trans_items,
3418           { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3419         { &hf_dcerpc_cn_bind_if_id,
3420           { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3421         { &hf_dcerpc_cn_bind_if_ver,
3422           { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3423         { &hf_dcerpc_cn_bind_if_ver_minor,
3424           { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3425         { &hf_dcerpc_cn_bind_trans_id,
3426           { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3427         { &hf_dcerpc_cn_bind_trans_ver,
3428           { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3429         { &hf_dcerpc_cn_alloc_hint,
3430           { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3431         { &hf_dcerpc_cn_sec_addr_len,
3432           { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3433         { &hf_dcerpc_cn_sec_addr,
3434           { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, "", HFILL }},
3435         { &hf_dcerpc_cn_num_results,
3436           { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3437         { &hf_dcerpc_cn_ack_result,
3438           { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, "", HFILL }},
3439         { &hf_dcerpc_cn_ack_reason,
3440           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, "", HFILL }},
3441         { &hf_dcerpc_cn_ack_trans_id,
3442           { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3443         { &hf_dcerpc_cn_ack_trans_ver,
3444           { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3445         { &hf_dcerpc_cn_reject_reason,
3446           { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, "", HFILL }},
3447         { &hf_dcerpc_cn_num_protocols,
3448           { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3449         { &hf_dcerpc_cn_protocol_ver_major,
3450           { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3451         { &hf_dcerpc_cn_protocol_ver_minor,
3452           { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3453         { &hf_dcerpc_cn_cancel_count,
3454           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3455         { &hf_dcerpc_cn_status,
3456           { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
3457         { &hf_dcerpc_auth_type,
3458           { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
3459         { &hf_dcerpc_auth_level,
3460           { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, "", HFILL }},
3461         { &hf_dcerpc_auth_pad_len,
3462           { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3463         { &hf_dcerpc_auth_rsrvd,
3464           { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3465         { &hf_dcerpc_auth_ctx_id,
3466           { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3467         { &hf_dcerpc_dg_flags1,
3468           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3469         { &hf_dcerpc_dg_flags1_rsrvd_01,
3470           { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_01, "", HFILL }},
3471         { &hf_dcerpc_dg_flags1_last_frag,
3472           { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_LASTFRAG, "", HFILL }},
3473         { &hf_dcerpc_dg_flags1_frag,
3474           { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_FRAG, "", HFILL }},
3475         { &hf_dcerpc_dg_flags1_nofack,
3476           { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_NOFACK, "", HFILL }},
3477         { &hf_dcerpc_dg_flags1_maybe,
3478           { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_MAYBE, "", HFILL }},
3479         { &hf_dcerpc_dg_flags1_idempotent,
3480           { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_IDEMPOTENT, "", HFILL }},
3481         { &hf_dcerpc_dg_flags1_broadcast,
3482           { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_BROADCAST, "", HFILL }},
3483         { &hf_dcerpc_dg_flags1_rsrvd_80,
3484           { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_80, "", HFILL }},
3485         { &hf_dcerpc_dg_flags2,
3486           { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3487         { &hf_dcerpc_dg_flags2_rsrvd_01,
3488           { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_01, "", HFILL }},
3489         { &hf_dcerpc_dg_flags2_cancel_pending,
3490           { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_CANCEL_PENDING, "", HFILL }},
3491         { &hf_dcerpc_dg_flags2_rsrvd_04,
3492           { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_04, "", HFILL }},
3493         { &hf_dcerpc_dg_flags2_rsrvd_08,
3494           { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_08, "", HFILL }},
3495         { &hf_dcerpc_dg_flags2_rsrvd_10,
3496           { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_10, "", HFILL }},
3497         { &hf_dcerpc_dg_flags2_rsrvd_20,
3498           { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_20, "", HFILL }},
3499         { &hf_dcerpc_dg_flags2_rsrvd_40,
3500           { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_40, "", HFILL }},
3501         { &hf_dcerpc_dg_flags2_rsrvd_80,
3502           { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_80, "", HFILL }},
3503         { &hf_dcerpc_dg_serial_lo,
3504           { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3505         { &hf_dcerpc_dg_serial_hi,
3506           { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
3507         { &hf_dcerpc_dg_ahint,
3508           { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
3509         { &hf_dcerpc_dg_ihint,
3510           { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
3511         { &hf_dcerpc_dg_frag_len,
3512           { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3513         { &hf_dcerpc_dg_frag_num,
3514           { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3515         { &hf_dcerpc_dg_auth_proto,
3516           { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
3517         { &hf_dcerpc_dg_seqnum,
3518           { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3519         { &hf_dcerpc_dg_server_boot,
3520           { "Server boot time", "dcerpc.dg_server_boot", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3521         { &hf_dcerpc_dg_if_ver,
3522           { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3523         { &hf_dcerpc_krb5_av_prot_level,
3524           { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, "", HFILL }},
3525         { &hf_dcerpc_krb5_av_key_vers_num,
3526           { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3527         { &hf_dcerpc_krb5_av_key_auth_verifier,
3528           { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
3529         { &hf_dcerpc_obj_id,
3530           { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3531         { &hf_dcerpc_dg_if_id,
3532           { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3533         { &hf_dcerpc_dg_act_id,
3534           { "Activitiy", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
3535         { &hf_dcerpc_opnum,
3536           { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3537
3538         { &hf_dcerpc_dg_cancel_vers,
3539           { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3540
3541         { &hf_dcerpc_dg_cancel_id,
3542           { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3543
3544         { &hf_dcerpc_dg_server_accepting_cancels,
3545           { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
3546
3547         { &hf_dcerpc_dg_fack_vers,
3548           { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
3549
3550         { &hf_dcerpc_dg_fack_window_size,
3551           { "Window Size", "dcerpc.fack_window size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3552
3553         { &hf_dcerpc_dg_fack_max_tsdu,
3554           { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3555
3556         { &hf_dcerpc_dg_fack_max_frag_size,
3557           { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
3558
3559         { &hf_dcerpc_dg_fack_serial_num,
3560           { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3561
3562         { &hf_dcerpc_dg_fack_selack_len,
3563           { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3564
3565         { &hf_dcerpc_dg_fack_selack,
3566           { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
3567
3568         { &hf_dcerpc_dg_status,
3569           { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
3570
3571         { &hf_dcerpc_array_max_count,
3572           { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
3573
3574         { &hf_dcerpc_array_offset,
3575           { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
3576
3577         { &hf_dcerpc_array_actual_count,
3578           { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
3579
3580         { &hf_dcerpc_op,
3581           { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
3582
3583         { &hf_dcerpc_fragments,
3584           { "DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
3585           NULL, 0x0, "DCE/RPC Fragments", HFILL }},
3586
3587         { &hf_dcerpc_fragment,
3588           { "DCE/RPC Fragment", "dcerpc.fragment", FT_NONE, BASE_NONE,
3589           NULL, 0x0, "DCE/RPC Fragment", HFILL }},
3590
3591         { &hf_dcerpc_fragment_overlap,
3592           { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
3593
3594         { &hf_dcerpc_fragment_overlap_conflict,
3595           { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
3596
3597         { &hf_dcerpc_fragment_multiple_tails,
3598           { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
3599
3600         { &hf_dcerpc_fragment_too_long_fragment,
3601           { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
3602
3603         { &hf_dcerpc_fragment_error,
3604           { "Defragmentation error", "dcerpc.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
3605
3606     };
3607     static gint *ett[] = {
3608         &ett_dcerpc,
3609         &ett_dcerpc_cn_flags,
3610         &ett_dcerpc_drep,
3611         &ett_dcerpc_dg_flags1,
3612         &ett_dcerpc_dg_flags2,
3613         &ett_dcerpc_pointer_data,
3614         &ett_dcerpc_fragments,
3615         &ett_dcerpc_fragment,
3616         &ett_decrpc_krb5_auth_verf,
3617     };
3618     module_t *dcerpc_module;
3619
3620     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
3621     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
3622     proto_register_subtree_array (ett, array_length (ett));
3623     register_init_routine (dcerpc_init_protocol);
3624     dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
3625     prefs_register_bool_preference (dcerpc_module,
3626                                     "desegment_dcerpc",
3627                                     "Desegment all DCE/RPC over TCP",
3628                                     "Whether the DCE/RPC dissector should desegment all DCE/RPC over TCP",
3629                                     &dcerpc_cn_desegment);
3630     prefs_register_bool_preference (dcerpc_module,
3631                                     "reassemble_dcerpc",
3632                                     "Reassemble DCE/RPC fragments",
3633                                     "Whether the DCE/RPC dissector should reassemble all fragmented PDUs",
3634                                     &dcerpc_reassemble);
3635     register_init_routine(dcerpc_reassemble_init);
3636     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
3637 }
3638
3639 void
3640 proto_reg_handoff_dcerpc (void)
3641 {
3642     heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
3643     heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
3644     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
3645     heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc);
3646     ntlmssp_handle = find_dissector("ntlmssp");
3647     gssapi_handle = find_dissector("gssapi");
3648 }