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
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 */
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 */
54 int bit_shift
= 8 - relative_bit_offset
- (int) no_of_bits
;
58 result
= (0x2B ^ tvb_get_uint8(tvb
, byte_offset
)) >> bit_shift
;
59 result
&= maskBits
[no_of_bits
];
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
);
72 * ================================================================================================
73 * set initial/start values in help data structure used for packing/unpacking operation
74 * ================================================================================================
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
;
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
:"-");
94 static const char* CSN_DESCR_type
[]=
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",
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 * ================================================================================================
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
)
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
;
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
)
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
);
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
)));
192 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK
, &ei_csn1_more_bits_to_unpack
, pDescr
);
196 remaining_bits_len
--;
202 { /* Empty member! */
203 bit_offset
+= pDescr
->i
;
210 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
212 if (remaining_bits_len
>= no_of_bits
)
216 uint8_t ui8
= tvb_get_bits8(tvb
, bit_offset
, no_of_bits
);
217 pui8
= pui8DATA(data
, pDescr
->offset
);
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
);
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
)
246 pui8
= pui8DATA(data
, pDescr
->offset
);
249 else if (no_of_bits
<= 16)
251 pui16
= pui16DATA(data
, pDescr
->offset
);
254 else if (no_of_bits
<= 32)
256 pui32
= pui32DATA(data
, pDescr
->offset
);
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
)));
263 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK
, &ei_csn1_more_bits_to_unpack
, pDescr
);
270 case CSN_UINT_OFFSET
:
272 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
274 if (remaining_bits_len
>= no_of_bits
)
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
);
308 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
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
;
324 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
326 if (remaining_bits_len
>= no_of_bits
)
330 uint8_t ui8
= tvb_get_masked_bits8(tvb
, bit_offset
, no_of_bits
);
331 pui8
= pui8DATA(data
, pDescr
->offset
);
333 proto_tree_add_bits_item(tree
, *(pDescr
->hf_ptr
), tvb
, bit_offset
, no_of_bits
, ENC_BIG_ENDIAN
);
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
);
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
;
354 uint8_t no_of_value_bits
= (uint8_t) pDescr
->i
;
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);
377 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
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
;
396 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK
, &ei_csn1_more_bits_to_unpack
, pDescr
);
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(...) */
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
);
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
);
437 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
442 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK
, &ei_csn1_more_bits_to_unpack
, pDescr
);
448 case CSN_VARIABLE_TARRAY_OFFSET
:
449 case CSN_VARIABLE_TARRAY
:
453 csnStream_t arT
= *ar
;
454 int16_t nCount
= pDescr
->i
;
455 uint16_t nSize
= (uint16_t)(int32_t)pDescr
->value
;
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 */
470 { /* resulting array of length 0 is possible
471 * but no bits shall be read from bitstream
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
);
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
;
501 { /* bitmap with given length. The result is left aligned! */
502 uint8_t no_of_bits
= (uint8_t) pDescr
->i
; /* length of bitmap */
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
);
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 */
536 csnStream_t arT
= *ar
;
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
);
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
);
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
;
556 /* Has already been processed: ProcessError("csnStreamDissector", Status, pDescr); */
566 int16_t count
= pDescr
->i
;
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 */
572 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_IN_SCRIPT
, &ei_csn1_script_error
, pDescr
);
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
)
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
);
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
;
606 test_tree
= proto_tree_add_subtree(tree
, tvb
, bit_offset
>>3, 1, ett_csn1
, &ti
, pDescr
->sz
);
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
);
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
;
635 /* Neither of the choice items matched => unknown value */
637 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
,
638 CSN_ERROR_STREAM_NOT_SUPPORTED
,
639 &ei_csn1_stream_not_supported
, pDescr
);
648 StreamSerializeFcn_t serialize
= (StreamSerializeFcn_t
)pDescr
->aux_fn
;
649 csnStream_t arT
= *ar
;
650 unsigned length_len
= pDescr
->i
;
653 proto_tree
*test_tree
;
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
);
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
);
676 remaining_bits_len
-= length
;
677 bit_offset
+= length
;
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
;
687 /* Has already been processed: */
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)");
717 if (CSN_UNION_LH
== pDescr
->type
)
719 t_index
|= tvb_get_masked_bits8(tvb
, bit_offset
, 1);
723 t_index
|= tvb_get_bits8(tvb
, bit_offset
, 1);
726 remaining_bits_len
--;
731 /* Assign UnionType */
732 pui8
= pui8DATA(data
, pDescr
->offset
);
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 */
743 pui8
= pui8DATA(data
, pDescr
->offset
);
745 proto_tree_add_bits_item(tree
, *(pDescr
->hf_ptr
), tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
748 if (tvb_get_bits8(tvb
, bit_offset
, 1) > 0)
752 remaining_bits_len
--;
759 { /* Empty member! */
760 bit_offset
+= pDescr
->i
;
767 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
768 if (remaining_bits_len
>= no_of_bits
)
772 uint8_t ui8
= tvb_get_bits8(tvb
, bit_offset
, no_of_bits
);
773 pui8
= pui8DATA(data
, pDescr
->offset
);
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
);
795 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
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
;
809 case CSN_UINT_OFFSET
:
811 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
813 if (remaining_bits_len
>= no_of_bits
)
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
);
838 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
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
;
854 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
856 if (remaining_bits_len
>= no_of_bits
)
860 uint8_t ui8
= tvb_get_masked_bits8(tvb
, bit_offset
, no_of_bits
);
861 pui8
= pui8DATA(data
, pDescr
->offset
);
863 proto_tree_add_bits_item(tree
, *(pDescr
->hf_ptr
), tvb
, bit_offset
, no_of_bits
, ENC_BIG_ENDIAN
);
866 { /* Maybe we should support more than 8 bits ? */
867 ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
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
;
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(...) */
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
);
897 pui8
= pui8DATA(data
, pDescr
->offset
);
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
++);
904 bit_offset
+= no_of_bits
;
908 else if (no_of_bits
<= 16)
910 pui16
= pui16DATA(data
, pDescr
->offset
);
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
;
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
);
928 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_GENERAL
, &ei_csn1_general
, pDescr
);
933 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK
, &ei_csn1_more_bits_to_unpack
, pDescr
);
940 case CSN_VARIABLE_TARRAY_OFFSET
:
941 case CSN_VARIABLE_TARRAY
:
945 csnStream_t arT
= *ar
;
946 uint16_t nCount
= (uint16_t) pDescr
->i
;
947 uint16_t nSize
= (uint16_t)(uint32_t)pDescr
->value
;
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. */
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
);
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
;
991 { /* bitmap with given length. The result is left aligned! */
992 uint8_t no_of_bits
= (uint8_t) pDescr
->i
; /* length of bitmap */
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 */
1015 csnStream_t arT
= *ar
;
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
);
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
);
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
;
1035 { /* return error code Has already been processed: */
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
;
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
);
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
);
1072 remaining_bits_len
--;
1078 ar
->remaining_bits_len
= remaining_bits_len
;
1079 ar
->bit_offset
= bit_offset
;
1080 return remaining_bits_len
;
1086 case CSN_NEXT_EXIST
:
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" */
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
);
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;
1115 for (i
= 0; i
< pDescr
->i
; i
++, pDescrNext
++)
1117 if (!pDescrNext
->may_be_null
)
1125 *pui8
= isnull
? 0 : 1;
1127 remaining_bits_len
--;
1131 { /* Skip 'i' entries */
1132 pDescr
+= pDescr
->i
;
1139 case CSN_NEXT_EXIST_LH
:
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" */
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
);
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;
1166 for (i
= 0; i
< pDescr
->i
; i
++, pDescrNext
++)
1168 if (!pDescrNext
->may_be_null
)
1176 *pui8
++ = isnull
? 0 : 1;
1178 remaining_bits_len
--;
1182 { /* Skip 'i' entries */
1183 pDescr
+= pDescr
->i
;
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 */
1196 * with a length set we have a regular variable length bitmap so we continue */
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
);
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
);
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 */
1231 * with a length set we have a regular left aligned variable length bitmap so we continue
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 */
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
);
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",
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 */
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);
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 */
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:
1311 * <list: octet(count + offset)>
1313 int16_t count
= *pui8DATA(data
, (int16_t)pDescr
->descr
.value
);
1315 count
+= pDescr
->i
; /* Adjusted by offset */
1319 pui8
= pui8DATA(data
, pDescr
->offset
);
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);
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
);
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)
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
);
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
);
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 */
1377 remaining_bits_len
--;
1379 /* Store the counted number of elements of the array */
1380 *pui8DATA(data
, (int16_t)pDescr
->descr
.value
) = ElementCount
;
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 */
1401 remaining_bits_len
--;
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
;
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
);
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
;
1431 { /* something went awry */
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 */
1444 remaining_bits_len
--;
1446 /* Store the counted number of elements of the array */
1447 *pui8DATA(data
, (int16_t)(int32_t)pDescr
->i
) = ElementCount
;
1453 case CSN_RECURSIVE_TARRAY_2
:
1454 { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
1459 * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
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;
1475 proto_tree
*test_tree
;
1478 { /* get data element */
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
);
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
;
1502 { /* something went awry */
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
));
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" */
1529 { /* Verify the fixed bits */
1530 uint8_t no_of_bits
= (uint8_t) pDescr
->i
;
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
);
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
;
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
;
1574 case CSN_TRAP_ERROR
:
1576 return ProcessError(tree
, ar
->pinfo
, tvb
, bit_offset
, -1, pDescr
->error
, pDescr
);
1581 ar
->remaining_bits_len
= remaining_bits_len
;
1582 ar
->bit_offset
= bit_offset
;
1583 return remaining_bits_len
;
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
);
1599 proto_register_csn1(void)
1601 static hf_register_info hf
[] = {
1603 { "NULL data", "csn1.null_data",
1604 FT_NONE
, BASE_NONE
, NULL
, 0x00,
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
1637 * indent-tabs-mode: nil
1640 * ex: set shiftwidth=2 tabstop=8 expandtab:
1641 * :indentSize=2:tabSize=8:noTabs=true: