[PATCH] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Tue Feb 27 13:34:59 UTC 2018


Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/6663

to look at the new patch set (#7).

gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp() for 3-digit MNC

osmo_mnc_from_str() preserves leading zeros in the string and is useful for
VTY config parsing (osmo-bsc, osmo-msc, osmo-sgsn, osmo-pcu).

osmo_{plmn,mnc}_cmp() takes care of the slight intricacy of ignoring the 3-digit flag
if the MNC is anyway >99. Will be used by osmo-sgsn.git and osmo-bsc.git.  (All
current users just care about identical MNC, but a proper cmp doesn't hurt.)

Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6
---
M include/osmocom/gsm/gsm23003.h
M src/gsm/gsm23003.c
M src/gsm/libosmogsm.map
M tests/gsm23003/gsm23003_test.c
M tests/gsm23003/gsm23003_test.ok
5 files changed, 157 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/63/6663/7

diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h
index 51e5ef8..660186e 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -95,3 +95,8 @@
 
 void osmo_plmn_to_bcd(uint8_t *bcd_dst, const struct osmo_plmn_id *plmn);
 void osmo_plmn_from_bcd(const uint8_t *bcd_src, struct osmo_plmn_id *plmn);
+
+int osmo_mnc_from_str(const char *mnc_str, uint16_t *mnc, bool *mnc_3_digits);
+
+int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits);
+int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b);
diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c
index 63de2b8..1f6bf7d 100644
--- a/src/gsm/gsm23003.c
+++ b/src/gsm/gsm23003.c
@@ -25,6 +25,9 @@
 
 #include <ctype.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
 
 #include <osmocom/gsm/gsm23003.h>
 #include <osmocom/gsm/protocol/gsm_23_003.h>
@@ -195,3 +198,77 @@
 		plmn->mnc_3_digits = true;
 	}
 }
+
+/* Convert string to MNC, detecting 3-digit MNC with leading zeros.
+ * Return mnc_3_digits as false if the MNC's most significant digit is encoded as 0xF, true
+ * otherwise; i.e. true if MNC > 99 or if it is represented with leading zeros instead of 0xF.
+ * \param mnc_str[in]	String representation of an MNC, with or without leading zeros.
+ * \param mnc[out]	MNC result buffer, or NULL.
+ * \param[out] mnc_3_digits	Result buffer for 3-digit flag, or NULL.
+ * \returns zero on success, -EINVAL in case of surplus characters, negative errno in case of conversion
+ *          errors.
+ */
+int osmo_mnc_from_str(const char *mnc_str, uint16_t *mnc, bool *mnc_3_digits)
+{
+	long int _mnc = 0;
+	bool _mnc_3_digits = false;
+	char *endptr;
+	int rc = 0;
+
+	if (!mnc_str || !isdigit(mnc_str[0]) || strlen(mnc_str) > 3) {
+		/* return invalid, but give strtol a shot anyway, for callers that don't want to be
+		 * strict */
+		rc = -EINVAL;
+	}
+	errno = 0;
+	_mnc = strtol(mnc_str, &endptr, 10);
+	if (errno)
+		rc = -errno;
+	else if (*endptr)
+		rc = -EINVAL;
+	if (_mnc < 0 || _mnc > 999)
+		rc = -EINVAL;
+	_mnc_3_digits = strlen(mnc_str) > 2;
+
+	if (mnc)
+		*mnc = (uint16_t)_mnc;
+	if (mnc_3_digits)
+		*mnc_3_digits = _mnc_3_digits;
+	return rc;
+}
+
+/* Compare two MNC with three-digit flag.
+ * The mnc_3_digits flags passed in only have an effect if the MNC are < 100, i.e. if they would amount
+ * to a change in leading zeros in a BCD representation. An MNC >= 100 implies three digits, and the flag
+ * is actually ignored.
+ * \param a_mnc[in]		"Left" side MNC.
+ * \param a_mnc_3_digits[in]	"Left" side three-digits flag.
+ * \param b_mnc[in]		"Right" side MNC.
+ * \param b_mnc_3_digits[in]	"Right" side three-digits flag.
+ * \returns 0 if the MNC are equal, -1 if a < b or a shorter, 1 if a > b or a longer. */
+int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits)
+{
+	if (a_mnc < b_mnc)
+		return -1;
+	if (a_mnc > b_mnc)
+		return 1;
+	/* a_mnc == b_mnc, but same amount of leading zeros? */
+	if (a_mnc < 100 && a_mnc_3_digits != b_mnc_3_digits)
+		return a_mnc_3_digits ? 1 : -1;
+	return 0;
+}
+
+/* Compare two PLMN.
+ * \param a[in]  "Left" side PLMN.
+ * \param b[in]  "Right" side PLMN.
+ * \returns 0 if the PLMN are equal, -1 if a < b or a shorter, 1 if a > b or a longer. */
+int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b)
+{
+	if (a == b)
+		return 0;
+	if (a->mcc < b->mcc)
+		return -1;
+	if (a->mcc > b->mcc)
+		return 1;
+	return osmo_mnc_cmp(a->mnc, a->mnc_3_digits, b->mnc, b->mnc_3_digits);
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 2c5b329..ffda6c2 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -270,6 +270,9 @@
 osmo_plmn_name2;
 osmo_lai_name;
 osmo_rai_name;
+osmo_mnc_from_str;
+osmo_mnc_cmp;
+osmo_plmn_cmp;
 gsm48_chan_mode_names;
 gsm_chan_t_names;
 gsm48_pdisc_names;
diff --git a/tests/gsm23003/gsm23003_test.c b/tests/gsm23003/gsm23003_test.c
index 64d756d..4411e29 100644
--- a/tests/gsm23003/gsm23003_test.c
+++ b/tests/gsm23003/gsm23003_test.c
@@ -22,6 +22,8 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
+#include <strings.h>
 
 #include <osmocom/gsm/gsm23003.h>
 #include <osmocom/core/utils.h>
@@ -114,12 +116,65 @@
 	return pass;
 }
 
+struct test_mnc_from_str_result {
+	int rc;
+	uint16_t mnc;
+	bool mnc_3_digits;
+};
+
+struct test_mnc_from_str {
+	const char *mnc_str;
+	struct test_mnc_from_str_result expect;
+};
+
+static struct test_mnc_from_str test_mnc_from_strs[] = {
+	{ "0",	 { 0, 0, false } },
+	{ "00",	 { 0, 0, false } },
+	{ "000", { 0, 0, true } },
+	{ "1",	 { 0, 1, false } },
+	{ "01",	 { 0, 1, false } },
+	{ "001", { 0, 1, true } },
+	{ "",	 { -EINVAL, 0, false } },
+	{ " ",	 { -EINVAL, 0, false } },
+	{ "-1",	 { -EINVAL, 65535, false } },
+	{ "1000", { -EINVAL, 1000, true } },
+	{ "0x",	 { -EINVAL, 0, false } },
+	{ " 23", { -EINVAL, 23, true } }, /* technically not a 3-digit MNC, but it's EINVAL anyway */
+	{ "23 ", { -EINVAL, 23, true } },
+	{ " 023", { -EINVAL, 23, true } },
+	{ "023 ", { -EINVAL, 23, true } },
+	{ "023 ", { -EINVAL, 23, true } },
+};
+
+static bool test_mnc_from_str()
+{
+	int i;
+	bool pass = true;
+	printf("----- %s\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(test_mnc_from_strs); i++) {
+		struct test_mnc_from_str *t = &test_mnc_from_strs[i];
+		struct test_mnc_from_str_result result;
+		bool ok;
+
+		result.rc = osmo_mnc_from_str(t->mnc_str, &result.mnc,
+						     &result.mnc_3_digits);
+		ok = !bcmp(&result, &t->expect, sizeof(result));
+		printf("%2d: \"%s\" rc=%d mnc=%u mnc_3_digits=%u %s\n",
+		       i, osmo_escape_str(t->mnc_str, -1), result.rc, result.mnc, result.mnc_3_digits,
+		       ok ? "pass" : "FAIL");
+		pass = pass && ok;
+	}
+	return pass;
+}
+
 int main(int argc, char **argv)
 {
 	bool pass = true;
 
 	pass = pass && test_valid_imsi();
 	pass = pass && test_valid_msisdn();
+	pass = pass && test_mnc_from_str();
 
 	OSMO_ASSERT(pass);
 
diff --git a/tests/gsm23003/gsm23003_test.ok b/tests/gsm23003/gsm23003_test.ok
index 7d7ffd1..565c38c 100644
--- a/tests/gsm23003/gsm23003_test.ok
+++ b/tests/gsm23003/gsm23003_test.ok
@@ -42,3 +42,20 @@
 17: expect=false result=false msisdn='123456	123456'
 18: expect=false result=false msisdn='123456
123456'
 19: expect=false result=false msisdn='(null)'
+----- test_mnc_from_str
+ 0: "0" rc=0 mnc=0 mnc_3_digits=0 pass
+ 1: "00" rc=0 mnc=0 mnc_3_digits=0 pass
+ 2: "000" rc=0 mnc=0 mnc_3_digits=1 pass
+ 3: "1" rc=0 mnc=1 mnc_3_digits=0 pass
+ 4: "01" rc=0 mnc=1 mnc_3_digits=0 pass
+ 5: "001" rc=0 mnc=1 mnc_3_digits=1 pass
+ 6: "" rc=-22 mnc=0 mnc_3_digits=0 pass
+ 7: " " rc=-22 mnc=0 mnc_3_digits=0 pass
+ 8: "-1" rc=-22 mnc=65535 mnc_3_digits=0 pass
+ 9: "1000" rc=-22 mnc=1000 mnc_3_digits=1 pass
+10: "0x" rc=-22 mnc=0 mnc_3_digits=0 pass
+11: " 23" rc=-22 mnc=23 mnc_3_digits=1 pass
+12: "23 " rc=-22 mnc=23 mnc_3_digits=1 pass
+13: " 023" rc=-22 mnc=23 mnc_3_digits=1 pass
+14: "023 " rc=-22 mnc=23 mnc_3_digits=1 pass
+15: "023 " rc=-22 mnc=23 mnc_3_digits=1 pass

-- 
To view, visit https://gerrit.osmocom.org/6663
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6
Gerrit-PatchSet: 7
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list