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

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I4bd958d0cd2ab4b0c4725e6d114f4404d725fcf7 </div>
<div style="display:none"> Gerrit-Change-Number: 18853 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>