2 * Routines for DCERPC NDR dissection
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include "packet-dcerpc.h"
19 * The NDR routines are for use by dcerpc subdissetors. They're
20 * primarily for making sure things are aligned properly according
21 * to the rules of NDR.
25 dissect_ndr_uint8(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
26 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
27 int hfindex
, uint8_t *pdata
)
29 /* Some callers expect us to initialize pdata, even in error conditions, so
30 * do it right away in case we forget later */
34 if (di
->conformant_run
) {
35 /* just a run to handle conformant arrays, no scalars to dissect */
39 /* no alignment needed */
40 return dissect_dcerpc_uint8(tvb
, offset
, pinfo
,
41 tree
, drep
, hfindex
, pdata
);
45 PIDL_dissect_uint8_val(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
46 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
47 int hfindex
, uint32_t param
, uint8_t *pval
)
51 if (di
->conformant_run
) {
52 /* just a run to handle conformant arrays, no scalars to dissect */
56 /* no alignment needed */
57 offset
= dissect_dcerpc_uint8(tvb
, offset
, pinfo
,
58 tree
, drep
, hfindex
, &val
);
60 if (param
&PIDL_SET_COL_INFO
) {
61 header_field_info
*hf_info
;
64 hf_info
= proto_registrar_get_nth(hfindex
);
66 valstr
= (char *)wmem_alloc(pinfo
->pool
, 64);
69 switch (hf_info
->display
) {
71 if (hf_info
->strings
) {
72 snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
74 snprintf(valstr
, 64, "%d", val
);
78 if (hf_info
->strings
) {
79 snprintf(valstr
, 64, "%s(0x%02x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
81 snprintf(valstr
, 64, "0x%02x", val
);
85 REPORT_DISSECTOR_BUG("Invalid hf->display value");
88 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
98 PIDL_dissect_uint8(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
99 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
100 int hfindex
, uint32_t param
)
102 return PIDL_dissect_uint8_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
107 dissect_ndr_uint16(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
108 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
109 int hfindex
, uint16_t *pdata
)
111 /* Some callers expect us to initialize pdata, even in error conditions, so
112 * do it right away in case we forget later */
116 if (di
->conformant_run
) {
117 /* just a run to handle conformant arrays, no scalars to dissect */
122 if (!di
->no_align
&& (offset
% 2)) {
125 return dissect_dcerpc_uint16(tvb
, offset
, pinfo
,
126 tree
, drep
, hfindex
, pdata
);
130 PIDL_dissect_uint16_val(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
131 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
132 int hfindex
, uint32_t param
, uint16_t *pval
)
136 if (di
->conformant_run
) {
137 /* just a run to handle conformant arrays, no scalars to dissect */
142 if (!di
->no_align
&& (offset
% 2)) {
145 offset
= dissect_dcerpc_uint16(tvb
, offset
, pinfo
,
146 tree
, drep
, hfindex
, &val
);
148 if (param
&PIDL_SET_COL_INFO
) {
149 header_field_info
*hf_info
;
152 hf_info
= proto_registrar_get_nth(hfindex
);
154 valstr
= (char *)wmem_alloc(pinfo
->pool
, 64);
157 switch (hf_info
->display
) {
159 if (hf_info
->strings
) {
160 snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
162 snprintf(valstr
, 64, "%d", val
);
166 if (hf_info
->strings
) {
167 snprintf(valstr
, 64, "%s(0x%04x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
169 snprintf(valstr
, 64, "0x%04x", val
);
173 REPORT_DISSECTOR_BUG("Invalid hf->display value");
176 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
186 PIDL_dissect_uint16(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
187 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
188 int hfindex
, uint32_t param
)
190 return PIDL_dissect_uint16_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
194 dissect_ndr_uint32(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
195 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
196 int hfindex
, uint32_t *pdata
)
198 /* Some callers expect us to initialize pdata, even in error conditions, so
199 * do it right away in case we forget later */
203 if ((di
!= NULL
) && (di
->conformant_run
)) {
204 /* just a run to handle conformant arrays, no scalars to dissect */
209 if ((di
!= NULL
) && (!di
->no_align
) && (offset
% 4)) {
210 offset
+= 4 - (offset
% 4);
212 return dissect_dcerpc_uint32(tvb
, offset
, pinfo
,
213 tree
, drep
, hfindex
, pdata
);
216 /* This is used to dissect the new datatypes, such as pointers and conformance
217 data, which is 4 bytes in size in NDR but 8 bytes in NDR64.
220 dissect_ndr_uint3264(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
221 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
222 int hfindex
, uint3264_t
*pdata
)
224 if (di
->call_data
->flags
& DCERPC_IS_NDR64
) {
225 return dissect_ndr_uint64(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, pdata
);
228 offset
= dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, &val
);
236 /* This is used to dissect the new datatypes, such as enums
237 that are 2 bytes in size in NDR but 4 bytes in NDR64.
240 dissect_ndr_uint1632(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
241 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
242 int hfindex
, uint1632_t
*pdata
)
244 if (di
->call_data
->flags
& DCERPC_IS_NDR64
) {
245 return dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, pdata
);
248 offset
= dissect_ndr_uint16(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, &val
);
257 PIDL_dissect_uint32_val(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
258 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
259 int hfindex
, uint32_t param
, uint32_t *rval
)
263 if (di
->conformant_run
) {
264 /* just a run to handle conformant arrays, no scalars to dissect */
269 if (!di
->no_align
&& (offset
% 4)) {
270 offset
+= 4 - (offset
% 4);
272 offset
= dissect_dcerpc_uint32(tvb
, offset
, pinfo
,
273 tree
, drep
, hfindex
, &val
);
275 if (param
&PIDL_SET_COL_INFO
) {
276 header_field_info
*hf_info
;
279 hf_info
= proto_registrar_get_nth(hfindex
);
281 valstr
= (char *)wmem_alloc(pinfo
->pool
, 64);
284 switch (hf_info
->display
) {
286 if (hf_info
->strings
) {
287 snprintf(valstr
, 64, "%s(%d)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
289 snprintf(valstr
, 64, "%d", val
);
293 if (hf_info
->strings
) {
294 snprintf(valstr
, 64, "%s(0x%08x)",val_to_str(val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
296 snprintf(valstr
, 64, "0x%08x", val
);
300 REPORT_DISSECTOR_BUG("Invalid hf->display value");
303 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
312 PIDL_dissect_uint32(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
313 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
314 int hfindex
, uint32_t param
)
316 return PIDL_dissect_uint32_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
320 This function dissects the 64bit datatype that is common for
321 ms interfaces and which is 32bit aligned.
322 It is really just 2 uint32's
325 dissect_ndr_duint32(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
326 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
327 int hfindex
, uint64_t *pdata
)
329 /* Some callers expect us to initialize pdata, even in error conditions, so
330 * do it right away in case we forget later */
334 if (di
->conformant_run
) {
335 /* just a run to handle conformant arrays, no scalars to dissect */
339 if (!di
->no_align
&& (offset
% 4)) {
340 offset
+= 4 - (offset
% 4);
342 return dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
343 tree
, di
, drep
, hfindex
, pdata
);
347 a 64 bit integer aligned to proper 8 byte boundaries
350 dissect_ndr_uint64(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
351 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
352 int hfindex
, uint64_t *pdata
)
354 /* Some callers expect us to initialize pdata, even in error conditions, so
355 * do it right away in case we forget later */
359 if (di
->conformant_run
) {
360 /* just a run to handle conformant arrays, no scalars to dissect */
364 if (!di
->no_align
&& (offset
% 8)) {
365 int padding
= 8 - (offset
% 8);
366 proto_tree_add_item(tree
, hf_dcerpc_ndr_padding
, tvb
, offset
, padding
, ENC_NA
);
369 return dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
370 tree
, di
, drep
, hfindex
, pdata
);
374 PIDL_dissect_uint64_val(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
375 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
376 int hfindex
, uint32_t param
, uint64_t *pval
)
380 if (di
->conformant_run
) {
381 /* just a run to handle conformant arrays, no scalars to dissect */
385 if (!di
->no_align
&& (offset
% 8)) {
386 offset
+= 8 - (offset
% 8);
388 offset
= dissect_dcerpc_uint64(tvb
, offset
, pinfo
,
389 tree
, di
, drep
, hfindex
, &val
);
391 if (param
&PIDL_SET_COL_INFO
) {
392 header_field_info
*hf_info
;
395 hf_info
= proto_registrar_get_nth(hfindex
);
397 valstr
= (char *)wmem_alloc(pinfo
->pool
, 64);
400 switch (hf_info
->display
) {
402 if (hf_info
->strings
) {
403 snprintf(valstr
, 64, "%s(%" PRIu64
")",val_to_str( (uint32_t) val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
405 snprintf(valstr
, 64, "%" PRIu64
, val
);
409 if (hf_info
->strings
) {
410 snprintf(valstr
, 64, "%s(0x%" PRIx64
")",val_to_str( (uint32_t) val
, (const value_string
*)hf_info
->strings
, "Unknown:%u"), val
);
412 snprintf(valstr
, 64, "0x%" PRIx64
, val
);
416 REPORT_DISSECTOR_BUG("Invalid hf->display value");
419 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s:%s", hf_info
->name
, valstr
);
429 PIDL_dissect_uint64(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
430 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
431 int hfindex
, uint32_t param
)
433 return PIDL_dissect_uint64_val(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, param
, NULL
);
437 dissect_ndr_float(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
438 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
439 int hfindex
, float *pdata
)
441 /* Some callers expect us to initialize pdata, even in error conditions, so
442 * do it right away in case we forget later */
447 if (di
->conformant_run
) {
448 /* just a run to handle conformant arrays, no scalars to dissect */
452 if (!di
->no_align
&& (offset
% 4)) {
453 offset
+= 4 - (offset
% 4);
455 return dissect_dcerpc_float(tvb
, offset
, pinfo
,
456 tree
, drep
, hfindex
, pdata
);
461 dissect_ndr_double(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
462 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
463 int hfindex
, double *pdata
)
465 /* Some callers expect us to initialize pdata, even in error conditions, so
466 * do it right away in case we forget later */
470 if (di
->conformant_run
) {
471 /* just a run to handle conformant arrays, no scalars to dissect */
475 if (!di
->no_align
&& (offset
% 8)) {
476 offset
+= 8 - (offset
% 8);
478 return dissect_dcerpc_double(tvb
, offset
, pinfo
,
479 tree
, drep
, hfindex
, pdata
);
482 /* handles unix 32 bit time_t */
484 dissect_ndr_time_t(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
485 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
486 int hfindex
, uint32_t *pdata
)
488 /* Some callers expect us to initialize pdata, even in error conditions, so
489 * do it right away in case we forget later */
493 if (di
->conformant_run
) {
494 /* just a run to handle conformant arrays, no scalars to dissect */
499 if (!di
->no_align
&& (offset
% 4)) {
500 offset
+= 4 - (offset
% 4);
502 return dissect_dcerpc_time_t(tvb
, offset
, pinfo
,
503 tree
, drep
, hfindex
, pdata
);
507 dissect_ndr_uuid_t(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
508 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
509 int hfindex
, e_guid_t
*pdata
)
511 /* Some callers expect us to initialize pdata, even in error conditions, so
512 * do it right away in case we forget later */
514 memset(pdata
, 0, sizeof(*pdata
));
516 if (di
->conformant_run
) {
517 /* just a run to handle conformant arrays, no scalars to dissect */
521 /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */
522 if (!di
->no_align
&& (offset
% 4)) {
523 offset
+= 4 - (offset
% 4);
525 return dissect_dcerpc_uuid_t(tvb
, offset
, pinfo
,
526 tree
, drep
, hfindex
, pdata
);
530 * XXX - at least according to the DCE RPC 1.1 "nbase.idl", an
531 * "ndr_context_handle" is an unsigned32 "context_handle_attributes"
532 * and a uuid_t "context_handle_uuid". The attributes do not appear to
533 * be used, and always appear to be set to 0, in the DCE RPC 1.1 code.
535 * Should we display an "ndr_context_handle" with a tree holding the
536 * attributes and the uuid_t?
539 dissect_ndr_ctx_hnd(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
,
540 proto_tree
*tree
, dcerpc_info
*di
, uint8_t *drep
,
541 int hfindex
, e_ctx_hnd
*pdata
)
543 static e_ctx_hnd ctx_hnd
;
545 if (di
->conformant_run
) {
546 /* just a run to handle conformant arrays, no scalars to dissect */
550 if (!di
->no_align
&& (offset
% 4)) {
551 offset
+= 4 - (offset
% 4);
553 ctx_hnd
.attributes
= dcerpc_tvb_get_ntohl(tvb
, offset
, drep
);
554 dcerpc_tvb_get_uuid(tvb
, offset
+4, drep
, &ctx_hnd
.uuid
);
556 /* Bytes is bytes - don't worry about the data representation */
557 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 20, ENC_NA
);
566 * Editor modelines - https://www.wireshark.org/tools/modelines.html
571 * indent-tabs-mode: nil
574 * vi: set shiftwidth=4 tabstop=8 expandtab:
575 * :indentSize=4:tabSize=8:noTabs=true: