2 * Routines for DCERPC NDR dissection
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/wmem/wmem.h>
32 #include "packet-dcerpc.h"
36 * The NDR routines are for use by dcerpc subdissetors. They're
37 * primarily for making sure things are aligned properly according
38 * to the rules of NDR.
42 dissect_ndr_uint8(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
43 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
44 int hfindex
, guint8
*pdata
)
46 /* Some callers expect us to initialize pdata, even in error conditions, so
47 * do it right away in case we forget later */
51 if (di
->conformant_run
) {
52 /* just a run to handle conformant arrays, no scalars to dissect */
56 /* no alignment needed */
57 return dissect_dcerpc_uint8(tvb
, offset
, pinfo
,
58 tree
, drep
, hfindex
, pdata
);
62 PIDL_dissect_uint8_val(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
63 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
64 int hfindex
, guint32 param
, guint8
*pval
)
68 if (di
->conformant_run
) {
69 /* just a run to handle conformant arrays, no scalars to dissect */
73 /* no alignment needed */
74 offset
= dissect_dcerpc_uint8(tvb
, offset
, pinfo
,
75 tree
, drep
, hfindex
, &val
);
77 if (param
&PIDL_SET_COL_INFO
) {
78 header_field_info
*hf_info
;
81 hf_info
= proto_registrar_get_nth(hfindex
);
83 valstr
= (char *)wmem_alloc(wmem_packet_scope(), 64);
86 switch (hf_info
->display
) {
88 if (hf_info
->strings
) {
89 g_snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
91 g_snprintf(valstr
, 64, "%d", val
);
95 if (hf_info
->strings
) {
96 g_snprintf(valstr
, 64, "%s(0x%02x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
98 g_snprintf(valstr
, 64, "0x%02x", val
);
102 REPORT_DISSECTOR_BUG("Invalid hf->display value");
105 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
115 PIDL_dissect_uint8(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
116 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
117 int hfindex
, guint32 param
)
119 return PIDL_dissect_uint8_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
124 dissect_ndr_uint16(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
125 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
126 int hfindex
, guint16
*pdata
)
128 /* Some callers expect us to initialize pdata, even in error conditions, so
129 * do it right away in case we forget later */
133 if (di
->conformant_run
) {
134 /* just a run to handle conformant arrays, no scalars to dissect */
139 if (!di
->no_align
&& (offset
% 2)) {
142 return dissect_dcerpc_uint16(tvb
, offset
, pinfo
,
143 tree
, drep
, hfindex
, pdata
);
147 PIDL_dissect_uint16_val(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
148 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
149 int hfindex
, guint32 param
, guint16
*pval
)
153 if (di
->conformant_run
) {
154 /* just a run to handle conformant arrays, no scalars to dissect */
159 if (!di
->no_align
&& (offset
% 2)) {
162 offset
= dissect_dcerpc_uint16(tvb
, offset
, pinfo
,
163 tree
, drep
, hfindex
, &val
);
165 if (param
&PIDL_SET_COL_INFO
) {
166 header_field_info
*hf_info
;
169 hf_info
= proto_registrar_get_nth(hfindex
);
171 valstr
= (char *)wmem_alloc(wmem_packet_scope(), 64);
174 switch (hf_info
->display
) {
176 if (hf_info
->strings
) {
177 g_snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
179 g_snprintf(valstr
, 64, "%d", val
);
183 if (hf_info
->strings
) {
184 g_snprintf(valstr
, 64, "%s(0x%04x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
186 g_snprintf(valstr
, 64, "0x%04x", val
);
190 REPORT_DISSECTOR_BUG("Invalid hf->display value");
193 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
203 PIDL_dissect_uint16(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
204 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
205 int hfindex
, guint32 param _U_
)
207 return PIDL_dissect_uint16_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
211 dissect_ndr_uint32(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
212 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
213 int hfindex
, guint32
*pdata
)
215 /* Some callers expect us to initialize pdata, even in error conditions, so
216 * do it right away in case we forget later */
220 if ((di
!= NULL
) && (di
->conformant_run
)) {
221 /* just a run to handle conformant arrays, no scalars to dissect */
226 if ((di
!= NULL
) && (!di
->no_align
) && (offset
% 4)) {
227 offset
+= 4 - (offset
% 4);
229 return dissect_dcerpc_uint32(tvb
, offset
, pinfo
,
230 tree
, drep
, hfindex
, pdata
);
233 /* This is used to dissect the new datatypes, such as pointers and conformance
234 data, which is 4 bytes in size in NDR but 8 bytes in NDR64.
237 dissect_ndr_uint3264(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
238 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
239 int hfindex
, guint3264
*pdata
)
241 if (di
->call_data
->flags
& DCERPC_IS_NDR64
) {
242 return dissect_ndr_uint64(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, pdata
);
245 offset
= dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, &val
);
253 /* This is used to dissect the new datatypes, such as enums
254 that are 2 bytes in size in NDR but 4 bytes in NDR64.
257 dissect_ndr_uint1632(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
258 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
259 int hfindex
, guint1632
*pdata
)
261 if (di
->call_data
->flags
& DCERPC_IS_NDR64
) {
262 return dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, pdata
);
265 offset
= dissect_ndr_uint16(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, &val
);
274 PIDL_dissect_uint32_val(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
275 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
276 int hfindex
, guint32 param
, guint32
*rval
)
280 if (di
->conformant_run
) {
281 /* just a run to handle conformant arrays, no scalars to dissect */
286 if (!di
->no_align
&& (offset
% 4)) {
287 offset
+= 4 - (offset
% 4);
289 offset
= dissect_dcerpc_uint32(tvb
, offset
, pinfo
,
290 tree
, drep
, hfindex
, &val
);
292 if (param
&PIDL_SET_COL_INFO
) {
293 header_field_info
*hf_info
;
296 hf_info
= proto_registrar_get_nth(hfindex
);
298 valstr
= (char *)wmem_alloc(wmem_packet_scope(), 64);
301 switch (hf_info
->display
) {
303 if (hf_info
->strings
) {
304 g_snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
306 g_snprintf(valstr
, 64, "%d", val
);
310 if (hf_info
->strings
) {
311 g_snprintf(valstr
, 64, "%s(0x%08x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
313 g_snprintf(valstr
, 64, "0x%08x", val
);
317 REPORT_DISSECTOR_BUG("Invalid hf->display value");
320 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
329 PIDL_dissect_uint32(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
330 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
331 int hfindex
, guint32 param
)
333 return PIDL_dissect_uint32_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
337 This function dissects the 64bit datatype that is common for
338 ms interfaces and which is 32bit aligned.
339 It is really just 2 uint32's
342 dissect_ndr_duint32(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
343 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
344 int hfindex
, guint64
*pdata
)
346 /* Some callers expect us to initialize pdata, even in error conditions, so
347 * do it right away in case we forget later */
351 if (di
->conformant_run
) {
352 /* just a run to handle conformant arrays, no scalars to dissect */
356 if (!di
->no_align
&& (offset
% 4)) {
357 offset
+= 4 - (offset
% 4);
359 return dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
360 tree
, drep
, hfindex
, pdata
);
364 a 64 bit integer aligned to proper 8 byte boundaries
367 dissect_ndr_uint64(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
368 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
369 int hfindex
, guint64
*pdata
)
371 /* Some callers expect us to initialize pdata, even in error conditions, so
372 * do it right away in case we forget later */
376 if (di
->conformant_run
) {
377 /* just a run to handle conformant arrays, no scalars to dissect */
381 if (!di
->no_align
&& (offset
% 8)) {
382 gint padding
= 8 - (offset
% 8);
383 /*add the item for padding bytes*/
384 proto_tree_add_text(tree
, tvb
, offset
, padding
, "NDR-Padding: %d bytes", padding
);
387 return dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
388 tree
, drep
, hfindex
, pdata
);
392 PIDL_dissect_uint64_val(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
393 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
394 int hfindex
, guint32 param
, guint64
*pval
)
398 if (di
->conformant_run
) {
399 /* just a run to handle conformant arrays, no scalars to dissect */
403 if (!di
->no_align
&& (offset
% 8)) {
404 offset
+= 8 - (offset
% 8);
406 offset
= dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
407 tree
, drep
, hfindex
, &val
);
409 if (param
&PIDL_SET_COL_INFO
) {
410 header_field_info
*hf_info
;
413 hf_info
= proto_registrar_get_nth(hfindex
);
415 valstr
= (char *)wmem_alloc(wmem_packet_scope(), 64);
418 switch (hf_info
->display
) {
420 if (hf_info
->strings
) {
421 g_snprintf(valstr
, 64, "%s(%" G_GINT64_MODIFIER
"u)",val_to_str( (guint32
) val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
423 g_snprintf(valstr
, 64, "%" G_GINT64_MODIFIER
"u", val
);
427 if (hf_info
->strings
) {
428 g_snprintf(valstr
, 64, "%s(0x%" G_GINT64_MODIFIER
"x)",val_to_str( (guint32
) val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
430 g_snprintf(valstr
, 64, "0x%" G_GINT64_MODIFIER
"x", val
);
434 REPORT_DISSECTOR_BUG("Invalid hf->display value");
437 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
447 PIDL_dissect_uint64(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
448 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
449 int hfindex
, guint32 param
)
451 return PIDL_dissect_uint64_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
455 dissect_ndr_float(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
456 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
457 int hfindex
, gfloat
*pdata
)
459 /* Some callers expect us to initialize pdata, even in error conditions, so
460 * do it right away in case we forget later */
465 if (di
->conformant_run
) {
466 /* just a run to handle conformant arrays, no scalars to dissect */
470 if (!di
->no_align
&& (offset
% 4)) {
471 offset
+= 4 - (offset
% 4);
473 return dissect_dcerpc_float(tvb
, offset
, pinfo
,
474 tree
, drep
, hfindex
, pdata
);
479 dissect_ndr_double(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
480 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
481 int hfindex
, gdouble
*pdata
)
483 /* Some callers expect us to initialize pdata, even in error conditions, so
484 * do it right away in case we forget later */
488 if (di
->conformant_run
) {
489 /* just a run to handle conformant arrays, no scalars to dissect */
493 if (!di
->no_align
&& (offset
% 8)) {
494 offset
+= 8 - (offset
% 8);
496 return dissect_dcerpc_double(tvb
, offset
, pinfo
,
497 tree
, drep
, hfindex
, pdata
);
500 /* handles unix 32 bit time_t */
502 dissect_ndr_time_t(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
503 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
504 int hfindex
, guint32
*pdata
)
506 /* Some callers expect us to initialize pdata, even in error conditions, so
507 * do it right away in case we forget later */
511 if (di
->conformant_run
) {
512 /* just a run to handle conformant arrays, no scalars to dissect */
517 if (!di
->no_align
&& (offset
% 4)) {
518 offset
+= 4 - (offset
% 4);
520 return dissect_dcerpc_time_t(tvb
, offset
, pinfo
,
521 tree
, drep
, hfindex
, pdata
);
525 dissect_ndr_uuid_t(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo
,
526 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
527 int hfindex
, e_uuid_t
*pdata
)
529 /* Some callers expect us to initialize pdata, even in error conditions, so
530 * do it right away in case we forget later */
532 memset(pdata
, 0, sizeof(*pdata
));
534 if (di
->conformant_run
) {
535 /* just a run to handle conformant arrays, no scalars to dissect */
539 /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */
540 if (!di
->no_align
&& (offset
% 4)) {
541 offset
+= 4 - (offset
% 4);
543 return dissect_dcerpc_uuid_t(tvb
, offset
, pinfo
,
544 tree
, drep
, hfindex
, pdata
);
548 * XXX - at least according to the DCE RPC 1.1 "nbase.idl", an
549 * "ndr_context_handle" is an unsigned32 "context_handle_attributes"
550 * and a uuid_t "context_handle_uuid". The attributes do not appear to
551 * be used, and always appear to be set to 0, in the DCE RPC 1.1 code.
553 * Should we display an "ndr_context_handle" with a tree holding the
554 * attributes and the uuid_t?
557 dissect_ndr_ctx_hnd(tvbuff_t
*tvb
, gint offset
, packet_info
*pinfo _U_
,
558 proto_tree
*tree
, dcerpc_info
*di
, guint8
*drep
,
559 int hfindex
, e_ctx_hnd
*pdata
)
561 static e_ctx_hnd ctx_hnd
;
563 if (di
->conformant_run
) {
564 /* just a run to handle conformant arrays, no scalars to dissect */
568 if (!di
->no_align
&& (offset
% 2)) {
569 offset
+= 4 - (offset
% 4);
571 ctx_hnd
.attributes
= dcerpc_tvb_get_ntohl(tvb
, offset
, drep
);
572 dcerpc_tvb_get_uuid(tvb
, offset
+4, drep
, &ctx_hnd
.uuid
);
574 /* Bytes is bytes - don't worry about the data representation */
575 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 20, ENC_NA
);