<p>Max has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/11827">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add GCR routines<br><br>Add functions to create and decode Global Call Reference as per<br>3GPP TS 29.205 Table B 2.1.9.1, add corresponding tests<br><br>Change-Id: Iee95aa4e5c056645b6cb5667e4a067097d52dfbf<br>Related: OS#2487<br>---<br>M include/osmocom/gsm/gsm0808.h<br>M include/osmocom/gsm/gsm0808_utils.h<br>M src/gsm/gsm0808.c<br>M src/gsm/gsm0808_utils.c<br>M src/gsm/libosmogsm.map<br>M tests/gsm0808/gsm0808_test.c<br>M tests/gsm0808/gsm0808_test.ok<br>7 files changed, 119 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/27/11827/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h</span><br><span>index 9b19d69..7777c23 100644</span><br><span>--- a/include/osmocom/gsm/gsm0808.h</span><br><span>+++ b/include/osmocom/gsm/gsm0808.h</span><br><span>@@ -52,6 +52,9 @@</span><br><span> struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);</span><br><span> struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause);</span><br><span> struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gsm0808_create_gcr(const struct gsm0808_gcr *g);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct msgb *gsm0808_create_classmark_request();</span><br><span> struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,</span><br><span>                                              const uint8_t *cm3, uint8_t cm3_len);</span><br><span>diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h</span><br><span>index c5bf280..59d8985 100644</span><br><span>--- a/include/osmocom/gsm/gsm0808_utils.h</span><br><span>+++ b/include/osmocom/gsm/gsm0808_utils.h</span><br><span>@@ -66,6 +66,16 @@</span><br><span>     bool corr_needed;                  /* ยง3.2.2.118 Correlation-Not-Needed */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Parsed representation of Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm0808_gcr {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *net;    /* Network ID, ITU-T Q.1902.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t net_len; /* length (3-5 octets) of \a net */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t node;   /* Node ID */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t *cr;     /* Call Reference ID (5 octets) */</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 gsm0808_dec_gcr(struct gsm0808_gcr *gcr, const struct msgb *m);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> extern const struct value_string gsm0808_cell_id_discr_names[];</span><br><span> static inline const char *gsm0808_cell_id_discr_name(enum CELL_IDENT id_discr)</span><br><span> { return get_value_string(gsm0808_cell_id_discr_names, id_discr); }</span><br><span>diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c</span><br><span>index a84e717..3a2c551 100644</span><br><span>--- a/src/gsm/gsm0808.c</span><br><span>+++ b/src/gsm/gsm0808.c</span><br><span>@@ -405,6 +405,30 @@</span><br><span>         return msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Create BSSMAP Global Call Reference</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] g Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns callee-allocated msgb with GCR */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gsm0808_create_gcr(const struct gsm0808_gcr *g)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t buf[2];</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,</span><br><span style="color: hsl(120, 100%, 40%);">+                                         "global call reference");</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!msg || !g)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (g->net_len < 3 || g->net_len > 5)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        msgb_lv_put(msg, g->net_len, g->net);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_store16be(g->node, &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_lv_put(msg, 2, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_lv_put(msg, 5, g->cr);</span><br><span style="color: hsl(120, 100%, 40%);">+</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> /*! Create BSSMAP SAPI N Reject message</span><br><span>  *  \param[in] link_id Link Identifier</span><br><span>  *  \returns callee-allocated msgb with BSSMAP SAPI N Reject message */</span><br><span>diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c</span><br><span>index c58d828..c73114d 100644</span><br><span>--- a/src/gsm/gsm0808_utils.c</span><br><span>+++ b/src/gsm/gsm0808_utils.c</span><br><span>@@ -28,6 +28,7 @@</span><br><span> #include <errno.h></span><br><span> #include <osmocom/gsm/protocol/gsm_08_08.h></span><br><span> #include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm0808.h></span><br><span> #include <osmocom/gsm/gsm0808_utils.h></span><br><span> </span><br><span> #define IP_V4_ADDR_LEN 4</span><br><span>@@ -667,6 +668,43 @@</span><br><span>        return *tlv_len + 2;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Decode BSSMAP Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] gcr Caller-provided memory to store Global Call Reference</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] m message buffer to be decoded</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns number of bytes parsed; negative on error */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0808_dec_gcr(struct gsm0808_gcr *gcr, const struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct tlv_parsed tp;</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint8_t *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t len, point = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     buf = TLVP_VAL_MINLEN(&tp, GSM0808_IE_GLOBAL_CALL_REF, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!buf)</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%);">+    len = TLVP_LEN(&tp, GSM0808_IE_GLOBAL_CALL_REF);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        gcr->net_len = buf[0];</span><br><span style="color: hsl(120, 100%, 40%);">+     if (gcr->net_len < 3 || gcr->net_len > 5)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -E2BIG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(gcr->net, buf + point, gcr->net_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    point += (gcr->net_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     gcr->node = osmo_load16be(buf + point);</span><br><span style="color: hsl(120, 100%, 40%);">+    point += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (buf[point] != 5) /* see Table B 2.1.9.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EBADSLT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(gcr->cr, buf + point + 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC. */</span><br><span> static void decode_lai(const uint8_t *data, struct osmo_location_area_id *decoded)</span><br><span> {</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index 217dcc3..85739b6 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -154,6 +154,8 @@</span><br><span> gsm0808_create_ass_compl;</span><br><span> gsm0808_create_assignment_failure;</span><br><span> gsm0808_create_ass_fail;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_create_gcr;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_dec_gcr;</span><br><span> gsm0808_create_cipher;</span><br><span> gsm0808_create_cipher_complete;</span><br><span> gsm0808_create_cipher_reject;</span><br><span>diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c</span><br><span>index 197ec06..d2f7250 100644</span><br><span>--- a/tests/gsm0808/gsm0808_test.c</span><br><span>+++ b/tests/gsm0808/gsm0808_test.c</span><br><span>@@ -130,6 +130,46 @@</span><br><span>        msgb_free(in_msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void test_create_gcr()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ static const uint8_t res[] = { 0x89, 0x0d, 0x03, 0x55, 0x55, 0x55, 0x02, 0xde, 0xad, 0x05, 0x46, 0x46, 0x46, 0x46, 0x46 };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm0808_gcr g = { .net_len = 3, .node = 0xDEAD }, p;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t net[g.net_len], pnet[g.net_len], cr[5], pcr[5] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     g.net = net;</span><br><span style="color: hsl(120, 100%, 40%);">+  g.cr = cr;</span><br><span style="color: hsl(120, 100%, 40%);">+    p.net = pnet;</span><br><span style="color: hsl(120, 100%, 40%);">+ p.cr = pcr;</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(pcr, 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(cr, 'F', 5);</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(net, 'U', g.net_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("Testing creating Global Call Reference\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = gsm0808_create_gcr(&g);</span><br><span style="color: hsl(120, 100%, 40%);">+     msg->l3h = msgb_wrap_with_TL(msg, GSM0808_IE_GLOBAL_CALL_REF);</span><br><span style="color: hsl(120, 100%, 40%);">+     VERIFY(msg, res, ARRAY_SIZE(res));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = gsm0808_dec_gcr(&p, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (p.net_len != g.net_len)</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("Network ID length parsed wrong: %u != %u\n", p.net_len, g.net_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (p.node != g.node)</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("Node ID parsed wrong: 0x%X != 0x%X\n", p.node, g.node);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (memcmp(p.net, g.net, g.net_len) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("Network ID parsed wrong: %s\n", osmo_hexdump(p.net, p.net_len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (memcmp(p.cr, g.cr, 5) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("Call ref. ID parsed wrong: %s\n", osmo_hexdump(p.cr, 5));</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+</span><br><span> static void test_create_reset()</span><br><span> {</span><br><span>         static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };</span><br><span>@@ -1774,6 +1814,7 @@</span><br><span>         test_create_layer3_aoip();</span><br><span>   test_create_reset();</span><br><span>         test_create_reset_ack();</span><br><span style="color: hsl(120, 100%, 40%);">+      test_create_gcr();</span><br><span>   test_create_clear_command();</span><br><span>         test_create_clear_complete();</span><br><span>        test_create_cipher();</span><br><span>diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok</span><br><span>index a48cf1d..db36594 100644</span><br><span>--- a/tests/gsm0808/gsm0808_test.ok</span><br><span>+++ b/tests/gsm0808/gsm0808_test.ok</span><br><span>@@ -3,6 +3,7 @@</span><br><span> Testing creating Layer3 (AoIP)</span><br><span> Testing creating Reset</span><br><span> Testing creating Reset Ack</span><br><span style="color: hsl(120, 100%, 40%);">+Testing creating Global Call Reference</span><br><span> Testing creating Clear Command</span><br><span> Testing creating Clear Complete</span><br><span> Testing creating Chipher Mode Command</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11827">change 11827</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/11827"/><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-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Iee95aa4e5c056645b6cb5667e4a067097d52dfbf </div>
<div style="display:none"> Gerrit-Change-Number: 11827 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Max <msuraev@sysmocom.de> </div>