diff options
| -rw-r--r-- | include/osmocom/gsm/gsm23003.h | 4 | ||||
| -rw-r--r-- | include/osmocom/gsm/protocol/gsm_23_003.h | 1 | ||||
| -rw-r--r-- | src/gsm/Makefile.am | 3 | ||||
| -rw-r--r-- | src/gsm/gsm23003.c | 65 | ||||
| -rw-r--r-- | src/gsm/libosmogsm.map | 3 | ||||
| -rw-r--r-- | tests/Makefile.am | 8 | ||||
| -rw-r--r-- | tests/gsm23003/gsm23003_test.c | 124 | ||||
| -rw-r--r-- | tests/gsm23003/gsm23003_test.ok | 42 | ||||
| -rw-r--r-- | tests/testsuite.at | 6 | 
9 files changed, 253 insertions, 3 deletions
| diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index 2bc75837..dd41bc5b 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -3,6 +3,7 @@  #pragma once  #include <stdint.h> +#include <stdbool.h>  /* 23.003 Chapter 12.1 */  struct osmo_plmn_id { @@ -81,3 +82,6 @@ struct osmo_guti {  	struct osmo_gummei gummei;  	uint32_t mtmsi;  }; + +bool osmo_imsi_str_valid(const char *imsi); +bool osmo_msisdn_str_valid(const char *msisdn); diff --git a/include/osmocom/gsm/protocol/gsm_23_003.h b/include/osmocom/gsm/protocol/gsm_23_003.h index 94243feb..0e669399 100644 --- a/include/osmocom/gsm/protocol/gsm_23_003.h +++ b/include/osmocom/gsm/protocol/gsm_23_003.h @@ -4,6 +4,7 @@  /* Chapter 2.2 */  #define GSM23003_IMSI_MAX_DIGITS	15 +#define GSM23003_IMSI_MIN_DIGITS	6  /* Chapter 2.4 */  #define GSM23003_TMSI_NUM_BYTES		4  /* Chapter 2.5 */ diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 08cd5e65..48b8b2cf 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -29,7 +29,8 @@ libgsmint_la_SOURCES =  a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \  			auth_milenage.c milenage/aes-encblock.c gea.c \  			milenage/aes-internal.c milenage/aes-internal-enc.c \  			milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \ -			gsup.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c +			gsup.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ +			gsm23003.c  libgsmint_la_LDFLAGS = -no-undefined  libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c new file mode 100644 index 00000000..004e20ff --- /dev/null +++ b/src/gsm/gsm23003.c @@ -0,0 +1,65 @@ +/*! \file gsm23003.c + * Utility function implementations related to 3GPP TS 23.003 */ +/* + * (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <ctype.h> + +#include <osmocom/gsm/gsm23003.h> +#include <osmocom/gsm/protocol/gsm_23_003.h> + +static bool is_n_digits(const char *str, int min_digits, int max_digits) +{ +	int len; +	/* Use unsigned char * to avoid a compiler warning of +	 * "error: array subscript has type 'char' [-Werror=char-subscripts]" */ +	const unsigned char *pos = (const unsigned char *)str; +	for (len = 0; *pos && len < max_digits; len++, pos++) +		if (!isdigit(*pos)) +			return false; +	if (len < min_digits) +		return false; +	/* With not too many digits, we should have reached *str == nul */ +	if (*pos) +		return false; +	return true; +} + +/*! Determine whether the given IMSI is valid according to 3GPP TS 23.003. + * \param imsi  IMSI digits in ASCII string representation. + * \returns true when the IMSI is valid, false for invalid characters or number + *          of digits. + */ +bool osmo_imsi_str_valid(const char *imsi) +{ +	return is_n_digits(imsi, GSM23003_IMSI_MIN_DIGITS, GSM23003_IMSI_MAX_DIGITS); +} + +/*! Determine whether the given MSISDN is valid according to 3GPP TS 23.003. + * \param msisdn  MSISDN digits in ASCII string representation. + * \returns true when the MSISDN is valid, false for invalid characters or number + *          of digits. + */ +bool osmo_msisdn_str_valid(const char *msisdn) +{ +	return is_n_digits(msisdn, 1, 15); +} diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 066f4107..95b2ca9f 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -418,5 +418,8 @@ osmo_gsup_message_type_names;  osmo_oap_encode;  osmo_oap_decode; +osmo_imsi_str_valid; +osmo_msisdn_str_valid; +  local: *;  }; diff --git a/tests/Makefile.am b/tests/Makefile.am index b1387174..dbe349f5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,7 +15,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test		\  		 write_queue/wqueue_test socket/socket_test		\  		 coding/coding_test conv/conv_gsm0503_test		\  		 abis/abis_test endian/endian_test sercomm/sercomm_test	\ -		 stats/stats_test prbs/prbs_test +		 stats/stats_test prbs/prbs_test gsm23003/gsm23003_test  if ENABLE_MSGFILE  check_PROGRAMS += msgfile/msgfile_test @@ -186,6 +186,9 @@ sercomm_sercomm_test_LDADD = $(top_builddir)/src/libosmocore.la  prbs_prbs_test_SOURCES = prbs/prbs_test.c  prbs_prbs_test_LDADD = $(top_builddir)/src/libosmocore.la +gsm23003_gsm23003_test_SOURCES = gsm23003/gsm23003_test.c +gsm23003_gsm23003_test_LDADD = $(top_builddir)/src/gsm/libosmogsm.la $(top_builddir)/src/libosmocore.la +  # The `:;' works around a Bash 3.2 bug when the output is not writeable.  $(srcdir)/package.m4: $(top_srcdir)/configure.ac  	:;{ \ @@ -241,7 +244,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE)		\  	     osmo-auc-gen/osmo-auc-gen_test.ok				\  	     osmo-auc-gen/osmo-auc-gen_test.err				\  	     conv/conv_gsm0503_test.ok endian/endian_test.ok 		\ -	     sercomm/sercomm_test.ok prbs/prbs_test.ok +	     sercomm/sercomm_test.ok prbs/prbs_test.ok			\ +	     gsm23003/gsm23003_test.ok  DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c  BUILT_SOURCES = conv/gsm0503_test_vectors.c diff --git a/tests/gsm23003/gsm23003_test.c b/tests/gsm23003/gsm23003_test.c new file mode 100644 index 00000000..682f1626 --- /dev/null +++ b/tests/gsm23003/gsm23003_test.c @@ -0,0 +1,124 @@ +/* + * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdio.h> + +#include <osmocom/gsm/gsm23003.h> +#include <osmocom/core/utils.h> + +#define BOOL_STR(b) ((b)? "true" : "false") + +static struct { +	const char *imsi; +	bool expect_ok; +} test_imsis[] = { +	{ "", false }, +	{ " ", false }, +	{ "1", false }, +	{ "123", false }, +	{ "12345", false }, +	{ "123456", true }, +	{ "1234567", true }, +	{ "1234567890123", true }, +	{ "123456789012345", true }, +	{ "000000000000000", true }, +	{ "999999999999999", true }, +	{ "1234567890123456", false }, +	{ "a23456789012345", false }, +	{ "1234567b9012345", false }, +	{ "12345678901234c", false }, +	{ "123456789 01234", false }, +	{ "1234567\n123456", false }, +	{ "123456\t123456", false }, +	{ "123456\r123456", false }, +}; + +bool test_valid_imsi() +{ +	int i; +	bool pass = true; +	bool ok = true; +	printf("----- %s\n", __func__); + +	for (i = 0; i < ARRAY_SIZE(test_imsis); i++) { +		ok = osmo_imsi_str_valid(test_imsis[i].imsi); +		pass = pass && (ok == test_imsis[i].expect_ok); +		printf("%2d: expect=%s result=%s imsi='%s'\n", +		       i, BOOL_STR(test_imsis[i].expect_ok), BOOL_STR(ok), +		       test_imsis[i].imsi); +	} +	return pass; +} + +static struct { +	const char *msisdn; +	bool expect_ok; +} test_msisdns[] = { +	{ "", false }, +	{ " ", false }, +	{ "1", true }, +	{ "123", true }, +	{ "12345", true }, +	{ "123456", true }, +	{ "1234567", true }, +	{ "1234567890123", true }, +	{ "123456789012345", true }, +	{ "000000000000000", true }, +	{ "999999999999999", true }, +	{ "1234567890123456", false }, +	{ "a23456789012345", false }, +	{ "1234567b9012345", false }, +	{ "12345678901234c", false }, +	{ "123456789 01234", false }, +	{ "1234567\n123456", false }, +	{ "123456\t123456", false }, +	{ "123456\r123456", false }, +}; + +bool test_valid_msisdn() +{ +	int i; +	bool pass = true; +	bool ok = true; +	printf("----- %s\n", __func__); + +	for (i = 0; i < ARRAY_SIZE(test_msisdns); i++) { +		ok = osmo_msisdn_str_valid(test_msisdns[i].msisdn); +		pass = pass && (ok == test_msisdns[i].expect_ok); +		printf("%2d: expect=%s result=%s msisdn='%s'\n", +		       i, BOOL_STR(test_msisdns[i].expect_ok), BOOL_STR(ok), +		       test_msisdns[i].msisdn); +	} +	return pass; +} + +int main(int argc, char **argv) +{ +	bool pass = true; + +	pass = pass && test_valid_imsi(); +	pass = pass && test_valid_msisdn(); + +	OSMO_ASSERT(pass); + +	return EXIT_SUCCESS; +} diff --git a/tests/gsm23003/gsm23003_test.ok b/tests/gsm23003/gsm23003_test.ok new file mode 100644 index 00000000..777451a8 --- /dev/null +++ b/tests/gsm23003/gsm23003_test.ok @@ -0,0 +1,42 @@ +----- test_valid_imsi + 0: expect=false result=false imsi='' + 1: expect=false result=false imsi=' ' + 2: expect=false result=false imsi='1' + 3: expect=false result=false imsi='123' + 4: expect=false result=false imsi='12345' + 5: expect=true result=true imsi='123456' + 6: expect=true result=true imsi='1234567' + 7: expect=true result=true imsi='1234567890123' + 8: expect=true result=true imsi='123456789012345' + 9: expect=true result=true imsi='000000000000000' +10: expect=true result=true imsi='999999999999999' +11: expect=false result=false imsi='1234567890123456' +12: expect=false result=false imsi='a23456789012345' +13: expect=false result=false imsi='1234567b9012345' +14: expect=false result=false imsi='12345678901234c' +15: expect=false result=false imsi='123456789 01234' +16: expect=false result=false imsi='1234567 +123456' +17: expect=false result=false imsi='123456	123456' +18: expect=false result=false imsi='123456
123456' +----- test_valid_msisdn + 0: expect=false result=false msisdn='' + 1: expect=false result=false msisdn=' ' + 2: expect=true result=true msisdn='1' + 3: expect=true result=true msisdn='123' + 4: expect=true result=true msisdn='12345' + 5: expect=true result=true msisdn='123456' + 6: expect=true result=true msisdn='1234567' + 7: expect=true result=true msisdn='1234567890123' + 8: expect=true result=true msisdn='123456789012345' + 9: expect=true result=true msisdn='000000000000000' +10: expect=true result=true msisdn='999999999999999' +11: expect=false result=false msisdn='1234567890123456' +12: expect=false result=false msisdn='a23456789012345' +13: expect=false result=false msisdn='1234567b9012345' +14: expect=false result=false msisdn='12345678901234c' +15: expect=false result=false msisdn='123456789 01234' +16: expect=false result=false msisdn='1234567 +123456' +17: expect=false result=false msisdn='123456	123456' +18: expect=false result=false msisdn='123456
123456' diff --git a/tests/testsuite.at b/tests/testsuite.at index 1954e66b..483860fc 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -287,3 +287,9 @@ AT_KEYWORDS([prbs])  cat $abs_srcdir/prbs/prbs_test.ok > expout  AT_CHECK([$abs_top_builddir/tests/prbs/prbs_test], [0], [expout], [ignore])  AT_CLEANUP + +AT_SETUP([gsm23003]) +AT_KEYWORDS([gsm23003]) +cat $abs_srcdir/gsm23003/gsm23003_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gsm23003/gsm23003_test], [0], [expout], [ignore]) +AT_CLEANUP | 
