Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-dcerpc-ndr.c
blob602f467d154167e33bb6e48c4a160a8763b9d141
1 /* packet-dcerpc-ndr.c
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
12 #include "config.h"
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.
24 int
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 */
31 if (pdata)
32 *pdata = 0;
34 if (di->conformant_run) {
35 /* just a run to handle conformant arrays, no scalars to dissect */
36 return offset;
39 /* no alignment needed */
40 return dissect_dcerpc_uint8(tvb, offset, pinfo,
41 tree, drep, hfindex, pdata);
44 int
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)
49 uint8_t val;
51 if (di->conformant_run) {
52 /* just a run to handle conformant arrays, no scalars to dissect */
53 return offset;
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;
62 char *valstr;
64 hf_info = proto_registrar_get_nth(hfindex);
66 valstr = (char *)wmem_alloc(pinfo->pool, 64);
67 valstr[0]=0;
69 switch (hf_info->display) {
70 case BASE_DEC:
71 if (hf_info->strings) {
72 snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val);
73 } else {
74 snprintf(valstr, 64, "%d", val);
76 break;
77 case BASE_HEX:
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);
80 } else {
81 snprintf(valstr, 64, "0x%02x", val);
83 break;
84 default:
85 REPORT_DISSECTOR_BUG("Invalid hf->display value");
88 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr);
90 if (pval) {
91 *pval = val;
94 return offset;
97 int
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 */
113 if (pdata)
114 *pdata = 0;
116 if (di->conformant_run) {
117 /* just a run to handle conformant arrays, no scalars to dissect */
118 return offset;
122 if (!di->no_align && (offset % 2)) {
123 offset++;
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)
134 uint16_t val;
136 if (di->conformant_run) {
137 /* just a run to handle conformant arrays, no scalars to dissect */
138 return offset;
142 if (!di->no_align && (offset % 2)) {
143 offset++;
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;
150 char *valstr;
152 hf_info = proto_registrar_get_nth(hfindex);
154 valstr = (char *)wmem_alloc(pinfo->pool, 64);
155 valstr[0]=0;
157 switch (hf_info->display) {
158 case BASE_DEC:
159 if (hf_info->strings) {
160 snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val);
161 } else {
162 snprintf(valstr, 64, "%d", val);
164 break;
165 case BASE_HEX:
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);
168 } else {
169 snprintf(valstr, 64, "0x%04x", val);
171 break;
172 default:
173 REPORT_DISSECTOR_BUG("Invalid hf->display value");
176 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr);
179 if (pval) {
180 *pval = val;
182 return offset;
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 */
200 if (pdata)
201 *pdata = 0;
203 if ((di != NULL) && (di->conformant_run)) {
204 /* just a run to handle conformant arrays, no scalars to dissect */
205 return offset;
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);
226 } else {
227 uint32_t val = 0;
228 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hfindex, &val);
229 if (pdata) {
230 *pdata = val;
232 return offset;
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);
246 } else {
247 uint16_t val = 0;
248 offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, di, drep, hfindex, &val);
249 if (pdata) {
250 *pdata = val;
252 return offset;
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)
261 uint32_t val;
263 if (di->conformant_run) {
264 /* just a run to handle conformant arrays, no scalars to dissect */
265 return offset;
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;
277 char *valstr;
279 hf_info = proto_registrar_get_nth(hfindex);
281 valstr = (char *)wmem_alloc(pinfo->pool, 64);
282 valstr[0]=0;
284 switch (hf_info->display) {
285 case BASE_DEC:
286 if (hf_info->strings) {
287 snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val);
288 } else {
289 snprintf(valstr, 64, "%d", val);
291 break;
292 case BASE_HEX:
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);
295 } else {
296 snprintf(valstr, 64, "0x%08x", val);
298 break;
299 default:
300 REPORT_DISSECTOR_BUG("Invalid hf->display value");
303 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr);
305 if (rval != NULL) {
306 *rval = val;
308 return offset;
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);
319 /* Double uint32
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 */
331 if (pdata)
332 *pdata = 0;
334 if (di->conformant_run) {
335 /* just a run to handle conformant arrays, no scalars to dissect */
336 return offset;
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);
346 /* uint64 : hyper
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 */
356 if (pdata)
357 *pdata = 0;
359 if (di->conformant_run) {
360 /* just a run to handle conformant arrays, no scalars to dissect */
361 return offset;
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);
367 offset += padding;
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)
378 uint64_t val;
380 if (di->conformant_run) {
381 /* just a run to handle conformant arrays, no scalars to dissect */
382 return offset;
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;
393 char *valstr;
395 hf_info = proto_registrar_get_nth(hfindex);
397 valstr = (char *)wmem_alloc(pinfo->pool, 64);
398 valstr[0]=0;
400 switch (hf_info->display) {
401 case BASE_DEC:
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);
404 } else {
405 snprintf(valstr, 64, "%" PRIu64, val);
407 break;
408 case BASE_HEX:
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);
411 } else {
412 snprintf(valstr, 64, "0x%" PRIx64, val);
414 break;
415 default:
416 REPORT_DISSECTOR_BUG("Invalid hf->display value");
419 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr);
422 if (pval) {
423 *pval = val;
425 return offset;
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 */
443 if (pdata)
444 *pdata = 0;
447 if (di->conformant_run) {
448 /* just a run to handle conformant arrays, no scalars to dissect */
449 return offset;
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 */
467 if (pdata)
468 *pdata = 0;
470 if (di->conformant_run) {
471 /* just a run to handle conformant arrays, no scalars to dissect */
472 return offset;
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 */
490 if (pdata)
491 *pdata = 0;
493 if (di->conformant_run) {
494 /* just a run to handle conformant arrays, no scalars to dissect */
495 return offset;
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 */
513 if (pdata)
514 memset(pdata, 0, sizeof(*pdata));
516 if (di->conformant_run) {
517 /* just a run to handle conformant arrays, no scalars to dissect */
518 return offset;
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 */
547 return offset;
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);
555 if (tree) {
556 /* Bytes is bytes - don't worry about the data representation */
557 proto_tree_add_item(tree, hfindex, tvb, offset, 20, ENC_NA);
559 if (pdata) {
560 *pdata = ctx_hnd;
562 return offset + 20;
566 * Editor modelines - https://www.wireshark.org/tools/modelines.html
568 * Local variables:
569 * c-basic-offset: 4
570 * tab-width: 8
571 * indent-tabs-mode: nil
572 * End:
574 * vi: set shiftwidth=4 tabstop=8 expandtab:
575 * :indentSize=4:tabSize=8:noTabs=true: