Change in libosmocore[master]: Add GCR routines

Max gerrit-no-reply at lists.osmocom.org
Mon Nov 19 11:53:04 UTC 2018


Max has uploaded this change for review. ( https://gerrit.osmocom.org/11827


Change subject: Add GCR routines
......................................................................

Add GCR routines

Add functions to create and decode Global Call Reference as per
3GPP TS 29.205 Table B 2.1.9.1, add corresponding tests

Change-Id: Iee95aa4e5c056645b6cb5667e4a067097d52dfbf
Related: OS#2487
---
M include/osmocom/gsm/gsm0808.h
M include/osmocom/gsm/gsm0808_utils.h
M src/gsm/gsm0808.c
M src/gsm/gsm0808_utils.c
M src/gsm/libosmogsm.map
M tests/gsm0808/gsm0808_test.c
M tests/gsm0808/gsm0808_test.ok
7 files changed, 119 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/27/11827/1

diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index 9b19d69..7777c23 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -52,6 +52,9 @@
 struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
 struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause);
 struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);
+
+struct msgb *gsm0808_create_gcr(const struct gsm0808_gcr *g);
+
 struct msgb *gsm0808_create_classmark_request();
 struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
 					     const uint8_t *cm3, uint8_t cm3_len);
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index c5bf280..59d8985 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -66,6 +66,16 @@
 	bool corr_needed;                  /* §3.2.2.118 Correlation-Not-Needed */
 };
 
+/*! Parsed representation of Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1 */
+struct gsm0808_gcr {
+	uint8_t *net;    /* Network ID, ITU-T Q.1902.3 */
+	uint8_t net_len; /* length (3-5 octets) of \a net */
+	uint16_t node;   /* Node ID */
+	uint8_t *cr;     /* Call Reference ID (5 octets) */
+};
+
+int gsm0808_dec_gcr(struct gsm0808_gcr *gcr, const struct msgb *m);
+
 extern const struct value_string gsm0808_cell_id_discr_names[];
 static inline const char *gsm0808_cell_id_discr_name(enum CELL_IDENT id_discr)
 { return get_value_string(gsm0808_cell_id_discr_names, id_discr); }
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c
index a84e717..3a2c551 100644
--- a/src/gsm/gsm0808.c
+++ b/src/gsm/gsm0808.c
@@ -405,6 +405,30 @@
 	return msg;
 }
 
+/*! Create BSSMAP Global Call Reference
+ *  \param[in] g Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1
+ *  \returns callee-allocated msgb with GCR */
+struct msgb *gsm0808_create_gcr(const struct gsm0808_gcr *g)
+{
+	uint8_t buf[2];
+	struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+					       "global call reference");
+	if (!msg || !g)
+		return NULL;
+
+	if (g->net_len < 3 || g->net_len > 5)
+		return NULL;
+
+	msgb_lv_put(msg, g->net_len, g->net);
+
+	osmo_store16be(g->node, &buf);
+	msgb_lv_put(msg, 2, buf);
+
+	msgb_lv_put(msg, 5, g->cr);
+
+	return msg;
+}
+
 /*! Create BSSMAP SAPI N Reject message
  *  \param[in] link_id Link Identifier
  *  \returns callee-allocated msgb with BSSMAP SAPI N Reject message */
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index c58d828..c73114d 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <osmocom/gsm/protocol/gsm_08_08.h>
 #include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm0808.h>
 #include <osmocom/gsm/gsm0808_utils.h>
 
 #define IP_V4_ADDR_LEN 4
@@ -667,6 +668,43 @@
 	return *tlv_len + 2;
 }
 
