PageRenderTime 31ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/epan/dissectors/packet-csn1.c

https://github.com/labx-technologies-llc/wireshark
C | 1627 lines | 1283 code | 241 blank | 103 comment | 160 complexity | b0b45500fc342f8cad090d2353b2b637 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  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
  6. *
  7. * $Id$
  8. *
  9. * Wireshark - Network traffic analyzer
  10. * By Gerald Combs <gerald@wireshark.org>
  11. * Copyright 1998 Gerald Combs
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License
  15. * as published by the Free Software Foundation; either version 2
  16. * of the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  26. */
  27. #include "config.h"
  28. #include <glib.h>
  29. #include <epan/packet.h>
  30. #include "packet-csn1.h"
  31. #define pvDATA(_pv, _offset) ((void*) ((unsigned char*)_pv + _offset))
  32. #define pui8DATA(_pv, _offset) ((guint8*) pvDATA(_pv, _offset))
  33. #define pui16DATA(_pv, _offset) ((guint16*) pvDATA(_pv, _offset))
  34. #define pui32DATA(_pv, _offset) ((guint32*) pvDATA(_pv, _offset))
  35. /* used to tag existence of next element in variable length lists */
  36. #define STANDARD_TAG 1
  37. #define REVERSED_TAG 0
  38. static const unsigned char ixBitsTab[] = {0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5};
  39. /* Returns no_of_bits (up to 8) masked with 0x2B */
  40. static guint8
  41. tvb_get_masked_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits)
  42. {
  43. static const guint8 maskBits[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
  44. gint byte_offset = bit_offset >> 3; /* divide by 8 */
  45. gint relative_bit_offset = bit_offset & 0x07; /* modulo 8 */
  46. guint8 result;
  47. gint bit_shift = 8 - relative_bit_offset - (gint) no_of_bits;
  48. if (bit_shift >= 0)
  49. {
  50. result = (0x2B ^ tvb_get_guint8(tvb, byte_offset)) >> bit_shift;
  51. result &= maskBits[no_of_bits];
  52. }
  53. else
  54. {
  55. guint8 hight_part = (0x2B ^ tvb_get_guint8(tvb, byte_offset)) & maskBits[8 - relative_bit_offset];
  56. hight_part = (guint8) (hight_part << (-bit_shift));
  57. result = (0x2B ^ tvb_get_guint8(tvb, byte_offset+1)) >> (8 + bit_shift);
  58. result |= hight_part;
  59. }
  60. return result;
  61. }
  62. /**
  63. * ================================================================================================
  64. * set initial/start values in help data structure used for packing/unpacking operation
  65. * ================================================================================================
  66. */
  67. void
  68. csnStreamInit(csnStream_t* ar, gint bit_offset, gint remaining_bits_len)
  69. {
  70. ar->remaining_bits_len = remaining_bits_len;
  71. ar->bit_offset = bit_offset;
  72. }
  73. static const char* ErrCodes[] =
  74. {
  75. "General 0",
  76. "General -1",
  77. "DATA_NOT VALID",
  78. "IN SCRIPT",
  79. "INVALID UNION INDEX",
  80. "NEED_MORE BITS TO UNPACK",
  81. "ILLEGAL BIT VALUE",
  82. "Internal",
  83. "STREAM_NOT_SUPPORTED",
  84. "MESSAGE_TOO_LONG"
  85. };
  86. static gint16
  87. ProcessError(proto_tree *tree, tvbuff_t *tvb, gint bit_offset, const unsigned char* sz, gint16 err, const CSN_DESCR* pDescr)
  88. {
  89. gint16 i = MIN(-err, ((gint16) ElementsOf(ErrCodes)-1));
  90. if (i >= 0)
  91. {
  92. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "ERROR %s %s (%s)", sz, ErrCodes[i], pDescr?pDescr->sz:"-");
  93. }
  94. else
  95. {
  96. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "ERROR %s (%s)", sz, pDescr?pDescr->sz:"-");
  97. }
  98. return err;
  99. }
  100. #if 0
  101. static const char* CSN_DESCR_type[]=
  102. {
  103. "CSN_END",
  104. "CSN_BIT",
  105. "CSN_UINT",
  106. "CSN_TYPE",
  107. "CSN_CHOICE",
  108. "CSN_UNION",
  109. "CSN_UNION_LH",
  110. "CSN_UINT_ARRAY",
  111. "CSN_TYPE_ARRAY",
  112. "CSN_BITMAP",
  113. "CSN_VARIABLE_BITMAP",
  114. "CSN_VARIABLE_BITMAP_1",
  115. "CSN_LEFT_ALIGNED_VAR_BMP",
  116. "CSN_LEFT_ALIGNED_VAR_BMP_1",
  117. "CSN_VARIABLE_ARRAY",
  118. "CSN_VARIABLE_TARRAY",
  119. "CSN_VARIABLE_TARRAY_OFFSET",
  120. "CSN_RECURSIVE_ARRAY",
  121. "CSN_RECURSIVE_TARRAY",
  122. "CSN_RECURSIVE_TARRAY_1",
  123. "CSN_RECURSIVE_TARRAY_2",
  124. "CSN_EXIST",
  125. "CSN_EXIST_LH",
  126. "CSN_NEXT_EXIST",
  127. "CSN_NEXT_EXIST_LH",
  128. "CSN_NULL",
  129. "CSN_FIXED",
  130. "CSN_CALLBACK",
  131. "CSN_UINT_OFFSET",
  132. "CSN_UINT_LH",
  133. "CSN_SERIALIZE",
  134. "CSN_TRAP_ERROR"
  135. "CSN_???"
  136. };
  137. #endif
  138. /**
  139. * ================================================================================================
  140. * Return TRUE if tag in bit stream indicates existence of next list element,
  141. * otherwise return FALSE.
  142. * Will work for tag values equal to both 0 and 1.
  143. * ================================================================================================
  144. */
  145. static gboolean
  146. existNextElement(tvbuff_t *tvb, gint bit_offset, guint8 Tag)
  147. {
  148. guint8 res = tvb_get_bits8(tvb, bit_offset, 1);
  149. if (Tag == STANDARD_TAG)
  150. {
  151. return (res > 0);
  152. }
  153. return (res == 0);
  154. }
  155. gint16
  156. csnStreamDissector(proto_tree *tree, csnStream_t* ar, const CSN_DESCR* pDescr, tvbuff_t *tvb, void* data, int ett_csn1)
  157. {
  158. gint remaining_bits_len = ar->remaining_bits_len;
  159. gint bit_offset = ar->bit_offset;
  160. guint8* pui8 = NULL;
  161. guint16* pui16;
  162. guint32* pui32;
  163. guint8 Tag = STANDARD_TAG;
  164. if (remaining_bits_len <= 0)
  165. {
  166. return 0;
  167. }
  168. do
  169. {
  170. switch (pDescr->type)
  171. {
  172. case CSN_BIT:
  173. {
  174. if (remaining_bits_len > 0)
  175. {
  176. pui8 = pui8DATA(data, pDescr->offset);
  177. *pui8 = tvb_get_bits8(tvb, bit_offset, 1);
  178. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s %s",
  179. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  180. pDescr->sz);
  181. /* end add the bit value to protocol tree */
  182. }
  183. else if(pDescr->may_be_null)
  184. {
  185. *pui8 = 0;
  186. proto_tree_add_text(tree, tvb, 0, 0, "[NULL data]: %s Not Present", pDescr->sz);
  187. }
  188. else
  189. {
  190. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  191. }
  192. pDescr++;
  193. remaining_bits_len--;
  194. bit_offset++;
  195. break;
  196. }
  197. case CSN_NULL:
  198. { /* Empty member! */
  199. bit_offset += pDescr->i;
  200. pDescr++;
  201. break;
  202. }
  203. case CSN_UINT:
  204. {
  205. guint8 no_of_bits = (guint8) pDescr->i;
  206. if (remaining_bits_len >= no_of_bits)
  207. {
  208. if (no_of_bits <= 8)
  209. {
  210. guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  211. pui8 = pui8DATA(data, pDescr->offset);
  212. *pui8 = ui8;
  213. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  214. }
  215. else if (no_of_bits <= 16)
  216. {
  217. guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  218. pui16 = pui16DATA(data, pDescr->offset);
  219. *pui16 = ui16;
  220. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  221. }
  222. else if (no_of_bits <= 32)
  223. {
  224. guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  225. pui32 = pui32DATA(data, pDescr->offset);
  226. *pui32 = ui32;
  227. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  228. }
  229. else
  230. {
  231. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  232. }
  233. remaining_bits_len -= no_of_bits;
  234. bit_offset += no_of_bits;
  235. }
  236. else if(pDescr->may_be_null)
  237. {
  238. if (no_of_bits <= 8)
  239. {
  240. pui8 = pui8DATA(data, pDescr->offset);
  241. *pui8 = 0;
  242. }
  243. else if (no_of_bits <= 16)
  244. {
  245. pui16 = pui16DATA(data, pDescr->offset);
  246. *pui16 = 0;
  247. }
  248. else if (no_of_bits <= 32)
  249. {
  250. pui32 = pui32DATA(data, pDescr->offset);
  251. *pui32 = 0;
  252. }
  253. proto_tree_add_text(tree, tvb, 0, 0, "[NULL data]: %s Not Present", pDescr->sz);
  254. }
  255. else
  256. {
  257. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  258. }
  259. pDescr++;
  260. break;
  261. }
  262. case CSN_UINT_OFFSET:
  263. {
  264. guint8 no_of_bits = (guint8) pDescr->i;
  265. if (remaining_bits_len >= no_of_bits)
  266. {
  267. if (no_of_bits <= 8)
  268. {
  269. guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  270. pui8 = pui8DATA(data, pDescr->offset);
  271. *pui8 = ui8 + (guint8)pDescr->descr.value;
  272. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  273. decode_bits_in_field(bit_offset, no_of_bits, ui8),
  274. pDescr->sz, ui8);
  275. }
  276. else if (no_of_bits <= 16)
  277. {
  278. guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  279. pui16 = pui16DATA(data, pDescr->offset);
  280. *pui16 = ui16 + (guint16)pDescr->descr.value;
  281. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  282. decode_bits_in_field(bit_offset, no_of_bits, ui16),
  283. pDescr->sz, ui16);
  284. }
  285. else if (no_of_bits <= 32)
  286. {
  287. guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  288. pui32 = pui32DATA(data, pDescr->offset);
  289. *pui32 = ui32 + (guint16)pDescr->descr.value;
  290. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  291. decode_bits_in_field(bit_offset, no_of_bits, ui32),
  292. pDescr->sz, ui32);
  293. }
  294. else
  295. {
  296. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  297. }
  298. }
  299. else
  300. {
  301. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  302. }
  303. remaining_bits_len -= no_of_bits;
  304. bit_offset += no_of_bits;
  305. pDescr++;
  306. break;
  307. }
  308. case CSN_UINT_LH:
  309. {
  310. guint8 no_of_bits = (guint8) pDescr->i;
  311. if (remaining_bits_len >= no_of_bits)
  312. {
  313. if (no_of_bits <= 8)
  314. {
  315. guint8 ui8 = tvb_get_masked_bits8(tvb, bit_offset, no_of_bits);
  316. pui8 = pui8DATA(data, pDescr->offset);
  317. *pui8 = ui8;
  318. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  319. }
  320. else
  321. {/* Maybe we should support more than 8 bits ? */
  322. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  323. }
  324. }
  325. else
  326. {
  327. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  328. }
  329. remaining_bits_len -= no_of_bits;
  330. bit_offset += no_of_bits;
  331. pDescr++;
  332. break;
  333. }
  334. case CSN_SPLIT_BITS:
  335. {
  336. guint8 no_of_value_bits = (guint8) pDescr->i;
  337. guint64 value;
  338. proto_tree_add_split_bits_item_ret_val(tree, *pDescr->format_p.hf_ptr, tvb, bit_offset, pDescr->descr.crumb_spec, &value);
  339. if (no_of_value_bits <= 8)
  340. {
  341. pui8 = pui8DATA(data, pDescr->offset);
  342. *pui8 = (guint8)value;
  343. }
  344. else if (no_of_value_bits <= 16)
  345. {
  346. pui16 = pui16DATA(data, pDescr->offset);
  347. *pui16 = (guint16)value;
  348. }
  349. else if (no_of_value_bits <= 32)
  350. {
  351. pui32 = pui32DATA(data, pDescr->offset);
  352. *pui32 = (guint32)value;
  353. }
  354. else
  355. {
  356. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  357. }
  358. pDescr++;
  359. break;
  360. }
  361. case CSN_SPLIT_BITS_CRUMB:
  362. {
  363. if (remaining_bits_len >= pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length)
  364. {
  365. proto_tree_add_split_bits_crumb(tree, *pDescr->format_p.hf_ptr, tvb, bit_offset,
  366. pDescr->descr.crumb_spec, pDescr->i);
  367. remaining_bits_len -= pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length;
  368. bit_offset += pDescr->descr.crumb_spec[pDescr->i].crumb_bit_length;
  369. }
  370. else
  371. {
  372. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  373. }
  374. pDescr++;
  375. break;
  376. }
  377. case CSN_UINT_ARRAY:
  378. {
  379. guint8 no_of_bits = (guint8) pDescr->i;
  380. guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
  381. int i =0;
  382. if (pDescr->format_p.value != 0)
  383. { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
  384. nCount = *pui16DATA(data, nCount);
  385. }
  386. if (remaining_bits_len >= no_of_bits)
  387. {
  388. if (no_of_bits <= 8)
  389. {
  390. pui8 = pui8DATA(data, pDescr->offset);
  391. do
  392. {
  393. *pui8++ = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  394. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s[%d]",
  395. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
  396. pDescr->sz,
  397. i++);
  398. remaining_bits_len -= no_of_bits;
  399. bit_offset += no_of_bits;
  400. } while (--nCount > 0);
  401. }
  402. else if (no_of_bits <= 16)
  403. {
  404. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector NOTIMPLEMENTED", 999, pDescr);
  405. }
  406. else if (no_of_bits <= 32)
  407. {
  408. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector NOTIMPLEMENTED", 999, pDescr);
  409. }
  410. else
  411. {
  412. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  413. }
  414. }
  415. else
  416. {
  417. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  418. }
  419. pDescr++;
  420. break;
  421. }
  422. case CSN_VARIABLE_TARRAY_OFFSET:
  423. case CSN_VARIABLE_TARRAY:
  424. case CSN_TYPE_ARRAY:
  425. {
  426. gint16 Status;
  427. csnStream_t arT = *ar;
  428. gint16 nCount = pDescr->i;
  429. guint16 nSize = (guint16)(gint32)pDescr->format_p.value;
  430. int i =0;
  431. pui8 = pui8DATA(data, pDescr->offset);
  432. if (pDescr->type == CSN_VARIABLE_TARRAY)
  433. { /* Count specified in field */
  434. nCount = *pui8DATA(data, pDescr->i);
  435. }
  436. else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
  437. { /* Count specified in field */
  438. nCount = *pui8DATA(data, pDescr->i);
  439. /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
  440. }
  441. while (nCount > 0)
  442. { /* resulting array of length 0 is possible
  443. * but no bits shall be read from bitstream
  444. */
  445. proto_item *ti;
  446. proto_tree *test_tree;
  447. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s[%d]",pDescr->sz, i++);
  448. test_tree = proto_item_add_subtree(ti, ett_csn1);
  449. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  450. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)pDescr->descr.ptr, tvb, pui8, ett_csn1);
  451. if (Status >= 0)
  452. {
  453. pui8 += nSize;
  454. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  455. remaining_bits_len = arT.remaining_bits_len;
  456. bit_offset = arT.bit_offset;
  457. }
  458. else
  459. {
  460. return Status;
  461. }
  462. nCount--;
  463. }
  464. pDescr++;
  465. break;
  466. }
  467. case CSN_BITMAP:
  468. { /* bitmap with given length. The result is left aligned! */
  469. guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
  470. if (no_of_bits > 0)
  471. {
  472. if (no_of_bits <= 32)
  473. {
  474. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  475. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN)),
  476. pDescr->sz);
  477. }
  478. else if (no_of_bits <= 64)
  479. {
  480. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  481. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN)),
  482. pDescr->sz);
  483. }
  484. else
  485. {
  486. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector NOT IMPLEMENTED", 999, pDescr);
  487. }
  488. remaining_bits_len -= no_of_bits;
  489. DISSECTOR_ASSERT(remaining_bits_len >= 0);
  490. bit_offset += no_of_bits;
  491. }
  492. /* bitmap was successfully extracted or it was empty */
  493. pDescr++;
  494. break;
  495. }
  496. case CSN_TYPE:
  497. {
  498. gint16 Status;
  499. csnStream_t arT = *ar;
  500. proto_item *ti;
  501. proto_tree *test_tree;
  502. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
  503. test_tree = proto_item_add_subtree(ti, ett_csn1);
  504. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  505. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
  506. if (Status >= 0)
  507. {
  508. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  509. remaining_bits_len = arT.remaining_bits_len;
  510. bit_offset = arT.bit_offset;
  511. pDescr++;
  512. }
  513. else
  514. {
  515. /* Has already been processed: ProcessError("csnStreamDissector", Status, pDescr); */
  516. return Status;
  517. }
  518. break;
  519. }
  520. case CSN_CHOICE:
  521. {
  522. gint16 count = pDescr->i;
  523. guint8 i = 0;
  524. const CSN_ChoiceElement_t* pChoice = (const CSN_ChoiceElement_t*) pDescr->descr.ptr;
  525. while (count > 0)
  526. {
  527. guint8 no_of_bits = pChoice->bits;
  528. guint8 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  529. if (value == pChoice->value)
  530. {
  531. CSN_DESCR descr[2];
  532. gint16 Status;
  533. csnStream_t arT = *ar;
  534. proto_item *ti = NULL;
  535. proto_tree *test_tree;
  536. descr[0] = pChoice->descr;
  537. memset(&descr[1], 0x00, sizeof(CSN_DESCR));
  538. descr[1].type = CSN_END;
  539. pui8 = pui8DATA(data, pDescr->offset);
  540. *pui8 = i;
  541. if (pDescr->sz) {
  542. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s Choice: %s (%d)",
  543. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
  544. pDescr->sz, value);
  545. }
  546. if (!pChoice->keep_bits) {
  547. bit_offset += no_of_bits;
  548. remaining_bits_len -= no_of_bits;
  549. }
  550. if (pDescr->sz) {
  551. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
  552. test_tree = proto_item_add_subtree(ti, ett_csn1);
  553. } else {
  554. test_tree = tree;
  555. }
  556. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  557. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR*)descr, tvb, data, ett_csn1);
  558. if (Status >= 0)
  559. {
  560. if (ti)
  561. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  562. remaining_bits_len = arT.remaining_bits_len;
  563. bit_offset = arT.bit_offset;
  564. }
  565. else
  566. {
  567. return Status;
  568. }
  569. break;
  570. }
  571. count--;
  572. pChoice++;
  573. i++;
  574. }
  575. pDescr++;
  576. break;
  577. }
  578. case CSN_SERIALIZE:
  579. {
  580. StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn;
  581. csnStream_t arT = *ar;
  582. guint length_len = pDescr->i;
  583. gint16 Status = -1;
  584. proto_item *ti;
  585. proto_tree *test_tree;
  586. guint8 length = 0;
  587. if (length_len) {
  588. length = tvb_get_bits8(tvb, bit_offset, length_len);
  589. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length_len-1)>>3)-(bit_offset>>3)+1, "%s %s length: %d",
  590. decode_bits_in_field(bit_offset, length_len, length),
  591. pDescr->sz, length);
  592. bit_offset += length_len;
  593. remaining_bits_len -= length_len;
  594. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length-1)>>3)-(bit_offset>>3) + 1, "%s", pDescr->sz);
  595. } else {
  596. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
  597. }
  598. test_tree = proto_item_add_subtree(ti, ett_csn1);
  599. csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len);
  600. Status = serialize(test_tree, &arT, tvb, pvDATA(data, pDescr->offset), ett_csn1);
  601. if (Status >= 0)
  602. {
  603. if (length > 0) {
  604. remaining_bits_len -= length;
  605. bit_offset += length;
  606. } else {
  607. proto_item_set_len(ti,((arT.bit_offset - bit_offset)>>3)+1);
  608. remaining_bits_len = arT.remaining_bits_len;
  609. bit_offset = arT.bit_offset;
  610. }
  611. pDescr++;
  612. }
  613. else
  614. {
  615. /* Has already been processed: */
  616. return Status;
  617. }
  618. break;
  619. }
  620. case CSN_UNION_LH:
  621. case CSN_UNION:
  622. {
  623. gint16 Bits;
  624. guint8 t_index;
  625. gint16 count = pDescr->i;
  626. const CSN_DESCR* pDescrNext = pDescr;
  627. pDescrNext += count + 1; /* now this is next after the union */
  628. if ((count <= 0) || (count > 16))
  629. {
  630. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_INVALID_UNION_INDEX, pDescr);
  631. }
  632. /* Now get the bits to extract the index */
  633. Bits = ixBitsTab[count];
  634. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+Bits-1)>>3)-(bit_offset>>3)+1, "%s Union:%s",
  635. decode_bits_in_field(bit_offset, Bits, tvb_get_bits8(tvb, bit_offset, Bits)),
  636. pDescr->sz);
  637. t_index = 0;
  638. while (Bits > 0)
  639. {
  640. t_index <<= 1;
  641. if (CSN_UNION_LH == pDescr->type)
  642. {
  643. t_index |= tvb_get_masked_bits8(tvb, bit_offset, 1);
  644. }
  645. else
  646. {
  647. t_index |= tvb_get_bits8(tvb, bit_offset, 1);
  648. }
  649. remaining_bits_len--;
  650. bit_offset++;
  651. Bits--;
  652. }
  653. /* Assign UnionType */
  654. pui8 = pui8DATA(data, pDescr->offset);
  655. *pui8 = t_index;
  656. /* script index to continue on, limited in case we do not have a power of 2 */
  657. pDescr += (MIN(t_index + 1, count));
  658. switch (pDescr->type)
  659. { /* get the right element of the union based on computed index */
  660. case CSN_BIT:
  661. {
  662. pui8 = pui8DATA(data, pDescr->offset);
  663. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s %s",
  664. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  665. pDescr->sz);
  666. *pui8 = 0x00;
  667. if (tvb_get_bits8(tvb, bit_offset, 1) > 0)
  668. {
  669. *pui8 = 0x01;
  670. }
  671. remaining_bits_len --;
  672. bit_offset++;
  673. pDescr++;
  674. break;
  675. }
  676. case CSN_NULL:
  677. { /* Empty member! */
  678. bit_offset += pDescr->i;
  679. pDescr++;
  680. break;
  681. }
  682. case CSN_UINT:
  683. {
  684. guint8 no_of_bits = (guint8) pDescr->i;
  685. if (remaining_bits_len >= no_of_bits)
  686. {
  687. if (no_of_bits <= 8)
  688. {
  689. guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  690. pui8 = pui8DATA(data, pDescr->offset);
  691. *pui8 = ui8;
  692. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  693. }
  694. else if (no_of_bits <= 16)
  695. {
  696. guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  697. pui16 = pui16DATA(data, pDescr->offset);
  698. *pui16 = ui16;
  699. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  700. }
  701. else if (no_of_bits <= 32)
  702. {
  703. guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  704. pui32 = pui32DATA(data, pDescr->offset);
  705. *pui32 = ui32;
  706. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  707. }
  708. else
  709. {
  710. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  711. }
  712. }
  713. else
  714. {
  715. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  716. }
  717. remaining_bits_len -= no_of_bits;
  718. bit_offset += no_of_bits;
  719. pDescr++;
  720. break;
  721. }
  722. case CSN_UINT_OFFSET:
  723. {
  724. guint8 no_of_bits = (guint8) pDescr->i;
  725. if (remaining_bits_len >= no_of_bits)
  726. {
  727. if (no_of_bits <= 8)
  728. {
  729. guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  730. pui8 = pui8DATA(data, pDescr->offset);
  731. *pui8 = ui8 + (guint8)pDescr->descr.value;
  732. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  733. decode_bits_in_field(bit_offset, no_of_bits, ui8),
  734. pDescr->sz, ui8);
  735. }
  736. else if (no_of_bits <= 16)
  737. {
  738. guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  739. pui16 = pui16DATA(data, pDescr->offset);
  740. *pui16 = ui16 + (guint16)pDescr->descr.value;
  741. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  742. decode_bits_in_field(bit_offset, no_of_bits, ui16),
  743. pDescr->sz, ui16);
  744. }
  745. else if (no_of_bits <= 32)
  746. {
  747. guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  748. pui32 = pui32DATA(data, pDescr->offset);
  749. *pui32 = ui32 + (guint16)pDescr->descr.value;
  750. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s (%d)",
  751. decode_bits_in_field(bit_offset, no_of_bits, ui32),
  752. pDescr->sz, ui32);
  753. }
  754. else
  755. {
  756. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  757. }
  758. }
  759. else
  760. {
  761. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  762. }
  763. remaining_bits_len -= no_of_bits;
  764. bit_offset += no_of_bits;
  765. pDescr++;
  766. break;
  767. }
  768. case CSN_UINT_LH:
  769. {
  770. guint8 no_of_bits = (guint8) pDescr->i;
  771. if (remaining_bits_len >= no_of_bits)
  772. {
  773. if (no_of_bits <= 8)
  774. {
  775. guint8 ui8 = tvb_get_masked_bits8(tvb, bit_offset, no_of_bits);
  776. pui8 = pui8DATA(data, pDescr->offset);
  777. *pui8 = ui8;
  778. proto_tree_add_bits_item(tree, *(pDescr->format_p.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  779. }
  780. else
  781. { /* Maybe we should support more than 8 bits ? */
  782. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  783. }
  784. }
  785. else
  786. {
  787. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  788. }
  789. remaining_bits_len -= no_of_bits;
  790. bit_offset += no_of_bits;
  791. pDescr++;
  792. break;
  793. }
  794. case CSN_UINT_ARRAY:
  795. {
  796. guint8 no_of_bits = (guint8) pDescr->i;
  797. guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
  798. gint i = 0;
  799. if (pDescr->format_p.value != 0)
  800. { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
  801. nCount = *pui16DATA(data, nCount);
  802. }
  803. if (remaining_bits_len >= no_of_bits)
  804. {
  805. if (no_of_bits <= 8)
  806. {
  807. pui8 = pui8DATA(data, pDescr->offset);
  808. while (nCount > 0)
  809. {
  810. *pui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  811. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s[%d]",
  812. decode_bits_in_field(bit_offset, no_of_bits, *pui8),
  813. pDescr->sz,
  814. i++);
  815. pui8++;
  816. remaining_bits_len -= no_of_bits;
  817. bit_offset += no_of_bits;
  818. nCount--;
  819. }
  820. }
  821. else if (no_of_bits <= 16)
  822. {
  823. pui16 = pui16DATA(data, pDescr->offset);
  824. while (nCount > 0)
  825. {
  826. *pui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  827. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s[%d]",
  828. decode_bits_in_field(bit_offset, no_of_bits, *pui16),
  829. pDescr->sz,
  830. i++);
  831. remaining_bits_len -= no_of_bits;
  832. bit_offset += no_of_bits;
  833. nCount--;
  834. }
  835. }
  836. else if (no_of_bits <= 32)
  837. { /* not supported */
  838. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector NOT IMPLEMENTED", 999, pDescr);
  839. }
  840. else
  841. {
  842. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_GENERAL, pDescr);
  843. }
  844. }
  845. else
  846. {
  847. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  848. }
  849. pDescr++;
  850. break;
  851. }
  852. case CSN_VARIABLE_TARRAY_OFFSET:
  853. case CSN_VARIABLE_TARRAY:
  854. case CSN_TYPE_ARRAY:
  855. {
  856. gint16 Status;
  857. csnStream_t arT = *ar;
  858. guint16 nCount = (guint16) pDescr->i;
  859. guint16 nSize = (guint16)(guint32)pDescr->format_p.value;
  860. gint i = 0;
  861. pui8 = pui8DATA(data, pDescr->offset);
  862. if (CSN_VARIABLE_TARRAY == pDescr->type)
  863. { /* Count specified in field */
  864. nCount = *pui8DATA(data, pDescr->i);
  865. }
  866. else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type)
  867. { /* Count specified in field */
  868. nCount = *pui8DATA(data, pDescr->i);
  869. nCount--; /* Offset 1 */
  870. }
  871. while (nCount--) /* Changed to handle length = 0. */
  872. {
  873. proto_item *ti;
  874. proto_tree *test_tree;
  875. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s[%d]",pDescr->sz, i++);
  876. test_tree = proto_item_add_subtree(ti, ett_csn1);
  877. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  878. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pui8, ett_csn1);
  879. if (Status >= 0)
  880. {
  881. pui8 += nSize;
  882. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  883. remaining_bits_len = arT.remaining_bits_len;
  884. bit_offset = arT.bit_offset;
  885. }
  886. else
  887. {
  888. return Status;
  889. }
  890. }
  891. pDescr++;
  892. break;
  893. }
  894. case CSN_BITMAP:
  895. { /* bitmap with given length. The result is left aligned! */
  896. guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
  897. if (no_of_bits > 0)
  898. { /* a non empty bitmap */
  899. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  900. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
  901. pDescr->sz);
  902. remaining_bits_len -= no_of_bits;
  903. bit_offset += no_of_bits;
  904. if (remaining_bits_len < 0)
  905. {
  906. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  907. }
  908. }
  909. /* bitmap was successfully extracted or it was empty */
  910. pDescr++;
  911. break;
  912. }
  913. case CSN_TYPE:
  914. {
  915. gint16 Status;
  916. csnStream_t arT = *ar;
  917. proto_item *ti;
  918. proto_tree *test_tree;
  919. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s",pDescr->sz);
  920. test_tree = proto_item_add_subtree(ti, ett_csn1);
  921. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  922. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
  923. if (Status >= 0)
  924. {
  925. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  926. remaining_bits_len = arT.remaining_bits_len;
  927. bit_offset = arT.bit_offset;
  928. pDescr++;
  929. }
  930. else
  931. { /* return error code Has already been processed: */
  932. return Status;
  933. }
  934. break;
  935. }
  936. default:
  937. { /* descriptions of union elements other than above are illegal */
  938. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_IN_SCRIPT, pDescr);
  939. }
  940. }
  941. pDescr = pDescrNext;
  942. break;
  943. }
  944. case CSN_EXIST:
  945. case CSN_EXIST_LH:
  946. {
  947. guint8 fExist;
  948. pui8 = pui8DATA(data, pDescr->offset);
  949. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "Exist:%s",pDescr->sz);
  950. if (CSN_EXIST_LH == pDescr->type)
  951. {
  952. fExist = tvb_get_masked_bits8(tvb, bit_offset, 1);
  953. }
  954. else
  955. {
  956. fExist = tvb_get_bits8(tvb, bit_offset, 1);
  957. }
  958. *pui8 = fExist;
  959. remaining_bits_len --;
  960. bit_offset++;
  961. pDescr++;
  962. if (!fExist)
  963. {
  964. ar->remaining_bits_len = remaining_bits_len;
  965. ar->bit_offset = bit_offset;
  966. return remaining_bits_len;
  967. }
  968. break;
  969. }
  970. case CSN_NEXT_EXIST:
  971. {
  972. guint8 fExist;
  973. pui8 = pui8DATA(data, pDescr->offset);
  974. /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
  975. if ((pDescr->may_be_null) && (remaining_bits_len == 0))
  976. { /* no more bits to decode is fine here - end of message detected and allowed */
  977. /* Skip i entries + this entry */
  978. pDescr += pDescr->i + 1;
  979. /* Set the data member to "not exist" */
  980. *pui8 = 0;
  981. break;
  982. }
  983. /* the "regular" M_NEXT_EXIST description element */
  984. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s %s",
  985. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  986. pDescr->sz);
  987. fExist = 0x00;
  988. if (tvb_get_bits8(tvb, bit_offset, 1))
  989. {
  990. fExist = 0x01;
  991. }
  992. *pui8 = fExist;
  993. remaining_bits_len --;
  994. bit_offset++;
  995. if (fExist == 0)
  996. { /* Skip 'i' entries */
  997. pDescr += pDescr->i;
  998. }
  999. pDescr++;
  1000. break;
  1001. }
  1002. case CSN_NEXT_EXIST_LH:
  1003. {
  1004. guint8 fExist;
  1005. pui8 = pui8DATA(data, pDescr->offset);
  1006. /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */
  1007. if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
  1008. { /* no more bits to decode is fine here - end of message detected and allowed */
  1009. /* skip 'i' entries + this entry */
  1010. pDescr += pDescr->i + 1;
  1011. /* set the data member to "not exist" */
  1012. *pui8 = 0;
  1013. break;
  1014. }
  1015. /* the "regular" M_NEXT_EXIST_LH description element */
  1016. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s %s",
  1017. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  1018. pDescr->sz);
  1019. fExist = tvb_get_masked_bits8(tvb, bit_offset, 1);
  1020. *pui8++ = fExist;
  1021. remaining_bits_len --;
  1022. bit_offset++;
  1023. if (fExist == 0)
  1024. { /* Skip 'i' entries */
  1025. pDescr += pDescr->i;
  1026. }
  1027. pDescr++;
  1028. break;
  1029. }
  1030. case CSN_VARIABLE_BITMAP_1:
  1031. { /* Bitmap from here and to the end of message */
  1032. *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
  1033. /*no break -
  1034. * with a length set we have a regular variable length bitmap so we continue */
  1035. }
  1036. case CSN_VARIABLE_BITMAP:
  1037. { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
  1038. * <N: bit (5)> <bitmap: bit(N + offset)>
  1039. * Bit array with length (in bits) specified in parameter (pDescr->descr)
  1040. * The result is right aligned!
  1041. */
  1042. gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);
  1043. no_of_bits += pDescr->i; /* adjusted by offset */
  1044. if (no_of_bits > 0)
  1045. {
  1046. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s",
  1047. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)));
  1048. if (remaining_bits_len < 0)
  1049. {
  1050. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1051. }
  1052. { /* extract bits */
  1053. guint8* t_pui8 = pui8DATA(data, pDescr->offset);
  1054. gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */
  1055. if (nB1 > 0)
  1056. { /* take care of the first byte - it will be right aligned */
  1057. *t_pui8++ = tvb_get_bits8(tvb, bit_offset, nB1);
  1058. no_of_bits -= nB1;
  1059. bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */
  1060. remaining_bits_len -= nB1;
  1061. }
  1062. /* remaining no_of_bits is a multiple of 8 or 0 */
  1063. while (no_of_bits > 0)
  1064. {
  1065. *t_pui8++ = tvb_get_bits8(tvb, bit_offset, 8);
  1066. no_of_bits -= 8;
  1067. remaining_bits_len -= 8;
  1068. }
  1069. }
  1070. }
  1071. pDescr++;
  1072. break;
  1073. }
  1074. case CSN_LEFT_ALIGNED_VAR_BMP_1:
  1075. { /* Bitmap from here and to the end of message */
  1076. *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
  1077. /* no break -
  1078. * with a length set we have a regular left aligned variable length bitmap so we continue
  1079. */
  1080. }
  1081. case CSN_LEFT_ALIGNED_VAR_BMP:
  1082. { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
  1083. * <N: bit (5)> <bitmap: bit(N + offset)>
  1084. * bit array with length (in bits) specified in parameter (pDescr->descr)
  1085. */
  1086. gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */
  1087. no_of_bits += pDescr->i;/* size adjusted by offset */
  1088. if (no_of_bits > 0)
  1089. {
  1090. if (no_of_bits <= 32)
  1091. {
  1092. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  1093. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN)),
  1094. pDescr->sz);
  1095. }
  1096. else if (no_of_bits <= 64)
  1097. {
  1098. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  1099. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN)),
  1100. pDescr->sz);
  1101. }
  1102. else
  1103. {
  1104. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %u bits",
  1105. pDescr->sz, no_of_bits);
  1106. }
  1107. bit_offset += no_of_bits;
  1108. remaining_bits_len -= no_of_bits;
  1109. if (remaining_bits_len < 0)
  1110. {
  1111. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1112. }
  1113. }
  1114. /* bitmap was successfully extracted or it was empty */
  1115. pDescr++;
  1116. break;
  1117. }
  1118. case CSN_PADDING_BITS:
  1119. { /* Padding from here and to the end of message */
  1120. if (remaining_bits_len > 0)
  1121. {
  1122. proto_item *ti = proto_tree_add_text(tree, tvb, bit_offset>>3, -1, "Padding Bits");
  1123. proto_tree *padding_tree = proto_item_add_subtree(ti, ett_csn1);
  1124. while (remaining_bits_len > 0)
  1125. {
  1126. gint bits_to_handle = remaining_bits_len + (bit_offset%8);
  1127. if (bits_to_handle > 32)
  1128. {
  1129. bits_to_handle = 32 - (bit_offset%8);
  1130. }
  1131. else
  1132. {
  1133. bits_to_handle -= (bit_offset%8);
  1134. }
  1135. proto_tree_add_text(padding_tree, tvb, bit_offset>>3, ((bit_offset+bits_to_handle-1)>>3)-(bit_offset>>3)+1, "%s %s",
  1136. decode_bits_in_field(bit_offset, bits_to_handle, tvb_get_bits(tvb, bit_offset, bits_to_handle, ENC_BIG_ENDIAN)),
  1137. pDescr->sz);
  1138. bit_offset += bits_to_handle;
  1139. remaining_bits_len -= bits_to_handle;
  1140. }
  1141. }
  1142. if (remaining_bits_len < 0)
  1143. {
  1144. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1145. }
  1146. /* Padding was successfully extracted or it was empty */
  1147. pDescr++;
  1148. break;
  1149. }
  1150. case CSN_VARIABLE_ARRAY:
  1151. { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
  1152. * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
  1153. * Array with length specified in parameter:
  1154. * <count: bit (x)>
  1155. * <list: octet(count + offset)>
  1156. */
  1157. gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value);
  1158. count += pDescr->i; /* Adjusted by offset */
  1159. if (count > 0)
  1160. {
  1161. if (remaining_bits_len < 0)
  1162. {
  1163. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1164. }
  1165. pui8 = pui8DATA(data, pDescr->offset);
  1166. while (count > 0)
  1167. {
  1168. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s %s",
  1169. decode_bits_in_field(bit_offset, 8, tvb_get_bits8(tvb, bit_offset, 8)),
  1170. pDescr->sz);
  1171. *pui8++ = tvb_get_bits8(tvb, bit_offset, 8);
  1172. bit_offset += 8;
  1173. remaining_bits_len -= 8;
  1174. count--;
  1175. }
  1176. }
  1177. pDescr++;
  1178. break;
  1179. }
  1180. case CSN_RECURSIVE_ARRAY:
  1181. { /* Recursive way to specify an array: <list> ::= {1 <number: bit (4)> <list> | 0}
  1182. * or more generally: <list> ::= { <tag> <element> <list> | <EndTag> }
  1183. * where <element> ::= bit(value)
  1184. * <tag> ::= 0 | 1
  1185. * <EndTag> ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa
  1186. * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
  1187. * REMARK: recursive way to specify an array but an iterative implementation!
  1188. */
  1189. gint16 no_of_bits = pDescr->i;
  1190. guint8 ElementCount = 0;
  1191. pui8 = pui8DATA(data, pDescr->offset);
  1192. while (existNextElement(tvb, bit_offset, Tag))
  1193. { /* tag control shows existence of next list elements */
  1194. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s Exist:%s",
  1195. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  1196. pDescr->sz);
  1197. bit_offset++;
  1198. remaining_bits_len--;
  1199. /* extract and store no_of_bits long element from bitstream */
  1200. *pui8++ = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  1201. ElementCount++;
  1202. if (remaining_bits_len < 0)
  1203. {
  1204. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1205. }
  1206. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  1207. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
  1208. pDescr->sz);
  1209. bit_offset += no_of_bits;
  1210. remaining_bits_len -= no_of_bits;
  1211. }
  1212. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s Exist:%s",
  1213. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  1214. pDescr->sz);
  1215. /* existNextElement() returned FALSE, 1 bit consumed */
  1216. bit_offset++;
  1217. remaining_bits_len--;
  1218. /* Store the counted number of elements of the array */
  1219. *pui8DATA(data, (gint16)pDescr->descr.value) = ElementCount;
  1220. pDescr++;
  1221. break;
  1222. }
  1223. case CSN_RECURSIVE_TARRAY:
  1224. { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
  1225. * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
  1226. * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
  1227. */
  1228. gint16 nSizeElement = (gint16)(gint32)pDescr->format_p.value;
  1229. guint8 ElementCount = 0;
  1230. while (existNextElement(tvb, bit_offset, Tag))
  1231. { /* tag control shows existence of next list elements */
  1232. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s Exist:%s",
  1233. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  1234. pDescr->sz);
  1235. /* existNextElement() returned TRUE, 1 bit consumed */
  1236. bit_offset++;
  1237. remaining_bits_len--;
  1238. ElementCount++;
  1239. { /* unpack the following data structure */
  1240. csnStream_t arT = *ar;
  1241. gint16 Status;
  1242. proto_item *ti;
  1243. proto_tree *test_tree;
  1244. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s",pDescr->sz);
  1245. test_tree = proto_item_add_subtree(ti, ett_csn1);
  1246. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  1247. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
  1248. if (Status >= 0)
  1249. { /* successful completion */
  1250. pui8 += nSizeElement; /* -> to next data element */
  1251. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  1252. remaining_bits_len = arT.remaining_bits_len;
  1253. bit_offset = arT.bit_offset;
  1254. }
  1255. else
  1256. { /* something went awry */
  1257. return Status;
  1258. }
  1259. }
  1260. if (remaining_bits_len < 0)
  1261. {
  1262. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1263. }
  1264. }
  1265. /* existNextElement() returned FALSE, 1 bit consumed */
  1266. bit_offset++;
  1267. remaining_bits_len --;
  1268. /* Store the counted number of elements of the array */
  1269. *pui8DATA(data, (gint16)(gint32)pDescr->i) = ElementCount;
  1270. pDescr++;
  1271. break;
  1272. }
  1273. case CSN_RECURSIVE_TARRAY_2:
  1274. { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
  1275. Tag = REVERSED_TAG;
  1276. /* NO break -
  1277. * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
  1278. */
  1279. }
  1280. case CSN_RECURSIVE_TARRAY_1:
  1281. { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
  1282. * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
  1283. * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
  1284. */
  1285. gint16 nSizeElement = (gint16)(gint32)pDescr->format_p.value;
  1286. guint8 ElementCount = 0;
  1287. csnStream_t arT = *ar;
  1288. gboolean EndOfList = FALSE;
  1289. gint16 Status;
  1290. proto_item *ti;
  1291. proto_tree *test_tree;
  1292. do
  1293. { /* get data element */
  1294. ElementCount++;
  1295. ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s[%d]",pDescr->sz, ElementCount-1);
  1296. test_tree = proto_item_add_subtree(ti, ett_csn1);
  1297. csnStreamInit(&arT, bit_offset, remaining_bits_len);
  1298. Status = csnStreamDissector(test_tree, &arT, (const CSN_DESCR *)pDescr->descr.ptr, tvb, pvDATA(data, pDescr->offset), ett_csn1);
  1299. if (Status >= 0)
  1300. { /* successful completion */
  1301. pui8 += nSizeElement; /* -> to next */
  1302. proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
  1303. remaining_bits_len = arT.remaining_bits_len;
  1304. bit_offset = arT.bit_offset;
  1305. }
  1306. else
  1307. { /* something went awry */
  1308. return Status;
  1309. }
  1310. if (remaining_bits_len < 0)
  1311. {
  1312. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1313. }
  1314. /* control of next element's tag */
  1315. proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s Exist:%s[%d]",
  1316. decode_bits_in_field(bit_offset, 1, tvb_get_bits8(tvb, bit_offset, 1)),
  1317. pDescr->sz, ElementCount);
  1318. EndOfList = !(existNextElement(tvb, bit_offset, Tag));
  1319. bit_offset++;
  1320. remaining_bits_len--; /* 1 bit consumed (tag) */
  1321. } while (!EndOfList);
  1322. /* Store the count of the array */
  1323. *pui8DATA(data, pDescr->i) = ElementCount;
  1324. Tag = STANDARD_TAG; /* in case it was set to "reversed" */
  1325. pDescr++;
  1326. break;
  1327. }
  1328. case CSN_FIXED:
  1329. { /* Verify the fixed bits */
  1330. guint8 no_of_bits = (guint8) pDescr->i;
  1331. guint32 ui32;
  1332. if (no_of_bits <= 8)
  1333. {
  1334. ui32 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
  1335. }
  1336. else if (no_of_bits <= 16)
  1337. {
  1338. ui32 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  1339. }
  1340. else if (no_of_bits <= 32)
  1341. {
  1342. ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
  1343. }
  1344. else
  1345. {
  1346. return ProcessError(tree, tvb, bit_offset,"no_of_bits > 32", -1, pDescr);
  1347. }
  1348. if (ui32 != (unsigned)(gint32)pDescr->offset)
  1349. {
  1350. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector FIXED value does not match", -1, pDescr);
  1351. }
  1352. proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s %s",
  1353. decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
  1354. pDescr->sz);
  1355. remaining_bits_len -= no_of_bits;
  1356. bit_offset += no_of_bits;
  1357. pDescr++;
  1358. break;
  1359. }
  1360. case CSN_CALLBACK:
  1361. {
  1362. guint16 no_of_bits;
  1363. DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn;
  1364. no_of_bits = callback(tree, tvb, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset), bit_offset, ett_csn1);
  1365. bit_offset += no_of_bits;
  1366. pDescr++;
  1367. break;
  1368. }
  1369. case CSN_TRAP_ERROR:
  1370. {
  1371. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", pDescr->i, pDescr);
  1372. }
  1373. case CSN_END:
  1374. {
  1375. ar->remaining_bits_len = remaining_bits_len;
  1376. ar->bit_offset = bit_offset;
  1377. return remaining_bits_len;
  1378. }
  1379. default:
  1380. {
  1381. DISSECTOR_ASSERT(0);
  1382. }
  1383. }
  1384. } while (remaining_bits_len >= 0);
  1385. return ProcessError(tree, tvb, bit_offset,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
  1386. }