diff options
| author | Neels Hofmeyr <neels@hofmeyr.de> | 2018-02-20 21:38:00 +0100 | 
|---|---|---|
| committer | Neels Hofmeyr <neels@hofmeyr.de> | 2018-02-28 19:26:43 +0100 | 
| commit | 721aa6ded9c736e3cc5b20824dd58b1af4f4a907 (patch) | |
| tree | 2af83106d1afbf097030502fb0ba828cffb1e6bc /src | |
| parent | 6c7b3e21d63b6f26de6dc53d7cb2bf92c42b9ce7 (diff) | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/gsm/gsm23003.c | 77 | ||||
| -rw-r--r-- | src/gsm/libosmogsm.map | 3 | 
2 files changed, 80 insertions, 0 deletions
| diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c index 63de2b81..1f6bf7d0 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 @@ void osmo_plmn_from_bcd(const uint8_t *bcd_src, struct osmo_plmn_id *plmn)  		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 531c5c13..0a1c0c6f 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -270,6 +270,9 @@ osmo_plmn_name;  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; | 
