Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-csn1.c
blobaaf39d46be529f54a6ebdf57451079a50fc9ffb8
1 /* packet-csn1.c
2 * Routines for CSN1 dissection in wireshark.
3 * By Vincent Helfre, based on original code by Jari Sassi
4 * with the gracious authorization of STE
5 * Copyright (c) 2011 ST-Ericsson
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/to_str.h>
18 #include "packet-csn1.h"
20 void proto_register_csn1(void);
22 static int hf_null_data;
24 static expert_field ei_csn1_more_bits_to_unpack;
25 static expert_field ei_csn1_general;
26 static expert_field ei_csn1_not_implemented;
27 static expert_field ei_csn1_union_index;
28 static expert_field ei_csn1_script_error;
29 static expert_field ei_csn1_more32bits;
30 static expert_field ei_csn1_fixed_not_matched;
31 static expert_field ei_csn1_stream_not_supported;
33 #define pvDATA(_pv, _offset) ((void*) ((unsigned char*)_pv + _offset))
34 #define pui8DATA(_pv, _offset) ((uint8_t*) pvDATA(_pv, _offset))
35 #define pui16DATA(_pv, _offset) ((uint16_t*) pvDATA(_pv, _offset))
36 #define pui32DATA(_pv, _offset) ((uint32_t*) pvDATA(_pv, _offset))
38 /* used to tag existence of next element in variable length lists */
39 #define STANDARD_TAG 1
40 #define REVERSED_TAG 0
42 static const unsigned char ixBitsTab[] = {0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5};
44 static int proto_csn1;
46 /* Returns no_of_bits (up to 8) masked with 0x2B */
47 static uint8_t
48 tvb_get_masked_bits8(tvbuff_t *tvb, int bit_offset, const int no_of_bits)
50 static const uint8_t maskBits[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
51 int byte_offset = bit_offset >> 3; /* divide by 8 */
52 int relative_bit_offset = bit_offset & 0x07; /* modulo 8 */
53 uint8_t result;
54 int bit_shift = 8 - relative_bit_offset - (int) no_of_bits;
56 if (bit_shift >= 0)
58 result = (0x2B ^ tvb_get_uint8(tvb, byte_offset)) >> bit_shift;
59 result &= maskBits[no_of_bits];
61 else
63 uint8_t hight_part = (0x2B ^ tvb_get_uint8(tvb, byte_offset)) & maskBits[8 - relative_bit_offset];
64 hight_part = (uint8_t) (hight_part << (-bit_shift));
65 result = (0x2B ^ tvb_get_uint8(tvb, byte_offset+1)) >> (8 + bit_shift);
66 result |= hight_part;
68 return result;
71 /**
72 * ================================================================================================
73 * set initial/start values in help data structure used for packing/unpacking operation
74 * ================================================================================================
76 void
77 csnStreamInit(csnStream_t* ar, int bit_offset, int remaining_bits_len, packet_info* pinfo)
79 ar->remaining_bits_len = remaining_bits_len;
80 ar->bit_offset = bit_offset;
81 ar->pinfo = pinfo;
84 static int16_t
85 ProcessError(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, int bit_offset, int16_t err, expert_field* err_field, const CSN_DESCR* pDescr)
87 if (err_field != NULL)
88 proto_tree_add_expert_format(tree, pinfo, err_field, tvb, bit_offset>>3, 1, "%s (%s)", expert_get_summary(err_field), pDescr?pDescr->sz:"-");
90 return err;
93 #if 0
94 static const char* CSN_DESCR_type[]=
96 "CSN_END",
97 "CSN_BIT",
98 "CSN_UINT",
99 "CSN_TYPE",
100 "CSN_CHOICE",
101 "CSN_UNION",
102 "CSN_UNION_LH",
103 "CSN_UINT_ARRAY",
104 "CSN_TYPE_ARRAY",
105 "CSN_BITMAP",
106 "CSN_VARIABLE_BITMAP",
107 "CSN_VARIABLE_BITMAP_1",
108 "CSN_LEFT_ALIGNED_VAR_BMP",
109 "CSN_LEFT_ALIGNED_VAR_BMP_1",
110 "CSN_VARIABLE_ARRAY",
111 "CSN_VARIABLE_TARRAY",
112 "CSN_VARIABLE_TARRAY_OFFSET",
113 "CSN_RECURSIVE_ARRAY",
114 "CSN_RECURSIVE_TARRAY",
115 "CSN_RECURSIVE_TARRAY_1",
116 "CSN_RECURSIVE_TARRAY_2",
117 "CSN_EXIST",
118 "CSN_EXIST_LH",
119 "CSN_NEXT_EXIST",
120 "CSN_NEXT_EXIST_LH",
121 "CSN_NULL",
122 "CSN_FIXED",
123 "CSN_CALLBACK",
124 "CSN_UINT_OFFSET",
125 "CSN_UINT_LH",
126 "CSN_SERIALIZE",
127 "CSN_TRAP_ERROR"
128 "CSN_???"
130 #endif
133 * ================================================================================================
134 * Return true if tag in bit stream indicates existence of next list element,
135 * otherwise return false.
136 * Will work for tag values equal to both 0 and 1.
137 * ================================================================================================
140 static bool
141 existNextElement(tvbuff_t *tvb, int bit_offset, uint8_t Tag)
143 uint8_t res = tvb_get_bits8(tvb, bit_offset, 1);
144 if (Tag == STANDARD_TAG)
146 return (res > 0);
148 return (res == 0);
152 int16_t
153 // NOLINTNEXTLINE(misc-no-recursion)
154 csnStreamDissector(proto_tree *tree, csnStream_t* ar, const CSN_DESCR* pDescr, tvbuff_t *tvb, void* data, int ett_csn1)
156 int remaining_bits_len = ar->remaining_bits_len;
157 int bit_offset = ar->bit_offset;
158 uint8_t* pui8 = NULL;
159 uint16_t* pui16;
160 uint32_t* pui32;
161 uint8_t Tag = STANDARD_TAG;
163 /* Negative number definitely indicates an error */
164 if (remaining_bits_len < 0)
166 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
171 switch (pDescr->type)
173 case CSN_BIT:
175 if (remaining_bits_len > 0)
177 pui8 = pui8DATA(data, pDescr->offset);
179 *pui8 = tvb_get_bits8(tvb, bit_offset, 1);
180 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
182 /* end add the bit value to protocol tree */
184 else if(pDescr->may_be_null)
186 pui8 = pui8DATA(data, pDescr->offset);
187 *pui8 = 0;
188 proto_tree_add_none_format(tree, hf_null_data, tvb, 0, 0, "[NULL data]: %s Not Present", proto_registrar_get_name(*(pDescr->hf_ptr)));
190 else
192 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
195 pDescr++;
196 remaining_bits_len--;
197 bit_offset++;
198 break;
201 case CSN_NULL:
202 { /* Empty member! */
203 bit_offset += pDescr->i;
204 pDescr++;
205 break;
208 case CSN_UINT:
210 uint8_t no_of_bits = (uint8_t) pDescr->i;
212 if (remaining_bits_len >= no_of_bits)
214 if (no_of_bits <= 8)
216 uint8_t ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
217 pui8 = pui8DATA(data, pDescr->offset);
218 *pui8 = ui8;
219 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
221 else if (no_of_bits <= 16)
223 uint16_t ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
224 pui16 = pui16DATA(data, pDescr->offset);
225 memcpy(pui16, &ui16, 2);
226 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
228 else if (no_of_bits <= 32)
230 uint32_t ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
231 pui32 = pui32DATA(data, pDescr->offset);
232 memcpy(pui32, &ui32, 4);
233 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
235 else
237 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
239 remaining_bits_len -= no_of_bits;
240 bit_offset += no_of_bits;
242 else if(pDescr->may_be_null)
244 if (no_of_bits <= 8)
246 pui8 = pui8DATA(data, pDescr->offset);
247 *pui8 = 0;
249 else if (no_of_bits <= 16)
251 pui16 = pui16DATA(data, pDescr->offset);
252 memset(pui16, 0, 2);
254 else if (no_of_bits <= 32)
256 pui32 = pui32DATA(data, pDescr->offset);
257 memset(pui32, 0, 4);
259 proto_tree_add_none_format(tree, hf_null_data, tvb, 0, 0, "[NULL data]: %s Not Present", proto_registrar_get_name(*(pDescr->hf_ptr)));
261 else
263 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
266 pDescr++;
267 break;
270 case CSN_UINT_OFFSET:
272 uint8_t no_of_bits = (uint8_t) pDescr->i;
274 if (remaining_bits_len >= no_of_bits)
276 if (no_of_bits <= 8)
278 uint8_t ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
279 pui8 = pui8DATA(data, pDescr->offset);
280 *pui8 = ui8 + (uint8_t)pDescr->descr.value;
282 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits,
283 *pui8, ENC_BIG_ENDIAN, "%u (Raw %u + Offset %u)", *pui8, ui8,
284 (uint8_t) pDescr->descr.value);
286 else if (no_of_bits <= 16)
288 uint16_t ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN) + (uint16_t)pDescr->descr.value;
289 pui16 = pui16DATA(data, pDescr->offset);
290 memcpy(pui16, &ui16, 2);
292 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits,
293 *pui16, ENC_BIG_ENDIAN, "%u (Raw %u + Offset %u)", *pui16, ui16,
294 (uint16_t) pDescr->descr.value);
296 else if (no_of_bits <= 32)
298 uint32_t ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN) + (uint16_t)pDescr->descr.value;
299 pui32 = pui32DATA(data, pDescr->offset);
300 memcpy(pui32, &ui32, 4);
302 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits,
303 *pui32, ENC_BIG_ENDIAN, "%u (Raw %u + Offset %u)", *pui32, ui32,
304 (uint16_t) pDescr->descr.value);
306 else
308 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
311 else
313 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
316 remaining_bits_len -= no_of_bits;
317 bit_offset += no_of_bits;
318 pDescr++;
319 break;
322 case CSN_UINT_LH:
324 uint8_t no_of_bits = (uint8_t) pDescr->i;
326 if (remaining_bits_len >= no_of_bits)
328 if (no_of_bits <= 8)
330 uint8_t ui8 = tvb_get_masked_bits8(tvb, bit_offset, no_of_bits);
331 pui8 = pui8DATA(data, pDescr->offset);
332 *pui8 = ui8;
333 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
336 else
337 {/* Maybe we should support more than 8 bits ? */
338 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
341 else
343 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
346 remaining_bits_len -= no_of_bits;
347 bit_offset += no_of_bits;
348 pDescr++;
349 break;
352 case CSN_SPLIT_BITS:
354 uint8_t no_of_value_bits = (uint8_t) pDescr->i;
355 uint64_t value;
357 proto_tree_add_split_bits_item_ret_val(tree, *pDescr->hf_ptr, tvb, bit_offset, pDescr->descr.crumb_spec, &value);
358 if (no_of_value_bits <= 8)
360 pui8 = pui8DATA(data, pDescr->offset);
361 *pui8 = (uint8_t)value;
363 else if (no_of_value_bits <= 16)
365 uint16_t ui16 = (uint16_t) value;
366 pui16 = pui16DATA(data, pDescr->offset);
367 memcpy(pui16, &ui16, 2);
369 else if (no_of_value_bits <= 32)
371 uint32_t ui32 = (uint32_t) value;
372 pui32 = pui32DATA(data, pDescr->offset);
373 memcpy(pui32, &ui32, 4);
375 else
377 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
380 pDescr++;
381 break;
384 case CSN_SPLIT_BITS_CRUMB:
386 if (remaining_bits_len >= pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length)
388 proto_tree_add_split_bits_crumb(tree, *pDescr->hf_ptr, tvb, bit_offset,
389 pDescr->descr.crumb_spec, pDescr->i);
391 remaining_bits_len -= pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length;
392 bit_offset += pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length;
394 else
396 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
399 pDescr++;
400 break;
403 case CSN_UINT_ARRAY:
405 uint8_t no_of_bits = (uint8_t) pDescr->i;
406 uint16_t nCount = (uint16_t)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
407 int i = 0;
409 if (pDescr->value != 0)
410 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
411 memcpy(&nCount, pui16DATA(data, nCount), 2);
414 if (remaining_bits_len >= (no_of_bits * nCount))
416 remaining_bits_len -= (no_of_bits * nCount);
417 if (no_of_bits <= 8)
419 pui8 = pui8DATA(data, pDescr->offset);
422 *pui8++ = tvb_get_bits8(tvb, bit_offset, no_of_bits);
423 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, *pui8, ENC_BIG_ENDIAN, " (Count %d)", i++);
424 bit_offset += no_of_bits;
425 } while (--nCount > 0);
427 else if (no_of_bits <= 16)
429 return ProcessError(tree, ar->pinfo, tvb, bit_offset, 999, &ei_csn1_not_implemented, pDescr);
431 else if (no_of_bits <= 32)
433 return ProcessError(tree, ar->pinfo, tvb, bit_offset, 999, &ei_csn1_not_implemented, pDescr);
435 else
437 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
440 else
442 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
444 pDescr++;
445 break;
448 case CSN_VARIABLE_TARRAY_OFFSET:
449 case CSN_VARIABLE_TARRAY:
450 case CSN_TYPE_ARRAY:
452 int16_t Status;
453 csnStream_t arT = *ar;
454 int16_t nCount = pDescr->i;
455 uint16_t nSize = (uint16_t)(int32_t)pDescr->value;
456 int i =0;
458 pui8 = pui8DATA(data, pDescr->offset);
459 if (pDescr->type == CSN_VARIABLE_TARRAY)
460 { /* Count specified in field */
461 nCount = *pui8DATA(data, pDescr->i);
463 else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
464 { /* Count specified in field */
465 nCount = *pui8DATA(data, pDescr->i);
466 /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
469 while (nCount > 0)
470 { /* resulting array of length 0 is possible
471 * but no bits shall be read from bitstream
473 proto_item *ti;
474 proto_tree *test_tree;
476 test_tree = proto_tree_add_subtree_format(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, "%s[%d]",pDescr->sz, i++);
478 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
479 increment_dissection_depth(ar->pinfo);
480 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)pDescr->descr.ptr, tvb, pui8, ett_csn1);
481 decrement_dissection_depth(ar->pinfo);
482 if (Status >= 0)
484 pui8 += nSize;
485 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
486 remaining_bits_len = arT.remaining_bits_len;
487 bit_offset = arT.bit_offset;
489 else
491 return Status;
493 nCount--;
496 pDescr++;
497 break;
500 case CSN_BITMAP:
501 { /* bitmap with given length. The result is left aligned! */
502 uint8_t no_of_bits = (uint8_t) pDescr->i; /* length of bitmap */
504 if (no_of_bits > 0)
506 if (no_of_bits > remaining_bits_len)
508 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
511 if (no_of_bits <= 32)
513 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
515 else if (no_of_bits <= 64)
517 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
519 else
521 return ProcessError(tree, ar->pinfo, tvb, bit_offset, 999, &ei_csn1_not_implemented, pDescr);
524 remaining_bits_len -= no_of_bits;
525 bit_offset += no_of_bits;
527 /* bitmap was successfully extracted or it was empty */
529 pDescr++;
530 break;
533 case CSN_TYPE:
535 int16_t Status;
536 csnStream_t arT = *ar;
537 proto_item *ti;
538 proto_tree *test_tree;
539 if (pDescr->may_be_null && remaining_bits_len == 0)
541 proto_tree_add_none_format(tree, hf_null_data, tvb, 0, 0, "[NULL data]: %s Not Present", pDescr->sz);
542 } else {
543 test_tree = proto_tree_add_subtree_format(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, "%s", pDescr->sz);
544 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
545 increment_dissection_depth(ar->pinfo);
546 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
547 decrement_dissection_depth(ar->pinfo);
548 if (Status >= 0)
550 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
551 remaining_bits_len = arT.remaining_bits_len;
552 bit_offset = arT.bit_offset;
554 else
556 /* Has already been processed: ProcessError("csnStreamDissector", Status, pDescr); */
557 return Status;
560 pDescr++;
561 break;
564 case CSN_CHOICE:
566 int16_t count = pDescr->i;
567 uint8_t i = 0;
568 const CSN_ChoiceElement_t* pChoice = (const CSN_ChoiceElement_t*) pDescr->descr.ptr;
570 /* Make sure that the list of choice items is not empty */
571 if (!count)
572 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_IN_SCRIPT, &ei_csn1_script_error, pDescr);
574 while (count > 0)
576 uint8_t no_of_bits = pChoice->bits;
577 uint8_t value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
579 if (value == pChoice->value)
581 CSN_DESCR descr[2];
582 int16_t Status;
583 csnStream_t arT = *ar;
584 proto_item *ti = NULL;
585 proto_tree *test_tree;
587 descr[0] = pChoice->descr;
588 memset(&descr[1], 0x00, sizeof(CSN_DESCR));
589 descr[1].type = CSN_END;
590 pui8 = pui8DATA(data, pDescr->offset);
591 *pui8 = i;
593 if (pDescr->sz)
595 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
598 if (!pChoice->keep_bits)
600 bit_offset += no_of_bits;
601 remaining_bits_len -= no_of_bits;
604 if (pDescr->sz)
606 test_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, pDescr->sz);
607 } else {
608 test_tree = tree;
611 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
612 increment_dissection_depth(ar->pinfo);
613 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)descr, tvb, data, ett_csn1);
614 decrement_dissection_depth(ar->pinfo);
616 if (Status >= 0)
618 if (ti)
619 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
620 remaining_bits_len = arT.remaining_bits_len;
621 bit_offset = arT.bit_offset;
623 else
625 return Status;
627 break;
630 count--;
631 pChoice++;
632 i++;
635 /* Neither of the choice items matched => unknown value */
636 if (!count) {
637 return ProcessError(tree, ar->pinfo, tvb, bit_offset,
638 CSN_ERROR_STREAM_NOT_SUPPORTED,
639 &ei_csn1_stream_not_supported, pDescr);
642 pDescr++;
643 break;
646 case CSN_SERIALIZE:
648 StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn;
649 csnStream_t arT = *ar;
650 unsigned length_len = pDescr->i;
651 int16_t Status = -1;
652 proto_item *ti;
653 proto_tree *test_tree;
654 uint8_t length = 0;
656 if (length_len)
658 length = tvb_get_bits8(tvb, bit_offset, length_len);
660 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, length_len, ENC_BIG_ENDIAN);
662 bit_offset += length_len;
663 remaining_bits_len -= length_len;
665 test_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, ((bit_offset+length-1)>>3)-(bit_offset>>3) + 1, ett_csn1, &ti, pDescr->sz);
666 } else {
667 test_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, pDescr->sz);
670 csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len, ar->pinfo);
671 Status = serialize(test_tree, &arT, tvb, pvDATA(data, pDescr->offset), ett_csn1);
673 if (Status >= 0)
675 if (length > 0) {
676 remaining_bits_len -= length;
677 bit_offset += length;
678 } else {
679 proto_item_set_len(ti,((arT.bit_offset - bit_offset)>>3)+1);
680 remaining_bits_len = arT.remaining_bits_len;
681 bit_offset = arT.bit_offset;
683 pDescr++;
685 else
687 /* Has already been processed: */
688 return Status;
691 break;
694 case CSN_UNION_LH:
695 case CSN_UNION:
697 int16_t Bits;
698 uint8_t t_index;
699 int16_t count = pDescr->i;
700 const CSN_DESCR* pDescrNext = pDescr;
702 pDescrNext += count + 1; /* now this is next after the union */
703 if ((count <= 0) || (count > 16))
705 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_INVALID_UNION_INDEX, &ei_csn1_union_index, pDescr);
708 /* Now get the bits to extract the index */
709 Bits = ixBitsTab[count];
710 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, Bits, tvb_get_bits8(tvb, bit_offset, Bits), ENC_BIG_ENDIAN, " (Union)");
711 t_index = 0;
713 while (Bits > 0)
715 t_index <<= 1;
717 if (CSN_UNION_LH == pDescr->type)
719 t_index |= tvb_get_masked_bits8(tvb, bit_offset, 1);
721 else
723 t_index |= tvb_get_bits8(tvb, bit_offset, 1);
726 remaining_bits_len--;
727 bit_offset++;
728 Bits--;
731 /* Assign UnionType */
732 pui8 = pui8DATA(data, pDescr->offset);
733 *pui8 = t_index;
735 /* script index to continue on, limited in case we do not have a power of 2 */
736 pDescr += (MIN(t_index + 1, count));
738 switch (pDescr->type)
739 { /* get the right element of the union based on computed index */
741 case CSN_BIT:
743 pui8 = pui8DATA(data, pDescr->offset);
745 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
747 *pui8 = 0x00;
748 if (tvb_get_bits8(tvb, bit_offset, 1) > 0)
750 *pui8 = 0x01;
752 remaining_bits_len --;
753 bit_offset++;
754 pDescr++;
755 break;
758 case CSN_NULL:
759 { /* Empty member! */
760 bit_offset += pDescr->i;
761 pDescr++;
762 break;
765 case CSN_UINT:
767 uint8_t no_of_bits = (uint8_t) pDescr->i;
768 if (remaining_bits_len >= no_of_bits)
770 if (no_of_bits <= 8)
772 uint8_t ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
773 pui8 = pui8DATA(data, pDescr->offset);
774 *pui8 = ui8;
775 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
778 else if (no_of_bits <= 16)
780 uint16_t ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
781 pui16 = pui16DATA(data, pDescr->offset);
782 memcpy(pui16, &ui16, 2);
783 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
785 else if (no_of_bits <= 32)
787 uint32_t ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
788 pui32 = pui32DATA(data, pDescr->offset);
789 memcpy(pui32, &ui32, 4);
790 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
793 else
795 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
798 else
800 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
803 remaining_bits_len -= no_of_bits;
804 bit_offset += no_of_bits;
805 pDescr++;
806 break;
809 case CSN_UINT_OFFSET:
811 uint8_t no_of_bits = (uint8_t) pDescr->i;
813 if (remaining_bits_len >= no_of_bits)
815 if (no_of_bits <= 8)
817 uint8_t ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
818 pui8 = pui8DATA(data, pDescr->offset);
819 *pui8 = ui8 + (uint8_t)pDescr->descr.value;
820 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ui8, ENC_BIG_ENDIAN, "%d", ui8);
822 else if (no_of_bits <= 16)
824 uint16_t ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN) + (uint16_t)pDescr->descr.value;
825 pui16 = pui16DATA(data, pDescr->offset);
826 memcpy(pui16, &ui16, 2);
827 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ui16, ENC_BIG_ENDIAN, "%d", ui16);
829 else if (no_of_bits <= 32)
831 uint32_t ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN) + (uint16_t)pDescr->descr.value;
832 pui32 = pui32DATA(data, pDescr->offset);
833 memcpy(pui32, &ui32, 4);
834 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ui32, ENC_BIG_ENDIAN, "%d", ui32);
836 else
838 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
841 else
843 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
846 remaining_bits_len -= no_of_bits;
847 bit_offset += no_of_bits;
848 pDescr++;
849 break;
852 case CSN_UINT_LH:
854 uint8_t no_of_bits = (uint8_t) pDescr->i;
856 if (remaining_bits_len >= no_of_bits)
858 if (no_of_bits <= 8)
860 uint8_t ui8 = tvb_get_masked_bits8(tvb, bit_offset, no_of_bits);
861 pui8 = pui8DATA(data, pDescr->offset);
862 *pui8 = ui8;
863 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
865 else
866 { /* Maybe we should support more than 8 bits ? */
867 ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
870 else
872 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
875 remaining_bits_len -= no_of_bits;
876 bit_offset += no_of_bits;
877 pDescr++;
878 break;
881 case CSN_UINT_ARRAY:
883 uint8_t no_of_bits = (uint8_t) pDescr->i;
884 uint16_t nCount = (uint16_t)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
885 int i = 0;
887 if (pDescr->value != 0)
888 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
889 memcpy(&nCount, pui16DATA(data, nCount), 2);
892 if (remaining_bits_len >= (no_of_bits * nCount))
894 remaining_bits_len -= (no_of_bits * nCount);
895 if (no_of_bits <= 8)
897 pui8 = pui8DATA(data, pDescr->offset);
899 while (nCount > 0)
901 *pui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
902 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, *pui8, ENC_BIG_ENDIAN, " (Count %d)", i++);
903 pui8++;
904 bit_offset += no_of_bits;
905 nCount--;
908 else if (no_of_bits <= 16)
910 pui16 = pui16DATA(data, pDescr->offset);
912 while (nCount > 0)
914 uint16_t ui16;
915 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
916 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ui16, ENC_BIG_ENDIAN, " (Count %d)", i++);
917 memcpy(pui16++, &ui16, sizeof(ui16));
918 bit_offset += no_of_bits;
919 nCount--;
922 else if (no_of_bits <= 32)
923 { /* not supported */
924 return ProcessError(tree, ar->pinfo, tvb, bit_offset, 999, &ei_csn1_not_implemented, pDescr);
926 else
928 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_GENERAL, &ei_csn1_general, pDescr);
931 else
933 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
936 pDescr++;
937 break;
940 case CSN_VARIABLE_TARRAY_OFFSET:
941 case CSN_VARIABLE_TARRAY:
942 case CSN_TYPE_ARRAY:
944 int16_t Status;
945 csnStream_t arT = *ar;
946 uint16_t nCount = (uint16_t) pDescr->i;
947 uint16_t nSize = (uint16_t)(uint32_t)pDescr->value;
948 int i = 0;
950 pui8 = pui8DATA(data, pDescr->offset);
952 if (CSN_VARIABLE_TARRAY == pDescr->type)
953 { /* Count specified in field */
954 nCount = *pui8DATA(data, pDescr->i);
956 else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type)
957 { /* Count specified in field */
958 nCount = *pui8DATA(data, pDescr->i);
959 nCount--; /* Offset 1 */
962 while (nCount--) /* Changed to handle length = 0. */
964 proto_item *ti;
965 proto_tree *test_tree;
967 test_tree = proto_tree_add_subtree_format(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, "%s[%d]",pDescr->sz, i++);
969 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
970 increment_dissection_depth(ar->pinfo);
971 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pui8, ett_csn1);
972 decrement_dissection_depth(ar->pinfo);
973 if (Status >= 0)
975 pui8 += nSize;
976 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
977 remaining_bits_len = arT.remaining_bits_len;
978 bit_offset = arT.bit_offset;
980 else
982 return Status;
986 pDescr++;
987 break;
990 case CSN_BITMAP:
991 { /* bitmap with given length. The result is left aligned! */
992 uint8_t no_of_bits = (uint8_t) pDescr->i; /* length of bitmap */
994 if (no_of_bits > 0)
995 { /* a non empty bitmap */
996 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
997 remaining_bits_len -= no_of_bits;
998 bit_offset += no_of_bits;
1000 if (remaining_bits_len < 0)
1002 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1006 /* bitmap was successfully extracted or it was empty */
1008 pDescr++;
1009 break;
1012 case CSN_TYPE:
1014 int16_t Status;
1015 csnStream_t arT = *ar;
1016 proto_item *ti;
1017 proto_tree *test_tree;
1019 if (pDescr->may_be_null && remaining_bits_len == 0)
1021 proto_tree_add_none_format(tree, hf_null_data, tvb, 0, 0, "[NULL data]: %s Not Present", pDescr->sz);
1022 } else {
1023 test_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, pDescr->sz);
1024 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
1025 increment_dissection_depth(ar->pinfo);
1026 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
1027 decrement_dissection_depth(ar->pinfo);
1028 if (Status >= 0)
1030 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
1031 remaining_bits_len = arT.remaining_bits_len;
1032 bit_offset = arT.bit_offset;
1034 else
1035 { /* return error code Has already been processed: */
1036 return Status;
1039 pDescr++;
1040 break;
1043 default:
1044 { /* descriptions of union elements other than above are illegal */
1045 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_IN_SCRIPT, &ei_csn1_script_error, pDescr);
1049 pDescr = pDescrNext;
1050 break;
1053 case CSN_EXIST:
1054 case CSN_EXIST_LH:
1056 uint8_t fExist;
1058 pui8 = pui8DATA(data, pDescr->offset);
1060 if (CSN_EXIST_LH == pDescr->type)
1062 fExist = tvb_get_masked_bits8(tvb, bit_offset, 1);
1063 proto_tree_add_uint(tree, *(pDescr->hf_ptr), tvb, bit_offset>>3, 1, fExist);
1065 else
1067 fExist = tvb_get_bits8(tvb, bit_offset, 1);
1068 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1071 *pui8 = fExist;
1072 remaining_bits_len --;
1073 bit_offset++;
1074 pDescr++;
1076 if (!fExist)
1078 ar->remaining_bits_len = remaining_bits_len;
1079 ar->bit_offset = bit_offset;
1080 return remaining_bits_len;
1083 break;
1086 case CSN_NEXT_EXIST:
1088 uint8_t isnull;
1090 pui8 = pui8DATA(data, pDescr->offset);
1092 /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
1093 if ((pDescr->may_be_null) && (remaining_bits_len == 0))
1094 { /* no more bits to decode is fine here - end of message detected and allowed */
1096 /* Skip i entries + this entry */
1097 pDescr += pDescr->i + 1;
1099 /* Set the data member to "not exist" */
1100 *pui8 = 0;
1101 break;
1104 /* the "regular" M_NEXT_EXIST description element */
1105 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1107 isnull = 1;
1108 if (tvb_get_bits8(tvb, bit_offset, 1))
1110 if (remaining_bits_len == 1)
1112 /* If { 1 < end > } and all next items may be null, store it as { 0 } */
1113 const CSN_DESCR* pDescrNext = pDescr + 1;
1114 uint8_t i;
1115 for (i = 0; i < pDescr->i; i++, pDescrNext++)
1117 if (!pDescrNext->may_be_null)
1118 isnull = 0;
1120 } else {
1121 isnull = 0;
1125 *pui8 = isnull ? 0 : 1;
1127 remaining_bits_len --;
1128 bit_offset++;
1130 if (isnull)
1131 { /* Skip 'i' entries */
1132 pDescr += pDescr->i;
1135 pDescr++;
1136 break;
1139 case CSN_NEXT_EXIST_LH:
1141 uint8_t isnull;
1142 pui8 = pui8DATA(data, pDescr->offset);
1144 /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */
1145 if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
1146 { /* no more bits to decode is fine here - end of message detected and allowed */
1148 /* skip 'i' entries + this entry */
1149 pDescr += pDescr->i + 1;
1151 /* set the data member to "not exist" */
1152 *pui8 = 0;
1153 break;
1156 /* the "regular" M_NEXT_EXIST_LH description element */
1157 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1159 isnull = 1;
1160 if (tvb_get_masked_bits8(tvb, bit_offset, 1))
1162 if (remaining_bits_len == 1) {
1163 /* If { 1 < end > } and all next items may be null, store it as { 0 } */
1164 const CSN_DESCR* pDescrNext = pDescr + 1;
1165 uint8_t i;
1166 for (i = 0; i < pDescr->i; i++, pDescrNext++)
1168 if (!pDescrNext->may_be_null)
1169 isnull = 0;
1171 } else {
1172 isnull = 0;
1176 *pui8++ = isnull ? 0 : 1;
1178 remaining_bits_len --;
1179 bit_offset++;
1181 if (isnull)
1182 { /* Skip 'i' entries */
1183 pDescr += pDescr->i;
1185 pDescr++;
1187 break;
1190 case CSN_VARIABLE_BITMAP_1:
1191 { /* Bitmap from here and to the end of message */
1193 *pui8DATA(data, (int16_t)pDescr->descr.value) = (uint8_t) remaining_bits_len; /* length of bitmap == remaining bits */
1195 /*no break -
1196 * with a length set we have a regular variable length bitmap so we continue */
1198 /* FALL THROUGH */
1199 case CSN_VARIABLE_BITMAP:
1200 { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1201 * <N: bit (5)> <bitmap: bit(N + offset)>
1202 * Bit array with length (in bits) specified in parameter (pDescr->descr)
1203 * The result is right aligned!
1205 int16_t no_of_bits = *pui8DATA(data, (int16_t)pDescr->descr.value);
1207 no_of_bits += pDescr->i; /* adjusted by offset */
1209 while (no_of_bits > 0)
1211 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1212 bit_offset++;
1213 no_of_bits--;
1214 remaining_bits_len--;
1216 if (remaining_bits_len < 0)
1218 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1221 pDescr++;
1222 break;
1225 case CSN_LEFT_ALIGNED_VAR_BMP_1:
1226 { /* Bitmap from here and to the end of message */
1228 *pui8DATA(data, (int16_t)pDescr->descr.value) = (uint8_t) remaining_bits_len; /* length of bitmap == remaining bits */
1230 /* no break -
1231 * with a length set we have a regular left aligned variable length bitmap so we continue
1234 /* FALL THROUGH */
1235 case CSN_LEFT_ALIGNED_VAR_BMP:
1236 { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1237 * <N: bit (5)> <bitmap: bit(N + offset)>
1238 * bit array with length (in bits) specified in parameter (pDescr->descr)
1240 int16_t no_of_bits = *pui8DATA(data, (int16_t)pDescr->descr.value);/* Size of bitmap */
1242 no_of_bits += pDescr->i;/* size adjusted by offset */
1244 if (no_of_bits > 0)
1246 if (no_of_bits <= 32)
1248 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1250 else if (no_of_bits <= 64)
1252 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1254 else
1256 proto_tree_add_uint64_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, no_of_bits, "%u bits",
1257 no_of_bits);
1259 bit_offset += no_of_bits;
1260 remaining_bits_len -= no_of_bits;
1262 if (remaining_bits_len < 0)
1264 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1268 /* bitmap was successfully extracted or it was empty */
1269 pDescr++;
1270 break;
1274 case CSN_PADDING_BITS:
1275 { /* Padding from here and to the end of message */
1277 if (remaining_bits_len > 0)
1279 proto_tree *padding_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, -1, ett_csn1, NULL, "Padding Bits");
1280 while (remaining_bits_len > 0)
1282 int bits_to_handle = remaining_bits_len + (bit_offset%8);
1283 if (bits_to_handle > 32)
1285 bits_to_handle = 32 - (bit_offset%8);
1287 else
1289 bits_to_handle -= (bit_offset%8);
1291 proto_tree_add_bits_item(padding_tree, *(pDescr->hf_ptr), tvb, bit_offset, bits_to_handle, ENC_BIG_ENDIAN);
1292 bit_offset += bits_to_handle;
1293 remaining_bits_len -= bits_to_handle;
1296 if (remaining_bits_len < 0)
1298 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1301 /* Padding was successfully extracted or it was empty */
1302 pDescr++;
1303 break;
1306 case CSN_VARIABLE_ARRAY:
1307 { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
1308 * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1309 * Array with length specified in parameter:
1310 * <count: bit (x)>
1311 * <list: octet(count + offset)>
1313 int16_t count = *pui8DATA(data, (int16_t)pDescr->descr.value);
1315 count += pDescr->i; /* Adjusted by offset */
1317 if (count > 0)
1319 pui8 = pui8DATA(data, pDescr->offset);
1321 while (count > 0)
1323 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 8, ENC_BIG_ENDIAN);
1324 *pui8++ = tvb_get_bits8(tvb, bit_offset, 8);
1325 bit_offset += 8;
1326 count--;
1327 remaining_bits_len -= 8;
1328 if (remaining_bits_len < 0)
1330 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1335 pDescr++;
1336 break;
1339 case CSN_RECURSIVE_ARRAY:
1340 { /* Recursive way to specify an array: <list> ::= {1 <number: bit (4)> <list> | 0}
1341 * or more generally: <list> ::= { <tag> <element> <list> | <EndTag> }
1342 * where <element> ::= bit(value)
1343 * <tag> ::= 0 | 1
1344 * <EndTag> ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa
1345 * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1346 * REMARK: recursive way to specify an array but an iterative implementation!
1348 int16_t no_of_bits = pDescr->i;
1349 uint8_t ElementCount = 0;
1351 pui8 = pui8DATA(data, pDescr->offset);
1353 while (existNextElement(tvb, bit_offset, Tag))
1354 { /* tag control shows existence of next list elements */
1355 proto_tree_add_bits_item(tree, *(pDescr->hf_exist_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1356 bit_offset++;
1357 remaining_bits_len--;
1359 /* extract and store no_of_bits long element from bitstream */
1360 *pui8++ = tvb_get_bits8(tvb, bit_offset, no_of_bits);
1361 ElementCount++;
1363 if (remaining_bits_len < 0)
1365 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1368 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1369 bit_offset += no_of_bits;
1370 remaining_bits_len -= no_of_bits;
1373 proto_tree_add_bits_item(tree, *(pDescr->hf_exist_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1375 /* existNextElement() returned false, 1 bit consumed */
1376 bit_offset++;
1377 remaining_bits_len--;
1379 /* Store the counted number of elements of the array */
1380 *pui8DATA(data, (int16_t)pDescr->descr.value) = ElementCount;
1382 pDescr++;
1383 break;
1386 case CSN_RECURSIVE_TARRAY:
1387 { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
1388 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
1389 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), NULL, NULL, (void_fn_t)array_length(((_STRUCT*)0)->_MEMBER)}
1391 int16_t nSizeElement = (int16_t)(int32_t)pDescr->value;
1392 uint32_t nSizeArray = (uint32_t)((uintptr_t)pDescr->aux_fn);
1393 uint8_t ElementCount = 0;
1395 while (existNextElement(tvb, bit_offset, Tag))
1396 { /* tag control shows existence of next list elements */
1397 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, ENC_BIG_ENDIAN);
1399 /* existNextElement() returned true, 1 bit consumed */
1400 bit_offset++;
1401 remaining_bits_len--;
1402 ElementCount++;
1404 if (ElementCount > nSizeArray)
1406 /* error: too many elements in recursive array. Increase its size! */
1407 return ProcessError(tree , ar->pinfo, tvb, bit_offset, CSN_ERROR_STREAM_NOT_SUPPORTED, &ei_csn1_stream_not_supported, pDescr);
1410 { /* unpack the following data structure */
1411 csnStream_t arT = *ar;
1412 int16_t Status;
1413 proto_item *ti;
1414 proto_tree *test_tree;
1416 test_tree = proto_tree_add_subtree(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, pDescr->sz);
1418 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
1419 increment_dissection_depth(ar->pinfo);
1420 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
1421 decrement_dissection_depth(ar->pinfo);
1423 if (Status >= 0)
1424 { /* successful completion */
1425 pui8 += nSizeElement; /* -> to next data element */
1426 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
1427 remaining_bits_len = arT.remaining_bits_len;
1428 bit_offset = arT.bit_offset;
1430 else
1431 { /* something went awry */
1432 return Status;
1436 if (remaining_bits_len < 0)
1438 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1442 /* existNextElement() returned false, 1 bit consumed */
1443 bit_offset++;
1444 remaining_bits_len --;
1446 /* Store the counted number of elements of the array */
1447 *pui8DATA(data, (int16_t)(int32_t)pDescr->i) = ElementCount;
1449 pDescr++;
1450 break;
1453 case CSN_RECURSIVE_TARRAY_2:
1454 { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
1456 Tag = REVERSED_TAG;
1458 /* NO break -
1459 * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
1462 /* FALL THROUGH */
1463 case CSN_RECURSIVE_TARRAY_1:
1464 { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
1465 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
1466 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), NULL, NULL, (void_fn_t)array_length(((_STRUCT*)0)->_MEMBER)}
1468 int16_t nSizeElement = (int16_t)(int32_t)pDescr->value;
1469 uint32_t nSizeArray = (uint32_t)((uintptr_t)pDescr->aux_fn);
1470 uint8_t ElementCount = 0;
1471 csnStream_t arT = *ar;
1472 bool EndOfList = false;
1473 int16_t Status;
1474 proto_item *ti;
1475 proto_tree *test_tree;
1478 { /* get data element */
1479 ElementCount++;
1481 if (ElementCount >= nSizeArray)
1483 /* error: too many elements in recursive array. Increase its size! */
1484 return ProcessError(tree , ar->pinfo, tvb, bit_offset, CSN_ERROR_STREAM_NOT_SUPPORTED, &ei_csn1_stream_not_supported, pDescr);
1487 test_tree = proto_tree_add_subtree_format(tree, tvb, bit_offset>>3, 1, ett_csn1, &ti, "%s[%d]", pDescr->sz, ElementCount-1);
1489 csnStreamInit(&arT, bit_offset, remaining_bits_len, ar->pinfo);
1490 increment_dissection_depth(ar->pinfo);
1491 Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
1492 decrement_dissection_depth(ar->pinfo);
1494 if (Status >= 0)
1495 { /* successful completion */
1496 pui8 += nSizeElement; /* -> to next */
1497 proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
1498 remaining_bits_len = arT.remaining_bits_len;
1499 bit_offset = arT.bit_offset;
1501 else
1502 { /* something went awry */
1503 return Status;
1506 if (remaining_bits_len < 0)
1508 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1511 /* control of next element's tag */
1512 proto_tree_add_uint_bits_format_value(tree, *(pDescr->hf_ptr), tvb, bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1), ENC_BIG_ENDIAN, "%s[%d]",
1513 proto_registrar_get_name(*(pDescr->hf_ptr)), ElementCount);
1514 EndOfList = !(existNextElement(tvb, bit_offset, Tag));
1516 bit_offset++;
1517 remaining_bits_len--; /* 1 bit consumed (tag) */
1518 } while (!EndOfList);
1521 /* Store the count of the array */
1522 *pui8DATA(data, pDescr->i) = ElementCount;
1523 Tag = STANDARD_TAG; /* in case it was set to "reversed" */
1524 pDescr++;
1525 break;
1528 case CSN_FIXED:
1529 { /* Verify the fixed bits */
1530 uint8_t no_of_bits = (uint8_t) pDescr->i;
1531 uint32_t ui32;
1533 if (no_of_bits <= 8)
1535 ui32 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
1537 else if (no_of_bits <= 16)
1539 ui32 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1541 else if (no_of_bits <= 32)
1543 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1545 else
1547 return ProcessError(tree, ar->pinfo, tvb, bit_offset, -1, &ei_csn1_more32bits, pDescr);
1549 if (ui32 != (unsigned)(int32_t)pDescr->offset)
1551 return ProcessError(tree, ar->pinfo, tvb, bit_offset, -1, &ei_csn1_fixed_not_matched, pDescr);
1553 proto_tree_add_bits_item(tree, *(pDescr->hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
1555 remaining_bits_len -= no_of_bits;
1556 bit_offset += no_of_bits;
1557 pDescr++;
1558 break;
1561 case CSN_CALLBACK:
1563 uint16_t no_of_bits;
1564 DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn;
1566 no_of_bits = callback(tree, tvb, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset), bit_offset, ett_csn1, ar->pinfo);
1567 bit_offset += no_of_bits;
1568 remaining_bits_len -= no_of_bits;
1570 pDescr++;
1571 break;
1574 case CSN_TRAP_ERROR:
1576 return ProcessError(tree, ar->pinfo, tvb, bit_offset, -1, pDescr->error, pDescr);
1579 case CSN_END:
1581 ar->remaining_bits_len = remaining_bits_len;
1582 ar->bit_offset = bit_offset;
1583 return remaining_bits_len;
1586 default:
1588 DISSECTOR_ASSERT(0);
1593 } while (remaining_bits_len >= 0);
1595 return ProcessError(tree, ar->pinfo, tvb, bit_offset, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, &ei_csn1_more_bits_to_unpack, pDescr);
1598 void
1599 proto_register_csn1(void)
1601 static hf_register_info hf[] = {
1602 { &hf_null_data,
1603 { "NULL data", "csn1.null_data",
1604 FT_NONE, BASE_NONE, NULL, 0x00,
1605 NULL, HFILL }
1609 static ei_register_info ei[] = {
1610 { &ei_csn1_more_bits_to_unpack, { "csn1.more_bits_to_unpack", PI_MALFORMED, PI_ERROR, "NEED_MORE BITS TO UNPACK", EXPFILL }},
1611 { &ei_csn1_general, { "csn1.general_error", PI_PROTOCOL, PI_WARN, "General -1", EXPFILL }},
1612 { &ei_csn1_not_implemented, { "csn1.not_implemented", PI_UNDECODED, PI_WARN, "NOT IMPLEMENTED", EXPFILL }},
1613 { &ei_csn1_union_index, { "csn1.union_index_invalid", PI_PROTOCOL, PI_WARN, "INVALID UNION INDEX", EXPFILL }},
1614 { &ei_csn1_script_error, { "csn1.script_error", PI_MALFORMED, PI_ERROR, "ERROR IN SCRIPT", EXPFILL }},
1615 { &ei_csn1_more32bits, { "csn1.more32bits", PI_PROTOCOL, PI_WARN, "no_of_bits > 32", EXPFILL }},
1616 { &ei_csn1_fixed_not_matched, { "csn1.fixed_not_matched", PI_PROTOCOL, PI_WARN, "FIXED value does not match", EXPFILL }},
1617 { &ei_csn1_stream_not_supported, { "csn1.stream_not_supported", PI_PROTOCOL, PI_WARN, "STREAM NOT SUPPORTED", EXPFILL }},
1620 expert_module_t* expert_csn1;
1622 proto_csn1 = proto_register_protocol("CSN.1", "CSN1", "csn1");
1624 proto_register_field_array(proto_csn1, hf, array_length(hf));
1625 expert_csn1 = expert_register_protocol(proto_csn1);
1626 expert_register_field_array(expert_csn1, ei, array_length(ei));
1628 proto_set_cant_toggle(proto_csn1);
1632 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1634 * Local Variables:
1635 * c-basic-offset: 2
1636 * tab-width: 8
1637 * indent-tabs-mode: nil
1638 * End:
1640 * ex: set shiftwidth=2 tabstop=8 expandtab:
1641 * :indentSize=2:tabSize=8:noTabs=true: