diff options
author | Ivan Kluchnikov <kluchnikovi@gmail.com> | 2012-10-10 19:43:37 +0400 |
---|---|---|
committer | Ivan Kluchnikov <kluchnikovi@gmail.com> | 2012-10-10 19:43:37 +0400 |
commit | 701d9f83f84aa8c51b49c23f196776b56fda15e0 (patch) | |
tree | 7e107394bb4165941b6c67e3e685f74e60d55241 /src/csn1.cpp | |
parent | 9eb552b2399a714495cff4b7dc38c70b133342bb (diff) |
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
Diffstat (limited to 'src/csn1.cpp')
-rw-r--r-- | src/csn1.cpp | 155 |
1 files changed, 125 insertions, 30 deletions
diff --git a/src/csn1.cpp b/src/csn1.cpp index b0ed73de..1859bebd 100644 --- a/src/csn1.cpp +++ b/src/csn1.cpp @@ -206,6 +206,12 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig 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 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig { 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 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig { 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)); + guint8 length = bitvec_read_field(vector, readIndex, length_len); + + LOGPC(DCSN1, LOGL_NOTICE, "%s length = %d | ", pDescr->sz , (int)length); arT.direction = 1; - bit_offset += 7; - remaining_bits_len -= 7; + bit_offset += length_len; + remaining_bits_len -= length_len; - csnStreamInit(&arT, bit_offset, remaining_bits_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 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig 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 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector { 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector { 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector 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 @@ gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector } bitvec_write_field(vector, writeIndex, !Tag, 1); bit_offset++; + remaining_bits_len--; Tag = STANDARD_TAG; /* in case it was set to "reversed" */ pDescr++; break; |