Conversation dissectors are called through a mechanism that doesn't
[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.2 2001/03/18 02:34:50 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 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 "packet.h"
39
40 typedef struct _e_uuid_t {
41     guint32 Data1;
42     guint16 Data2;
43     guint16 Data3;
44     guint8 Data4[8];
45 } e_uuid_t;
46
47
48 static const value_string pckt_vals[] = {
49     { 0, "Request"},
50     { 1, "Ping"},
51     { 2, "Response"},
52     { 3, "Fault"},
53     { 4, "Working"},
54     { 5, "Nocall"},
55     { 6, "Reject"},
56     { 7, "Ack"},
57     { 8, "Cl_cancel"},
58     { 9, "Fack"},
59     { 10, "Cancel_ack"},
60     { 11, "Bind"},
61     { 12, "Bind_ack"},
62     { 13, "Bind_nak"},
63     { 14, "Alter_context"},
64     { 15, "Alter_context_resp"},
65     { 16, "AUTH3?"},
66     { 17, "Shutdown"},
67     { 18, "Co_cancel"},
68     { 19, "Orphaned"},
69 };
70
71 static const true_false_string flags_set_truth = {
72   "Set",
73   "Not set"
74 };
75
76 static int proto_dcerpc = -1;
77
78 /* field defines */
79 static int hf_dcerpc_ver = -1;
80 static int hf_dcerpc_ver_minor = -1;
81 static int hf_dcerpc_packet_type = -1;
82 static int hf_dcerpc_cn_flags = -1;
83 static int hf_dcerpc_cn_flags_first_frag = -1;
84 static int hf_dcerpc_cn_flags_last_frag = -1;
85 static int hf_dcerpc_cn_flags_cancel_pending = -1;
86 static int hf_dcerpc_cn_flags_reserved = -1;
87 static int hf_dcerpc_cn_flags_mpx = -1;
88 static int hf_dcerpc_cn_flags_dne = -1;
89 static int hf_dcerpc_cn_flags_maybe = -1;
90 static int hf_dcerpc_cn_flags_object = -1;
91 static int hf_dcerpc_cn_frag_len = -1;
92 static int hf_dcerpc_cn_auth_len = -1;
93 static int hf_dcerpc_cn_call_id = -1;
94 static int hf_dcerpc_dg_flags1 = -1;
95 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
96 static int hf_dcerpc_dg_flags1_last_frag = -1;
97 static int hf_dcerpc_dg_flags1_frag = -1;
98 static int hf_dcerpc_dg_flags1_nofack = -1;
99 static int hf_dcerpc_dg_flags1_maybe = -1;
100 static int hf_dcerpc_dg_flags1_idempotent = -1;
101 static int hf_dcerpc_dg_flags1_broadcast = -1;
102 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
103 static int hf_dcerpc_dg_flags2 = -1;
104 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
105 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
106 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
107 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
108 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
109 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
110 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
111 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
112 static int hf_dcerpc_dg_serial_hi = -1;
113 static int hf_dcerpc_dg_obj_id = -1;
114 static int hf_dcerpc_dg_if_id = -1;
115 static int hf_dcerpc_dg_act_id = -1;
116 static int hf_dcerpc_dg_serial_lo = -1;
117 static int hf_dcerpc_dg_ahint = -1;
118 static int hf_dcerpc_dg_ihint = -1;
119 static int hf_dcerpc_dg_frag_len = -1;
120 static int hf_dcerpc_dg_frag_num = -1;
121 static int hf_dcerpc_dg_auth_proto = -1;
122 static int hf_dcerpc_dg_opnum = -1;
123 static int hf_dcerpc_dg_seqnum = -1;
124 static int hf_dcerpc_dg_server_boot = -1;
125 static int hf_dcerpc_dg_if_ver = -1;
126
127 static gint ett_dcerpc = -1;
128 static gint ett_dcerpc_cn_flags = -1;
129 static gint ett_dcerpc_dg_flags1 = -1;
130 static gint ett_dcerpc_dg_flags2 = -1;
131
132
133 guint16
134 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
135 {
136     if (drep[0] & 0x10) {
137         return tvb_get_letohs (tvb, offset);
138     } else {
139         return tvb_get_ntohs (tvb, offset);
140     }
141 }
142
143 guint32
144 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
145 {
146     if (drep[0] & 0x10) {
147         return tvb_get_letohl (tvb, offset);
148     } else {
149         return tvb_get_ntohl (tvb, offset);
150     }
151 }
152
153 void
154 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
155 {
156     int i;
157     uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
158     uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
159     uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
160
161     for (i=0; i<sizeof (uuid->Data4); i++) {
162         uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
163     }
164 }
165
166
167 /*
168  * DCERPC dissector for connection oriented calls
169  */
170 static gboolean
171 dissect_dcerpc_cn (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
172 {
173     proto_item *ti = NULL;
174     proto_item *tf = NULL;
175     proto_tree *dcerpc_tree = NULL;
176     proto_tree *cn_flags_tree = NULL;
177     unsigned char ver, ver_minor, pkt_type, pkt_flags;
178     int offset = 0;
179     char drep[4];
180     guint16 frag_len, auth_len;
181     guint32 call_id;
182
183     /*
184      * Check if this looks like a C/O DCERPC call
185      */
186     if (!tvb_bytes_exist (tvb, 0, 16)) {
187         return FALSE;
188     }
189     if (tvb_get_guint8 (tvb, 0) != 5)
190         return FALSE;
191     ver_minor = tvb_get_guint8 (tvb, 1);
192     if (ver_minor != 0 && ver_minor != 1)
193         return FALSE;
194     pkt_type = tvb_get_guint8 (tvb, 2);
195     if (pkt_type > 19)
196         return FALSE;
197
198
199
200     if (check_col (pinfo->fd, COL_PROTOCOL))
201         col_set_str (pinfo->fd, COL_PROTOCOL, "DCERPC");
202     if (check_col (pinfo->fd, COL_INFO))
203         col_set_str (pinfo->fd, COL_INFO, pckt_vals[pkt_type].strptr);
204     if (tree) {
205         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE);
206         if (ti) {
207             dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
208         }
209         ver = tvb_get_guint8 (tvb, offset);
210         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, ver);
211         ver_minor = tvb_get_guint8 (tvb, offset);
212         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, ver_minor);
213         pkt_type = tvb_get_guint8 (tvb, offset);
214         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, pkt_type);
215         pkt_flags = tvb_get_guint8 (tvb, offset);
216         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, pkt_flags);
217         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
218         if (cn_flags_tree) {
219             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, pkt_flags);
220             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, pkt_flags);
221             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, pkt_flags);
222             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, pkt_flags);
223             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, pkt_flags);
224             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, pkt_flags);
225             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, pkt_flags);
226             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, pkt_flags);
227         }
228         offset++;
229
230         tvb_memcpy (tvb, (guint8 *)drep, offset, sizeof (drep));
231         proto_tree_add_text (dcerpc_tree, tvb, offset, sizeof (drep), "Data Rep");
232         offset += sizeof (drep);
233
234         frag_len = dcerpc_tvb_get_ntohs (tvb, offset, drep);
235         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, frag_len);
236         offset += 2;
237
238         auth_len = dcerpc_tvb_get_ntohs (tvb, offset, drep);
239         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, auth_len);
240         offset += 2;
241
242         call_id = dcerpc_tvb_get_ntohl (tvb, offset, drep);
243         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, call_id);
244         offset += 4;
245
246         /*
247          * Packet type specific stuff is next.
248          */
249     }
250     return TRUE;
251 }
252
253 /*
254  * DCERPC dissector for connectionless calls
255  */
256 static gboolean
257 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
258 {
259     proto_item *ti = NULL;
260     proto_item *tf = NULL;
261     proto_tree *dcerpc_tree = NULL;
262     proto_tree *dg_flags1_tree = NULL;
263     proto_tree *dg_flags2_tree = NULL;
264     unsigned char ver, pkt_type, pkt_flags1, pkt_flags2;
265     int offset = 0;
266     char drep[3];
267     char serial_lo, serial_hi;
268     guint16 ahint, ihint;
269     guint32 server_boot, if_ver, seqnum;
270     guint16 opnum, frag_len, frag_num;
271     char auth_proto;
272     e_uuid_t obj_id;
273     e_uuid_t if_id;
274     e_uuid_t act_id;
275
276     /*
277      * Check if this looks like a CL DCERPC call.  All dg packets
278      * have an 80 byte header on them.  Which starts with
279      * version (4), pkt_type.
280      */
281     if (!tvb_bytes_exist (tvb, 0, 80)) {
282         return FALSE;
283     }
284     if (tvb_get_guint8 (tvb, 0) != 4)
285         return FALSE;
286     pkt_type = tvb_get_guint8 (tvb, 1);
287     if (pkt_type > 19)
288         return FALSE;
289     
290
291     if (check_col (pinfo->fd, COL_PROTOCOL))
292         col_set_str (pinfo->fd, COL_PROTOCOL, "DCERPC");
293     if (check_col (pinfo->fd, COL_INFO))
294         col_set_str (pinfo->fd, COL_INFO, pckt_vals[pkt_type].strptr);
295     if (tree) {
296         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE);
297         if (ti) {
298             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
299         }
300         ver = tvb_get_guint8 (tvb, offset);
301         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, ver);
302
303         pkt_type = tvb_get_guint8 (tvb, offset);
304         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, pkt_type);
305
306         pkt_flags1 = tvb_get_guint8 (tvb, offset);
307         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, pkt_flags1);
308         dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
309         if (dg_flags1_tree) {
310             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, pkt_flags1);
311             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, pkt_flags1);
312             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, pkt_flags1);
313             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, pkt_flags1);
314             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, pkt_flags1);
315             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, pkt_flags1);
316             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, pkt_flags1);
317             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, pkt_flags1);
318         }
319         offset++;
320
321         pkt_flags2 = tvb_get_guint8 (tvb, offset);
322         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, pkt_flags2);
323         dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
324         if (dg_flags2_tree) {
325             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, pkt_flags2);
326             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, pkt_flags2);
327             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, pkt_flags2);
328             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, pkt_flags2);
329             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, pkt_flags2);
330             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, pkt_flags2);
331             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, pkt_flags2);
332             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, pkt_flags2);
333         }
334         offset++;
335
336         tvb_memcpy (tvb, (guint8 *)drep, offset, sizeof (drep));
337         proto_tree_add_text (dcerpc_tree, tvb, offset, sizeof (drep), "Data Rep");
338         offset += sizeof (drep);
339
340         serial_hi = tvb_get_guint8 (tvb, offset);
341         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset++, 1, serial_hi);
342
343         dcerpc_tvb_get_uuid (tvb, offset, drep, &obj_id);
344         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_obj_id, tvb,
345                                       offset, 16, "HMMM",
346                                       "Object: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
347                                       obj_id.Data1, obj_id.Data2, obj_id.Data3,
348                                       obj_id.Data4[0],
349                                       obj_id.Data4[1],
350                                       obj_id.Data4[2],
351                                       obj_id.Data4[3],
352                                       obj_id.Data4[4],
353                                       obj_id.Data4[5],
354                                       obj_id.Data4[6],
355                                       obj_id.Data4[7]);
356         offset += 16;
357
358         dcerpc_tvb_get_uuid (tvb, offset, drep, &if_id);
359         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
360                                       offset, 16, "HMMM",
361                                       "Interface: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
362                                       if_id.Data1, if_id.Data2, if_id.Data3,
363                                       if_id.Data4[0],
364                                       if_id.Data4[1],
365                                       if_id.Data4[2],
366                                       if_id.Data4[3],
367                                       if_id.Data4[4],
368                                       if_id.Data4[5],
369                                       if_id.Data4[6],
370                                       if_id.Data4[7]);
371         offset += 16;
372
373         dcerpc_tvb_get_uuid (tvb, offset, drep, &act_id);
374         proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
375                                       offset, 16, "HMMM",
376                                       "Activity: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
377                                       act_id.Data1, act_id.Data2, act_id.Data3,
378                                       act_id.Data4[0],
379                                       act_id.Data4[1],
380                                       act_id.Data4[2],
381                                       act_id.Data4[3],
382                                       act_id.Data4[4],
383                                       act_id.Data4[5],
384                                       act_id.Data4[6],
385                                       act_id.Data4[7]);
386         offset += 16;
387
388         server_boot = dcerpc_tvb_get_ntohl (tvb, offset, drep);
389         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_server_boot, tvb, offset, 4, server_boot);
390         offset += 4;
391
392         if_ver = dcerpc_tvb_get_ntohl (tvb, offset, drep);
393         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, if_ver);
394         offset += 4;
395
396         seqnum = dcerpc_tvb_get_ntohl (tvb, offset, drep);
397         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, seqnum);
398         offset += 4;
399
400         opnum = dcerpc_tvb_get_ntohl (tvb, offset, drep);
401         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_opnum, tvb, offset, 2, opnum);
402         offset += 2;
403
404         ihint = dcerpc_tvb_get_ntohl (tvb, offset, drep);
405         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, ihint);
406         offset += 2;
407
408         ahint = dcerpc_tvb_get_ntohl (tvb, offset, drep);
409         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, ahint);
410         offset += 2;
411
412         frag_len = dcerpc_tvb_get_ntohl (tvb, offset, drep);
413         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, frag_len);
414         offset += 2;
415
416         frag_num = dcerpc_tvb_get_ntohl (tvb, offset, drep);
417         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, frag_num);
418         offset += 2;
419
420         auth_proto = tvb_get_guint8 (tvb, offset);
421         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, auth_proto);
422         offset++;
423
424         serial_lo = tvb_get_guint8 (tvb, offset);
425         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 4, serial_lo);
426         offset++;
427
428         /*
429          * Packet type specific stuff is next.
430          */
431
432     }
433     return TRUE;
434 }
435
436
437 void
438 proto_register_dcerpc(void)
439 {
440     static hf_register_info hf[] = {
441         { &hf_dcerpc_ver,
442           { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
443         { &hf_dcerpc_ver_minor,
444           { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
445         { &hf_dcerpc_packet_type,
446           { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_HEX, VALS (pckt_vals), 0x0, "" }},
447         { &hf_dcerpc_cn_flags,
448           { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
449         { &hf_dcerpc_cn_flags_first_frag,
450           { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x1, "" }},
451         { &hf_dcerpc_cn_flags_last_frag,
452           { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x2, "" }},
453         { &hf_dcerpc_cn_flags_cancel_pending,
454           { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x4, "" }},
455         { &hf_dcerpc_cn_flags_reserved,
456           { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x8, "" }},
457         { &hf_dcerpc_cn_flags_mpx,
458           { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "" }},
459         { &hf_dcerpc_cn_flags_dne,
460           { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "" }},
461         { &hf_dcerpc_cn_flags_maybe,
462           { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "" }},
463         { &hf_dcerpc_cn_flags_object,
464           { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "" }},
465         { &hf_dcerpc_cn_frag_len,
466           { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
467         { &hf_dcerpc_cn_auth_len,
468           { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
469         { &hf_dcerpc_cn_call_id,
470           { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "" }},
471         { &hf_dcerpc_dg_flags1,
472           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
473         { &hf_dcerpc_dg_flags1_rsrvd_01,
474           { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "" }},
475         { &hf_dcerpc_dg_flags1_last_frag,
476           { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "" }},
477         { &hf_dcerpc_dg_flags1_frag,
478           { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "" }},
479         { &hf_dcerpc_dg_flags1_nofack,
480           { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "" }},
481         { &hf_dcerpc_dg_flags1_maybe,
482           { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "" }},
483         { &hf_dcerpc_dg_flags1_idempotent,
484           { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "" }},
485         { &hf_dcerpc_dg_flags1_broadcast,
486           { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "" }},
487         { &hf_dcerpc_dg_flags1_rsrvd_80,
488           { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "" }},
489         { &hf_dcerpc_dg_flags2,
490           { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
491         { &hf_dcerpc_dg_flags2_rsrvd_01,
492           { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x01, "" }},
493         { &hf_dcerpc_dg_flags2_cancel_pending,
494           { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x02, "" }},
495         { &hf_dcerpc_dg_flags2_rsrvd_04,
496           { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x04, "" }},
497         { &hf_dcerpc_dg_flags2_rsrvd_08,
498           { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x08, "" }},
499         { &hf_dcerpc_dg_flags2_rsrvd_10,
500           { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x10, "" }},
501         { &hf_dcerpc_dg_flags2_rsrvd_20,
502           { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x20, "" }},
503         { &hf_dcerpc_dg_flags2_rsrvd_40,
504           { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x40, "" }},
505         { &hf_dcerpc_dg_flags2_rsrvd_80,
506           { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), 0x80, "" }},
507         { &hf_dcerpc_dg_serial_lo,
508           { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
509         { &hf_dcerpc_dg_serial_hi,
510           { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
511         { &hf_dcerpc_dg_ahint,
512           { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "" }},
513         { &hf_dcerpc_dg_ihint,
514           { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "" }},
515         { &hf_dcerpc_dg_frag_len,
516           { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_HEX, NULL, 0x0, "" }},
517         { &hf_dcerpc_dg_frag_num,
518           { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_HEX, NULL, 0x0, "" }},
519         { &hf_dcerpc_dg_auth_proto,
520           { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
521         { &hf_dcerpc_dg_opnum,
522           { "Opnum", "dcerpc.dg_opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
523         { &hf_dcerpc_dg_seqnum,
524           { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_HEX, NULL, 0x0, "" }},
525         { &hf_dcerpc_dg_server_boot,
526           { "Server boot time", "dcerpc.dg_server_boot", FT_UINT32, BASE_HEX, NULL, 0x0, "" }},
527         { &hf_dcerpc_dg_if_ver,
528           { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "" }},
529         { &hf_dcerpc_dg_obj_id,
530           { "Object", "dcerpc.dg_obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "" }},
531         { &hf_dcerpc_dg_if_id,
532           { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "" }},
533         { &hf_dcerpc_dg_act_id,
534           { "Activitiy", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "" }},
535
536
537     };
538     static gint *ett[] = {
539         &ett_dcerpc,
540         &ett_dcerpc_cn_flags,
541         &ett_dcerpc_dg_flags1,
542         &ett_dcerpc_dg_flags2,
543     };
544
545     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
546     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
547     proto_register_subtree_array (ett, array_length (ett));
548 }
549
550 void
551 proto_reg_handoff_dcerpc(void)
552 {
553     heur_dissector_add ("tcp", dissect_dcerpc_cn, proto_dcerpc);
554     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
555 }