ipse has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/18231 )
Change subject: gsm0808: Implement helper functions for CONFUSION BSSMAP message decoding. ...................................................................... gsm0808: Implement helper functions for CONFUSION BSSMAP message decoding. Also add a test for an actual CONFUSION message parsing. Change-Id: If8afd2d096fb66c6c2f255a08fc1129de3d09cec --- M include/osmocom/gsm/gsm0808.h M include/osmocom/gsm/protocol/gsm_08_08.h M src/gsm/gsm0808.c M src/gsm/libosmogsm.map M tests/gsm0808/gsm0808_test.c M tests/gsm0808/gsm0808_test.ok 6 files changed, 111 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/31/18231/1 diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 5a33f60..34cec3c 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -319,6 +319,9 @@ * \returns Cause value */ enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp); +const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer); +const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer); + extern const struct value_string gsm0808_lcls_config_names[]; extern const struct value_string gsm0808_lcls_control_names[]; extern const struct value_string gsm0808_lcls_status_names[]; diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index e791b07..8b7ed8c 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -669,3 +669,16 @@ GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04, GSM0808_LCLS_STS_NA = 0xFF }; + +/* 3GPP TS 48.008 3.2.2.32 Diagnostics */ +struct gsm0808_diagnostics { + uint8_t error_pointer_octet; +#if OSMO_IS_LITTLE_ENDIAN + uint8_t error_pointer_bit_spare:4, + error_pointer_bit:4; +#elif OSMO_IS_BIG_ENDIAN + uint8_t error_pointer_bit:4, + error_pointer_bit_spare:4; +#endif + uint8_t msg[0]; /*! received message which provoked the error */ +} __attribute__((packed)); diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 788f6c3..28f487e 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -21,6 +21,8 @@ * */ +#include <string.h> + #include <osmocom/core/byteswap.h> #include <osmocom/gsm/gsm0808.h> #include <osmocom/gsm/gsm0808_utils.h> @@ -34,6 +36,9 @@ * message generation/encoding. */ +/*! Char buffer to return strings from functions */ +static __thread char str_buff[512]; + /*! Create "Complete L3 Info" for AoIP, legacy implementation. * Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros. * \param[in] msg_l3 msgb containing Layer 3 Message @@ -1670,6 +1675,37 @@ return buf[0]; } +const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer) +{ + if (pointer == 0) + return "Error location not determined"; + else if (pointer == 1) + return "The first octet of the message received (i.e. the message type) was found erroneous (unknown)"; + else if (pointer == 0xfd) + return "The first octet of the BSSAP header (Discrimination) was found erroneous"; + else if (pointer == 0xfe) + return "(DTAP only) The DLCI (second) octet of the BSSAP header was found erroneous"; + else if (pointer == 0xff) + return "The last octet of the BSSAP header (length indicator) was found erroneous"; + + snprintf(str_buff, sizeof(str_buff), "The %d octet of the message received was found erroneous", pointer); + return str_buff; +} + +const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer) +{ + if (bit_pointer == 0) { + return "No particular part of the octet is indicated"; + } else if (bit_pointer > 8) { + return "Reserved value"; + } + + snprintf(str_buff, sizeof(str_buff), + "An error was provoked by the field whose most significant bit is in bit position %d", + bit_pointer); + return str_buff; +} + const struct value_string gsm0808_lcls_config_names[] = { { GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" }, { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL, diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 1ff1286..bf0cc01 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -158,6 +158,8 @@ gsm0808_cause_name; gsm0808_cause_class_name; gsm0808_get_cause; +gsm0808_diagnostics_octet_location_str; +gsm0808_diagnostics_bit_location_str; gsm0808_create_ass; gsm0808_create_ass2; gsm0808_create_assignment_completed; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index ce73390..9e1e52e 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -379,6 +379,55 @@ msgb_free(msg); } +static void test_dec_confusion() +{ + static const uint8_t hex[] = + { 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 }; + struct tlv_parsed tp; + int diag_len; + enum gsm0808_cause cause; + enum gsm0808_cause_class cause_class; + struct gsm0808_diagnostics *diag; + + printf("Testing decoding CONFUSION\n"); + + tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0); + + /* Check for the Cause and Diagnostic mandatory elements */ + if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) { + printf("Either Cause or Diagnostic mandatory IE are not detected\n"); + return; + } + + diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC); + if (diag_len < 5) { + printf("Diagnostic length is too short: %d (expected > 5)\n", + diag_len); + return; + } + + cause = gsm0808_get_cause(&tp); + if ((int)cause < 0) { + printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause)); + return; + } + cause_class = gsm0808_cause_class(cause); + printf(" Cause class %d/0x%x (%s)\n", + cause_class, cause_class, gsm0808_cause_class_name(cause_class)); + printf(" Cause %d/0x%x (%s)\n", + cause, cause, gsm0808_cause_name(cause)); + + diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC); + printf(" Diagnostics error octet location %d (%s)\n", + diag->error_pointer_octet, + gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet)); + printf(" Diagnostics error bit location %d (%s)\n", + diag->error_pointer_bit, + gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit)); + printf(" Diagnostics message that provoked the error: %s\n", + osmo_hexdump(diag->msg, diag_len-2)); +} + static void test_create_ass() { static const uint8_t res1[] = @@ -2422,6 +2471,8 @@ test_gsm0808_cell_id_to_from_cgi(); + test_dec_confusion(); + printf("Done\n"); return EXIT_SUCCESS; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index b620e36..eaae7a6 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -910,4 +910,10 @@ --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777 --> gsm0808_cell_id{LAI} = LAI:777-007-7777 --> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777 +Testing decoding CONFUSION + Cause class 5/0x5 (Invalid message) + Cause 82/0x52 (INFORMATION ELEMENT OR FIELD MISSING) + Diagnostics error octet location 0 (Error location not determined) + Diagnostics error bit location 15 (Reserved value) + Diagnostics message that provoked the error: 00 03 25 03 25 Done -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/18231 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: If8afd2d096fb66c6c2f255a08fc1129de3d09cec Gerrit-Change-Number: 18231 Gerrit-PatchSet: 1 Gerrit-Owner: ipse <alexander.cheme...@gmail.com> Gerrit-MessageType: newchange