<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/18507">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_mobile_identity API<br><br>While implementing osmo-bsc's MSC pooling feature, this API will be used to<br>reduce the number of times a Mobile Identity is extracted from a raw RSL<br>message.<br><br>Rationale:<br><br>Extracting the Mobile Identity from messages has numerous duplicate<br>implementations across our code with various levels of specialization.<br>https://xkcd.com/927/<br><br>To name a few:<br>- libosmocore: gsm48_mi_to_string(), osmo_mi_name_buf()<br>- osmo-bsc: extract_sub()<br>- osmo-msc: mm_rx_loc_upd_req(), cm_serv_reuse_conn(), gsm48_rx_mm_serv_req(),<br>  vlr_proc_acc_req()<br><br>We have existing functions to produce a human readable string from a Mobile<br>Identity, more or less awkward:<br>- gsm48_mi_to_string() decodes a TMSI as a decimal number. These days we use<br>  hexadecimal TMSI everywhere.<br>- osmo_mi_name_buf() decodes the BCD digits from a raw MI every time, so we'd<br>  need to pass around the raw message bytes. Also, osmo_mi_name_buf() has the<br>  wrong signature, it should return a length like snprintf().<br>- osmo-bsc's extract_sub() first uses gsm48_mi_to_string() which encodes the<br>  raw uint32_t TMSI to a string, and then calls strtoul() via<br>  tmsi_from_string() to code those back to a raw uint32_t.<br><br>Each of the above implementations employ their own size overflow checks, each<br>invoke osmo_bcd2str() and implement their own TMSI osmo_load32be() handling.<br>Too much code dup, let's hope that each and every one is correct.<br><br>In osmo-bsc, I am now implementing MSC pooling, and need to extract NRI bits<br>from a TMSI Mobile Identity. Since none of the above functions are general<br>enough to be re-used, I found myself again copy-pasting Mobile Identity code:<br>locating the MI in a 24.008 message with proper size checks, decoding MI<br>octets. This time I would like it to become a generally re-usable API which<br>might subsequently replace older code dup.<br><br>struct osmo_mobile_identity is a decoded representation of the raw Mobile<br>Identity, with a string representation as well as dedicated raw uint32_t TMSI.<br>The aim is to remove all uncertainty about decoded buffer sizes / data types.<br><br>Two API functions provide properly size-checking implementations of:<br>- decoding a raw MI from a bunch of MI octets;<br>- locating and decoding MI from a full 3GPP TS 24.008 Complete Layer 3 msgb.<br><br>New validity checks so far not implemented anywhere else:<br>- stricter validation of number of digits of IMSI, IMEI, IMEI-SV MI.<br>- stricter on filler nibbles to be 0xf.<br><br>Change-Id: Ic3f969e739654c1e8c387aedeeba5cce07fe2307<br>---<br>M include/osmocom/gsm/gsm48.h<br>M src/gsm/gsm48.c<br>M src/gsm/libosmogsm.map<br>M tests/gsm0408/gsm0408_test.c<br>M tests/gsm0408/gsm0408_test.ok<br>5 files changed, 706 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/07/18507/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h</span><br><span>index 7c68b1d..15c17e2 100644</span><br><span>--- a/include/osmocom/gsm/gsm48.h</span><br><span>+++ b/include/osmocom/gsm/gsm48.h</span><br><span>@@ -52,13 +52,31 @@</span><br><span> int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);</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%);">-/* Convert Mobile Identity (10.5.1.4) to string */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Convert encoded Mobile Identity (10.5.1.4) to string */</span><br><span> 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> const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len);</span><br><span> char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len);</span><br><span> 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(120, 100%, 40%);">+/*! Decoded representation of a Mobile Identity (3GPP TS 24.008 10.5.1.4).</span><br><span style="color: hsl(120, 100%, 40%);">+ * See osmo_mobile_identity_decode() and osmo_mobile_identity_from_compl_l3(). */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_mobile_identity {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! A GSM_MI_TYPE_* constant (like GSM_MI_TYPE_IMSI). */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t type;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Decoded human readable string of the Mobile Identity digits. IMSI, IMEI and IMEISV as digits like</span><br><span style="color: hsl(120, 100%, 40%);">+  * "12345678", and TMSI as "0x" and 8 hexadecimal digits like "0x1234ABCD". */</span><br><span style="color: hsl(120, 100%, 40%);">+  char string[GSM48_MI_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! TMSI / P-TMSI / M-TMSI integer value if type == GSM_MI_TYPE_TMSI, or OSMO_TMSI_UNASSIGNED otherwise. */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t tmsi;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_mobile_identity_name_buf(char *buf, size_t buflen, const struct osmo_mobile_identity *mi);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mobile_identity_name_c(void *ctx, const struct osmo_mobile_identity *mi);</span><br><span style="color: hsl(120, 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(120, 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(120, 100%, 40%);">+int osmo_mobile_identity_from_compl_l3(struct osmo_mobile_identity *mi, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</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> void gsm48_encode_ra(struct gsm48_ra_id *out, const struct gprs_ra_id *raid);</span><br><span>diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c</span><br><span>index 8d0998b..084d776 100644</span><br><span>--- a/src/gsm/gsm48.c</span><br><span>+++ b/src/gsm/gsm48.c</span><br><span>@@ -45,6 +45,7 @@</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(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_23_003.h></span><br><span> </span><br><span> /*! \addtogroup gsm0408</span><br><span>  *  @{</span><br><span>@@ -524,6 +525,291 @@</span><br><span>      return osmo_mi_name_buf(mi_name, buf_len, mi, mi_len);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Extract Mobile Identity from encoded bytes (3GPP TS 24.008 10.5.1.4).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+ * GSM_RESERVED_TMSI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+ * or GSM_MI_TYPE_IMEISV).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+ * IMEISV as digits like "12345678", and TMSI as "0x" and 8 hexadecimal digits like "0x1234abcd".</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+ * otherwise.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] mi  Return buffer for decoded Mobile Identity.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi_data  The encoded Mobile Identity octets.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi_len  Number of octets in mi_data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, negative on error: -EBADMSG = invalid length indication or invalid data,</span><br><span style="color: hsl(120, 100%, 40%);">+ *          -EINVAL = unknown Mobile Identity type.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       int nibbles_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!mi_data || mi_len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    nibbles_len = (mi_len - 1) * 2 + ((mi_data[0] & GSM_MI_ODD) ? 1 : 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *mi = (struct osmo_mobile_identity){</span><br><span style="color: hsl(120, 100%, 40%);">+          .type = mi_data[0] & GSM_MI_TYPE_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+            .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+    };</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%);">+                if (nibbles_len != (GSM23003_TMSI_NUM_BYTES * 2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</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%);">+                if (nibbles_len < GSM23003_IMSI_MIN_DIGITS || nibbles_len > GSM23003_IMSI_MAX_DIGITS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_MI_TYPE_IMEI:</span><br><span style="color: hsl(120, 100%, 40%);">+                if (nibbles_len != GSM23003_IMEI_NUM_DIGITS && nibbles_len != GSM23003_IMEI_NUM_DIGITS_NO_CHK) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_MI_TYPE_IMEISV:</span><br><span style="color: hsl(120, 100%, 40%);">+              if (nibbles_len != GSM23003_IMEISV_NUM_DIGITS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+         goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</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%);">+                /* MI is a 32bit integer TMSI. Length has been checked above. */</span><br><span style="color: hsl(120, 100%, 40%);">+              if ((mi_data[0] & 0xf0) != 0xf0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* A TMSI always has the first nibble == 0xf */</span><br><span style="color: hsl(120, 100%, 40%);">+                       rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             mi->tmsi = osmo_load32be(&mi_data[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = snprintf(mi->string, sizeof(mi->string), "0x%08" PRIX32, mi->tmsi);</span><br><span style="color: hsl(120, 100%, 40%);">+           /* rc checked below */</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</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%);">+              /* If the length is even, the last nibble (higher nibble of last octet) must be 0xf */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!(mi_data[0] & GSM_MI_ODD)</span><br><span style="color: hsl(120, 100%, 40%);">+                && ((mi_data[mi_len - 1] & 0xf0) != 0xf0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = osmo_bcd2str(mi->string, sizeof(mi->string), mi_data, 1, 1 + nibbles_len, false);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* rc checked below */</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Already handled above, but as future bug paranoia: */</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+         goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* check mi->string printing rc */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 1 || rc >= sizeof(mi->string)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                goto return_error;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+return_error:</span><br><span style="color: hsl(120, 100%, 40%);">+    *mi = (struct osmo_mobile_identity){</span><br><span style="color: hsl(120, 100%, 40%);">+          .type = GSM_MI_TYPE_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+             .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Extract Mobile Identity from a Complete Layer 3 message.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Determine the Mobile Identity data and call osmo_mobile_identity_decode() to return a decoded struct</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_mobile_identity.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] mi  Return buffer for decoded Mobile Identity.</span><br><span style="color: hsl(120, 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(120, 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(120, 100%, 40%);">+ *          -ENOTSUP = not a Complete Layer 3 message,</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_mobile_identity_from_compl_l3(struct osmo_mobile_identity *mi, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+   int8_t pdisc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t mtype = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct gsm48_loc_upd_req *lu;</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint8_t *cm2_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t cm2_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      const uint8_t *mi_start;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm48_pag_resp *paging_response;</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint8_t *mi_data;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t mi_len;</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct gsm48_imsi_detach_ind *idi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    *mi = (struct osmo_mobile_identity){</span><br><span style="color: hsl(120, 100%, 40%);">+          .type = GSM_MI_TYPE_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+             .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (msgb_l3len(msg) < sizeof(*gh))</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+  mtype = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (pdisc) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM48_PDISC_MM:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                switch (mtype) {</span><br><span style="color: hsl(120, 100%, 40%);">+              case GSM48_MT_MM_LOC_UPD_REQUEST:</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* First make sure that lu-> can be dereferenced */</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu))</span><br><span style="color: hsl(120, 100%, 40%);">+                           return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+                       lu = (struct gsm48_loc_upd_req*)gh->data;</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu) + lu->mi_len)</span><br><span style="color: hsl(120, 100%, 40%);">+                           return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                      mi_data = lu->mi;</span><br><span style="color: hsl(120, 100%, 40%);">+                  mi_len = lu->mi_len;</span><br><span style="color: hsl(120, 100%, 40%);">+                       goto got_mi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_MM_CM_SERV_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* Unfortunately in Phase1 the Classmark2 length is variable, so we cannot</span><br><span style="color: hsl(120, 100%, 40%);">+                     * just use gsm48_service_request struct, and need to parse it manually. */</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (msgb_l3len(msg) < sizeof(*gh) + 2)</span><br><span style="color: hsl(120, 100%, 40%);">+                             return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    cm2_len = gh->data[1];</span><br><span style="color: hsl(120, 100%, 40%);">+                     cm2_buf = gh->data + 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto got_cm2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               case GSM48_MT_MM_IMSI_DETACH_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*idi))</span><br><span style="color: hsl(120, 100%, 40%);">+                          return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                      idi = (struct gsm48_imsi_detach_ind*) gh->data;</span><br><span style="color: hsl(120, 100%, 40%);">+                    mi_data = idi->mi;</span><br><span style="color: hsl(120, 100%, 40%);">+                 mi_len = idi->mi_len;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto got_mi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM48_PDISC_RR:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                switch (mtype) {</span><br><span style="color: hsl(120, 100%, 40%);">+              case GSM48_MT_RR_PAG_RESP:</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*paging_response))</span><br><span style="color: hsl(120, 100%, 40%);">+                              return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+                      paging_response = (struct gsm48_pag_resp*)gh->data;</span><br><span style="color: hsl(120, 100%, 40%);">+                        cm2_len = paging_response->cm2_len;</span><br><span style="color: hsl(120, 100%, 40%);">+                        cm2_buf = (uint8_t*)&paging_response->cm2;</span><br><span style="color: hsl(120, 100%, 40%);">+                     goto got_cm2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return -ENOTSUP;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+got_cm2:</span><br><span style="color: hsl(120, 100%, 40%);">+  /* MI (Mobile Identity) LV follows the Classmark2 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* There must be at least a mi_len byte after the CM2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (cm2_buf + cm2_len + 1 > msg->tail)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    mi_start = cm2_buf + cm2_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ mi_len = mi_start[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ mi_data = mi_start + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+got_mi:</span><br><span style="color: hsl(120, 100%, 40%);">+    /* mi_data points at the start of the Mobile Identity coding of mi_len bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (mi_data + mi_len > msg->tail)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return osmo_mobile_identity_decode(mi, mi_data, mi_len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return a human readable representation of a struct osmo_mobile_identity.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Write a string like "IMSI-1234567", "TMSI-0x1234ABCD" or "NONE", "NULL".</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf  String buffer to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] buflen  sizeof(buf).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi  Decoded Mobile Identity data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return the strlen() of the string written when buflen is sufficiently large, like snprintf().</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_mobile_identity_name_buf(char *buf, size_t buflen, const struct osmo_mobile_identity *mi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!mi)</span><br><span style="color: hsl(120, 100%, 40%);">+              return snprintf(buf, buflen, "NULL");</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_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%);">+      case GSM_MI_TYPE_TMSI:</span><br><span style="color: hsl(120, 100%, 40%);">+                return snprintf(buf, buflen, "%s-%s", gsm48_mi_type_name(mi->type), mi->string);</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return snprintf(buf, buflen, "%s", gsm48_mi_type_name(mi->type));</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Like osmo_mobile_identity_name_buf(), but return the string in a talloc buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx  Talloc context to allocate from.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi  Decoded Mobile Identity data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return a string like "IMSI-1234567", "TMSI-0x1234ABCD" or "NONE", "NULL".</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mobile_identity_name_c(void *ctx, const struct osmo_mobile_identity *mi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_NAME_C_IMPL(ctx, 32, "ERROR", osmo_mobile_identity_name_buf, mi)</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Compare two osmo_mobile_identity structs, returning typical cmp() result.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] a  Left side osmo_mobile_identity.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] b  Right side osmo_mobile_identity.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 if both are equal, -1 if a < b, 1 if a > b.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 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(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (a == b)</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!a)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!b)</span><br><span style="color: hsl(120, 100%, 40%);">+               return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     cmp = OSMO_CMP(a->type, b->type);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (cmp)</span><br><span style="color: hsl(120, 100%, 40%);">+              return cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp = OSMO_CMP(a->tmsi, b->tmsi);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (cmp)</span><br><span style="color: hsl(120, 100%, 40%);">+              return cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+   return strncmp(a->string, b->string, sizeof(a->string));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Checks is particular message is cipherable in A/Gb mode according to</span><br><span>  *         3GPP TS 24.008 Â§ 4.7.1.2</span><br><span>  *  \param[in] hdr Message header</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index 98cdac5..bf8c384 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -363,6 +363,11 @@</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(120, 100%, 40%);">+osmo_mobile_identity_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mobile_identity_name_c;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mobile_identity_cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mobile_identity_decode;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mobile_identity_from_compl_l3;</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/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c</span><br><span>index 9617823..bfc8bd4 100644</span><br><span>--- a/tests/gsm0408/gsm0408_test.c</span><br><span>+++ b/tests/gsm0408/gsm0408_test.c</span><br><span>@@ -611,6 +611,354 @@</span><br><span>      printf("\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb *msg = msgb_alloc_headroom(size, 4, label);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+     msg->l3h = msgb_put(msg, osmo_hexparse(hex, msg->data, msgb_tailroom(msg)));</span><br><span style="color: hsl(120, 100%, 40%);">+    return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mobile_identity_tc {</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *label;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *compl_l3_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     int expect_rc;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_mobile_identity expect_mi;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Some Complete Layer 3 messages copied from real GSM network traces. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mobile_identity_tc mobile_identity_tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with IMSI 901700000004620",</span><br><span style="color: hsl(120, 100%, 40%);">+            .compl_l3_msg = "050802008168000130" "089910070000006402",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "901700000004620",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with TMSI 0x0980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "05084262f224002a50" "05f40980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "0x0980AD8A",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .tmsi = 0x0980ad8a,</span><br><span style="color: hsl(120, 100%, 40%);">+           },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with invalid MI type",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "050802008168000130" "089d10070000006402",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = -EINVAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with truncated IMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "050802008168000130" "0899100700000064",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with too short IMSI MI (12345)",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "050802008168000130" "03193254",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with just long enough IMSI MI 123456",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "050802008168000130" "04113254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with max length IMSI MI 123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+              .compl_l3_msg = "050802008168000130" "081932547698103254",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with just too long IMSI MI 1234567890123456",</span><br><span style="color: hsl(120, 100%, 40%);">+          .compl_l3_msg = "050802008168000130" "091132547698103254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with truncated TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "05084262f224002a50" "05f40980ad",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with odd length TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "05084262f224002a50" "05fc0980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with too long TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "05084262f224002a50" "06f40980ad23",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "LU with too short TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+          .compl_l3_msg = "05084262f224002a50" "04f480ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with IMSI 123456",</span><br><span style="color: hsl(120, 100%, 40%);">+             .compl_l3_msg = "052401035058a6" "04113254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with TMSI 0x5a42e404",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "052401035058a6" "05f45a42e404",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "0x5A42E404",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .tmsi = 0x5a42e404,</span><br><span style="color: hsl(120, 100%, 40%);">+           },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with shorter CM2, with IMSI 123456",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "052401025058" "04113254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with longer CM2, with IMSI 123456",</span><br><span style="color: hsl(120, 100%, 40%);">+            .compl_l3_msg = "052401055058a62342" "04113254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with shorter CM2, with TMSI 0x00000000",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "052401025058" "05f400000000",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "0x00000000",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .tmsi = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with invalid MI type",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "052401035058a6" "089d10070000006402",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EINVAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with truncated IMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "052401035058a6" "0899100700000064",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with truncated TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "0524010150" "05f40980ad",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with odd length TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "052401045058a623" "05fc0980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with too long TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "052401035058a6" "06f40980ad23",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "CM Service Request with too short TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+          .compl_l3_msg = "052401035058a6" "04f480ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with IMSI 1234567",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "06270003505886" "0419325476",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "1234567",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with TMSI 0xb48883de",</span><br><span style="color: hsl(120, 100%, 40%);">+            .compl_l3_msg = "06270003505886" "05f4b48883de",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "0xB48883DE",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .tmsi = 0xb48883de,</span><br><span style="color: hsl(120, 100%, 40%);">+           },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with TMSI, with unused nibble not 0xf",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "06270003505886" "0504b48883de",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with too short IMEI (1234567)",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "06270003505886" "041a325476",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with IMEI 123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "06270003505886" "081a32547698103254",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMEI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with IMEI 12345678901234 (no Luhn checksum)",</span><br><span style="color: hsl(120, 100%, 40%);">+             .compl_l3_msg = "06270003505886" "0812325476981032f4",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMEI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "12345678901234",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with IMEISV 1234567890123456",</span><br><span style="color: hsl(120, 100%, 40%);">+            .compl_l3_msg = "06270003505886" "091332547698103254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMEISV,</span><br><span style="color: hsl(120, 100%, 40%);">+                   .string = "1234567890123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                       .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with too short IMEISV 123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "06270003505886" "081b32547698103254",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with too long IMEISV 12345678901234567",</span><br><span style="color: hsl(120, 100%, 40%);">+          .compl_l3_msg = "06270003505886" "091b3254769810325476",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "Paging Response with IMSI 123456789012345 and flipped ODD bit",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "06270003505886" "081132547698103254",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with IMSI 901700000004620",</span><br><span style="color: hsl(120, 100%, 40%);">+           .compl_l3_msg = "050130" "089910070000006402",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "901700000004620",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with TMSI 0x0980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "050130" "05f40980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "0x0980AD8A",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .tmsi = 0x0980ad8a,</span><br><span style="color: hsl(120, 100%, 40%);">+           },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with invalid MI type",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "050130" "089d10070000006402",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EINVAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with truncated IMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+              .compl_l3_msg = "050130" "0899100700000064",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with too short IMSI MI (12345)",</span><br><span style="color: hsl(120, 100%, 40%);">+              .compl_l3_msg = "050130" "03193254",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with just long enough IMSI MI 123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "050130" "04113254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456",</span><br><span style="color: hsl(120, 100%, 40%);">+                 .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with max length IMSI MI 123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+             .compl_l3_msg = "050130" "081932547698103254",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_mi = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .type = GSM_MI_TYPE_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .string = "123456789012345",</span><br><span style="color: hsl(120, 100%, 40%);">+                        .tmsi = GSM_RESERVED_TMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+            },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with just too long IMSI MI 1234567890123456",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "050130" "091132547698103254f6",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with truncated TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+              .compl_l3_msg = "050130" "05f40980ad",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with odd length TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+                .compl_l3_msg = "050130" "05fc0980ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with too long TMSI MI",</span><br><span style="color: hsl(120, 100%, 40%);">+               .compl_l3_msg = "050130" "06f40980ad23",</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .label = "IMSI-Detach with too short TMSI",</span><br><span style="color: hsl(120, 100%, 40%);">+         .compl_l3_msg = "050130" "04f480ad8a",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = -EBADMSG,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void test_struct_mobile_identity()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct mobile_identity_tc *t;</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("%s()\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (t = mobile_identity_tests; (t - mobile_identity_tests) < ARRAY_SIZE(mobile_identity_tests); t++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct osmo_mobile_identity mi;</span><br><span style="color: hsl(120, 100%, 40%);">+               struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+             int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+               memset(&mi, 0xff, sizeof(mi));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          msg = msgb_from_hex(t->label, 1024, t->compl_l3_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = osmo_mobile_identity_from_compl_l3(&mi, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("%s: rc = %d", t->label, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf(", mi = %s", osmo_mobile_identity_name_c(OTC_SELECT, &mi));</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (rc == t->expect_rc</span><br><span style="color: hsl(120, 100%, 40%);">+                 && ((rc != 0) || !osmo_mobile_identity_cmp(&mi, &t->expect_mi))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf(" ok");</span><br><span style="color: hsl(120, 100%, 40%);">+              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("  ERROR: Expected rc = %d", t->expect_rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (!t->expect_rc)</span><br><span style="color: hsl(120, 100%, 40%);">+                         printf(", mi = %s", osmo_mobile_identity_name_c(OTC_SELECT, &t->expect_mi));</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 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>@@ -1182,6 +1530,7 @@</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(120, 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 d343869..b012cb6 100644</span><br><span>--- a/tests/gsm0408/gsm0408_test.ok</span><br><span>+++ b/tests/gsm0408/gsm0408_test.ok</span><br><span>@@ -139,6 +139,53 @@</span><br><span>     rc=1</span><br><span>     returned empty string</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+test_struct_mobile_identity()</span><br><span style="color: hsl(120, 100%, 40%);">+LU with IMSI 901700000004620: rc = 0, mi = IMSI-901700000004620 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with TMSI 0x0980ad8a: rc = 0, mi = TMSI-0x0980AD8A ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with invalid MI type: rc = -22 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with truncated IMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with too short IMSI MI (12345): rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with just long enough IMSI MI 123456: rc = 0, mi = IMSI-123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with max length IMSI MI 123456789012345: rc = 0, mi = IMSI-123456789012345 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with just too long IMSI MI 1234567890123456: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with truncated TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with odd length TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with too long TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+LU with too short TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with IMSI 123456: rc = 0, mi = IMSI-123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with TMSI 0x5a42e404: rc = 0, mi = TMSI-0x5A42E404 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with shorter CM2, with IMSI 123456: rc = 0, mi = IMSI-123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with longer CM2, with IMSI 123456: rc = 0, mi = IMSI-123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with shorter CM2, with TMSI 0x00000000: rc = 0, mi = TMSI-0x00000000 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with invalid MI type: rc = -22 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with truncated IMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with truncated TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with odd length TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with too long TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+CM Service Request with too short TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with IMSI 1234567: rc = 0, mi = IMSI-1234567 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with TMSI 0xb48883de: rc = 0, mi = TMSI-0xB48883DE ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with TMSI, with unused nibble not 0xf: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with too short IMEI (1234567): rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with IMEI 123456789012345: rc = 0, mi = IMEI-123456789012345 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with IMEI 12345678901234 (no Luhn checksum): rc = 0, mi = IMEI-12345678901234 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with IMEISV 1234567890123456: rc = 0, mi = IMEI-SV-1234567890123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with too short IMEISV 123456789012345: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with too long IMEISV 12345678901234567: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+Paging Response with IMSI 123456789012345 and flipped ODD bit: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with IMSI 901700000004620: rc = 0, mi = IMSI-901700000004620 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with TMSI 0x0980ad8a: rc = 0, mi = TMSI-0x0980AD8A ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with invalid MI type: rc = -22 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with truncated IMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with too short IMSI MI (12345): rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with just long enough IMSI MI 123456: rc = 0, mi = IMSI-123456 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with max length IMSI MI 123456789012345: rc = 0, mi = IMSI-123456789012345 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with just too long IMSI MI 1234567890123456: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with truncated TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with odd length TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with too long TMSI MI: rc = -74 ok</span><br><span style="color: hsl(120, 100%, 40%);">+IMSI-Detach with too short TMSI: rc = -74 ok</span><br><span style="color: hsl(120, 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></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/18507">change 18507</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/+/18507"/><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: Ic3f969e739654c1e8c387aedeeba5cce07fe2307 </div>
<div style="display:none"> Gerrit-Change-Number: 18507 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>