This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
laforge gerrit-no-reply at lists.osmocom.orglaforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/18853 ) Change subject: Revert "add osmo_mobile_identity API" ...................................................................... Revert "add osmo_mobile_identity API" This reverts commit d1ceca9d48eb3d8b212f386a1ebb35d8fc612297, as it introduces regressions in both osmo-msc and osmo-nitb which have been causing failing builds for several days now. Change-Id: I4bd958d0cd2ab4b0c4725e6d114f4404d725fcf7 --- M include/osmocom/core/utils.h M include/osmocom/gsm/gsm48.h M src/gb/gprs_bssgp.c M src/gb/gprs_bssgp_bss.c M src/gsm/gsm0808.c M src/gsm/gsm29118.c M src/gsm/gsm48.c M src/gsm/libosmogsm.map M src/utils.c M tests/gsm0408/gsm0408_test.c M tests/gsm0408/gsm0408_test.ok M tests/utils/utils_test.c M tests/utils/utils_test.ok 13 files changed, 150 insertions(+), 1,165 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/53/18853/1 diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 8619120..e637786 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -55,7 +55,6 @@ uint8_t osmo_char2bcd(char c); int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibble, int end_nibble, bool allow_hex); -int osmo_str2bcd(uint8_t *dst, size_t dst_size, const char *digits, int start_nibble, int end_nibble, bool allow_hex); int osmo_hexparse(const char *str, uint8_t *b, int max_len); diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index 81f6028..7c68b1d 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -4,12 +4,10 @@ #include <stdbool.h> -#include <osmocom/core/defs.h> #include <osmocom/core/msgb.h> #include <osmocom/gsm/tlv.h> #include <osmocom/gsm/protocol/gsm_04_08.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> #include <osmocom/gsm/gsm48_ie.h> #include <osmocom/gsm/gsm23003.h> @@ -50,55 +48,16 @@ void gsm48_generate_lai2(struct gsm48_loc_area_id *lai48, const struct osmo_location_area_id *lai); #define GSM48_MID_MAX_SIZE 11 -int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi) - OSMO_DEPRECATED("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);" - " *l = osmo_mobile_identity_encode_msgb(...)"); -int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi) - OSMO_DEPRECATED("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);" - " *l = osmo_mobile_identity_encode_msgb(...)"); -uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type) - OSMO_DEPRECATED("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);" - " *l = osmo_mobile_identity_encode_msgb(...)"); +int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi); +int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi); +uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type); +/* Convert Mobile Identity (10.5.1.4) to string */ +int gsm48_mi_to_string(char *string, int str_len, const uint8_t *mi, int mi_len); const char *gsm48_mi_type_name(uint8_t mi); -/* Convert encoded Mobile Identity (10.5.1.4) to string */ -int gsm48_mi_to_string(char *string, int str_len, const uint8_t *mi, int mi_len) - OSMO_DEPRECATED("Instead use osmo_mobile_identity_decode()"); -const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) - OSMO_DEPRECATED("Instead use osmo_mobile_identity_to_str_c()"); -char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len) - OSMO_DEPRECATED("Instead use osmo_mobile_identity_to_str_buf()"); -char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len) - OSMO_DEPRECATED("Instead use osmo_mobile_identity_to_str_c()"); - -/*! Decoded representation of a Mobile Identity (3GPP TS 24.008 10.5.1.4). - * See osmo_mobile_identity_decode() and osmo_mobile_identity_from_l3(). */ -struct osmo_mobile_identity { - /*! A GSM_MI_TYPE_* constant (like GSM_MI_TYPE_IMSI). */ - uint8_t type; - /*! Decoded Mobile Identity digits or TMSI value. IMSI, IMEI and IMEISV as digits like - * "12345678", and TMSI is represented as raw uint32_t. */ - union { - /*! type == GSM_MI_TYPE_IMSI. */ - char imsi[GSM23003_IMSI_MAX_DIGITS + 1]; - /*! type == GSM_MI_TYPE_IMEI. */ - char imei[GSM23003_IMEI_NUM_DIGITS + 1]; - /*! type == GSM_MI_TYPE_IMEISV. */ - char imeisv[GSM23003_IMEISV_NUM_DIGITS + 1]; - /*! TMSI / P-TMSI / M-TMSI integer value if type == GSM_MI_TYPE_TMSI. */ - uint32_t tmsi; - }; -}; - -int osmo_mobile_identity_to_str_buf(char *buf, size_t buflen, const struct osmo_mobile_identity *mi); -char *osmo_mobile_identity_to_str_c(void *ctx, const struct osmo_mobile_identity *mi); -int osmo_mobile_identity_cmp(const struct osmo_mobile_identity *a, const struct osmo_mobile_identity *b); -int osmo_mobile_identity_decode(struct osmo_mobile_identity *mi, const uint8_t *mi_data, uint8_t mi_len, - bool allow_hex); -int osmo_mobile_identity_decode_from_l3(struct osmo_mobile_identity *mi, struct msgb *msg, bool allow_hex); -int osmo_mobile_identity_encoded_len(const struct osmo_mobile_identity *mi, int *mi_digits); -int osmo_mobile_identity_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_mobile_identity *mi, bool allow_hex); -int osmo_mobile_identity_encode_msgb(struct msgb *msg, const struct osmo_mobile_identity *mi, bool allow_hex); +const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len); +char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len); +char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len); /* Parse Routeing Area Identifier */ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf); diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index 2784d0a..38794c2 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -1170,20 +1170,19 @@ /* IMSI */ if (dup->imsi && strlen(dup->imsi)) { - struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, dup->imsi); - msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - if (osmo_mobile_identity_encode_msgb(msg, &mi, false) <= 0) { - if (log_check_level(DBSSGP, LOGL_NOTICE)) { - char strbuf[64]; - osmo_mobile_identity_to_str_buf(strbuf, sizeof(strbuf), &mi); - LOGP(DBSSGP, LOGL_ERROR, - "NSEI=%u/BVCI=%u Cannot encode Mobile Identity %s\n", - nsei, bvci, strbuf); - } - msgb_free(msg); - return -EINVAL; - } + uint8_t mi[GSM48_MID_MAX_SIZE]; +/* gsm48_generate_mid_from_imsi() is guaranteed to never return more than 11, + * but somehow gcc (8.2) is not smart enough to figure this out and claims that + * the memcpy in msgb_tvlv_put() below will cause and out-of-bounds access up to + * mi[131], which is wrong */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + int imsi_len = gsm48_generate_mid_from_imsi(mi, dup->imsi); + OSMO_ASSERT(imsi_len <= GSM48_MID_MAX_SIZE); + if (imsi_len > 2) + msgb_tvlv_push(msg, BSSGP_IE_IMSI, + imsi_len-2, mi+2); +#pragma GCC diagnostic pop } /* DRX parameters */ @@ -1228,8 +1227,12 @@ struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph)); uint16_t drx_params = osmo_htons(pinfo->drx_params); + uint8_t mi[GSM48_MID_MAX_SIZE]; + int imsi_len = gsm48_generate_mid_from_imsi(mi, pinfo->imsi); struct gsm48_ra_id ra; - struct osmo_mobile_identity mi; + + if (imsi_len < 2) + return -EINVAL; msgb_nsei(msg) = nsei; msgb_bvci(msg) = ns_bvci; @@ -1238,23 +1241,16 @@ bgph->pdu_type = BSSGP_PDUT_PAGING_PS; else bgph->pdu_type = BSSGP_PDUT_PAGING_CS; - /* IMSI */ - mi = (struct osmo_mobile_identity){ .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, pinfo->imsi); - msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - if (osmo_mobile_identity_encode_msgb(msg, &mi, false) <= 0) { - if (log_check_level(DBSSGP, LOGL_NOTICE)) { - char strbuf[64]; - osmo_mobile_identity_to_str_buf(strbuf, sizeof(strbuf), &mi); - LOGP(DBSSGP, LOGL_ERROR, - "NSEI=%u/BVCI=%u Cannot encode Mobile Identity %s\n", - nsei, ns_bvci, strbuf); - } - msgb_free(msg); - return -EINVAL; - } - +/* gsm48_generate_mid_from_imsi() is guaranteed to never return more than 11, + * but somehow gcc (8.2) is not smart enough to figure this out and claims that + * the memcpy in msgb_tvlv_put() below will cause and out-of-bounds access up to + * mi[131], which is wrong */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + OSMO_ASSERT(imsi_len <= GSM48_MID_MAX_SIZE); + msgb_tvlv_put(msg, BSSGP_IE_IMSI, imsi_len-2, mi+2); +#pragma GCC diagnostic pop /* DRX Parameters */ msgb_tvlv_put(msg, BSSGP_IE_DRX_PARAMS, 2, (uint8_t *) &drx_params); diff --git a/src/gb/gprs_bssgp_bss.c b/src/gb/gprs_bssgp_bss.c index 9e9cefc..5c9d11c 100644 --- a/src/gb/gprs_bssgp_bss.c +++ b/src/gb/gprs_bssgp_bss.c @@ -178,17 +178,22 @@ const char *imsi) { struct msgb *msg = common_tx_radio_status(bctx); - struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, imsi); + uint8_t mi[GSM48_MID_MAX_SIZE]; + int imsi_len = gsm48_generate_mid_from_imsi(mi, imsi); if (!msg) return -ENOMEM; - - msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - if (osmo_mobile_identity_encode_msgb(msg, &mi, false) <= 0) { - msgb_free(msg); - return -EINVAL; - } +/* gsm48_generate_mid_from_imsi() is guaranteed to never return more than 11, + * but somehow gcc (8.2) is not smart enough to figure this out and claims that + * the memcpy in msgb_tvlv_put() below will cause and out-of-bounds access up to + * mi[131], which is wrong */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + OSMO_ASSERT(imsi_len <= GSM48_MID_MAX_SIZE); + /* strip the MI type and length values (2 bytes) */ + if (imsi_len > 2) + msgb_tvlv_put(msg, BSSGP_IE_IMSI, imsi_len-2, mi+2); +#pragma GCC diagnostic pop LOGPC(DBSSGP, LOGL_NOTICE, "IMSI=%s ", imsi); return common_tx_radio_status2(msg, cause); @@ -481,7 +486,6 @@ struct tlv_parsed tp; uint8_t ra[6]; int rc, data_len; - struct osmo_mobile_identity mi; memset(ra, 0, sizeof(ra)); @@ -506,11 +510,9 @@ goto err_mand_ie; if (!pinfo->imsi) pinfo->imsi = talloc_zero_size(pinfo, GSM_IMSI_LENGTH); - if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&tp, BSSGP_IE_IMSI), TLVP_LEN(&tp, BSSGP_IE_IMSI), false)) - goto err_mand_ie; - if (mi.type != GSM_MI_TYPE_IMSI) - goto err_mand_ie; - osmo_talloc_replace_string(pinfo, &pinfo->imsi, mi.imsi); + gsm48_mi_to_string(pinfo->imsi, GSM_IMSI_LENGTH, + TLVP_VAL(&tp, BSSGP_IE_IMSI), + TLVP_LEN(&tp, BSSGP_IE_IMSI)); /* DRX Parameters */ if (!TLVP_PRESENT(&tp, BSSGP_IE_DRX_PARAMS)) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 6560d4b..9fdf379 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -730,10 +730,9 @@ const uint8_t *chan_needed) { struct msgb *msg; - struct osmo_mobile_identity mi; + uint8_t mid_buf[GSM48_MI_SIZE + 2]; + int mid_len; uint32_t tmsi_sw; - uint8_t *l; - int rc; /* Mandatory elements! */ OSMO_ASSERT(imsi); @@ -751,15 +750,8 @@ msgb_v_put(msg, BSS_MAP_MSG_PAGING); /* mandatory IMSI 3.2.2.6 */ - mi = (struct osmo_mobile_identity){ .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, imsi); - l = msgb_tl_put(msg, GSM0808_IE_IMSI); - rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); - if (rc <= 0) { - msgb_free(msg); - return NULL; - } - *l = rc; + mid_len = gsm48_generate_mid_from_imsi(mid_buf, imsi); + msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2); /* TMSI 3.2.2.7 */ if (tmsi) { @@ -975,17 +967,9 @@ /* IMSI 3.2.2.6 */ if (params->imsi) { - uint8_t *l; - int rc; - struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, params->imsi); - l = msgb_tl_put(msg, GSM0808_IE_IMSI); - rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); - if (rc <= 0) { - msgb_free(msg); - return NULL; - } - *l = rc; + uint8_t mid_buf[GSM48_MI_SIZE + 2]; + int mid_len = gsm48_generate_mid_from_imsi(mid_buf, params->imsi); + msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2); } if (params->aoip_transport_layer) diff --git a/src/gsm/gsm29118.c b/src/gsm/gsm29118.c index 5c72b4d..2c02b2f 100644 --- a/src/gsm/gsm29118.c +++ b/src/gsm/gsm29118.c @@ -219,14 +219,12 @@ /* Encode IMSI from string representation and append to SGSaAP msg */ static void msgb_sgsap_imsi_put(struct msgb *msg, const char *imsi) { - int rc; - struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - uint8_t *l; - OSMO_STRLCPY_ARRAY(mi.imsi, imsi); - l = msgb_tl_put(msg, SGSAP_IE_IMSI); - rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); - /* This function fails to do error handling, so in case of error, leave the len == 0. */ - *l = rc > 0? rc : 0; + uint8_t buf[16]; + uint8_t len; + /* encoding is just like TS 04.08 */ + len = gsm48_generate_mid_from_imsi(buf, imsi); + /* skip first two bytes (tag+length) so we can use msgb_tlv_put */ + msgb_tlv_put(msg, SGSAP_IE_IMSI, len - 2, buf + 2); } /* Encode LAI from struct representation and append to SGSaAP msg */ diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index 11bd361..8d0998b 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -45,7 +45,6 @@ #include <osmocom/gsm/protocol/gsm_04_80.h> #include <osmocom/gsm/protocol/gsm_08_58.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> /*! \addtogroup gsm0408 * @{ @@ -459,500 +458,70 @@ return get_value_string(mi_type_names, mi); } -/*! Deprecated, see osmo_mobile_identity instead. - * Return a human readable representation of a Mobile Identity in caller-provided buffer. +/*! Return a human readable representation of a Mobile Identity in caller-provided buffer. * \param[out] buf caller-provided output buffer * \param[in] buf_len size of buf in bytes * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. * \param[in] mi_len Length of mi. * \return buf */ -char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi_data, uint8_t mi_len) +char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len) { - struct osmo_mobile_identity mi; - if (osmo_mobile_identity_decode(&mi, mi_data, mi_len, true)) { + uint8_t mi_type; + uint32_t tmsi; + char mi_string[GSM48_MI_SIZE]; + + mi_type = (mi && mi_len) ? (mi[0] & GSM_MI_TYPE_MASK) : GSM_MI_TYPE_NONE; + + switch (mi_type) { + case GSM_MI_TYPE_TMSI: + /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ + if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { + tmsi = osmo_load32be(&mi[1]); + snprintf(buf, buf_len, "TMSI-0x%08" PRIX32, tmsi); + } else { + snprintf(buf, buf_len, "TMSI-invalid"); + } + return buf; + + case GSM_MI_TYPE_IMSI: + case GSM_MI_TYPE_IMEI: + case GSM_MI_TYPE_IMEISV: + osmo_bcd2str(mi_string, sizeof(mi_string), mi, 1, (mi_len * 2) - (mi[0] & GSM_MI_ODD ? 0 : 1), true); + snprintf(buf, buf_len, "%s-%s", gsm48_mi_type_name(mi_type), mi_string); + return buf; + + default: snprintf(buf, buf_len, "unknown"); return buf; } - osmo_mobile_identity_to_str_buf(buf, buf_len, &mi); - return buf; } -/*! Deprecated, see osmo_mobile_identity instead. - * Return a human readable representation of a Mobile Identity in static buffer. +/*! Return a human readable representation of a Mobile Identity in static buffer. * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. * \param[in] mi_len Length of mi. * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid"... */ -const char *osmo_mi_name(const uint8_t *mi_data, uint8_t mi_len) +const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) { static __thread char mi_name[10 + GSM48_MI_SIZE + 1]; - struct osmo_mobile_identity mi; - if (osmo_mobile_identity_decode(&mi, mi_data, mi_len, true) == 0) - osmo_mobile_identity_to_str_buf(mi_name, sizeof(mi_name), &mi); - else - snprintf(mi_name, sizeof(mi_name), "unknown"); - return mi_name; + return osmo_mi_name_buf(mi_name, sizeof(mi_name), mi, mi_len); } -/*! Deprecated, see osmo_mobile_identity instead. - * Return a human readable representation of a Mobile Identity in dynamically-allocated buffer. +/*! Return a human readable representation of a Mobile Identity in dynamically-allocated buffer. * \param[in] ctx talloc context from which to allocate output buffer * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. * \param[in] mi_len Length of mi. * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid" in a * dynamically-allocated output buffer. */ -char *osmo_mi_name_c(const void *ctx, const uint8_t *mi_data, uint8_t mi_len) +char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len) { - struct osmo_mobile_identity mi; - if (osmo_mobile_identity_decode(&mi, mi_data, mi_len, true)) - return talloc_strdup((void*)ctx, "unknown"); - return osmo_mobile_identity_to_str_c((void*)ctx, &mi); -} - -/*! Extract Mobile Identity from encoded bytes (3GPP TS 24.008 10.5.1.4). - * - * On failure (negative return value), mi->type == GSM_MI_TYPE_NONE, mi->string[] is all-zero and mi->tmsi == - * GSM_RESERVED_TMSI. - * - * On success, mi->type reflects the decoded Mobile Identity type (GSM_MI_TYPE_IMSI, GSM_MI_TYPE_TMSI, GSM_MI_TYPE_IMEI - * or GSM_MI_TYPE_IMEISV). - * - * On success, mi->string always contains a human readable representation of the Mobile Identity digits: IMSI, IMEI and - * IMEISV as digits like "12345678", and TMSI as "0x" and 8 hexadecimal digits like "0x1234abcd". - * - * mi->tmsi contains the uint32_t TMSI value iff the extracted Mobile Identity was a TMSI, or GSM_RESERVED_TMSI - * otherwise. - * - * \param[out] mi Return buffer for decoded Mobile Identity. - * \param[in] mi_data The encoded Mobile Identity octets. - * \param[in] mi_len Number of octets in mi_data. - * \param[in] allow_hex If false, hexadecimal digits (>9) result in an error return value. - * \returns 0 on success, negative on error: -EBADMSG = invalid length indication or invalid data, - * -EINVAL = unknown Mobile Identity type. - */ -int osmo_mobile_identity_decode(struct osmo_mobile_identity *mi, const uint8_t *mi_data, uint8_t mi_len, - bool allow_hex) -{ - int rc; - int nibbles_len; - char *str; - size_t str_size; - - if (!mi_data || mi_len < 1) - return -EBADMSG; - - nibbles_len = (mi_len - 1) * 2 + ((mi_data[0] & GSM_MI_ODD) ? 1 : 0); - - *mi = (struct osmo_mobile_identity){ - .type = mi_data[0] & GSM_MI_TYPE_MASK, - }; - - /* First do length checks */ - switch (mi->type) { - case GSM_MI_TYPE_TMSI: - mi->tmsi = GSM_RESERVED_TMSI; - if (nibbles_len != (GSM23003_TMSI_NUM_BYTES * 2)) { - rc = -EBADMSG; - goto return_error; - } - break; - - case GSM_MI_TYPE_IMSI: - if (nibbles_len < GSM23003_IMSI_MIN_DIGITS || nibbles_len > GSM23003_IMSI_MAX_DIGITS) { - rc = -EBADMSG; - goto return_error; - } - str = mi->imsi; - str_size = sizeof(mi->imsi); - break; - - case GSM_MI_TYPE_IMEI: - if (nibbles_len != GSM23003_IMEI_NUM_DIGITS && nibbles_len != GSM23003_IMEI_NUM_DIGITS_NO_CHK) { - rc = -EBADMSG; - goto return_error; - } - str = mi->imei; - str_size = sizeof(mi->imei); - break; - - case GSM_MI_TYPE_IMEISV: - if (nibbles_len != GSM23003_IMEISV_NUM_DIGITS) { - rc = -EBADMSG; - goto return_error; - } - str = mi->imeisv; - str_size = sizeof(mi->imeisv); - break; - - default: - rc = -EINVAL; - goto return_error; - } - - /* Decode BCD digits */ - switch (mi->type) { - case GSM_MI_TYPE_TMSI: - /* MI is a 32bit integer TMSI. Length has been checked above. */ - if ((mi_data[0] & 0xf0) != 0xf0) { - /* A TMSI always has the first nibble == 0xf */ - rc = -EBADMSG; - goto return_error; - } - mi->tmsi = osmo_load32be(&mi_data[1]); - return 0; - - case GSM_MI_TYPE_IMSI: - case GSM_MI_TYPE_IMEI: - case GSM_MI_TYPE_IMEISV: - /* If the length is even, the last nibble (higher nibble of last octet) must be 0xf */ - if (!(mi_data[0] & GSM_MI_ODD) - && ((mi_data[mi_len - 1] & 0xf0) != 0xf0)) { - rc = -EBADMSG; - goto return_error; - } - rc = osmo_bcd2str(str, str_size, mi_data, 1, 1 + nibbles_len, allow_hex); - /* rc checked below */ - break; - - default: - /* Already handled above, but as future bug paranoia: */ - rc = -EINVAL; - goto return_error; - } - - /* check mi->str printing rc */ - if (rc < 1 || rc >= str_size) { - rc = -EBADMSG; - goto return_error; - } - return 0; - -return_error: - *mi = (struct osmo_mobile_identity){ - .type = GSM_MI_TYPE_NONE, - }; - return rc; -} - -/*! Return the number of encoded Mobile Identity octets, without actually encoding. - * Useful to write tag-length header before encoding the MI. - * \param[in] mi Mobile Identity. - * \param[out] mi_digits If not NULL, store the number of nibbles of used MI data (i.e. strlen(mi->string) or 8 for a TMSI). - * \return octets that osmo_mobile_identity_encode_msgb() will write for this mi. - */ -int osmo_mobile_identity_encoded_len(const struct osmo_mobile_identity *mi, int *mi_digits) -{ - int mi_nibbles; - if (!mi) - return -EINVAL; - switch (mi->type) { - case GSM_MI_TYPE_TMSI: - mi_nibbles = GSM23003_TMSI_NUM_BYTES * 2; - break; - case GSM_MI_TYPE_IMSI: - mi_nibbles = strlen(mi->imsi); - if (mi_nibbles < GSM23003_IMSI_MIN_DIGITS - || mi_nibbles > GSM23003_IMSI_MAX_DIGITS) - return -EINVAL; - break; - case GSM_MI_TYPE_IMEI: - mi_nibbles = strlen(mi->imei); - if (mi_nibbles < GSM23003_IMEI_NUM_DIGITS_NO_CHK - || mi_nibbles > GSM23003_IMEI_NUM_DIGITS) - return -EINVAL; - break; - case GSM_MI_TYPE_IMEISV: - mi_nibbles = strlen(mi->imeisv); - if (mi_nibbles != GSM23003_IMEISV_NUM_DIGITS) - return -EINVAL; - break; - default: - return -ENOTSUP; - } - - if (mi_digits) - *mi_digits = mi_nibbles; - - /* one type nibble, plus the MI nibbles, plus a filler nibble to complete the last octet: - * mi_octets = ceil((float)(mi_nibbles + 1) / 2) - */ - return (mi_nibbles + 2) / 2; -} - -/*! Encode Mobile Identity from uint32_t (TMSI) or digits string (all others) (3GPP TS 24.008 10.5.1.4). - * - * \param[out] buf Return buffer for encoded Mobile Identity. - * \param[in] buflen sizeof(buf). - * \param[in] mi Mobile identity to encode. - * \param[in] allow_hex If false, hexadecimal digits (>9) result in an error return value. - * \returns Amount of bytes written to buf, or negative on error. - */ -int osmo_mobile_identity_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_mobile_identity *mi, bool allow_hex) -{ - int rc; - int nibbles_len; - int mi_octets; - const char *mi_str; - - if (!buf || !buflen) - return -EIO; - - mi_octets = osmo_mobile_identity_encoded_len(mi, &nibbles_len); - if (mi_octets < 0) - return mi_octets; - if (mi_octets > buflen) - return -ENOSPC; - - buf[0] = (mi->type & GSM_MI_TYPE_MASK) | ((nibbles_len & 1) ? GSM_MI_ODD : 0); - - switch (mi->type) { - case GSM_MI_TYPE_TMSI: - buf[0] |= 0xf0; - osmo_store32be(mi->tmsi, &buf[1]); - return mi_octets; - - case GSM_MI_TYPE_IMSI: - mi_str = mi->imsi; - break; - case GSM_MI_TYPE_IMEI: - mi_str = mi->imei; - break; - case GSM_MI_TYPE_IMEISV: - mi_str = mi->imeisv; - break; - default: - return -ENOTSUP; - } - rc = osmo_str2bcd(buf, buflen, mi_str, 1, -1, allow_hex); - if (rc != mi_octets) - return -EINVAL; - return mi_octets; -} - -/*! Encode Mobile Identity type and BCD digits, appended to a msgb. - * Example to add a GSM48_IE_MOBILE_ID IEI with tag and length to a msgb: - * - * struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, .tmsi = random_tmsi, }; - * uint8_t *l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID); - * int rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); - * if (rc < 0) - * goto error; - * *l = rc; - * - * Example to add a BSSGP_IE_IMSI with tag and variable-size length, where the - * length needs to be known at the time of writing the IE tag-length header: - * - * struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - * OSMO_STRLCPY_ARRAY(mi.imsi, pinfo->imsi); - * msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - * if (osmo_mobile_identity_encode_msgb(msg, &mi, false) < 0) - * goto error; - */ -int osmo_mobile_identity_encode_msgb(struct msgb *msg, const struct osmo_mobile_identity *mi, bool allow_hex) -{ - int rc = osmo_mobile_identity_encode_buf(msg->tail, msgb_tailroom(msg), mi, allow_hex); - if (rc < 0) - return rc; - msgb_put(msg, rc); - return rc; -} - -/*! Extract Mobile Identity from a Complete Layer 3 message. - * - * Determine the Mobile Identity data and call osmo_mobile_identity_decode() to return a decoded struct - * osmo_mobile_identity. - * - * \param[out] mi Return buffer for decoded Mobile Identity. - * \param[in] msg The Complete Layer 3 message to extract from (LU, CM Service Req or Paging Resp). - * \returns 0 on success, negative on error: return codes as defined in osmo_mobile_identity_decode(), or - * -ENOTSUP = not a Complete Layer 3 message, - */ -int osmo_mobile_identity_decode_from_l3(struct osmo_mobile_identity *mi, struct msgb *msg, bool allow_hex) -{ - const struct gsm48_hdr *gh; - int8_t pdisc = 0; - uint8_t mtype = 0; - const struct gsm48_loc_upd_req *lu; - const uint8_t *cm2_buf; - uint8_t cm2_len; - const uint8_t *mi_start; - const struct gsm48_pag_resp *paging_response; - const uint8_t *mi_data; - uint8_t mi_len; - const struct gsm48_imsi_detach_ind *idi; - - *mi = (struct osmo_mobile_identity){ - .type = GSM_MI_TYPE_NONE, - .tmsi = GSM_RESERVED_TMSI, - }; - - if (msgb_l3len(msg) < sizeof(*gh)) - return -EBADMSG; - - gh = msgb_l3(msg); - pdisc = gsm48_hdr_pdisc(gh); - mtype = gsm48_hdr_msg_type(gh); - - switch (pdisc) { - case GSM48_PDISC_MM: - - switch (mtype) { - case GSM48_MT_MM_LOC_UPD_REQUEST: - /* First make sure that lu-> can be dereferenced */ - if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) - return -EBADMSG; - - /* Now we know there is enough msgb data to read a lu->mi_len, so also check that */ - lu = (struct gsm48_loc_upd_req*)gh->data; - if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu) + lu->mi_len) - return -EBADMSG; - mi_data = lu->mi; - mi_len = lu->mi_len; - goto got_mi; - - case GSM48_MT_MM_CM_SERV_REQ: - case GSM48_MT_MM_CM_REEST_REQ: - /* Unfortunately in Phase1 the Classmark2 length is variable, so we cannot - * just use gsm48_service_request struct, and need to parse it manually. */ - if (msgb_l3len(msg) < sizeof(*gh) + 2) - return -EBADMSG; - - cm2_len = gh->data[1]; - cm2_buf = gh->data + 2; - goto got_cm2; - - case GSM48_MT_MM_IMSI_DETACH_IND: - if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*idi)) - return -EBADMSG; - idi = (struct gsm48_imsi_detach_ind*) gh->data; - mi_data = idi->mi; - mi_len = idi->mi_len; - goto got_mi; - - case GSM48_MT_MM_ID_RESP: - if (msgb_l3len(msg) < sizeof(*gh) + 2) - return -EBADMSG; - mi_data = gh->data+1; - mi_len = gh->data[0]; - goto got_mi; - - default: - break; - } - break; - - case GSM48_PDISC_RR: - - switch (mtype) { - case GSM48_MT_RR_PAG_RESP: - if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*paging_response)) - return -EBADMSG; - paging_response = (struct gsm48_pag_resp*)gh->data; - cm2_len = paging_response->cm2_len; - cm2_buf = (uint8_t*)&paging_response->cm2; - goto got_cm2; - - default: - break; - } - break; - } - - return -ENOTSUP; - -got_cm2: - /* MI (Mobile Identity) LV follows the Classmark2 */ - - /* There must be at least a mi_len byte after the CM2 */ - if (cm2_buf + cm2_len + 1 > msg->tail) - return -EBADMSG; - - mi_start = cm2_buf + cm2_len; - mi_len = mi_start[0]; - mi_data = mi_start + 1; - -got_mi: - /* mi_data points at the start of the Mobile Identity coding of mi_len bytes */ - if (mi_data + mi_len > msg->tail) - return -EBADMSG; - - return osmo_mobile_identity_decode(mi, mi_data, mi_len, allow_hex); -} - -/*! Return a human readable representation of a struct osmo_mobile_identity. - * Write a string like "IMSI-1234567", "TMSI-0x1234ABCD" or "NONE", "NULL". - * \param[out] buf String buffer to write to. - * \param[in] buflen sizeof(buf). - * \param[in] mi Decoded Mobile Identity data. - * \return the strlen() of the string written when buflen is sufficiently large, like snprintf(). - */ -int osmo_mobile_identity_to_str_buf(char *buf, size_t buflen, const struct osmo_mobile_identity *mi) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - if (!mi) - return snprintf(buf, buflen, "NULL"); - OSMO_STRBUF_PRINTF(sb, "%s", gsm48_mi_type_name(mi->type)); - switch (mi->type) { - case GSM_MI_TYPE_TMSI: - OSMO_STRBUF_PRINTF(sb, "-0x%08" PRIX32, mi->tmsi); - break; - case GSM_MI_TYPE_IMSI: - OSMO_STRBUF_PRINTF(sb, "-%s", mi->imsi); - break; - case GSM_MI_TYPE_IMEI: - OSMO_STRBUF_PRINTF(sb, "-%s", mi->imei); - break; - case GSM_MI_TYPE_IMEISV: - OSMO_STRBUF_PRINTF(sb, "-%s", mi->imeisv); - break; - default: - break; - } - return sb.chars_needed; -} - -/*! Like osmo_mobile_identity_to_str_buf(), but return the string in a talloc buffer. - * \param[in] ctx Talloc context to allocate from. - * \param[in] mi Decoded Mobile Identity data. - * \return a string like "IMSI-1234567", "TMSI-0x1234ABCD" or "NONE", "NULL". - */ -char *osmo_mobile_identity_to_str_c(void *ctx, const struct osmo_mobile_identity *mi) -{ - OSMO_NAME_C_IMPL(ctx, 32, "ERROR", osmo_mobile_identity_to_str_buf, mi) -} - -/*! Compare two osmo_mobile_identity structs, returning typical cmp() result. - * \param[in] a Left side osmo_mobile_identity. - * \param[in] b Right side osmo_mobile_identity. - * \returns 0 if both are equal, -1 if a < b, 1 if a > b. - */ -int osmo_mobile_identity_cmp(const struct osmo_mobile_identity *a, const struct osmo_mobile_identity *b) -{ - int cmp; - if (a == b) - return 0; - if (!a) - return -1; - if (!b) - return 1; - cmp = OSMO_CMP(a->type, b->type); - if (cmp) - return cmp; - switch (a->type) { - case GSM_MI_TYPE_TMSI: - return OSMO_CMP(a->tmsi, b->tmsi); - case GSM_MI_TYPE_IMSI: - return strncmp(a->imsi, b->imsi, sizeof(a->imsi)); - case GSM_MI_TYPE_IMEI: - return strncmp(a->imei, b->imei, sizeof(a->imei)); - case GSM_MI_TYPE_IMEISV: - return strncmp(a->imeisv, b->imeisv, sizeof(a->imeisv)); - default: - /* No known type, but both have the same type. */ - return 0; - } + size_t buf_len = 10 + GSM48_MI_SIZE + 1; + char *mi_name = talloc_size(ctx, buf_len); + if (!mi_name) + return NULL; + return osmo_mi_name_buf(mi_name, buf_len, mi, mi_len); } /*! Checks is particular message is cipherable in A/Gb mode according to @@ -1107,76 +676,64 @@ } } -static int legacy_compat_generate_mid(uint8_t *buf, const struct osmo_mobile_identity *mi) -{ - int rc; - buf[0] = GSM48_IE_MOBILE_ID; - rc = osmo_mobile_identity_encode_buf(buf + 2, GSM48_MID_MAX_SIZE - 2, mi, false); - if (rc <= 0) - return 0; - OSMO_ASSERT(rc <= 9); - buf[1] = rc; - return 2 + rc; -} - -/*! Deprecated, see osmo_mobile_identity instead. - * Generate TS 04.08 Mobile ID from TMSI +/*! Generate TS 04.08 Mobile ID from TMSI * \param[out] buf Caller-provided output buffer (7 bytes) * \param[in] tmsi TMSI to be encoded * \returns number of byes encoded (always 7) */ int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi) { - struct osmo_mobile_identity mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = tmsi, - }; - return legacy_compat_generate_mid(buf, &mi); + uint32_t tmsi_be = osmo_htonl(tmsi); + + buf[0] = GSM48_IE_MOBILE_ID; + buf[1] = GSM48_TMSI_LEN; + buf[2] = 0xf0 | GSM_MI_TYPE_TMSI; + memcpy(&buf[3], &tmsi_be, sizeof(tmsi_be)); + + return 7; } -/*! Deprecated, see osmo_mobile_identity instead. - * Generate TS 24.008 §10.5.1.4 Mobile ID of BCD type from ASCII string +/*! Generate TS 24.008 §10.5.1.4 Mobile ID of BCD type from ASCII string * \param[out] buf Caller-provided output buffer of at least GSM48_MID_MAX_SIZE bytes * \param[in] id Identity to be encoded * \param[in] mi_type Type of identity (e.g. GSM_MI_TYPE_IMSI, IMEI, IMEISV) * \returns number of bytes used in \a buf */ uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type) { - struct osmo_mobile_identity mi = { .type = mi_type }; - switch (mi_type) { - case GSM_MI_TYPE_TMSI: - mi.tmsi = strtoul(id, NULL, 10); - break; - case GSM_MI_TYPE_IMSI: - OSMO_STRLCPY_ARRAY(mi.imsi, id); - break; - case GSM_MI_TYPE_IMEI: - OSMO_STRLCPY_ARRAY(mi.imei, id); - break; - case GSM_MI_TYPE_IMEISV: - OSMO_STRLCPY_ARRAY(mi.imeisv, id); - break; - default: - return 0; + uint8_t length = strnlen(id, 16), i, off = 0, odd = (length & 1) == 1; + /* maximum length == 16 (IMEISV) */ + + buf[0] = GSM48_IE_MOBILE_ID; + buf[2] = osmo_char2bcd(id[0]) << 4 | (mi_type & GSM_MI_TYPE_MASK) | (odd << 3); + + /* if the length is even we will fill half of the last octet */ + buf[1] = (length + (odd ? 1 : 2)) >> 1; + /* buf[1] maximum = 18/2 = 9 */ + OSMO_ASSERT(buf[1] <= 9); + + for (i = 1; i < buf[1]; ++i) { + uint8_t upper, lower = osmo_char2bcd(id[++off]); + if (!odd && off + 1 == length) + upper = 0x0f; + else + upper = osmo_char2bcd(id[++off]) & 0x0f; + + buf[2 + i] = (upper << 4) | lower; } - return legacy_compat_generate_mid(buf, &mi); + + /* maximum return value: 2 + 9 = 11 */ + return 2 + buf[1]; } -/*! Deprecated, see osmo_mobile_identity instead. - * Generate TS 04.08 Mobile ID from IMSI +/*! Generate TS 04.08 Mobile ID from IMSI * \param[out] buf Caller-provided output buffer * \param[in] imsi IMSI to be encoded * \returns number of bytes used in \a buf */ int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi) { - struct osmo_mobile_identity mi = { - .type = GSM_MI_TYPE_IMSI, - }; - OSMO_STRLCPY_ARRAY(mi.imsi, imsi); - return legacy_compat_generate_mid(buf, &mi); + return gsm48_generate_mid(buf, imsi, GSM_MI_TYPE_IMSI); } -/*! Deprecated, see osmo_mobile_identity instead. - * Convert TS 04.08 Mobile Identity (10.5.1.4) to string. +/*! Convert TS 04.08 Mobile Identity (10.5.1.4) to string. * This function does not validate the Mobile Identity digits, i.e. digits > 9 are returned as 'A'-'F'. * \param[out] string Caller-provided buffer for output * \param[in] str_len Length of \a string in bytes diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 742cec3..ac9aeb2 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -363,14 +363,6 @@ gsm48_generate_mid_from_imsi; gsm48_generate_mid_from_tmsi; gsm48_mi_to_string; -osmo_mobile_identity_to_str_buf; -osmo_mobile_identity_to_str_c; -osmo_mobile_identity_cmp; -osmo_mobile_identity_decode; -osmo_mobile_identity_decode_from_l3; -osmo_mobile_identity_encoded_len; -osmo_mobile_identity_encode_buf; -osmo_mobile_identity_encode_msgb; gsm48_mm_att_tlvdef; gsm48_number_of_paging_subchannels; gsm48_parse_ra; diff --git a/src/utils.c b/src/utils.c index 3c4a8c9..18e105f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -175,65 +175,6 @@ return OSMO_MAX(0, end_nibble - start_nibble); } -/*! Convert string to BCD. - * The given nibble offsets are interpreted in BCD order, i.e. nibble 0 is bcd[0] & 0x0f, nibble 1 is bcd[0] & 0xf0, nibble - * 3 is bcd[1] & 0x0f, etc.. - * \param[out] dst Output BCD buffer. - * \param[in] dst_size sizeof() the output string buffer. - * \param[in] digits String containing decimal or hexadecimal digits in upper or lower case. - * \param[in] start_nibble Offset to start from, in nibbles, typically 1 to skip the first (MI type) nibble. - * \param[in] end_nibble Negative to write all digits found in str, followed by 0xf nibbles to fill any started octet. - * If >= 0, stop before this offset in nibbles, e.g. to get default behavior, pass - * start_nibble + strlen(str) + ((start_nibble + strlen(str)) & 1? 1 : 0) + 1. - * \param[in] allow_hex If false, return error if there are hexadecimal digits (A-F). If true, write those to - * BCD. - * \returns The buffer size in octets that is used to place all bcd digits (including the skipped nibbles - * from 'start_nibble' and rounded up to full octets); -EINVAL on invalid digits; - * -ENOMEM if dst is NULL, if dst_size is too small to contain all nibbles, or if start_nibble is negative. - */ -int osmo_str2bcd(uint8_t *dst, size_t dst_size, const char *digits, int start_nibble, int end_nibble, bool allow_hex) -{ - const char *digit = digits; - int nibble_i; - - if (!dst || !dst_size || start_nibble < 0) - return -ENOMEM; - - if (end_nibble < 0) { - end_nibble = start_nibble + strlen(digits); - /* If the last octet is not complete, add another filler nibble */ - if (end_nibble & 1) - end_nibble++; - } - if ((end_nibble / 2) > dst_size) - return -ENOMEM; - - for (nibble_i = start_nibble; nibble_i < end_nibble; nibble_i++) { - uint8_t nibble = 0xf; - int octet = nibble_i >> 1; - if (*digit) { - char c = *digit; - digit++; - if (c >= '0' && c <= '9') - nibble = c - '0'; - else if (allow_hex && c >= 'A' && c <= 'F') - nibble = 0xa + (c - 'A'); - else if (allow_hex && c >= 'a' && c <= 'f') - nibble = 0xa + (c - 'a'); - else - return -EINVAL; - } - nibble &= 0xf; - if ((nibble_i & 1)) - dst[octet] = (nibble << 4) | (dst[octet] & 0x0f); - else - dst[octet] = (dst[octet] & 0xf0) | nibble; - } - - /* floor(float(end_nibble) / 2) */ - return end_nibble / 2; -} - /*! Parse a string containing hexadecimal digits * \param[in] str string containing ASCII encoded hexadecimal digits * \param[out] b output buffer diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c index a86fe11..9617823 100644 --- a/tests/gsm0408/gsm0408_test.c +++ b/tests/gsm0408/gsm0408_test.c @@ -18,8 +18,6 @@ * */ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -388,9 +386,8 @@ { .mi_type = GSM_MI_TYPE_IMSI | GSM_MI_ODD, .mi_str = "423423", - .expect_str = "", - .expect_rc = 1, - .mi_name = "unknown", + .mi_name = "IMSI-423423", + .expect_mi_tlv_hex = "1704413224f3", }, { .mi_type = GSM_MI_TYPE_IMSI, @@ -474,21 +471,21 @@ .mi_type = GSM_MI_TYPE_NONE, .mi_str = "123", .mi_name = "unknown", - .expect_mi_tlv_hex = "", + .expect_mi_tlv_hex = "17021832", /* encoding invalid MI type */ .expect_str = "", }, { .mi_type = GSM_MI_TYPE_NONE, .mi_str = "1234", .mi_name = "unknown", - .expect_mi_tlv_hex = "", + .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */ .expect_str = "", }, { .mi_type = GSM_MI_ODD, .mi_str = "1234", .mi_name = "unknown", - .expect_mi_tlv_hex = "", + .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */ .expect_str = "", }, }; @@ -525,14 +522,9 @@ printf(" ERROR: expected '%s'\n", t->expect_mi_tlv_hex); } - if (tlv_len) { - /* skip the GSM48_IE_MOBILE_ID tag and length */ - mi_buf = tlv_buf + 2; - mi_len = tlv_len - 2; - } else { - mi_buf = NULL; - mi_len = 0; - } + /* skip the GSM48_IE_MOBILE_ID tag and length */ + mi_buf = tlv_buf + 2; + mi_len = tlv_len - 2; rc = gsm48_mi_to_string(str, str_size, mi_buf, mi_len); printf(" -> MI-str=%s rc=%d\n", osmo_quote_str(str, -1), rc); @@ -619,368 +611,6 @@ printf("\n"); } -struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex) -{ - struct msgb *msg = msgb_alloc_headroom(size, 4, label); - OSMO_ASSERT(msg); - msg->l3h = msgb_put(msg, osmo_hexparse(hex, msg->data, msgb_tailroom(msg))); - return msg; -} - -struct mobile_identity_tc { - const char *label; - const char *compl_l3_msg; - int expect_rc; - struct osmo_mobile_identity expect_mi; -}; - -/* Some Complete Layer 3 messages copied from real GSM network traces. */ -struct mobile_identity_tc mobile_identity_tests[] = { - { - .label = "LU with IMSI 901700000004620", - .compl_l3_msg = "050802008168000130" "089910070000006402", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "901700000004620", - }, - }, - { - .label = "LU with TMSI 0x0980ad8a", - .compl_l3_msg = "05084262f224002a50" "05f40980ad8a", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0x0980ad8a, - }, - }, - { - .label = "LU with invalid MI type", - .compl_l3_msg = "050802008168000130" "089d10070000006402", - .expect_rc = -EINVAL, - }, - { - .label = "LU with truncated IMSI MI", - .compl_l3_msg = "050802008168000130" "0899100700000064", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with too short IMSI MI (12345)", - .compl_l3_msg = "050802008168000130" "03193254", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with just long enough IMSI MI 123456", - .compl_l3_msg = "050802008168000130" "04113254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456", - }, - }, - { - .label = "LU with max length IMSI MI 123456789012345", - .compl_l3_msg = "050802008168000130" "081932547698103254", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456789012345", - }, - }, - { - .label = "LU with just too long IMSI MI 1234567890123456", - .compl_l3_msg = "050802008168000130" "091132547698103254f6", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with truncated TMSI MI", - .compl_l3_msg = "05084262f224002a50" "05f40980ad", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with odd length TMSI", - .compl_l3_msg = "05084262f224002a50" "05fc0980ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with too long TMSI MI", - .compl_l3_msg = "05084262f224002a50" "06f40980ad23", - .expect_rc = -EBADMSG, - }, - { - .label = "LU with too short TMSI", - .compl_l3_msg = "05084262f224002a50" "04f480ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Request with IMSI 123456", - .compl_l3_msg = "052401035058a6" "04113254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456", - }, - }, - { - .label = "CM Service Request with TMSI 0x5a42e404", - .compl_l3_msg = "052401035058a6" "05f45a42e404", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0x5a42e404, - }, - }, - { - .label = "CM Service Request with shorter CM2, with IMSI 123456", - .compl_l3_msg = "052401025058" "04113254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456", - }, - }, - { - .label = "CM Service Request with longer CM2, with IMSI 123456", - .compl_l3_msg = "052401055058a62342" "04113254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456", - }, - }, - { - .label = "CM Service Request with shorter CM2, with TMSI 0x00000000", - .compl_l3_msg = "052401025058" "05f400000000", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0, - }, - }, - { - .label = "CM Service Request with invalid MI type", - .compl_l3_msg = "052401035058a6" "089d10070000006402", - .expect_rc = -EINVAL, - }, - { - .label = "CM Service Request with truncated IMSI MI", - .compl_l3_msg = "052401035058a6" "0899100700000064", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Request with truncated TMSI MI", - .compl_l3_msg = "0524010150" "05f40980ad", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Request with odd length TMSI", - .compl_l3_msg = "052401045058a623" "05fc0980ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Request with too long TMSI MI", - .compl_l3_msg = "052401035058a6" "06f40980ad23", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Request with too short TMSI", - .compl_l3_msg = "052401035058a6" "04f480ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "CM Service Reestablish Request with TMSI 0x5a42e404", - .compl_l3_msg = "052801035058a6" "05f45a42e404", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0x5a42e404, - }, - }, - { - .label = "Paging Response with IMSI 1234567", - .compl_l3_msg = "06270003505886" "0419325476", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "1234567", - }, - }, - { - .label = "Paging Response with TMSI 0xb48883de", - .compl_l3_msg = "06270003505886" "05f4b48883de", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0xb48883de, - }, - }, - { - .label = "Paging Response with TMSI, with unused nibble not 0xf", - .compl_l3_msg = "06270003505886" "0504b48883de", - .expect_rc = -EBADMSG, - }, - { - .label = "Paging Response with too short IMEI (1234567)", - .compl_l3_msg = "06270003505886" "041a325476", - .expect_rc = -EBADMSG, - }, - { - .label = "Paging Response with IMEI 123456789012345", - .compl_l3_msg = "06270003505886" "081a32547698103254", - .expect_mi = { - .type = GSM_MI_TYPE_IMEI, - .imei = "123456789012345", - }, - }, - { - .label = "Paging Response with IMEI 12345678901234 (no Luhn checksum)", - .compl_l3_msg = "06270003505886" "0812325476981032f4", - .expect_mi = { - .type = GSM_MI_TYPE_IMEI, - .imei = "12345678901234", - }, - }, - { - .label = "Paging Response with IMEISV 1234567890123456", - .compl_l3_msg = "06270003505886" "091332547698103254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMEISV, - .imeisv = "1234567890123456", - }, - }, - { - .label = "Paging Response with too short IMEISV 123456789012345", - .compl_l3_msg = "06270003505886" "081b32547698103254", - .expect_rc = -EBADMSG, - }, - { - .label = "Paging Response with too long IMEISV 12345678901234567", - .compl_l3_msg = "06270003505886" "091b3254769810325476", - .expect_rc = -EBADMSG, - }, - { - .label = "Paging Response with IMSI 123456789012345 and flipped ODD bit", - .compl_l3_msg = "06270003505886" "081132547698103254", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with IMSI 901700000004620", - .compl_l3_msg = "050130" "089910070000006402", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "901700000004620", - }, - }, - { - .label = "IMSI-Detach with TMSI 0x0980ad8a", - .compl_l3_msg = "050130" "05f40980ad8a", - .expect_mi = { - .type = GSM_MI_TYPE_TMSI, - .tmsi = 0x0980ad8a, - }, - }, - { - .label = "IMSI-Detach with invalid MI type", - .compl_l3_msg = "050130" "089d10070000006402", - .expect_rc = -EINVAL, - }, - { - .label = "IMSI-Detach with truncated IMSI MI", - .compl_l3_msg = "050130" "0899100700000064", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with too short IMSI MI (12345)", - .compl_l3_msg = "050130" "03193254", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with just long enough IMSI MI 123456", - .compl_l3_msg = "050130" "04113254f6", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456", - }, - }, - { - .label = "IMSI-Detach with max length IMSI MI 123456789012345", - .compl_l3_msg = "050130" "081932547698103254", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "123456789012345", - }, - }, - { - .label = "IMSI-Detach with just too long IMSI MI 1234567890123456", - .compl_l3_msg = "050130" "091132547698103254f6", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with truncated TMSI MI", - .compl_l3_msg = "050130" "05f40980ad", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with odd length TMSI", - .compl_l3_msg = "050130" "05fc0980ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with too long TMSI MI", - .compl_l3_msg = "050130" "06f40980ad23", - .expect_rc = -EBADMSG, - }, - { - .label = "IMSI-Detach with too short TMSI", - .compl_l3_msg = "050130" "04f480ad8a", - .expect_rc = -EBADMSG, - }, - { - .label = "Identity Response with IMSI 901700000004620", - .compl_l3_msg = "0519" "089910070000006402", - .expect_mi = { - .type = GSM_MI_TYPE_IMSI, - .imsi = "901700000004620", - }, - }, - { - .label = "Identity Response with IMEI 123456789012345", - .compl_l3_msg = "0519" "081a32547698103254", - .expect_mi = { - .type = GSM_MI_TYPE_IMEI, - .imei = "123456789012345", - }, - }, - { - .label = "Identity Response with IMEISV 9876543210987654", - .compl_l3_msg = "0519" "099378563412907856f4", - .expect_mi = { - .type = GSM_MI_TYPE_IMEISV, - .imeisv = "9876543210987654", - }, - }, -}; - -void test_struct_mobile_identity() -{ - struct mobile_identity_tc *t; - printf("%s()\n", __func__); - for (t = mobile_identity_tests; (t - mobile_identity_tests) < ARRAY_SIZE(mobile_identity_tests); t++) { - struct osmo_mobile_identity mi; - struct msgb *msg; - int rc; - memset(&mi, 0xff, sizeof(mi)); - - msg = msgb_from_hex(t->label, 1024, t->compl_l3_msg); - rc = osmo_mobile_identity_decode_from_l3(&mi, msg, false); - msgb_free(msg); - - printf("%s: rc = %d", t->label, rc); - if (!rc) { - printf(", mi = %s", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi)); - } - - if (rc == t->expect_rc - && ((rc != 0) || !osmo_mobile_identity_cmp(&mi, &t->expect_mi))) { - printf(" ok"); - } else { - printf(" ERROR: Expected rc = %d", t->expect_rc); - if (!t->expect_rc) - printf(", mi = %s", osmo_mobile_identity_to_str_c(OTC_SELECT, &t->expect_mi)); - } - printf("\n"); - } - printf("\n"); -} - static const struct bcd_number_test { /* Human-readable test name */ const char *test_name; @@ -1552,7 +1182,6 @@ test_mid_from_imsi(); test_mid_encode_decode(); test_mid_decode_zero_length(); - test_struct_mobile_identity(); test_bcd_number_encode_decode(); test_ra_cap(); test_lai_encode_decode(); diff --git a/tests/gsm0408/gsm0408_test.ok b/tests/gsm0408/gsm0408_test.ok index f8de54a..d343869 100644 --- a/tests/gsm0408/gsm0408_test.ok +++ b/tests/gsm0408/gsm0408_test.ok @@ -17,9 +17,9 @@ -> MI-str="423423" rc=7 -> MI-name="IMSI-423423" - unknown 0x9 423423 - -> MI-TLV-hex='' - -> MI-str="" rc=1 - -> MI-name="unknown" + -> MI-TLV-hex='1704413224f3' + -> MI-str="423423" rc=7 + -> MI-name="IMSI-423423" - IMSI 4234235 -> MI-TLV-hex='170449322453' -> MI-str="4234235" rc=8 @@ -65,15 +65,15 @@ -> MI-str="3054" rc=9 -> MI-name="TMSI-0x12345678" - NONE 123 - -> MI-TLV-hex='' + -> MI-TLV-hex='17021832' -> MI-str="" rc=1 -> MI-name="unknown" - NONE 1234 - -> MI-TLV-hex='' + -> MI-TLV-hex='17031032f4' -> MI-str="" rc=1 -> MI-name="unknown" - unknown 0x8 1234 - -> MI-TLV-hex='' + -> MI-TLV-hex='17031032f4' -> MI-str="" rc=1 -> MI-name="unknown" @@ -139,57 +139,6 @@ rc=1 returned empty string -test_struct_mobile_identity() -LU with IMSI 901700000004620: rc = 0, mi = IMSI-901700000004620 ok -LU with TMSI 0x0980ad8a: rc = 0, mi = TMSI-0x0980AD8A ok -LU with invalid MI type: rc = -22 ok -LU with truncated IMSI MI: rc = -74 ok -LU with too short IMSI MI (12345): rc = -74 ok -LU with just long enough IMSI MI 123456: rc = 0, mi = IMSI-123456 ok -LU with max length IMSI MI 123456789012345: rc = 0, mi = IMSI-123456789012345 ok -LU with just too long IMSI MI 1234567890123456: rc = -74 ok -LU with truncated TMSI MI: rc = -74 ok -LU with odd length TMSI: rc = -74 ok -LU with too long TMSI MI: rc = -74 ok -LU with too short TMSI: rc = -74 ok -CM Service Request with IMSI 123456: rc = 0, mi = IMSI-123456 ok -CM Service Request with TMSI 0x5a42e404: rc = 0, mi = TMSI-0x5A42E404 ok -CM Service Request with shorter CM2, with IMSI 123456: rc = 0, mi = IMSI-123456 ok -CM Service Request with longer CM2, with IMSI 123456: rc = 0, mi = IMSI-123456 ok -CM Service Request with shorter CM2, with TMSI 0x00000000: rc = 0, mi = TMSI-0x00000000 ok -CM Service Request with invalid MI type: rc = -22 ok -CM Service Request with truncated IMSI MI: rc = -74 ok -CM Service Request with truncated TMSI MI: rc = -74 ok -CM Service Request with odd length TMSI: rc = -74 ok -CM Service Request with too long TMSI MI: rc = -74 ok -CM Service Request with too short TMSI: rc = -74 ok -CM Service Reestablish Request with TMSI 0x5a42e404: rc = 0, mi = TMSI-0x5A42E404 ok -Paging Response with IMSI 1234567: rc = 0, mi = IMSI-1234567 ok -Paging Response with TMSI 0xb48883de: rc = 0, mi = TMSI-0xB48883DE ok -Paging Response with TMSI, with unused nibble not 0xf: rc = -74 ok -Paging Response with too short IMEI (1234567): rc = -74 ok -Paging Response with IMEI 123456789012345: rc = 0, mi = IMEI-123456789012345 ok -Paging Response with IMEI 12345678901234 (no Luhn checksum): rc = 0, mi = IMEI-12345678901234 ok -Paging Response with IMEISV 1234567890123456: rc = 0, mi = IMEI-SV-1234567890123456 ok -Paging Response with too short IMEISV 123456789012345: rc = -74 ok -Paging Response with too long IMEISV 12345678901234567: rc = -74 ok -Paging Response with IMSI 123456789012345 and flipped ODD bit: rc = -74 ok -IMSI-Detach with IMSI 901700000004620: rc = 0, mi = IMSI-901700000004620 ok -IMSI-Detach with TMSI 0x0980ad8a: rc = 0, mi = TMSI-0x0980AD8A ok -IMSI-Detach with invalid MI type: rc = -22 ok -IMSI-Detach with truncated IMSI MI: rc = -74 ok -IMSI-Detach with too short IMSI MI (12345): rc = -74 ok -IMSI-Detach with just long enough IMSI MI 123456: rc = 0, mi = IMSI-123456 ok -IMSI-Detach with max length IMSI MI 123456789012345: rc = 0, mi = IMSI-123456789012345 ok -IMSI-Detach with just too long IMSI MI 1234567890123456: rc = -74 ok -IMSI-Detach with truncated TMSI MI: rc = -74 ok -IMSI-Detach with odd length TMSI: rc = -74 ok -IMSI-Detach with too long TMSI MI: rc = -74 ok -IMSI-Detach with too short TMSI: rc = -74 ok -Identity Response with IMSI 901700000004620: rc = 0, mi = IMSI-901700000004620 ok -Identity Response with IMEI 123456789012345: rc = 0, mi = IMEI-123456789012345 ok -Identity Response with IMEISV 9876543210987654: rc = 0, mi = IMEI-SV-9876543210987654 ok - BSD number encoding / decoding test - Running test: regular 9-digit MSISDN - Encoding ASCII (buffer limit=0) '123456789'... diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index e15cf5f..e87cb22 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -487,7 +487,6 @@ { int i; uint8_t bcd[64]; - uint8_t bcd2[64]; int rc; printf("\nTesting bcd to string conversion\n"); @@ -512,12 +511,6 @@ printf(" ERROR: expected rc=%d\n", t->expect_rc); if (strcmp(str, t->expect_str)) printf(" ERROR: expected result %s\n", osmo_quote_str(t->expect_str, -1)); - - memset(bcd2, 0xff, sizeof(bcd2)); - rc = osmo_str2bcd(bcd2, sizeof(bcd2), str, t->start_nibble, -1, t->allow_hex); - printf("osmo_str2bcd(start_nibble=%d) -> rc=%d\n", t->start_nibble, rc); - if (rc > 0) - printf(" = %s\n", osmo_hexdump(bcd2, rc)); } printf("- zero output buffer\n"); diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index cbab72a..baa708e 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -181,41 +181,27 @@ - BCD-input='1a 32 54 76 98 f0' nibbles=[1..11[ str_size=64 rc=10 -> "1234567890" -osmo_str2bcd(start_nibble=1) -> rc=6 - = 1f 32 54 76 98 f0 - BCD-input='1a 32 a4 cb 9d f0' nibbles=[1..11[ str_size=64 rc=-22 -> "1234ABCD90" -osmo_str2bcd(start_nibble=1) -> rc=-22 - BCD-input='1a 32 a4 cb 9d f0' nibbles=[1..11[ str_size=64 rc=10 -> "1234ABCD90" -osmo_str2bcd(start_nibble=1) -> rc=6 - = 1f 32 a4 cb 9d f0 - BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=64 rc=-22 -> "1234567890F" -osmo_str2bcd(start_nibble=1) -> rc=-22 - BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=64 rc=11 -> "1234567890F" -osmo_str2bcd(start_nibble=1) -> rc=6 - = 1f 32 54 76 98 f0 - BCD-input='1a 32 54 76 98 f0' nibbles=[0..12[ str_size=64 rc=12 -> "A1234567890F" -osmo_str2bcd(start_nibble=0) -> rc=6 - = 1a 32 54 76 98 f0 - BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=5 rc=11 -> "1234" -osmo_str2bcd(start_nibble=1) -> rc=3 - = 1f 32 f4 - BCD-input='' nibbles=[1..1[ str_size=64 rc=0 -> "" -osmo_str2bcd(start_nibble=1) -> rc=1 - = ff - zero output buffer bcd2str(NULL, ...) -> -12 bcd2str(dst, 0, ...) -> -12 -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/18853 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I4bd958d0cd2ab4b0c4725e6d114f4404d725fcf7 Gerrit-Change-Number: 18853 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge at osmocom.org> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200616/3ed69fd0/attachment.htm>