Ported fixes and improvements from Wireshark for RLC/MAC control block decoding. Part 1.
Generic improvements to the csn.1 dissector include:
• Added a flag to the type descriptor structure so that any type can (potentially) flagged as xxx_OR_NULL. This was specifically needed for UINT_OR_NULL for the ms capabilities struct.
• Changed the CSN_SERIALIZE so that the length of the length field can be specified.
• For CSN_NEXT_EXIST removed the requirement that the next type be CSN_END, to allow truncation of multiple IEs.
• For CSN_LEFT_ALIGNED_VAR_BITMAP corrected the handling of bit_offset.
• Added a new type CSN_PADDING_BITS to make inspection of padding bits more convenient.
• Improved the CSN_RECURSIVE_TARRAY_1 to show the array index.
Improvements to the gsm_rlcmac dissector include:
• Rework the definition of EGPRS Ack/Nack Description so that the length IE (and absence thereof) is handled correctly.
• Added Padding Bits definitions to all PDUs
• Change the Multislot_capability_t and Content_t definitions to allow truncation at any IE
diff --git a/src/csn1.cpp b/src/csn1.cpp
index b0ed73d..1859beb 100644
--- a/src/csn1.cpp
+++ b/src/csn1.cpp
@@ -206,6 +206,12 @@
LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
/* end add the bit value to protocol tree */
}
+ else if(pDescr->may_be_null)
+ {
+ pui8 = pui8DATA(data, pDescr->offset);
+ *pui8 = 0;
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = NULL | ", pDescr->sz);
+ }
else
{
return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
@@ -254,14 +260,33 @@
{
return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
}
+ remaining_bits_len -= no_of_bits;
+ bit_offset += no_of_bits;
+ }
+ else if(pDescr->may_be_null)
+ {
+ if (no_of_bits <= 8)
+ {
+ pui8 = pui8DATA(data, pDescr->offset);
+ *pui8 = 0;
+ }
+ else if (no_of_bits <= 16)
+ {
+ pui16 = pui16DATA(data, pDescr->offset);
+ *pui16 = 0;
+ }
+ else if (no_of_bits <= 32)
+ {
+ pui32 = pui32DATA(data, pDescr->offset);
+ *pui32 = 0;
+ }
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = NULL | ", pDescr->sz);
}
else
{
return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
}
- remaining_bits_len -= no_of_bits;
- bit_offset += no_of_bits;
pDescr++;
break;
}
@@ -548,20 +573,23 @@
{
StreamSerializeFcn_t serialize = pDescr->serialize.fcn;
csnStream_t arT = *ar;
+ guint8 length_len = pDescr->i;
gint16 Status = -1;
- LOGPC(DCSN1, LOGL_NOTICE, "%s length = %d | ", pDescr->sz , (int)bitvec_read_field(vector, readIndex, 7));
- arT.direction = 1;
- bit_offset += 7;
- remaining_bits_len -= 7;
+ guint8 length = bitvec_read_field(vector, readIndex, length_len);
- csnStreamInit(&arT, bit_offset, remaining_bits_len);
+ LOGPC(DCSN1, LOGL_NOTICE, "%s length = %d | ", pDescr->sz , (int)length);
+ arT.direction = 1;
+ bit_offset += length_len;
+ remaining_bits_len -= length_len;
+
+ csnStreamInit(&arT, bit_offset, length);
Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
if (Status >= 0)
{
- remaining_bits_len = arT.remaining_bits_len;
- bit_offset = arT.bit_offset;
+ remaining_bits_len -= length;
+ bit_offset += length;
pDescr++;
}
else
@@ -958,18 +986,12 @@
pui8 = pui8DATA(data, pDescr->offset);
/* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
- if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
+ if ((pDescr->may_be_null) && (remaining_bits_len == 0))
{ /* no more bits to decode is fine here - end of message detected and allowed */
/* Skip i entries + this entry */
pDescr += pDescr->i + 1;
- /* pDescr now must be pointing to a CSN_END entry, if not this is an error */
- if ( pDescr->type != CSN_END )
- { /* Substract one more bit from remaining_bits_len to make the "not enough bits" error to be triggered */
- remaining_bits_len--;
- }
-
/* Set the data member to "not exist" */
*pui8 = 0;
break;
@@ -1147,6 +1169,38 @@
break;
}
+ case CSN_PADDING_BITS:
+ { /* Padding from here and to the end of message */
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = ", pDescr->sz);
+ if (remaining_bits_len > 0)
+ {
+ while (remaining_bits_len > 0)
+ {
+ guint8 bits_to_handle = remaining_bits_len%8;
+ if (bits_to_handle > 0)
+ {
+ LOGPC(DCSN1, LOGL_NOTICE, "%u|", bitvec_read_field(vector, readIndex, bits_to_handle));
+ remaining_bits_len -= bits_to_handle;
+ bit_offset += bits_to_handle;
+ }
+ else if (bits_to_handle == 0)
+ {
+ LOGPC(DCSN1, LOGL_NOTICE, "%u|", bitvec_read_field(vector, readIndex, 8));
+ remaining_bits_len -= 8;
+ bit_offset += 8;
+ }
+ }
+ }
+ if (remaining_bits_len < 0)
+ {
+ return ProcessError(readIndex,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
+ }
+
+ /* Padding was successfully extracted or it was empty */
+ pDescr++;
+ break;
+ }
+
case CSN_VARIABLE_ARRAY:
{ /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
* {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
@@ -1434,6 +1488,10 @@
LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
/* end add the bit value to protocol tree */
}
+ else if(pDescr->may_be_null)
+ {
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = NULL | ", pDescr->sz);
+ }
else
{
return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
@@ -1479,14 +1537,19 @@
{
return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr);
}
+
+ remaining_bits_len -= no_of_bits;
+ bit_offset += no_of_bits;
+ }
+ else if(pDescr->may_be_null)
+ {
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = NULL | ", pDescr->sz);
}
else
{
return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
}
- remaining_bits_len -= no_of_bits;
- bit_offset += no_of_bits;
pDescr++;
break;
}
@@ -1766,19 +1829,20 @@
{
StreamSerializeFcn_t serialize = pDescr->serialize.fcn;
csnStream_t arT = *ar;
+ guint8 length_len = pDescr->i;
gint16 Status = -1;
unsigned lengthIndex;
// store writeIndex for length value (7 bit)
- lengthIndex = writeIndex;
- writeIndex += 7;
- bit_offset += 7;
- remaining_bits_len -= 7;
+ lengthIndex = writeIndex;
+ writeIndex += length_len;
+ bit_offset += length_len;
+ remaining_bits_len -= length_len;
arT.direction = 0;
csnStreamInit(&arT, bit_offset, remaining_bits_len);
Status = serialize(&arT, vector, writeIndex, pvDATA(data, pDescr->offset));
-
- bitvec_write_field(vector, lengthIndex, writeIndex-lengthIndex-7, 7);
+
+ bitvec_write_field(vector, lengthIndex, writeIndex-lengthIndex-length_len, length_len);
LOGPC(DCSN1, LOGL_NOTICE, "%s length = %u | ", pDescr->sz , (unsigned)(writeIndex-lengthIndex));
if (Status >= 0)
@@ -2179,18 +2243,12 @@
pui8 = pui8DATA(data, pDescr->offset);
/* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
- if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
+ if ((pDescr->may_be_null) && (remaining_bits_len == 0))
{ /* no more bits to decode is fine here - end of message detected and allowed */
/* Skip i entries + this entry */
pDescr += pDescr->i + 1;
- /* pDescr now must be pointing to a CSN_END entry, if not this is an error */
- if ( pDescr->type != CSN_END )
- { /* Substract one more bit from remaining_bits_len to make the "not enough bits" error to be triggered */
- remaining_bits_len--;
- }
-
break;
}
@@ -2365,6 +2423,42 @@
break;
}
+ case CSN_PADDING_BITS:
+ { /* Padding from here and to the end of message */
+ LOGPC(DCSN1, LOGL_NOTICE, "%s = ", pDescr->sz);
+ guint8 filler = 0x2b;
+ if (remaining_bits_len > 0)
+ {
+ while (remaining_bits_len > 0)
+ {
+ guint8 bits_to_handle = remaining_bits_len%8;
+ if (bits_to_handle > 0)
+ {
+ guint8 fl = filler&(0xff>>(8-bits_to_handle));
+ bitvec_write_field(vector, writeIndex, fl, bits_to_handle);
+ LOGPC(DCSN1, LOGL_NOTICE, "%u|", fl);
+ remaining_bits_len -= bits_to_handle;
+ bit_offset += bits_to_handle;
+ }
+ else if (bits_to_handle == 0)
+ {
+ bitvec_write_field(vector, writeIndex, filler, 8);
+ LOGPC(DCSN1, LOGL_NOTICE, "%u|", filler);
+ remaining_bits_len -= 8;
+ bit_offset += 8;
+ }
+ }
+ }
+ if (remaining_bits_len < 0)
+ {
+ return ProcessError(writeIndex,"csnStreamDissector", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
+ }
+
+ /* Padding was successfully extracted or it was empty */
+ pDescr++;
+ break;
+ }
+
case CSN_VARIABLE_ARRAY:
{ /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
* {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
@@ -2555,6 +2649,7 @@
}
bitvec_write_field(vector, writeIndex, !Tag, 1);
bit_offset++;
+ remaining_bits_len--;
Tag = STANDARD_TAG; /* in case it was set to "reversed" */
pDescr++;
break;