CSN_DESCR descr[2];
gint16 Status;
csnStream_t arT = *ar;
- proto_item *ti;
+ proto_item *ti = NULL;
proto_tree *test_tree;
descr[0] = pChoice->descr;
descr[1].type = CSN_END;
pui8 = pui8DATA(data, pDescr->offset);
*pui8 = i;
- proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s Choice: %s (%d)",
- decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
- pDescr->sz, value);
- bit_offset += no_of_bits;
- remaining_bits_len -= no_of_bits;
+ if (pDescr->sz) {
+ proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+no_of_bits-1)>>3)-(bit_offset>>3)+1, "%s Choice: %s (%d)",
+ decode_bits_in_field(bit_offset, no_of_bits, tvb_get_bits8(tvb, bit_offset, no_of_bits)),
+ pDescr->sz, value);
+ }
- ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
- test_tree = proto_item_add_subtree(ti, ett_csn1);
+ if (!pChoice->keep_bits) {
+ bit_offset += no_of_bits;
+ remaining_bits_len -= no_of_bits;
+ }
+
+ if (pDescr->sz) {
+ ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
+ test_tree = proto_item_add_subtree(ti, ett_csn1);
+ } else {
+ test_tree = tree;
+ }
csnStreamInit(&arT, bit_offset, remaining_bits_len);
Status = csnStreamDissector(test_tree, &arT, descr, tvb, data, ett_csn1);
if (Status >= 0)
{
- proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
+ if (ti)
+ proto_item_set_len(ti,((arT.bit_offset-1)>>3) - (bit_offset>>3)+1);
remaining_bits_len = arT.remaining_bits_len;
bit_offset = arT.bit_offset;
}
gint16 Status = -1;
proto_item *ti;
proto_tree *test_tree;
- guint8 length = tvb_get_bits8(tvb, bit_offset, length_len);
+ guint8 length = 0;
+
+ if (length_len) {
+ length = tvb_get_bits8(tvb, bit_offset, length_len);
- proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length_len-1)>>3)-(bit_offset>>3)+1, "%s %s length: %d",
- decode_bits_in_field(bit_offset, length_len, length),
- pDescr->sz, length);
+ proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length_len-1)>>3)-(bit_offset>>3)+1, "%s %s length: %d",
+ decode_bits_in_field(bit_offset, length_len, length),
+ pDescr->sz, length);
- bit_offset += length_len;
- remaining_bits_len -= length_len;
- ti = proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length-1)>>3)-(bit_offset>>3) + 1, "%s", pDescr->sz);
+ bit_offset += length_len;
+ remaining_bits_len -= length_len;
+
+ ti = proto_tree_add_text(tree, tvb, bit_offset>>3, ((bit_offset+length-1)>>3)-(bit_offset>>3) + 1, "%s", pDescr->sz);
+ } else {
+ ti = proto_tree_add_text(tree, tvb, bit_offset>>3, 1, "%s", pDescr->sz);
+ }
test_tree = proto_item_add_subtree(ti, ett_csn1);
- csnStreamInit(&arT, bit_offset, length);
+ csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len);
Status = serialize(test_tree, &arT, tvb, pvDATA(data, pDescr->offset), ett_csn1);
if (Status >= 0)
{
- remaining_bits_len -= length;
- bit_offset += length;
+ if (length > 0) {
+ remaining_bits_len -= length;
+ bit_offset += length;
+ } else {
+ proto_item_set_len(ti,((arT.bit_offset - bit_offset)>>3)+1);
+ remaining_bits_len = arT.remaining_bits_len;
+ bit_offset = arT.bit_offset;
+ }
pDescr++;
}
else
guint8 no_of_bits = (guint8) pDescr->i;
if (remaining_bits_len >= no_of_bits)
{
- if (no_of_bits <= 8)
- {
- guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
- pui8 = pui8DATA(data, pDescr->offset);
- *pui8 = ui8;
- proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
+ if (no_of_bits <= 8)
+ {
+ guint8 ui8 = tvb_get_bits8(tvb, bit_offset, no_of_bits);
+ pui8 = pui8DATA(data, pDescr->offset);
+ *pui8 = ui8;
+ proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
- }
- else if (no_of_bits <= 16)
- {
- guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
- pui16 = pui16DATA(data, pDescr->offset);
- *pui16 = ui16;
- proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
- }
- else if (no_of_bits <= 32)
- {
- guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
- pui32 = pui32DATA(data, pDescr->offset);
- *pui32 = ui32;
- proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
+ }
+ else if (no_of_bits <= 16)
+ {
+ guint16 ui16 = tvb_get_bits16(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
+ pui16 = pui16DATA(data, pDescr->offset);
+ *pui16 = ui16;
+ proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
+ }
+ else if (no_of_bits <= 32)
+ {
+ guint32 ui32 = tvb_get_bits32(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
+ pui32 = pui32DATA(data, pDescr->offset);
+ *pui32 = ui32;
+ proto_tree_add_bits_item(tree, *(pDescr->serialize.hf_ptr), tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
}
else
{
guint8 bits;
guint8 value;
+ gboolean keep_bits;
CSN_DESCR descr;
} CSN_ChoiceElement_t;
#define M_TYPE(_STRUCT, _MEMBER, _MEMBER_TYPE)\
{CSN_TYPE, 0, {(void*)CSNDESCR_##_MEMBER_TYPE}, offsetof(_STRUCT, _MEMBER), FALSE, #_MEMBER, {(StreamSerializeFcn_t)0}}
+/******************************************************************************
+ * M_TYPE_LABEL(Par1, Par2, Par3, Par4)
+ * Same as M_TYPE but allows to define a custom string for the subtree
+ * <list> ::= {1 <type>} ** 0 ;
+ * Par1: C structure name
+ * Par2: C structure element name
+ * Par3: type of member
+ * Par4: C string for the text
+ *****************************************************************************/
+#define M_TYPE_LABEL(_STRUCT, _MEMBER, _MEMBER_TYPE, _LABEL)\
+ {CSN_TYPE, 0, {(void*)CSNDESCR_##_MEMBER_TYPE}, offsetof(_STRUCT, _MEMBER), FALSE, _LABEL, {(StreamSerializeFcn_t)0}}
+
/******************************************************************************
* M_UNION(Par1, Par2)
* Informs the CSN.1 library that a union follows and how many possible choices
#define M_CHOICE(_STRUCT, _MEMBER, _CHOICE, _ElementCount)\
{CSN_CHOICE, _ElementCount, {(void*)_CHOICE}, offsetof(_STRUCT, _MEMBER), FALSE, #_CHOICE, {(StreamSerializeFcn_t)0}}
+/******************************************************************************
+ * M_CHOICE_IL(Par1, Par2, Par3, Par4)
+ * See M_CHOICE above, but displayed inline (i.e. no specific elements are
+ * displayed to show there was a choice
+ *****************************************************************************/
+#define M_CHOICE_IL(_STRUCT, _MEMBER, _CHOICE, _ElementCount)\
+ {CSN_CHOICE, _ElementCount, {(void*)_CHOICE}, offsetof(_STRUCT, _MEMBER), FALSE, NULL, {(StreamSerializeFcn_t)0}}
+
/******************************************************************************
* M_FIXED(Par1, Par2, Par3)
* Defines a fixed value of type integer which should be fetched from or stored
* Par1: C structure name
* Par2: gives the length of the fixed number in bits.
* Par3: the value of the number. If the expected value is not present in
-* the message the unpacking procedure is aborted
+ * the message the unpacking procedure is aborted
*****************************************************************************/
#define M_FIXED(_STRUCT, _BITS, _BITVALUE)\
{CSN_FIXED, _BITS, {0}, _BITVALUE, FALSE, #_BITVALUE, {(StreamSerializeFcn_t)0}}
+/******************************************************************************
+ * M_FIXED_LABEL(Par1, Par2, Par3, Par4)
+ * Same as M_FIXED but allows to define a custom string for the subtree
+ * Par1: C structure name
+ * Par2: gives the length of the fixed number in bits.
+ * Par3: the value of the number. If the expected value is not present in
+ * the message the unpacking procedure is aborted
+ * Par4: C string for the text
+ *****************************************************************************/
+#define M_FIXED_LABEL(_STRUCT, _BITS, _BITVALUE, _LABEL)\
+ {CSN_FIXED, _BITS, {0}, _BITVALUE, FALSE, _LABEL, {(StreamSerializeFcn_t)0}}
+
/******************************************************************************
* M_SERIALIZE(Par1, Par2, Par3)
* Allows using a complete free format of data being encoded or decoded.
static const
CSN_ChoiceElement_t IA_EGPRS_Choice[] =
{
- {2, 0x00, M_TYPE (IA_EGPRS_t, u.IA_EGPRS_PUA, IA_EGPRS_00_t)},
- {2, 0x01, CSN_ERROR(IA_EGPRS_t, "01 <IA_EGPRS>", CSN_ERROR_STREAM_NOT_SUPPORTED)},
- {1, 0x01, CSN_ERROR(IA_EGPRS_t, "1 <IA_EGPRS>", CSN_ERROR_STREAM_NOT_SUPPORTED)}
+ {2, 0x00, 0, M_TYPE (IA_EGPRS_t, u.IA_EGPRS_PUA, IA_EGPRS_00_t)},
+ {2, 0x01, 0, CSN_ERROR(IA_EGPRS_t, "01 <IA_EGPRS>", CSN_ERROR_STREAM_NOT_SUPPORTED)},
+ {1, 0x01, 0, CSN_ERROR(IA_EGPRS_t, "1 <IA_EGPRS>", CSN_ERROR_STREAM_NOT_SUPPORTED)}
};
/* Please observe the double usage of UnionType element.
static const
CSN_ChoiceElement_t PacketPollingID[] =
{
- {1, 0, M_TYPE(PacketPollingID_t, u.Global_TFI, Global_TFI_t)},
- {2, 0x02, M_UINT(PacketPollingID_t, u.TLLI, 32, &hf_packetpollingid_tlli)},
- {3, 0x06, M_UINT(PacketPollingID_t, u.TQI, 16, &hf_packetpollingid_tqi)},
-/*{3, 0x07 , M_TYPE(PacketUplinkID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},*/
+ {1, 0, 0, M_TYPE(PacketPollingID_t, u.Global_TFI, Global_TFI_t)},
+ {2, 0x02, 0, M_UINT(PacketPollingID_t, u.TLLI, 32, &hf_packetpollingid_tlli)},
+ {3, 0x06, 0, M_UINT(PacketPollingID_t, u.TQI, 16, &hf_packetpollingid_tqi)},
+/*{3, 0x07 , 0, M_TYPE(PacketUplinkID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},*/
};
static const
static const
CSN_ChoiceElement_t SI13_PBCCH_Description_Channel[] =
{/* this one is used in SI13*/
- {2, 0x00 , M_NULL(PBCCH_Description_t, u.dummy)},/*Default to BCCH carrier*/
- {2, 0x01 , M_UINT(PBCCH_Description_t, u.ARFCN, 10, &hf_pbcch_description_arfcn)},
- {1, 0x01 , M_UINT(PBCCH_Description_t, u.MAIO, 6, &hf_pbcch_description_maio)},
+ {2, 0x00, 0, M_NULL(PBCCH_Description_t, u.dummy)},/*Default to BCCH carrier*/
+ {2, 0x01, 0, M_UINT(PBCCH_Description_t, u.ARFCN, 10, &hf_pbcch_description_arfcn)},
+ {1, 0x01, 0, M_UINT(PBCCH_Description_t, u.MAIO, 6, &hf_pbcch_description_maio)},
};
static const
static const
CSN_ChoiceElement_t MS_RA_capability_value_Choice[] =
{
- {4, AccTech_GSMP, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
- {4, AccTech_GSME, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
- {4, AccTech_GSM1800, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
- {4, AccTech_GSM1900, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
- {4, AccTech_GSM850, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
- {4, AccTech_GSMOther, M_SERIALIZE (MS_RA_capability_value_t, u.Additional_access_technologies, 7, Additional_access_technologies_Dissector)}, /* Short Form */
+ {4, AccTech_GSMP, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
+ {4, AccTech_GSME, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
+ {4, AccTech_GSM1800, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
+ {4, AccTech_GSM1900, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
+ {4, AccTech_GSM850, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Content, 7, Content_Dissector)}, /* Long Form */
+ {4, AccTech_GSMOther, 0, M_SERIALIZE (MS_RA_capability_value_t, u.Additional_access_technologies, 7, Additional_access_technologies_Dissector)}, /* Short Form */
};
static const
static const
CSN_ChoiceElement_t MultibandChoice[] =
{
- {3, 0x00, M_UINT(Multiband_t, u.A5_Bits, 4, &hf_multiband_a5_bits)},
- {3, 0x05, M_TYPE(Multiband_t, u.ARC, ARC_t)},
- {3, 0x06, M_TYPE(Multiband_t, u.ARC, ARC_t)},
- {3, 0x01, M_TYPE(Multiband_t, u.ARC, ARC_t)},
- {3, 0x02, M_TYPE(Multiband_t, u.ARC, ARC_t)},
- {3, 0x04, M_TYPE(Multiband_t, u.ARC, ARC_t)},
+ {3, 0x00, 0, M_UINT(Multiband_t, u.A5_Bits, 4, &hf_multiband_a5_bits)},
+ {3, 0x05, 0, M_TYPE(Multiband_t, u.ARC, ARC_t)},
+ {3, 0x06, 0, M_TYPE(Multiband_t, u.ARC, ARC_t)},
+ {3, 0x01, 0, M_TYPE(Multiband_t, u.ARC, ARC_t)},
+ {3, 0x02, 0, M_TYPE(Multiband_t, u.ARC, ARC_t)},
+ {3, 0x04, 0, M_TYPE(Multiband_t, u.ARC, ARC_t)},
};
static const
static const
CSN_ChoiceElement_t PacketResourceRequestID[] =
{
- {1, 0, M_TYPE(PacketResourceRequestID_t, u.Global_TFI, Global_TFI_t)},
- {1, 0x01, M_UINT(PacketResourceRequestID_t, u.TLLI, 32, &hf_packetresourcerequestid_tlli)},
+ {1, 0, 0, M_TYPE(PacketResourceRequestID_t, u.Global_TFI, Global_TFI_t)},
+ {1, 0x01, 0, M_UINT(PacketResourceRequestID_t, u.TLLI, 32, &hf_packetresourcerequestid_tlli)},
};
static const
static const
CSN_ChoiceElement_t PacketUplinkID[] =
{
- {1, 0 , M_TYPE(PacketUplinkID_t, u.Global_TFI, Global_TFI_t)},
- {2, 0x02 , M_UINT(PacketUplinkID_t, u.TLLI, 32, &hf_packetuplinkid_tlli)},
- {3, 0x06 , M_UINT(PacketUplinkID_t, u.TQI, 16, &hf_packetuplinkid_tqi)},
- {3, 0x07 , M_TYPE(PacketUplinkID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
+ {1, 0, 0, M_TYPE(PacketUplinkID_t, u.Global_TFI, Global_TFI_t)},
+ {2, 0x02, 0, M_UINT(PacketUplinkID_t, u.TLLI, 32, &hf_packetuplinkid_tlli)},
+ {3, 0x06, 0, M_UINT(PacketUplinkID_t, u.TQI, 16, &hf_packetuplinkid_tqi)},
+ {3, 0x07, 0, M_TYPE(PacketUplinkID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
};
static const
static const
CSN_ChoiceElement_t PacketDownlinkID[] =
{
- {1, 0, M_TYPE(PacketDownlinkID_t, u.Global_TFI, Global_TFI_t)},
- {2, 0x02, M_UINT(PacketDownlinkID_t, u.TLLI, 32, &hf_packetdownlinkid_tlli)},
+ {1, 0, 0, M_TYPE(PacketDownlinkID_t, u.Global_TFI, Global_TFI_t)},
+ {2, 0x02, 0, M_UINT(PacketDownlinkID_t, u.TLLI, 32, &hf_packetdownlinkid_tlli)},
};
static const
static const
CSN_ChoiceElement_t PacketPowerControlTimingAdvanceID[] =
{
- {1, 0, M_TYPE(PacketPowerControlTimingAdvanceID_t, u.Global_TFI, Global_TFI_t)},
- {3, 0x06, M_UINT(PacketPowerControlTimingAdvanceID_t, u.TQI, 16, &hf_packetpowercontroltimingadvanceid_tqi)},
- {3, 0x07, M_TYPE(PacketPowerControlTimingAdvanceID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
+ {1, 0, 0, M_TYPE(PacketPowerControlTimingAdvanceID_t, u.Global_TFI, Global_TFI_t)},
+ {3, 0x06, 0, M_UINT(PacketPowerControlTimingAdvanceID_t, u.TQI, 16, &hf_packetpowercontroltimingadvanceid_tqi)},
+ {3, 0x07, 0, M_TYPE(PacketPowerControlTimingAdvanceID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
};
static const
static const
CSN_ChoiceElement_t RejectID[] =
{
- {1, 0x00, M_UINT(RejectID_t, u.TLLI, 32, &hf_rejectid_tlli)},
- {2, 0x02, M_TYPE(RejectID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
- {2, 0x03, M_TYPE(RejectID_t, u.Global_TFI, Global_TFI_t)},
+ {1, 0x00, 0, M_UINT(RejectID_t, u.TLLI, 32, &hf_rejectid_tlli)},
+ {2, 0x02, 0, M_TYPE(RejectID_t, u.Packet_Request_Reference, Packet_Request_Reference_t)},
+ {2, 0x03, 0, M_TYPE(RejectID_t, u.Global_TFI, Global_TFI_t)},
};
static const
static const
CSN_ChoiceElement_t PacketCellChangeOrderID[] =
{
- {1, 0, M_TYPE(PacketCellChangeOrderID_t, u.Global_TFI, Global_TFI_t)},
- {2, 0x02, M_UINT(PacketCellChangeOrderID_t, u.TLLI, 32, &hf_packetcellchangeorderid_tlli)},
+ {1, 0, 0, M_TYPE(PacketCellChangeOrderID_t, u.Global_TFI, Global_TFI_t)},
+ {2, 0x02, 0, M_UINT(PacketCellChangeOrderID_t, u.TLLI, 32, &hf_packetcellchangeorderid_tlli)},
};
/* PacketCellChangeOrderID_t; */
static const
CSN_ChoiceElement_t PNCDContainer[] =
{
- {1, 0x0, M_TYPE(PNCDContainer_t, u.PNCD_Container_Without_ID, PNCD_Container_Without_ID_t)},
- {1, 0x1, M_TYPE(PNCDContainer_t, u.PNCD_Container_With_ID, PNCD_Container_With_ID_t)},
+ {1, 0x0, 0, M_TYPE(PNCDContainer_t, u.PNCD_Container_Without_ID, PNCD_Container_Without_ID_t)},
+ {1, 0x1, 0, M_TYPE(PNCDContainer_t, u.PNCD_Container_With_ID, PNCD_Container_With_ID_t)},
};
static const
static const
CSN_ChoiceElement_t AdditionalMsRadAccessCapID[] =
{
- {1, 0, M_TYPE(AdditionalMsRadAccessCapID_t, u.Global_TFI, Global_TFI_t)},
- {1, 0x01, M_UINT(AdditionalMsRadAccessCapID_t, u.TLLI, 32, &hf_additionalmsradcap_tlli)},
+ {1, 0, 0, M_TYPE(AdditionalMsRadAccessCapID_t, u.Global_TFI, Global_TFI_t)},
+ {1, 0x01, 0, M_UINT(AdditionalMsRadAccessCapID_t, u.TLLI, 32, &hf_additionalmsradcap_tlli)},
};
static const