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