blob: fa29e27edc89ba53b603877839ab169e4da9b4f4 [file] [log] [blame]
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001/* csn1.cpp
2 * Routines for CSN1 dissection in wireshark.
3 *
4 * Copyright (C) 2011 Ivan Klyuchnikov
5 *
6 * By Vincent Helfre, based on original code by Jari Sassi
7 * with the gracious authorization of STE
8 * Copyright (c) 2011 ST-Ericsson
9 *
10 * $Id: packet-csn1.c 39140 2011-09-25 22:01:50Z wmeier $
11 *
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 */
30
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +040031#include <assert.h>
32#include <string.h>
Holger Hans Peter Freythercf0265a2013-07-28 15:57:20 +020033#define __STDC_FORMAT_MACROS
34#include <inttypes.h>
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030035#include "csn1.h"
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +040036#include <gprs_debug.h>
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030037
Pau Espin Pedrold636f742020-02-03 15:37:08 +010038#include <osmocom/core/logging.h>
39#include <osmocom/core/utils.h>
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030040
41#define pvDATA(_pv, _offset) ((void*) ((unsigned char*)_pv + _offset))
42#define pui8DATA(_pv, _offset) ((guint8*) pvDATA(_pv, _offset))
43#define pui16DATA(_pv, _offset) ((guint16*) pvDATA(_pv, _offset))
44#define pui32DATA(_pv, _offset) ((guint32*) pvDATA(_pv, _offset))
45#define pui64DATA(_pv, _offset) ((guint64*) pvDATA(_pv, _offset))
46/* used to tag existence of next element in variable length lists */
47#define STANDARD_TAG 1
48#define REVERSED_TAG 0
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030049
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030050static const unsigned char ixBitsTab[] = {0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5};
51
52
53/* Returns no_of_bits (up to 8) masked with 0x2B */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030054static guint8
Vadim Yanitskiy39a65052020-01-25 01:24:59 +070055get_masked_bits8(struct bitvec *vector, unsigned *readIndex, gint bit_offset, const gint no_of_bits)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030056{
57 static const guint8 maskBits[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
58 //gint byte_offset = bit_offset >> 3; /* divide by 8 */
59 gint relative_bit_offset = bit_offset & 0x07; /* modulo 8 */
60 guint8 result;
61 gint bit_shift = 8 - relative_bit_offset - (gint) no_of_bits;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +070062 *readIndex -= relative_bit_offset;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030063 if (bit_shift >= 0)
64 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +070065 result = (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) >> bit_shift;
66 *readIndex-= bit_shift;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030067 result &= maskBits[no_of_bits];
68 }
69 else
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +010070 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +070071 guint8 hight_part = (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) & maskBits[8 - relative_bit_offset];
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030072 hight_part = (guint8) (hight_part << (-bit_shift));
Vadim Yanitskiy39a65052020-01-25 01:24:59 +070073 result = (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) >> (8 + bit_shift);
74 *readIndex = *readIndex - (8 - (-bit_shift));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030075 result |= hight_part;
76 }
77 return result;
78}
79
80/**
81 * ================================================================================================
82 * set initial/start values in help data structure used for packing/unpacking operation
83 * ================================================================================================
84 */
85void
86csnStreamInit(csnStream_t* ar, gint bit_offset, gint remaining_bits_len)
87{
88 ar->remaining_bits_len = remaining_bits_len;
89 ar->bit_offset = bit_offset;
Ivan Kluchnikov1b517342013-12-30 14:26:06 +040090 ar->direction = 0;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +030091}
92
Pau Espin Pedrold636f742020-02-03 15:37:08 +010093static const struct value_string csn1_error_names[] = {
94 { CSN_OK, "General 0" },
95 { CSN_ERROR_GENERAL, "General -1" },
96 { CSN_ERROR_DATA_NOT_VALID, "DATA_NOT VALID" },
97 { CSN_ERROR_IN_SCRIPT, "IN SCRIPT" },
98 { CSN_ERROR_INVALID_UNION_INDEX, "INVALID UNION INDEX" },
99 { CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, "NEED_MORE BITS TO UNPACK" },
Vadim Yanitskiyfee767f2020-02-11 05:28:02 +0700100 { CSN_ERROR_ILLEGAL_BIT_VALUE, "ILLEGAL BIT VALUE" },
101 { CSN_ERROR_INTERNAL, "INTERNAL" },
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100102 { CSN_ERROR_STREAM_NOT_SUPPORTED, "STREAM_NOT_SUPPORTED" },
103 { CSN_ERROR_MESSAGE_TOO_LONG, "MESSAGE_TOO_LONG" },
104 { 0, NULL }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300105};
106
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100107
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700108static gint16 ProcessError_impl(const char *file, int line, unsigned *readIndex,
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100109 const char* sz, gint16 err, const CSN_DESCR* pDescr)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300110{
Pau Espin Pedrolac2b8662020-02-03 18:58:24 +0100111 /* Don't add trailing newline, top caller is responsible for appending it */
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100112 if (err != CSN_OK)
Vadim Yanitskiy15530492020-02-17 19:38:22 +0700113 LOGPSRC(DCSN1, LOGL_ERROR, file, line, "%s: error %s (%d) at %s (idx %u)",
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100114 sz, get_value_string(csn1_error_names, err), err,
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700115 pDescr ? pDescr->sz : "-", *readIndex);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300116 return err;
117}
118
Pau Espin Pedrold636f742020-02-03 15:37:08 +0100119#define ProcessError(readIndex, sz, err, pDescr) \
120 ProcessError_impl(__FILE__, __LINE__, readIndex, sz, err, pDescr)
121
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300122
123/**
124 * ================================================================================================
125 * Return TRUE if tag in bit stream indicates existence of next list element,
126 * otherwise return FALSE.
127 * Will work for tag values equal to both 0 and 1.
128 * ================================================================================================
129 */
130
131static gboolean
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700132existNextElement(struct bitvec *vector, unsigned *readIndex, guint8 Tag)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300133{
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700134 int res = bitvec_get_bit_pos(vector, (*readIndex)++);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300135 if (Tag == STANDARD_TAG)
136 {
137 return (res > 0);
138 }
139 return (res == 0);
140}
141
142
143gint16
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700144csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *readIndex, void* data)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300145{
146 gint remaining_bits_len = ar->remaining_bits_len;
147 gint bit_offset = ar->bit_offset;
Anders Bromanc0190c82020-01-24 14:34:14 +0100148 guint8* pui8 = NULL;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300149 guint16* pui16;
150 guint32* pui32;
151 guint64* pui64;
152 guint8 Tag = STANDARD_TAG;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700153 unsigned ib;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300154
Vadim Yanitskiy29aeb902020-03-06 08:53:36 +0700155 if (remaining_bits_len < 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300156 {
Vadim Yanitskiy29aeb902020-03-06 08:53:36 +0700157 return ProcessError(readIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300158 }
159
160 do
161 {
162 switch (pDescr->type)
163 {
164 case CSN_BIT:
165 {
166 if (remaining_bits_len > 0)
167 {
168 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700169 *pui8 = bitvec_read_field(vector, readIndex, 1);
Harald Welte570f9132020-03-19 15:03:01 +0100170 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300171 /* end add the bit value to protocol tree */
172 }
Pau Espin Pedrol16705a42020-10-27 10:24:57 +0100173 else if (pDescr->may_be_null)
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400174 {
175 pui8 = pui8DATA(data, pDescr->offset);
176 *pui8 = 0;
Harald Welte570f9132020-03-19 15:03:01 +0100177 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400178 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300179 else
180 {
181 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
182 }
183
184 pDescr++;
185 remaining_bits_len--;
186 bit_offset++;
187 break;
188 }
189
190 case CSN_NULL:
191 { /* Empty member! */
Anders Broman72c102a2020-01-24 14:31:15 +0100192 bit_offset += pDescr->i;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300193 pDescr++;
194 break;
195 }
196
197 case CSN_UINT:
198 {
199 guint8 no_of_bits = (guint8) pDescr->i;
200
201 if (remaining_bits_len >= no_of_bits)
202 {
203 if (no_of_bits <= 8)
204 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700205 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300206 pui8 = pui8DATA(data, pDescr->offset);
207 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100208 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300209 }
210 else if (no_of_bits <= 16)
211 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700212 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300213 pui16 = pui16DATA(data, pDescr->offset);
214 *pui16 = ui16;
Harald Welte570f9132020-03-19 15:03:01 +0100215 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300216 }
217 else if (no_of_bits <= 32)
218 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700219 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300220 pui32 = pui32DATA(data, pDescr->offset);
221 *pui32 = ui32;
Harald Welte570f9132020-03-19 15:03:01 +0100222 LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%08x | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300223 }
224 else
225 {
226 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
227 }
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400228 remaining_bits_len -= no_of_bits;
229 bit_offset += no_of_bits;
230 }
Pau Espin Pedrol16705a42020-10-27 10:24:57 +0100231 else if (pDescr->may_be_null)
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400232 {
233 if (no_of_bits <= 8)
234 {
235 pui8 = pui8DATA(data, pDescr->offset);
236 *pui8 = 0;
237 }
238 else if (no_of_bits <= 16)
239 {
240 pui16 = pui16DATA(data, pDescr->offset);
241 *pui16 = 0;
242 }
243 else if (no_of_bits <= 32)
244 {
245 pui32 = pui32DATA(data, pDescr->offset);
246 *pui32 = 0;
247 }
Harald Welte570f9132020-03-19 15:03:01 +0100248 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300249 }
250 else
251 {
252 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
253 }
254
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300255 pDescr++;
256 break;
257 }
258
259 case CSN_UINT_OFFSET:
260 {
261 guint8 no_of_bits = (guint8) pDescr->i;
262
263 if (remaining_bits_len >= no_of_bits)
264 {
265 if (no_of_bits <= 8)
266 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700267 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300268 pui8 = pui8DATA(data, pDescr->offset);
269 *pui8 = ui8 + (guint8)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100270 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300271 }
272 else if (no_of_bits <= 16)
273 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700274 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300275 pui16 = pui16DATA(data, pDescr->offset);
276 *pui16 = ui16 + (guint16)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100277 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300278 }
279 else if (no_of_bits <= 32)
280 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700281 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300282 pui32 = pui32DATA(data, pDescr->offset);
283 *pui32 = ui32 + (guint16)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100284 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300285 }
286 else
287 {
288 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
289 }
290 }
291 else
292 {
293 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
294 }
295
296 remaining_bits_len -= no_of_bits;
297 bit_offset += no_of_bits;
298 pDescr++;
299 break;
300 }
301
302 case CSN_UINT_LH:
303 {
304 guint8 no_of_bits = (guint8) pDescr->i;
305
306 if (remaining_bits_len >= no_of_bits)
307 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300308 if (no_of_bits <= 8)
309 {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100310 guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300311 pui8 = pui8DATA(data, pDescr->offset);
312 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100313 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300314 }
315 else
316 {/* Maybe we should support more than 8 bits ? */
317 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
318 }
319 }
320 else
321 {
322 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
323 }
324
325 remaining_bits_len -= no_of_bits;
326 bit_offset += no_of_bits;
327 pDescr++;
328 break;
329 }
330
331 case CSN_UINT_ARRAY:
332 {
333 guint8 no_of_bits = (guint8) pDescr->i;
334 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
335
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +0100336 if (pDescr->value != 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300337 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
338 nCount = *pui16DATA(data, nCount);
339 }
340
Pau Espin Pedrolf5e275a2020-03-26 19:54:29 +0100341 if (remaining_bits_len >= (no_of_bits * nCount))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300342 {
343 remaining_bits_len -= (no_of_bits*nCount);
344 if (no_of_bits <= 8)
345 {
346 pui8 = pui8DATA(data, pDescr->offset);
347 do
348 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700349 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +0100350 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300351 pui8++;
352 bit_offset += no_of_bits;
353 } while (--nCount > 0);
354 }
355 else if (no_of_bits <= 16)
356 {
357 return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr);
358 }
359 else if (no_of_bits <= 32)
360 {
361 return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr);
362 }
363 else
364 {
365 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
366 }
367 }
368 else
369 {
370 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
371 }
372 pDescr++;
373 break;
374 }
375
376 case CSN_VARIABLE_TARRAY_OFFSET:
377 case CSN_VARIABLE_TARRAY:
378 case CSN_TYPE_ARRAY:
379 {
380 gint16 Status;
381 csnStream_t arT = *ar;
382 gint16 nCount = pDescr->i;
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +0100383 guint16 nSize = (guint16)(gint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300384
385 pui8 = pui8DATA(data, pDescr->offset);
386 if (pDescr->type == CSN_VARIABLE_TARRAY)
387 { /* Count specified in field */
388 nCount = *pui8DATA(data, pDescr->i);
389 }
390 else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
391 { /* Count specified in field */
392 nCount = *pui8DATA(data, pDescr->i);
393 /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
394 }
395
396 while (nCount > 0)
397 { /* resulting array of length 0 is possible
398 * but no bits shall be read from bitstream
399 */
400
Harald Welte570f9132020-03-19 15:03:01 +0100401 LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300402 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100403 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300404 if (Status >= 0)
405 {
406 pui8 += nSize;
407 remaining_bits_len = arT.remaining_bits_len;
408 bit_offset = arT.bit_offset;
409 }
410 else
411 {
412 return Status;
413 }
414 nCount--;
415 }
416
417 pDescr++;
418 break;
419 }
420
421 case CSN_BITMAP:
422 { /* bitmap with given length. The result is left aligned! */
423 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
424
425 if (no_of_bits > 0)
426 {
Pau Espin Pedrolc8280a52020-03-26 20:29:53 +0100427 if (no_of_bits > remaining_bits_len)
428 {
429 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
430 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300431
432 if (no_of_bits <= 32)
433 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700434 for(ib = 0; ib < 4; ib++)
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400435 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700436 guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400437 pui8 = pui8DATA(data, pDescr->offset+ib);
438 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100439 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400440 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300441 }
442 else if (no_of_bits <= 64)
443 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700444 for(ib = 0; ib < 8; ib++)
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400445 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700446 guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400447 pui8 = pui8DATA(data, pDescr->offset+ib);
448 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100449 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +0400450 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300451 }
452 else
453 {
454 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
455 }
456
457 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300458 bit_offset += no_of_bits;
459 }
460 /* bitmap was successfully extracted or it was empty */
461
462 pDescr++;
463 break;
464 }
465
466 case CSN_TYPE:
467 {
468 gint16 Status;
469 csnStream_t arT = *ar;
Harald Welte570f9132020-03-19 15:03:01 +0100470 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300471 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100472 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
Harald Welte570f9132020-03-19 15:03:01 +0100473 LOGPC(DCSN1, LOGL_DEBUG, ": End %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300474 if (Status >= 0)
475 {
476 remaining_bits_len = arT.remaining_bits_len;
477 bit_offset = arT.bit_offset;
478 pDescr++;
479 }
480 else
481 {
482 /* Has already been processed: ProcessError("csnStreamDecoder", Status, pDescr); */
483 return Status;
484 }
485
486 break;
487 }
488
489 case CSN_CHOICE:
490 {
491 gint16 count = pDescr->i;
492 guint8 i = 0;
493 CSN_ChoiceElement_t* pChoice = (CSN_ChoiceElement_t*) pDescr->descr.ptr;
494
Vadim Yanitskiy5574a582020-02-11 05:39:06 +0700495 /* Make sure that the list of choice items is not empty */
496 if (!count)
497 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
Vadim Yanitskiyc9915662020-05-23 17:24:37 +0700498 else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */
499 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
Vadim Yanitskiy5574a582020-02-11 05:39:06 +0700500
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300501 while (count > 0)
502 {
503 guint8 no_of_bits = pChoice->bits;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700504 guint8 value = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300505 if (value == pChoice->value)
506 {
507 CSN_DESCR descr[2];
508 gint16 Status;
509 csnStream_t arT = *ar;
510
511 descr[0] = pChoice->descr;
512 memset(&descr[1], 0x00, sizeof(CSN_DESCR));
513 descr[1].type = CSN_END;
514 pui8 = pui8DATA(data, pDescr->offset);
515 *pui8 = i;
Harald Welte570f9132020-03-19 15:03:01 +0100516 LOGPC(DCSN1, LOGL_DEBUG, "Choice %s = %u | ", pDescr->sz , (unsigned)value);
Pau Espin Pedrol7cce8252020-01-24 16:41:14 +0100517 if (!pChoice->keep_bits) {
518 bit_offset += no_of_bits;
519 remaining_bits_len -= no_of_bits;
520 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300521
522 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100523 Status = csnStreamDecoder(&arT, descr, vector, readIndex, data);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300524
525 if (Status >= 0)
526 {
527 remaining_bits_len = arT.remaining_bits_len;
528 bit_offset = arT.bit_offset;
529 }
530 else
531 {
532 return Status;
533 }
534 break;
535 }
536
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700537 *readIndex -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300538 count--;
539 pChoice++;
540 i++;
541 }
542
Vadim Yanitskiy5574a582020-02-11 05:39:06 +0700543 /* Neither of the choice items matched => unknown value */
544 if (!count)
545 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
546
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300547 pDescr++;
548 break;
549 }
550
551 case CSN_SERIALIZE:
552 {
Pau Espin Pedrol5b716972020-01-24 17:24:01 +0100553 StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300554 csnStream_t arT = *ar;
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400555 guint8 length_len = pDescr->i;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300556 gint16 Status = -1;
557
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700558 guint8 length = bitvec_read_field(vector, readIndex, length_len);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300559
Harald Welte570f9132020-03-19 15:03:01 +0100560 LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , length);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400561 bit_offset += length_len;
562 remaining_bits_len -= length_len;
563
Pau Espin Pedrol98e4c532020-01-24 16:26:37 +0100564 csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len);
Daniel Willmann6f0796a2014-01-15 09:57:07 +0100565 arT.direction = 1;
Harald Welte570f9132020-03-19 15:03:01 +0100566 LOGPC(DCSN1, LOGL_DEBUG, "offset = %u | ", pDescr->offset);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100567 Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300568
569 if (Status >= 0)
570 {
Pau Espin Pedrol98e4c532020-01-24 16:26:37 +0100571 if (length > 0) {
572 remaining_bits_len -= length;
573 bit_offset += length;
574 } else {
575 remaining_bits_len = arT.remaining_bits_len;
576 bit_offset = arT.bit_offset;
577 }
Vadim Yanitskiy2679ec02020-03-06 07:21:32 +0700578
579 /* Skip bits not handled by serialize(), if any */
580 if (Status > 0) {
Harald Welte570f9132020-03-19 15:03:01 +0100581 LOGPC(DCSN1, LOGL_DEBUG, "skipped = %d | ", Status);
Vadim Yanitskiy2679ec02020-03-06 07:21:32 +0700582 *readIndex += Status;
583 }
584
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300585 pDescr++;
586 }
587 else
588 {
589 /* Has already been processed: */
590 return Status;
591 }
592
593 break;
594 }
595
596 case CSN_UNION_LH:
597 case CSN_UNION:
598 {
599 gint16 Bits;
600 guint8 index;
601 gint16 count = pDescr->i;
602 const CSN_DESCR* pDescrNext = pDescr;
603
604 pDescrNext += count + 1; /* now this is next after the union */
605 if ((count <= 0) || (count > 16))
606 {
607 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr);
608 }
609
610 /* Now get the bits to extract the index */
611 Bits = ixBitsTab[count];
612 index = 0;
613
614 while (Bits > 0)
615 {
616 index <<= 1;
617
618 if (CSN_UNION_LH == pDescr->type)
619 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700620 index |= get_masked_bits8(vector, readIndex, bit_offset, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300621 }
622 else
623 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700624 index |= bitvec_read_field(vector, readIndex, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300625 }
626 remaining_bits_len--;
627 bit_offset++;
628 Bits--;
629 }
630
631 /* Assign UnionType */
632 pui8 = pui8DATA(data, pDescr->offset);
633 *pui8 = index;
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +0100634
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300635
636 /* script index to continue on, limited in case we do not have a power of 2 */
637 pDescr += (MIN(index + 1, count));
Harald Welte570f9132020-03-19 15:03:01 +0100638 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300639
640 switch (pDescr->type)
641 { /* get the right element of the union based on computed index */
642
643 case CSN_BIT:
644 {
645 pui8 = pui8DATA(data, pDescr->offset);
646 *pui8 = 0x00;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700647 if (bitvec_read_field(vector, readIndex, 1) > 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300648 {
649 *pui8 = 0x01;
650 }
Harald Welte570f9132020-03-19 15:03:01 +0100651 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300652 remaining_bits_len -= 1;
653 bit_offset++;
654 pDescr++;
655 break;
656 }
657
658 case CSN_NULL:
659 { /* Empty member! */
Anders Broman72c102a2020-01-24 14:31:15 +0100660 bit_offset += pDescr->i;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300661 pDescr++;
662 break;
663 }
664
665 case CSN_UINT:
666 {
667 guint8 no_of_bits = (guint8) pDescr->i;
668 if (remaining_bits_len >= no_of_bits)
669 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300670 if (no_of_bits <= 8)
671 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700672 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300673 pui8 = pui8DATA(data, pDescr->offset);
674 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100675 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300676 }
677 else if (no_of_bits <= 16)
678 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700679 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300680 pui16 = pui16DATA(data, pDescr->offset);
681 *pui16 = ui16;
Harald Welte570f9132020-03-19 15:03:01 +0100682 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300683 }
684 else if (no_of_bits <= 32)
685 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700686 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300687 pui32 = pui32DATA(data, pDescr->offset);
688 *pui32 = ui32;
Harald Welte570f9132020-03-19 15:03:01 +0100689 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300690 }
691 else
692 {
693 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
694 }
695 }
696 else
697 {
698 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
699 }
700
Vadim Yanitskiye87066d2020-02-17 18:02:32 +0700701 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300702 bit_offset += no_of_bits;
703 pDescr++;
704 break;
705 }
706
707 case CSN_UINT_OFFSET:
708 {
709 guint8 no_of_bits = (guint8) pDescr->i;
710
711 if (remaining_bits_len >= no_of_bits)
712 {
713 if (no_of_bits <= 8)
714 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700715 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300716 pui8 = pui8DATA(data, pDescr->offset);
717 *pui8 = ui8 + (guint8)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100718 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300719 }
720 else if (no_of_bits <= 16)
721 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700722 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300723 pui16 = pui16DATA(data, pDescr->offset);
724 *pui16 = ui16 + (guint16)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100725 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300726 }
727 else if (no_of_bits <= 32)
728 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700729 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300730 pui32 = pui32DATA(data, pDescr->offset);
731 *pui32 = ui32 + (guint16)pDescr->descr.value;
Harald Welte570f9132020-03-19 15:03:01 +0100732 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300733 }
734 else
735 {
736 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
737 }
738 }
739 else
740 {
741 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
742 }
743
Vadim Yanitskiye87066d2020-02-17 18:02:32 +0700744 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300745 bit_offset += no_of_bits;
746 pDescr++;
747 break;
748 }
749
750 case CSN_UINT_LH:
751 {
752 guint8 no_of_bits = (guint8) pDescr->i;
753
754 if (remaining_bits_len >= no_of_bits)
755 {
756 if (no_of_bits <= 8)
757 {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100758 guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300759 pui8 = pui8DATA(data, pDescr->offset);
760 *pui8 = ui8;
Harald Welte570f9132020-03-19 15:03:01 +0100761 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300762 }
763 else
764 { /* Maybe we should support more than 8 bits ? */
765 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
766 }
767 }
768 else
769 {
770 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
771 }
772
Vadim Yanitskiye87066d2020-02-17 18:02:32 +0700773 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300774 bit_offset += no_of_bits;
775 pDescr++;
776 break;
777 }
778
779 case CSN_UINT_ARRAY:
780 {
781 guint8 no_of_bits = (guint8) pDescr->i;
782 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
783
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +0100784 if (pDescr->value != 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300785 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
786 nCount = *pui16DATA(data, nCount);
787 }
788
Pau Espin Pedrolf5e275a2020-03-26 19:54:29 +0100789 if (remaining_bits_len >= (no_of_bits * nCount))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300790 {
791 remaining_bits_len -= (no_of_bits * nCount);
792 if (no_of_bits <= 8)
793 {
794 pui8 = pui8DATA(data, pDescr->offset);
795
796 while (nCount > 0)
797 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700798 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +0100799 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300800 pui8++;
801 bit_offset += no_of_bits;
802 nCount--;
803 }
804 }
805 else if (no_of_bits <= 16)
806 {
807 pui16 = pui16DATA(data, pDescr->offset);
808
809 while (nCount > 0)
810 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700811 *pui16 = bitvec_read_field(vector, readIndex, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +0100812 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300813 pui16++;
814 bit_offset += no_of_bits;
815 nCount--;
816 }
817 }
818 else if (no_of_bits <= 32)
819 { /* not supported */
820 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
821 }
822 else
823 {
824 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
825 }
826 }
827 else
828 {
829 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
830 }
831
832 pDescr++;
833 break;
834 }
835
836 case CSN_VARIABLE_TARRAY_OFFSET:
837 case CSN_VARIABLE_TARRAY:
838 case CSN_TYPE_ARRAY:
839 {
840 gint16 Status;
841 csnStream_t arT = *ar;
842 guint16 nCount = (guint16) pDescr->i;
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +0100843 guint16 nSize = (guint16)(guint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300844
845 pui8 = pui8DATA(data, pDescr->offset);
846
847 if (CSN_VARIABLE_TARRAY == pDescr->type)
848 { /* Count specified in field */
849 nCount = *pui8DATA(data, pDescr->i);
850 }
851 else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type)
852 { /* Count specified in field */
853 nCount = *pui8DATA(data, pDescr->i);
854 nCount--; /* Offset 1 */
855 }
856
857 while (nCount--) /* Changed to handle length = 0. */
858 {
Harald Welte570f9132020-03-19 15:03:01 +0100859 LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300860 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100861 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300862 if (Status >= 0)
863 {
864 pui8 += nSize;
865 remaining_bits_len = arT.remaining_bits_len;
866 bit_offset = arT.bit_offset;
867 }
868 else
869 {
870 return Status;
871 }
872 }
873
874 pDescr++;
875 break;
876 }
877
878 case CSN_BITMAP:
879 { /* bitmap with given length. The result is left aligned! */
880 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
881
882 if (no_of_bits > 0)
883 {
Pau Espin Pedrolc8280a52020-03-26 20:29:53 +0100884 if (no_of_bits > remaining_bits_len)
885 {
886 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
887 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300888
889 if (no_of_bits <= 32)
890 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700891 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300892 pui32 = pui32DATA(data, pDescr->offset);
893 *pui32 = ui32;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300894 }
895 else if (no_of_bits <= 64)
896 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700897 guint64 ui64 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300898 pui64 = pui64DATA(data, pDescr->offset);
899 *pui64 = ui64;
Harald Welte570f9132020-03-19 15:03:01 +0100900 LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300901 }
902 else
903 {
904 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
905 }
906
907 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300908 bit_offset += no_of_bits;
909 }
910 /* bitmap was successfully extracted or it was empty */
911
912 pDescr++;
913 break;
914 }
915
916 case CSN_TYPE:
917 {
918 gint16 Status;
919 csnStream_t arT = *ar;
Harald Welte570f9132020-03-19 15:03:01 +0100920 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300921 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100922 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
Harald Welte570f9132020-03-19 15:03:01 +0100923 LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300924 if (Status >= 0)
925 {
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
935 break;
936 }
937
938 default:
939 { /* descriptions of union elements other than above are illegal */
940 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
941 }
942 }
943
944 pDescr = pDescrNext;
945 break;
946 }
947
948 case CSN_EXIST:
949 case CSN_EXIST_LH:
950 {
951 guint8 fExist;
952
953 pui8 = pui8DATA(data, pDescr->offset);
954
955 if (CSN_EXIST_LH == pDescr->type)
956 {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100957 fExist = get_masked_bits8(vector, readIndex, bit_offset, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300958 }
959 else
960 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +0700961 fExist = bitvec_read_field(vector, readIndex, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300962 }
963
964 *pui8 = fExist;
Harald Welte570f9132020-03-19 15:03:01 +0100965 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300966 pDescr++;
Vadim Yanitskiyd8e5e8b2020-02-17 18:16:20 +0700967 bit_offset++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300968 remaining_bits_len -= 1;
969
970 if (!fExist)
971 {
972 ar->remaining_bits_len = remaining_bits_len;
973 ar->bit_offset = bit_offset;
974 return remaining_bits_len;
975 }
976
977 break;
978 }
979
980 case CSN_NEXT_EXIST:
981 {
982 guint8 fExist;
983
984 pui8 = pui8DATA(data, pDescr->offset);
985
986 /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +0400987 if ((pDescr->may_be_null) && (remaining_bits_len == 0))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300988 { /* no more bits to decode is fine here - end of message detected and allowed */
989
990 /* Skip i entries + this entry */
991 pDescr += pDescr->i + 1;
992
Ivan Kluchnikov487a1412011-12-21 13:17:53 +0300993 /* Set the data member to "not exist" */
994 *pui8 = 0;
995 break;
996 }
997
998 /* the "regular" M_NEXT_EXIST description element */
999
1000 fExist = 0x00;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001001 if (bitvec_read_field(vector, readIndex, 1))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001002 {
1003 fExist = 0x01;
1004 }
1005
1006 *pui8 = fExist;
1007 remaining_bits_len -= 1;
Harald Welte570f9132020-03-19 15:03:01 +01001008 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001009 ++bit_offset;
1010
1011 if (fExist == 0)
1012 { /* Skip 'i' entries */
1013 pDescr += pDescr->i;
1014 }
1015
1016 pDescr++;
1017 break;
1018 }
1019
1020 case CSN_NEXT_EXIST_LH:
1021 {
1022 guint8 fExist;
1023 pui8 = pui8DATA(data, pDescr->offset);
1024
1025 /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */
1026 if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
1027 { /* no more bits to decode is fine here - end of message detected and allowed */
1028
1029 /* skip 'i' entries + this entry */
1030 pDescr += pDescr->i + 1;
1031
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001032 /* set the data member to "not exist" */
1033 *pui8 = 0;
1034 break;
1035 }
1036
1037 /* the "regular" M_NEXT_EXIST_LH description element */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001038 fExist = get_masked_bits8(vector, readIndex, bit_offset, 1);
Harald Welte570f9132020-03-19 15:03:01 +01001039 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)fExist);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001040 *pui8++ = fExist;
1041 remaining_bits_len -= 1;
1042
1043 bit_offset++;
1044
1045 if (fExist == 0)
1046 { /* Skip 'i' entries */
1047 pDescr += pDescr->i;
1048 }
1049 pDescr++;
1050
1051 break;
1052 }
1053
1054 case CSN_VARIABLE_BITMAP_1:
1055 { /* Bitmap from here and to the end of message */
1056
1057 *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
1058
1059 /*no break -
1060 * with a length set we have a regular variable length bitmap so we continue */
1061 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01001062 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001063 case CSN_VARIABLE_BITMAP:
1064 { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1065 * <N: bit (5)> <bitmap: bit(N + offset)>
1066 * Bit array with length (in bits) specified in parameter (pDescr->descr)
1067 * The result is right aligned!
1068 */
1069 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);
1070
1071 no_of_bits += pDescr->i; /* adjusted by offset */
1072
1073 if (no_of_bits > 0)
1074 {
1075 remaining_bits_len -= no_of_bits;
1076
1077 if (remaining_bits_len < 0)
1078 {
1079 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1080 }
1081
1082 { /* extract bits */
1083 guint8* pui8 = pui8DATA(data, pDescr->offset);
1084 gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */
1085
1086 if (nB1 > 0)
1087 { /* take care of the first byte - it will be right aligned */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001088 *pui8 = bitvec_read_field(vector, readIndex, nB1);
Harald Welte570f9132020-03-19 15:03:01 +01001089 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001090 pui8++;
1091 no_of_bits -= nB1;
1092 bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */
1093 }
1094
1095 /* remaining no_of_bits is a multiple of 8 or 0 */
1096 while (no_of_bits > 0)
1097 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001098 *pui8 = bitvec_read_field(vector, readIndex, 8);
Harald Welte570f9132020-03-19 15:03:01 +01001099 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001100 pui8++;
1101 no_of_bits -= 8;
1102 }
1103 }
1104 }
1105 pDescr++;
1106 break;
1107 }
1108
1109 case CSN_LEFT_ALIGNED_VAR_BMP_1:
1110 { /* Bitmap from here and to the end of message */
1111
1112 *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
1113
1114 /* no break -
1115 * with a length set we have a regular left aligned variable length bitmap so we continue
1116 */
1117 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01001118 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001119 case CSN_LEFT_ALIGNED_VAR_BMP:
1120 { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1121 * <N: bit (5)> <bitmap: bit(N + offset)>
1122 * bit array with length (in bits) specified in parameter (pDescr->descr)
1123 */
1124 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */
1125
1126 no_of_bits += pDescr->i;/* size adjusted by offset */
1127
1128 if (no_of_bits > 0)
1129 {
1130 remaining_bits_len -= no_of_bits;
1131
1132 if (remaining_bits_len < 0)
1133 {
1134 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1135 }
1136
1137 { /* extract bits */
1138 guint8* pui8 = pui8DATA(data, pDescr->offset);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001139
Neels Hofmeyr02415262016-09-02 02:15:26 +02001140 while (no_of_bits >= 8)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001141 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001142 *pui8 = bitvec_read_field(vector, readIndex, 8);
Harald Welte570f9132020-03-19 15:03:01 +01001143 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001144 pui8++;
1145 no_of_bits -= 8;
1146 }
Neels Hofmeyr02415262016-09-02 02:15:26 +02001147 if (no_of_bits > 0)
Pau Espin Pedrol70a21172020-03-26 19:50:50 +01001148 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001149 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001150 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001151 pui8++;
Neels Hofmeyr02415262016-09-02 02:15:26 +02001152 bit_offset += no_of_bits;
1153 no_of_bits = 0;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001154 }
1155 }
1156 }
1157
1158 /* bitmap was successfully extracted or it was empty */
1159 pDescr++;
1160 break;
1161 }
1162
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001163 case CSN_PADDING_BITS:
1164 { /* Padding from here and to the end of message */
Harald Welte570f9132020-03-19 15:03:01 +01001165 LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001166 if (remaining_bits_len > 0)
1167 {
1168 while (remaining_bits_len > 0)
1169 {
Pascal Quantinc5155512020-01-24 17:33:06 +01001170 guint bits_to_handle = remaining_bits_len%8;
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001171 if (bits_to_handle > 0)
1172 {
Harald Welte570f9132020-03-19 15:03:01 +01001173 LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, bits_to_handle));
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001174 remaining_bits_len -= bits_to_handle;
1175 bit_offset += bits_to_handle;
1176 }
1177 else if (bits_to_handle == 0)
1178 {
Harald Welte570f9132020-03-19 15:03:01 +01001179 LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, 8));
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001180 remaining_bits_len -= 8;
1181 bit_offset += 8;
1182 }
1183 }
1184 }
1185 if (remaining_bits_len < 0)
1186 {
Pau Espin Pedrol70a21172020-03-26 19:50:50 +01001187 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001188 }
1189
1190 /* Padding was successfully extracted or it was empty */
1191 pDescr++;
1192 break;
1193 }
1194
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001195 case CSN_VARIABLE_ARRAY:
1196 { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
1197 * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1198 * Array with length specified in parameter:
1199 * <count: bit (x)>
1200 * <list: octet(count + offset)>
1201 */
1202 gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value);
1203
1204 count += pDescr->i; /* Adjusted by offset */
1205
1206 if (count > 0)
1207 {
1208 remaining_bits_len -= count * 8;
1209
1210 if (remaining_bits_len < 0)
1211 {
1212 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1213 }
1214
1215 pui8 = pui8DATA(data, pDescr->offset);
1216
1217 while (count > 0)
1218 {
1219 readIndex -= 8;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001220 *pui8 = bitvec_read_field(vector, readIndex, 8);
Harald Welte570f9132020-03-19 15:03:01 +01001221 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001222 pui8++;
1223 bit_offset += 8;
1224 count--;
1225 }
1226 }
1227
1228 pDescr++;
1229 break;
1230 }
1231
1232 case CSN_RECURSIVE_ARRAY:
1233 { /* Recursive way to specify an array: <list> ::= {1 <number: bit (4)> <list> | 0}
1234 * or more generally: <list> ::= { <tag> <element> <list> | <EndTag> }
1235 * where <element> ::= bit(value)
1236 * <tag> ::= 0 | 1
1237 * <EndTag> ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa
1238 * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1239 * REMARK: recursive way to specify an array but an iterative implementation!
1240 */
1241 gint16 no_of_bits = pDescr->i;
1242 guint8 ElementCount = 0;
1243
1244 pui8 = pui8DATA(data, pDescr->offset);
1245
Alexander Couzensccde5c92017-02-04 03:10:08 +01001246 while (existNextElement(vector, readIndex, Tag))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001247 { /* tag control shows existence of next list elements */
Harald Welte570f9132020-03-19 15:03:01 +01001248 LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001249 bit_offset++;
1250 remaining_bits_len--;
1251
1252 /* extract and store no_of_bits long element from bitstream */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001253 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001254 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001255 pui8++;
1256 remaining_bits_len -= no_of_bits;
1257 ElementCount++;
1258
1259 if (remaining_bits_len < 0)
1260 {
1261 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1262 }
1263
1264 bit_offset += no_of_bits;
1265 }
1266
Harald Welte570f9132020-03-19 15:03:01 +01001267 LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001268 /* existNextElement() returned FALSE, 1 bit consumed */
1269 bit_offset++;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01001270 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001271
1272 /* Store the counted number of elements of the array */
1273 *pui8DATA(data, (gint16)pDescr->descr.value) = ElementCount;
1274
1275 pDescr++;
1276 break;
1277 }
1278
1279 case CSN_RECURSIVE_TARRAY:
1280 { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
1281 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001282 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001283 */
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01001284 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001285 guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001286 guint8 ElementCount = 0;
1287 pui8 = pui8DATA(data, pDescr->offset);
1288
Alexander Couzensccde5c92017-02-04 03:10:08 +01001289 while (existNextElement(vector, readIndex, Tag))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001290 { /* tag control shows existence of next list elements */
Harald Welte570f9132020-03-19 15:03:01 +01001291 LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001292 /* existNextElement() returned TRUE, 1 bit consumed */
1293 bit_offset++;
1294 remaining_bits_len--;
1295 ElementCount++;
1296
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001297 if (ElementCount > nSizeArray)
1298 {
1299 LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
1300 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
1301 }
1302
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001303 { /* unpack the following data structure */
1304 csnStream_t arT = *ar;
1305 gint16 Status;
1306 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +01001307 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001308
1309 if (Status >= 0)
1310 { /* successful completion */
1311 pui8 += nSizeElement; /* -> to next data element */
1312 remaining_bits_len = arT.remaining_bits_len;
1313 bit_offset = arT.bit_offset;
1314 }
1315 else
1316 { /* something went awry */
1317 return Status;
1318 }
1319 }
1320
1321 if (remaining_bits_len < 0)
1322 {
1323 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1324 }
1325 }
1326
Harald Welte570f9132020-03-19 15:03:01 +01001327 LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001328
1329 /* existNextElement() returned FALSE, 1 bit consumed */
Vadim Yanitskiye87066d2020-02-17 18:02:32 +07001330 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001331 bit_offset++;
1332
1333 /* Store the counted number of elements of the array */
1334 *pui8DATA(data, (gint16)(gint32)pDescr->i) = ElementCount;
1335
1336 pDescr++;
1337 break;
1338 }
1339
1340 case CSN_RECURSIVE_TARRAY_2:
1341 { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
1342
1343 Tag = REVERSED_TAG;
1344
1345 /* NO break -
1346 * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
1347 */
1348 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01001349 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001350 case CSN_RECURSIVE_TARRAY_1:
1351 { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
1352 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001353 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001354 */
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01001355 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001356 guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001357 guint8 ElementCount = 0;
1358 csnStream_t arT = *ar;
1359 gboolean EndOfList = FALSE;
1360 gint16 Status;
1361 pui8 = pui8DATA(data, pDescr->offset);
1362
1363 do
1364 { /* get data element */
1365 ElementCount++;
1366
Pau Espin Pedrolefad80b2020-03-23 14:35:26 +01001367 if (ElementCount > nSizeArray)
1368 {
1369 LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
1370 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
1371 }
1372
Harald Welte570f9132020-03-19 15:03:01 +01001373 LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz);
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +01001374
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001375 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Alexander Couzensccde5c92017-02-04 03:10:08 +01001376 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001377
1378 if (Status >= 0)
1379 { /* successful completion */
1380 pui8 += nSizeElement; /* -> to next */
1381 remaining_bits_len = arT.remaining_bits_len;
1382 bit_offset = arT.bit_offset;
1383 }
1384 else
1385 { /* something went awry */
1386 return Status;
1387 }
1388
1389 if (remaining_bits_len < 0)
1390 {
1391 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1392 }
1393
1394 /* control of next element's tag */
Harald Welte570f9132020-03-19 15:03:01 +01001395 LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz);
Alexander Couzensccde5c92017-02-04 03:10:08 +01001396 EndOfList = !(existNextElement(vector, readIndex, Tag));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001397
1398 bit_offset++;
1399 remaining_bits_len--; /* 1 bit consumed (tag) */
1400 } while (!EndOfList);
1401
1402
1403 /* Store the count of the array */
1404 *pui8DATA(data, pDescr->i) = ElementCount;
1405 Tag = STANDARD_TAG; /* in case it was set to "reversed" */
1406 pDescr++;
1407 break;
1408 }
1409
1410 case CSN_FIXED:
1411 { /* Verify the fixed bits */
1412 guint8 no_of_bits = (guint8) pDescr->i;
1413 guint32 ui32;
1414
1415 if (no_of_bits <= 32)
1416 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001417 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001418 }
1419 else
1420 {
1421 return ProcessError(readIndex,"no_of_bits > 32", -1, pDescr);
1422 }
1423 if (ui32 != (unsigned)(gint32)pDescr->offset)
1424 {
1425 return ProcessError(readIndex,"csnStreamDecoder FIXED value does not match", -1, pDescr);
1426 }
1427
Harald Welte570f9132020-03-19 15:03:01 +01001428 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)ui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001429 remaining_bits_len -= no_of_bits;
1430 bit_offset += no_of_bits;
1431 pDescr++;
1432 break;
1433 }
1434
1435 case CSN_CALLBACK:
1436 {
Pau Espin Pedrolf3ac06b2020-03-26 18:13:19 +01001437 guint16 no_of_bits;
1438 DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn;
1439 LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz);
1440 no_of_bits = callback(vector, readIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset));
1441 remaining_bits_len -= no_of_bits;
1442 bit_offset += no_of_bits;
1443 pDescr++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001444 break;
1445 }
1446
1447 case CSN_TRAP_ERROR:
1448 {
1449 return ProcessError(readIndex,"csnStreamDecoder", pDescr->i, pDescr);
1450 }
1451
1452 case CSN_END:
1453 {
1454 ar->remaining_bits_len = remaining_bits_len;
1455 ar->bit_offset = bit_offset;
1456 return remaining_bits_len;
1457 }
1458
1459 default:
1460 {
1461 assert(0);
1462 }
1463
1464
1465 }
1466
1467 } while (remaining_bits_len >= 0);
1468
1469 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1470}
1471
1472
1473
1474
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001475gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *writeIndex, void* data)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001476{
1477 gint remaining_bits_len = ar->remaining_bits_len;
1478 gint bit_offset = ar->bit_offset;
1479 guint8* pui8;
1480 guint16* pui16;
1481 guint32* pui32;
1482 guint64* pui64;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001483 unsigned ib;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001484
1485 guint8 Tag = STANDARD_TAG;
1486
Vadim Yanitskiy29aeb902020-03-06 08:53:36 +07001487 if (remaining_bits_len < 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001488 {
Vadim Yanitskiy29aeb902020-03-06 08:53:36 +07001489 return ProcessError(writeIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001490 }
1491
1492 do
1493 {
1494 switch (pDescr->type)
1495 {
1496 case CSN_BIT:
1497 {
1498 if (remaining_bits_len > 0)
1499 {
1500 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001501 bitvec_write_field(vector, writeIndex, *pui8, 1);
Harald Welte570f9132020-03-19 15:03:01 +01001502 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001503 /* end add the bit value to protocol tree */
1504 }
Pau Espin Pedrol16705a42020-10-27 10:24:57 +01001505 else if (pDescr->may_be_null)
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001506 {
Harald Welte570f9132020-03-19 15:03:01 +01001507 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001508 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001509 else
1510 {
1511 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1512 }
1513
1514 pDescr++;
1515 remaining_bits_len--;
1516 bit_offset++;
1517 break;
1518 }
1519
1520 case CSN_NULL:
1521 { /* Empty member! */
1522 pDescr++;
1523 break;
1524 }
1525
1526 case CSN_UINT:
1527 {
1528 guint8 no_of_bits = (guint8) pDescr->i;
1529
1530 if (remaining_bits_len >= no_of_bits)
1531 {
1532 if (no_of_bits <= 8)
1533 {
1534 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001535 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001536 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001537 }
1538 else if (no_of_bits <= 16)
1539 {
1540 pui16 = pui16DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001541 bitvec_write_field(vector, writeIndex, *pui16, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001542 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001543 }
1544 else if (no_of_bits <= 32)
1545 {
1546 pui32 = pui32DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001547 bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001548 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001549 }
1550 else
1551 {
1552 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1553 }
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001554
1555 remaining_bits_len -= no_of_bits;
1556 bit_offset += no_of_bits;
1557 }
Pau Espin Pedrol16705a42020-10-27 10:24:57 +01001558 else if (pDescr->may_be_null)
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001559 {
Harald Welte570f9132020-03-19 15:03:01 +01001560 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001561 }
1562 else
1563 {
1564 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1565 }
1566
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001567 pDescr++;
1568 break;
1569 }
1570
1571 case CSN_UINT_OFFSET:
1572 {
1573 guint8 no_of_bits = (guint8) pDescr->i;
1574
1575 if (remaining_bits_len >= no_of_bits)
1576 {
1577 if (no_of_bits <= 8)
1578 {
1579 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001580 bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001581 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001582 }
1583 else if (no_of_bits <= 16)
1584 {
1585 pui16 = pui16DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001586 bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001587 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001588 }
1589 else if (no_of_bits <= 32)
1590 {
1591 pui32 = pui32DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001592 bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001593 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001594 }
1595 else
1596 {
1597 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1598 }
1599 }
1600 else
1601 {
1602 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1603 }
1604
1605 remaining_bits_len -= no_of_bits;
1606 bit_offset += no_of_bits;
1607 pDescr++;
1608 break;
1609 }
1610
1611 case CSN_UINT_LH:
1612 {
1613 guint8 no_of_bits = (guint8) pDescr->i;
1614
1615 if (remaining_bits_len >= no_of_bits)
1616 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001617 if (no_of_bits <= 8)
1618 {
1619 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001620 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001621 // TODO : Change get_masked_bits8()
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001622 *writeIndex -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001623 guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001624 *writeIndex -= no_of_bits;
1625 bitvec_write_field(vector, writeIndex, ui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001626 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001627
1628 }
1629 else
1630 {/* Maybe we should support more than 8 bits ? */
1631 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1632 }
1633 }
1634 else
1635 {
1636 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1637 }
1638
1639 remaining_bits_len -= no_of_bits;
1640 bit_offset += no_of_bits;
1641 pDescr++;
1642 break;
1643 }
1644
1645 case CSN_UINT_ARRAY:
1646 {
1647 guint8 no_of_bits = (guint8) pDescr->i;
1648 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
1649
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01001650 if (pDescr->value != 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001651 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
1652 nCount = *pui16DATA(data, nCount);
1653 }
1654
Pau Espin Pedrolf5e275a2020-03-26 19:54:29 +01001655 if (remaining_bits_len >= (no_of_bits * nCount))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001656 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001657 if (no_of_bits <= 8)
1658 {
1659 pui8 = pui8DATA(data, pDescr->offset);
1660 do
1661 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001662 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001663 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001664 pui8++;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01001665 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001666 bit_offset += no_of_bits;
1667 } while (--nCount > 0);
1668 }
1669 else if (no_of_bits <= 16)
1670 {
1671 return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr);
1672 }
1673 else if (no_of_bits <= 32)
1674 {
1675 return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr);
1676 }
1677 else
1678 {
1679 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1680 }
1681 }
1682 else
1683 {
1684 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1685 }
1686 pDescr++;
1687 break;
1688 }
1689
1690 case CSN_VARIABLE_TARRAY_OFFSET:
1691 case CSN_VARIABLE_TARRAY:
1692 case CSN_TYPE_ARRAY:
1693 {
1694 gint16 Status;
1695 csnStream_t arT = *ar;
1696 gint16 nCount = pDescr->i;
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01001697 guint16 nSize = (guint16)(gint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001698
1699 pui8 = pui8DATA(data, pDescr->offset);
1700 if (pDescr->type == CSN_VARIABLE_TARRAY)
1701 { /* Count specified in field */
1702 nCount = *pui8DATA(data, pDescr->i);
1703 }
1704 else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
1705 { /* Count specified in field */
1706 nCount = *pui8DATA(data, pDescr->i);
1707 /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
1708 }
1709
1710 while (nCount > 0)
1711 { /* resulting array of length 0 is possible
1712 * but no bits shall be read from bitstream
1713 */
1714
Harald Welte570f9132020-03-19 15:03:01 +01001715 LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001716 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1717 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8);
1718 if (Status >= 0)
1719 {
1720 pui8 += nSize;
1721 remaining_bits_len = arT.remaining_bits_len;
1722 bit_offset = arT.bit_offset;
1723
1724 }
1725 else
1726 {
1727 return Status;
1728 }
1729 nCount--;
1730 }
1731
1732 pDescr++;
1733 break;
1734 }
1735
1736 case CSN_BITMAP:
1737 { /* bitmap with given length. The result is left aligned! */
1738 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
1739
1740 if (no_of_bits > 0)
1741 {
Pau Espin Pedrolc8280a52020-03-26 20:29:53 +01001742 if (no_of_bits > remaining_bits_len)
1743 {
1744 return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1745 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001746
1747 if (no_of_bits <= 32)
1748 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001749 for(ib = 0; ib < 4; ib++)
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +04001750 {
1751 pui8 = pui8DATA(data, pDescr->offset+ib);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001752 bitvec_write_field(vector, writeIndex, *pui8, 8);
Harald Welte570f9132020-03-19 15:03:01 +01001753 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +04001754 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001755 }
1756 else if (no_of_bits <= 64)
1757 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001758 for(ib = 0; ib < 8; ib++)
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +04001759 {
1760 pui8 = pui8DATA(data, pDescr->offset+ib);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001761 bitvec_write_field(vector, writeIndex, *pui8, 8);
Harald Welte570f9132020-03-19 15:03:01 +01001762 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
Ivan Kluchnikov74b459f2012-04-11 22:02:15 +04001763 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001764 }
1765 else
1766 {
1767 return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr);
1768 }
1769
1770 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001771 bit_offset += no_of_bits;
1772 }
1773 /* bitmap was successfully extracted or it was empty */
1774
1775 pDescr++;
1776 break;
1777 }
1778
1779 case CSN_TYPE:
1780 {
1781 gint16 Status;
1782 csnStream_t arT = *ar;
Harald Welte570f9132020-03-19 15:03:01 +01001783 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001784 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1785 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset));
Harald Welte570f9132020-03-19 15:03:01 +01001786 LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001787 if (Status >= 0)
1788 {
1789
1790 remaining_bits_len = arT.remaining_bits_len;
1791 bit_offset = arT.bit_offset;
1792 pDescr++;
1793 }
1794 else
1795 {
1796 /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */
1797 return Status;
1798 }
1799
1800 break;
1801 }
1802
1803 case CSN_CHOICE:
1804 {
Vadim Yanitskiyfac83322020-05-23 17:33:07 +07001805 gint16 count = pDescr->i;
Anders Broman60bf8452020-01-24 17:35:48 +01001806 const CSN_ChoiceElement_t* pChoice = (const CSN_ChoiceElement_t*) pDescr->descr.ptr;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001807
Vadim Yanitskiyfac83322020-05-23 17:33:07 +07001808 /* Make sure that the list of choice items is not empty */
1809 if (!count)
1810 return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr);
1811 else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */
1812 return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr);
1813
Vadim Yanitskiy0614e932020-05-23 17:43:45 +07001814 /* Make sure that choice index is not out of range */
1815 pui8 = pui8DATA(data, pDescr->offset);
1816 if (*pui8 >= count)
1817 return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr);
1818
1819 pChoice += *pui8;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001820 guint8 no_of_bits = pChoice->bits;
1821 guint8 value = pChoice->value;
Harald Welte570f9132020-03-19 15:03:01 +01001822 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pChoice->descr.sz , (unsigned)value);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001823 bitvec_write_field(vector, writeIndex, value, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001824
1825 CSN_DESCR descr[2];
1826 gint16 Status;
1827 csnStream_t arT = *ar;
1828
1829 descr[0] = pChoice->descr;
1830 memset(&descr[1], 0x00, sizeof(CSN_DESCR));
1831 descr[1].type = CSN_END;
1832 bit_offset += no_of_bits;
1833 remaining_bits_len -= no_of_bits;
1834
1835 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1836 Status = csnStreamEncoder(&arT, descr, vector, writeIndex, data);
1837
1838 if (Status >= 0)
1839 {
1840 remaining_bits_len = arT.remaining_bits_len;
1841 bit_offset = arT.bit_offset;
1842 }
1843 else
1844 {
1845 return Status;
1846 }
1847
1848 pDescr++;
1849 break;
1850 }
1851
1852 case CSN_SERIALIZE:
1853 {
Pau Espin Pedrol5b716972020-01-24 17:24:01 +01001854 StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001855 csnStream_t arT = *ar;
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001856 guint8 length_len = pDescr->i;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001857 gint16 Status = -1;
Ivan Kluchnikov9b06ff02012-06-15 10:13:30 +04001858 unsigned lengthIndex;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001859
1860 // store writeIndex for length value (7 bit)
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001861 lengthIndex = *writeIndex;
1862 *writeIndex += length_len;
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001863 bit_offset += length_len;
1864 remaining_bits_len -= length_len;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001865 arT.direction = 0;
1866 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1867 Status = serialize(&arT, vector, writeIndex, pvDATA(data, pDescr->offset));
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04001868
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001869 bitvec_write_field(vector, &lengthIndex, *writeIndex - lengthIndex - length_len, length_len);
Harald Welte570f9132020-03-19 15:03:01 +01001870 LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , (unsigned)(*writeIndex - lengthIndex));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001871
1872 if (Status >= 0)
1873 {
1874 remaining_bits_len = arT.remaining_bits_len;
1875 bit_offset = arT.bit_offset;
1876 pDescr++;
1877 }
1878 else
1879 {
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +01001880 // Has already been processed:
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001881 return Status;
1882 }
1883
1884 break;
1885 }
1886
1887 case CSN_UNION_LH:
1888 case CSN_UNION:
1889 {
1890 gint16 Bits;
1891 guint8 index;
1892 gint16 count = pDescr->i;
1893 const CSN_DESCR* pDescrNext = pDescr;
1894
1895 pDescrNext += count + 1; /* now this is next after the union */
1896 if ((count <= 0) || (count > 16))
1897 {
1898 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr);
1899 }
1900
1901 /* Now get the bits to extract the index */
1902 Bits = ixBitsTab[count];
1903 index = 0;
1904
1905 /* Assign UnionType */
1906 pui8 = pui8DATA(data, pDescr->offset);
1907 //read index from data and write to vector
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001908 bitvec_write_field(vector, writeIndex, *pui8, Bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001909
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +01001910 //decode index
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001911 *writeIndex -= Bits;
Pau Espin Pedrolf960d5b2020-01-23 19:05:00 +01001912
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001913 while (Bits > 0)
1914 {
1915 index <<= 1;
1916
1917 if (CSN_UNION_LH == pDescr->type)
1918 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001919 index |= get_masked_bits8(vector, writeIndex, bit_offset, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001920 }
1921 else
1922 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001923 index |= bitvec_read_field(vector, writeIndex, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001924 }
1925
1926 remaining_bits_len--;
1927 bit_offset++;
1928 Bits--;
1929 }
1930
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001931 *writeIndex -= Bits;
1932 bitvec_write_field(vector, writeIndex, index, Bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001933
1934
1935 /* script index to continue on, limited in case we do not have a power of 2 */
1936 pDescr += (MIN(index + 1, count));
Harald Welte570f9132020-03-19 15:03:01 +01001937 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)index);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001938
1939 switch (pDescr->type)
1940 { /* get the right element of the union based on computed index */
1941
1942 case CSN_BIT:
1943 {
1944 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001945 bitvec_write_field(vector, writeIndex, *pui8, 1);
Harald Welte570f9132020-03-19 15:03:01 +01001946 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01001947 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001948 bit_offset++;
1949 pDescr++;
1950 break;
1951 }
1952
1953 case CSN_NULL:
1954 { /* Empty member! */
1955 pDescr++;
1956 break;
1957 }
1958
1959 case CSN_UINT:
1960 {
1961 guint8 no_of_bits = (guint8) pDescr->i;
1962 if (remaining_bits_len >= no_of_bits)
1963 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001964 if (no_of_bits <= 8)
1965 {
1966 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001967 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001968 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001969 }
1970 else if (no_of_bits <= 16)
1971 {
1972 pui16 = pui16DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001973 bitvec_write_field(vector, writeIndex, *pui16, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001974 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001975 }
1976 else if (no_of_bits <= 32)
1977 {
1978 pui32 = pui32DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07001979 bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01001980 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001981 }
1982 else
1983 {
1984 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1985 }
1986 }
1987 else
1988 {
1989 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
1990 }
1991
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01001992 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03001993 bit_offset += no_of_bits;
1994 pDescr++;
1995 break;
1996 }
1997
1998 case CSN_UINT_OFFSET:
1999 {
2000 guint8 no_of_bits = (guint8) pDescr->i;
2001
2002 if (remaining_bits_len >= no_of_bits)
2003 {
2004 if (no_of_bits <= 8)
2005 {
2006 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002007 bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002008 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002009 }
2010 else if (no_of_bits <= 16)
2011 {
2012 pui16 = pui16DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002013 bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002014 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002015 }
2016 else if (no_of_bits <= 32)
2017 {
2018 pui32 = pui32DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002019 bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002020 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002021 }
2022 else
2023 {
2024 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
2025 }
2026 }
2027 else
2028 {
2029 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2030 }
2031
2032 remaining_bits_len -= no_of_bits;
2033 bit_offset += no_of_bits;
2034 pDescr++;
2035 break;
2036 }
2037
2038 case CSN_UINT_LH:
2039 {
2040 guint8 no_of_bits = (guint8) pDescr->i;
2041
2042 if (remaining_bits_len >= no_of_bits)
2043 {
2044 remaining_bits_len -= no_of_bits;
2045 if (no_of_bits <= 8)
2046 {
2047 pui8 = pui8DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002048 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002049 // TODO : Change get_masked_bits8()
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002050 *writeIndex -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002051 guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002052 *writeIndex -= no_of_bits;
2053 bitvec_write_field(vector, writeIndex, ui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002054 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002055
2056 }
2057 else
2058 {/* Maybe we should support more than 8 bits ? */
2059 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
2060 }
2061 }
2062 else
2063 {
2064 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2065 }
2066
2067 remaining_bits_len -= no_of_bits;
2068 bit_offset += no_of_bits;
2069 pDescr++;
2070 break;
2071 }
2072
2073 case CSN_UINT_ARRAY:
2074 {
2075 guint8 no_of_bits = (guint8) pDescr->i;
2076 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
2077
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01002078 if (pDescr->value != 0)
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002079 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
2080 nCount = *pui16DATA(data, nCount);
2081 }
2082
Pau Espin Pedrolf5e275a2020-03-26 19:54:29 +01002083 if (remaining_bits_len >= (no_of_bits * nCount))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002084 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002085 if (no_of_bits <= 8)
2086 {
2087 pui8 = pui8DATA(data, pDescr->offset);
2088 do
2089 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002090 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002091 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002092 pui8++;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002093 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002094 bit_offset += no_of_bits;
2095 } while (--nCount > 0);
2096 }
2097 else if (no_of_bits <= 16)
2098 {
2099 return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr);
2100 }
2101 else if (no_of_bits <= 32)
2102 {
2103 return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr);
2104 }
2105 else
2106 {
2107 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
2108 }
2109 }
2110 else
2111 {
2112 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2113 }
2114 pDescr++;
2115 break;
2116 }
2117
2118 case CSN_VARIABLE_TARRAY_OFFSET:
2119 case CSN_VARIABLE_TARRAY:
2120 case CSN_TYPE_ARRAY:
2121 {
2122 gint16 Status;
2123 csnStream_t arT = *ar;
2124 gint16 nCount = pDescr->i;
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01002125 guint16 nSize = (guint16)(gint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002126
2127 pui8 = pui8DATA(data, pDescr->offset);
2128 if (pDescr->type == CSN_VARIABLE_TARRAY)
2129 { /* Count specified in field */
2130 nCount = *pui8DATA(data, pDescr->i);
2131 }
2132 else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
2133 { /* Count specified in field */
2134 nCount = *pui8DATA(data, pDescr->i);
2135 /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
2136 }
2137
2138 while (nCount > 0)
2139 { /* resulting array of length 0 is possible
2140 * but no bits shall be read from bitstream
2141 */
2142
Harald Welte570f9132020-03-19 15:03:01 +01002143 LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002144 csnStreamInit(&arT, bit_offset, remaining_bits_len);
2145 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8);
2146 if (Status >= 0)
2147 {
2148 pui8 += nSize;
2149 remaining_bits_len = arT.remaining_bits_len;
2150 bit_offset = arT.bit_offset;
2151 }
2152 else
2153 {
2154 return Status;
2155 }
2156 nCount--;
2157 }
2158
2159 pDescr++;
2160 break;
2161 }
2162
2163 case CSN_BITMAP:
2164 { /* bitmap with given length. The result is left aligned! */
2165 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
2166
2167 if (no_of_bits > 0)
2168 {
Pau Espin Pedrolc8280a52020-03-26 20:29:53 +01002169 if (no_of_bits > remaining_bits_len)
2170 {
2171 return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2172 }
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002173
2174 if (no_of_bits <= 32)
2175 {
2176 pui32 = pui32DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002177 bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002178 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002179 }
2180 else if (no_of_bits <= 64)
2181 {
2182 pui64 = pui64DATA(data, pDescr->offset);
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002183 bitvec_write_field(vector, writeIndex, *pui64, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002184 LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002185 }
2186 else
2187 {
2188 return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr);
2189 }
2190
2191 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002192 bit_offset += no_of_bits;
2193 }
2194 /* bitmap was successfully extracted or it was empty */
2195
2196 pDescr++;
2197 break;
2198 }
2199
2200 case CSN_TYPE:
2201 {
2202 gint16 Status;
2203 csnStream_t arT = *ar;
Harald Welte570f9132020-03-19 15:03:01 +01002204 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002205 csnStreamInit(&arT, bit_offset, remaining_bits_len);
2206 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset));
Harald Welte570f9132020-03-19 15:03:01 +01002207 LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002208 if (Status >= 0)
2209 {
2210 remaining_bits_len = arT.remaining_bits_len;
2211 bit_offset = arT.bit_offset;
2212 pDescr++;
2213 }
2214 else
2215 {
2216 /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */
2217 return Status;
2218 }
2219
2220 break;
2221 }
2222
2223 default:
2224 { /* descriptions of union elements other than above are illegal */
2225 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr);
2226 }
2227 }
2228
2229 pDescr = pDescrNext;
2230 break;
2231 }
2232
2233 case CSN_EXIST:
2234 case CSN_EXIST_LH:
2235 {
2236 guint8 fExist;
2237 unsigned exist = 0;
2238 pui8 = pui8DATA(data, pDescr->offset);
2239 exist = *pui8;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002240 bitvec_write_field(vector, writeIndex, *pui8, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002241 writeIndex--;
2242 if (CSN_EXIST_LH == pDescr->type)
2243 {
2244 fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1);
2245 }
2246 else
2247 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002248 fExist = bitvec_read_field(vector, writeIndex, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002249 }
2250 writeIndex--;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002251 bitvec_write_field(vector, writeIndex, fExist, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002252 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz, (unsigned)fExist);
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002253 remaining_bits_len--;
2254 bit_offset++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002255 pDescr++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002256
2257 if (!exist)
2258 {
2259 ar->remaining_bits_len = remaining_bits_len;
2260 ar->bit_offset = bit_offset;
2261 return remaining_bits_len;
2262 }
2263 break;
2264 }
2265
2266 case CSN_NEXT_EXIST:
2267 {
2268 guint8 fExist;
2269
2270 pui8 = pui8DATA(data, pDescr->offset);
2271
2272 /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002273 if ((pDescr->may_be_null) && (remaining_bits_len == 0))
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002274 { /* no more bits to decode is fine here - end of message detected and allowed */
2275
2276 /* Skip i entries + this entry */
2277 pDescr += pDescr->i + 1;
2278
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002279 break;
2280 }
2281
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002282 bitvec_write_field(vector, writeIndex, *pui8, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002283 fExist = *pui8;
Harald Welte570f9132020-03-19 15:03:01 +01002284 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002285
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002286 remaining_bits_len--;
2287 bit_offset++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002288
2289 if (fExist == 0)
2290 { /* Skip 'i' entries */
2291 pDescr += pDescr->i;
2292 }
2293
2294 pDescr++;
2295 break;
2296 }
2297
2298 case CSN_NEXT_EXIST_LH:
2299 {
2300 guint8 fExist;
2301 pui8 = pui8DATA(data, pDescr->offset);
2302
2303 /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */
2304 if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
2305 { /* no more bits to decode is fine here - end of message detected and allowed */
2306
2307 /* skip 'i' entries + this entry */
2308 pDescr += pDescr->i + 1;
2309
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002310 /* set the data member to "not exist" */
2311 //*pui8 = 0;
2312 break;
2313 }
2314
2315 /* the "regular" M_NEXT_EXIST_LH description element */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002316 bitvec_write_field(vector, writeIndex, *pui8, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002317 writeIndex--;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002318 fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002319 writeIndex--;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002320 bitvec_write_field(vector, writeIndex, fExist, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002321 pui8++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002322
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002323 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002324 bit_offset++;
2325
2326 if (fExist == 0)
2327 { /* Skip 'i' entries */
2328 pDescr += pDescr->i;
2329 }
2330 pDescr++;
2331
2332 break;
2333 }
2334
2335 case CSN_VARIABLE_BITMAP_1:
2336 { /* Bitmap from here and to the end of message */
2337
2338 //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
2339
2340 /*no break -
2341 * with a length set we have a regular variable length bitmap so we continue */
2342 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01002343 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002344 case CSN_VARIABLE_BITMAP:
2345 { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
2346 * <N: bit (5)> <bitmap: bit(N + offset)>
2347 * Bit array with length (in bits) specified in parameter (pDescr->descr)
2348 * The result is right aligned!
2349 */
2350 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);
2351
2352 no_of_bits += pDescr->i; /* adjusted by offset */
2353
2354 if (no_of_bits > 0)
2355 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002356
2357 if (remaining_bits_len < 0)
2358 {
2359 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2360 }
2361
2362 { /* extract bits */
2363 guint8* pui8 = pui8DATA(data, pDescr->offset);
2364 gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */
2365
2366 if (nB1 > 0)
2367 { /* take care of the first byte - it will be right aligned */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002368 bitvec_write_field(vector, writeIndex, *pui8, nB1);
Harald Welte570f9132020-03-19 15:03:01 +01002369 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002370 pui8++;
2371 no_of_bits -= nB1;
2372 bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002373 remaining_bits_len -= nB1;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002374 }
2375
2376 /* remaining no_of_bits is a multiple of 8 or 0 */
2377 while (no_of_bits > 0)
2378 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002379 bitvec_write_field(vector, writeIndex, *pui8, 8);
Harald Welte570f9132020-03-19 15:03:01 +01002380 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002381 pui8++;
2382 no_of_bits -= 8;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002383 remaining_bits_len -= 8;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002384 }
2385 }
2386 }
2387 pDescr++;
2388 break;
2389 }
2390
2391 case CSN_LEFT_ALIGNED_VAR_BMP_1:
2392 { /* Bitmap from here and to the end of message */
2393
2394 //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
2395
2396 /* no break -
2397 * with a length set we have a regular left aligned variable length bitmap so we continue
2398 */
2399 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01002400 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002401 case CSN_LEFT_ALIGNED_VAR_BMP:
2402 { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
2403 * <N: bit (5)> <bitmap: bit(N + offset)>
2404 * bit array with length (in bits) specified in parameter (pDescr->descr)
2405 */
2406
2407 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */
2408
2409 no_of_bits += pDescr->i;/* size adjusted by offset */
2410
2411 if (no_of_bits > 0)
2412 {
2413 remaining_bits_len -= no_of_bits;
2414
2415 if (remaining_bits_len < 0)
2416 {
2417 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2418 }
2419
2420 { /* extract bits */
2421 guint8* pui8 = pui8DATA(data, pDescr->offset);
2422 gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */
2423
2424 while (no_of_bits > 0)
2425 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002426 bitvec_write_field(vector, writeIndex, *pui8, 8);
Harald Welte570f9132020-03-19 15:03:01 +01002427 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002428 pui8++;
2429 no_of_bits -= 8;
2430 }
2431 if (nB1 > 0)
2432 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002433 bitvec_write_field(vector, writeIndex, *pui8, nB1);
Harald Welte570f9132020-03-19 15:03:01 +01002434 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002435 pui8++;
2436 no_of_bits -= nB1;
2437 bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */
2438 }
2439 }
2440
2441 }
2442
2443 /* bitmap was successfully extracted or it was empty */
2444 pDescr++;
2445 break;
2446 }
2447
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002448 case CSN_PADDING_BITS:
2449 { /* Padding from here and to the end of message */
Harald Welte570f9132020-03-19 15:03:01 +01002450 LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002451 guint8 filler = 0x2b;
2452 if (remaining_bits_len > 0)
2453 {
2454 while (remaining_bits_len > 0)
2455 {
2456 guint8 bits_to_handle = remaining_bits_len%8;
2457 if (bits_to_handle > 0)
2458 {
Saurabh Sharan656eed52016-03-10 14:15:29 +05302459 /* section 11 of 44.060
2460 * The padding bits may be the 'null' string. Otherwise, the
2461 * padding bits starts with bit '0', followed by 'spare padding'
2462 * < padding bits > ::= { null | 0 < spare padding > ! < Ignore : 1 bit** = < no string > > } ;
2463 */
2464 guint8 fl = filler&(0xff>>(8-bits_to_handle + 1));
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002465 bitvec_write_field(vector, writeIndex, fl, bits_to_handle);
Harald Welte570f9132020-03-19 15:03:01 +01002466 LOGPC(DCSN1, LOGL_DEBUG, "%u|", fl);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002467 remaining_bits_len -= bits_to_handle;
2468 bit_offset += bits_to_handle;
2469 }
2470 else if (bits_to_handle == 0)
2471 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002472 bitvec_write_field(vector, writeIndex, filler, 8);
Harald Welte570f9132020-03-19 15:03:01 +01002473 LOGPC(DCSN1, LOGL_DEBUG, "%u|", filler);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002474 remaining_bits_len -= 8;
2475 bit_offset += 8;
2476 }
2477 }
2478 }
2479 if (remaining_bits_len < 0)
2480 {
Pau Espin Pedrol70a21172020-03-26 19:50:50 +01002481 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002482 }
2483
2484 /* Padding was successfully extracted or it was empty */
2485 pDescr++;
2486 break;
2487 }
2488
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002489 case CSN_VARIABLE_ARRAY:
2490 { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
2491 * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
2492 * Array with length specified in parameter:
2493 * <count: bit (x)>
2494 * <list: octet(count + offset)>
2495 */
2496 gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value);
2497
2498 count += pDescr->i; /* Adjusted by offset */
2499
2500 if (count > 0)
2501 {
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002502 if (remaining_bits_len < 0)
2503 {
2504 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2505 }
2506
2507 pui8 = pui8DATA(data, pDescr->offset);
2508
2509 while (count > 0)
2510 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002511 bitvec_write_field(vector, writeIndex, *pui8, 8);
Harald Welte570f9132020-03-19 15:03:01 +01002512 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002513 pui8++;
2514 bit_offset += 8;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002515 remaining_bits_len -= 8;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002516 count--;
2517 }
2518 }
2519
2520 pDescr++;
2521 break;
2522 }
2523
2524 case CSN_RECURSIVE_ARRAY:
2525 { /* Recursive way to specify an array: <list> ::= {1 <number: bit (4)> <list> | 0}
2526 * or more generally: <list> ::= { <tag> <element> <list> | <EndTag> }
2527 * where <element> ::= bit(value)
2528 * <tag> ::= 0 | 1
2529 * <EndTag> ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa
2530 * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
2531 * REMARK: recursive way to specify an array but an iterative implementation!
2532 */
2533 gint16 no_of_bits = pDescr->i;
2534 guint8 ElementCount = 0;
2535 pui8 = pui8DATA(data, pDescr->offset);
2536 ElementCount = *pui8DATA(data, (gint16)pDescr->descr.value);
2537 while (ElementCount > 0)
2538 { /* tag control shows existence of next list elements */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002539 bitvec_write_field(vector, writeIndex, Tag, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002540 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002541 bit_offset++;
2542 remaining_bits_len--;
2543
2544 /* extract and store no_of_bits long element from bitstream */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002545 bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002546 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002547 pui8++;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002548 ElementCount--;
2549
2550 if (remaining_bits_len < 0)
2551 {
2552 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2553 }
2554
2555 bit_offset += no_of_bits;
Jeff Morrissc0b4f4a2020-01-24 15:00:58 +01002556 remaining_bits_len -= no_of_bits;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002557 }
2558
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002559 bitvec_write_field(vector, writeIndex, !Tag, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002560 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002561 bit_offset++;
Saurabh Sharan2b09c392016-03-16 19:17:32 +05302562 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002563
2564 pDescr++;
2565 break;
2566 }
2567
2568 case CSN_RECURSIVE_TARRAY:
2569 { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
2570 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
2571 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
2572 */
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01002573 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002574 guint8 ElementCount = 0;
2575 pui8 = pui8DATA(data, pDescr->offset);
2576 /* Store the counted number of elements of the array */
2577 ElementCount = *pui8DATA(data, (gint16)(gint32)pDescr->i);
2578
2579 while (ElementCount > 0)
2580 { /* tag control shows existence of next list elements */
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002581 bitvec_write_field(vector, writeIndex, Tag, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002582 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002583 bit_offset++;
2584
2585 remaining_bits_len--;
2586 ElementCount--;
2587
2588 { /* unpack the following data structure */
2589 csnStream_t arT = *ar;
2590 gint16 Status;
2591 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Ivan Kluchnikov44408452013-03-01 02:46:10 +04002592 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002593
2594 if (Status >= 0)
2595 { /* successful completion */
2596 pui8 += nSizeElement; /* -> to next data element */
2597 remaining_bits_len = arT.remaining_bits_len;
2598 bit_offset = arT.bit_offset;
2599 }
2600 else
2601 { /* something went awry */
2602 return Status;
2603 }
2604 }
2605
2606 if (remaining_bits_len < 0)
2607 {
2608 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2609 }
2610 }
2611
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002612 bitvec_write_field(vector, writeIndex, !Tag, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002613 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag));
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002614 bit_offset++;
2615
2616 pDescr++;
2617 break;
2618 }
2619
2620 case CSN_RECURSIVE_TARRAY_2:
2621 { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
2622
2623 Tag = REVERSED_TAG;
2624
2625 /* NO break -
2626 * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
2627 */
2628 }
Alexis La Gouttee36fb5b2020-01-24 18:22:35 +01002629 /* FALL THROUGH */
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002630 case CSN_RECURSIVE_TARRAY_1:
2631 { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
2632 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
2633 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
2634 */
Pau Espin Pedrol900c2e22020-01-24 18:05:00 +01002635 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002636 guint8 ElementCount = 0;
2637 guint8 ElementNum = 0;
2638 csnStream_t arT = *ar;
2639 gint16 Status;
2640
2641 pui8 = pui8DATA(data, pDescr->offset);
2642 /* Store the count of the array */
2643 ElementCount = *pui8DATA(data, pDescr->i);
2644 ElementNum = ElementCount;
2645
2646 while (ElementCount > 0)
2647 { /* get data element */
2648 if (ElementCount != ElementNum)
2649 {
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002650 bitvec_write_field(vector, writeIndex, Tag, 1);
Harald Welte570f9132020-03-19 15:03:01 +01002651 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002652 bit_offset++;
2653 remaining_bits_len--;
2654 }
2655 ElementCount--;
Harald Welte570f9132020-03-19 15:03:01 +01002656 LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002657 csnStreamInit(&arT, bit_offset, remaining_bits_len);
Ivan Kluchnikov44408452013-03-01 02:46:10 +04002658 Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8);
Harald Welte570f9132020-03-19 15:03:01 +01002659 LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002660 if (Status >= 0)
2661 { /* successful completion */
2662 pui8 += nSizeElement; /* -> to next */
2663 remaining_bits_len = arT.remaining_bits_len;
2664 bit_offset = arT.bit_offset;
2665 }
2666 else
2667 { /* something went awry */
2668 return Status;
2669 }
2670
2671 if (remaining_bits_len < 0)
2672 {
2673 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2674 }
2675
2676 }
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002677 bitvec_write_field(vector, writeIndex, !Tag, 1);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002678 bit_offset++;
Ivan Kluchnikov701d9f82012-10-10 19:43:37 +04002679 remaining_bits_len--;
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002680 Tag = STANDARD_TAG; /* in case it was set to "reversed" */
2681 pDescr++;
2682 break;
2683 }
2684
2685 case CSN_FIXED:
2686 { /* Verify the fixed bits */
2687 guint8 no_of_bits = (guint8) pDescr->i;
Vadim Yanitskiy39a65052020-01-25 01:24:59 +07002688 bitvec_write_field(vector, writeIndex, pDescr->offset, no_of_bits);
Harald Welte570f9132020-03-19 15:03:01 +01002689 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)pDescr->offset);
Ivan Kluchnikov487a1412011-12-21 13:17:53 +03002690 remaining_bits_len -= no_of_bits;
2691 bit_offset += no_of_bits;
2692 pDescr++;
2693 break;
2694 }
2695
2696 case CSN_CALLBACK:
2697 {
2698 return ProcessError(writeIndex,"csnStreamEncoder Callback not implemented", -1, pDescr);
2699 break;
2700 }
2701
2702 case CSN_TRAP_ERROR:
2703 {
2704 return ProcessError(writeIndex,"csnStreamEncoder", pDescr->i, pDescr);
2705 }
2706
2707 case CSN_END:
2708 {
2709 ar->remaining_bits_len = remaining_bits_len;
2710 ar->bit_offset = bit_offset;
2711 return remaining_bits_len;
2712 }
2713
2714 default:
2715 {
2716 assert(0);
2717 }
2718
2719 }
2720
2721 } while (remaining_bits_len >= 0);
2722
2723 return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
2724}