+/*! Decode BSSMAP Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1
+ *  \param[out] gcr Caller-provided memory to store Global Call Reference
+ *  \param[in] m message buffer to be decoded
+ *  \returns number of bytes parsed; negative on error */
+int gsm0808_dec_gcr(struct gsm0808_gcr *gcr, const struct msgb *msg)
+{
+	struct tlv_parsed tp;
+	const uint8_t *buf;
+	uint16_t len, point = 1;
+	int rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));
+	if (rc < 0)
+		return -EINVAL;
+
+	buf = TLVP_VAL_MINLEN(&tp, GSM0808_IE_GLOBAL_CALL_REF, 13);
+	if (!buf)
+		return -EBADMSG;
+
+	len = TLVP_LEN(&tp, GSM0808_IE_GLOBAL_CALL_REF);
+
+	gcr->net_len = buf[0];
+	if (gcr->net_len < 3 || gcr->net_len > 5)
+		return -E2BIG;
+
+	memcpy(gcr->net, buf + point, gcr->net_len);
+	point += (gcr->net_len + 1);
+
+	gcr->node = osmo_load16be(buf + point);
+	point += 2;
+
+	if (buf[point] != 5) /* see Table B 2.1.9.2 */
+		return -EBADSLT;
+
+	memcpy(gcr->cr, buf + point + 1, 5);
+
+	return len;
+}
+
 /* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC. */
 static void decode_lai(const uint8_t *data, struct osmo_location_area_id *decoded)
 {
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 217dcc3..85739b6 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -154,6 +154,8 @@
 gsm0808_create_ass_compl;
 gsm0808_create_assignment_failure;
 gsm0808_create_ass_fail;
+gsm0808_create_gcr;
+gsm0808_dec_gcr;
 gsm0808_create_cipher;
 gsm0808_create_cipher_complete;
 gsm0808_create_cipher_reject;
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index 197ec06..d2f7250 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -130,6 +130,46 @@
 	msgb_free(in_msg);
 }
 
+static void test_create_gcr()
+{
+	static const uint8_t res[] = { 0x89, 0x0d, 0x03, 0x55, 0x55, 0x55, 0x02, 0xde, 0xad, 0x05, 0x46, 0x46, 0x46, 0x46, 0x46 };
+	struct msgb *msg;
+	struct gsm0808_gcr g = { .net_len = 3, .node = 0xDEAD }, p;
+	uint8_t net[g.net_len], pnet[g.net_len], cr[5], pcr[5] = { 0 };
+	int rc;
+
+	g.net = net;
+	g.cr = cr;
+	p.net = pnet;
+	p.cr = pcr;
+	memset(pcr, 0, 5);
+	memset(cr, 'F', 5);
+	memset(net, 'U', g.net_len);
+
+	printf("Testing creating Global Call Reference\n");
+	msg = gsm0808_create_gcr(&g);
+	msg->l3h = msgb_wrap_with_TL(msg, GSM0808_IE_GLOBAL_CALL_REF);
+	VERIFY(msg, res, ARRAY_SIZE(res));
+
+	rc = gsm0808_dec_gcr(&p, msg);
+	if (rc < 0)
+		printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
+
+	if (p.net_len != g.net_len)
+		printf("Network ID length parsed wrong: %u != %u\n", p.net_len, g.net_len);
+
+	if (p.node != g.node)
+		printf("Node ID parsed wrong: 0x%X != 0x%X\n", p.node, g.node);
+
+	if (memcmp(p.net, g.net, g.net_len) != 0)
+		printf("Network ID parsed wrong: %s\n", osmo_hexdump(p.net, p.net_len));
+
+	if (memcmp(p.cr, g.cr, 5) != 0)
+		printf("Call ref. ID parsed wrong: %s\n", osmo_hexdump(p.cr, 5));
+
+	msgb_free(msg);
+}
+
 static void test_create_reset()
 {
 	static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
@@ -1774,6 +1814,7 @@
 	test_create_layer3_aoip();
 	test_create_reset();
 	test_create_reset_ack();
+	test_create_gcr();
 	test_create_clear_command();
 	test_create_clear_complete();
 	test_create_cipher();
diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok
index a48cf1d..db36594 100644
--- a/tests/gsm0808/gsm0808_test.ok
+++ b/tests/gsm0808/gsm0808_test.ok
@@ -3,6 +3,7 @@
 Testing creating Layer3 (AoIP)
 Testing creating Reset
 Testing creating Reset Ack
+Testing creating Global Call Reference
 Testing creating Clear Command
 Testing creating Clear Complete
 Testing creating Chipher Mode Command

-- 
To view, visit https://gerrit.osmocom.org/11827
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iee95aa4e5c056645b6cb5667e4a067097d52dfbf
Gerrit-Change-Number: 11827
Gerrit-PatchSet: 1
Gerrit-Owner: Max <msuraev at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20181119/b142ebcb/attachment.html>


More information about the gerrit-log mailing list