[MERGED] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Harald Welte has submitted this change and it was merged. Change subject: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp() for 3-digit MNC .. 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(-) Approvals: Harald Welte: Looks good to me, approved Jenkins Builder: Verified 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 #include +#include +#include +#include #include #include @@ -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_digitsResult 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, , 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
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 7: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 7 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr Gerrit-HasComments: No
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 7: (1 comment) https://gerrit.osmocom.org/#/c/6663/7/tests/gsm23003/gsm23003_test.ok File tests/gsm23003/gsm23003_test.ok: Line 63 looks like gerrit gets mixed up with the \r character above. The patch colorizing is off by two lines. -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 7 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr Gerrit-HasComments: Yes
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 7: (added a str decoding test) -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 7 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr Gerrit-HasComments: No
[PATCH] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
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 #include +#include +#include +#include #include #include @@ -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_digitsResult 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, , 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 +++
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 6: (1 comment) https://gerrit.osmocom.org/#/c/6663/6/src/gsm/gsm23003.c File src/gsm/gsm23003.c: Line 233: if (mnc_3_digits) > I can understand the f(mnc_3_digits) as the caller might not be interested a user of this is CTRL interface verification, which is not interested in the values, just whether it can be decoded properly, and passes only NULL args: https://gerrit.osmocom.org/#/c/6668/3/src/libbsc/bsc_ctrl_commands.c line 80 If you think this should not be allowed, that caller can of course let the values be decoded into unused local vars instead, let me know how you decide. -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 6 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr Gerrit-HasComments: Yes
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 6: Code-Review+1 (1 comment) https://gerrit.osmocom.org/#/c/6663/6/src/gsm/gsm23003.c File src/gsm/gsm23003.c: Line 233: if (mnc_3_digits) I can understand the f(mnc_3_digits) as the caller might not be interested in that. But do you thin that mnc=NULL is a valid API use of this function? I think it might be better to OSMO_ASSERT() in that case or at least to return an error code. Basically you can all the function with mnc=NULL by accident and it will still successfulyl return, which sounds a bit dangerous to me. what do you think? -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 6 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-HasComments: Yes
[PATCH] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
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 (#6). 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 3 files changed, 83 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/63/6663/6 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..81ab58c 100644 --- a/src/gsm/gsm23003.c +++ b/src/gsm/gsm23003.c @@ -25,6 +25,9 @@ #include #include +#include +#include +#include #include #include @@ -195,3 +198,75 @@ 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_digitsResult 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) +{ + uint16_t _mnc = 0; + bool _mnc_3_digits = false; + char *endptr; + int rc = 0; + + if (!mnc_str || !isdigit(mnc_str[0])) { + /* 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, , 10); + if (errno) + rc = -errno; + else if (*endptr) + rc = -EINVAL; + _mnc_3_digits = strlen(mnc_str) > 2; + + if (mnc) + *mnc = _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;
libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Patch Set 5: mncc_from_str: we always have the output argument first, thee input arguments last (think of memcpy) -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 5 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels HofmeyrGerrit-Reviewer: Harald Welte Gerrit-Reviewer: Jenkins Builder Gerrit-HasComments: No
[ABANDON] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Neels Hofmeyr has abandoned this change. Change subject: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp() for 3-digit MNC .. Abandoned change-id mixup -- To view, visit https://gerrit.osmocom.org/6959 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: abandon Gerrit-Change-Id: I0910aee1e6be696002f37fe8d5c308cbd2bfc10b Gerrit-PatchSet: 1 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels Hofmeyr
[PATCH] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
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 (#5). 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/gsm48.h M src/gsm/gsm48.c M src/gsm/libosmogsm.map 3 files changed, 80 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/63/6663/5 diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index d3732f3..3364d53 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -64,3 +64,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/gsm48.c b/src/gsm/gsm48.c index 62f9277..8d31477 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -533,6 +533,78 @@ } } +/* 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_digitsResult 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) +{ + uint16_t _mnc = 0; + bool _mnc_3_digits = false; + char *endptr; + int rc = 0; + + if (!mnc_str || !isdigit(mnc_str[0])) { + /* 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, , 10); + if (errno) + rc = -errno; + else if (*endptr) + rc = -EINVAL; + _mnc_3_digits = strlen(mnc_str) > 2; + + if (mnc) + *mnc = _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); +} + /*! Encode TS 04.08 Location Area Identifier, legacy implementation. * Instead use osmo_generate_lai(), which is capable of three-digit MNC with leading zeros. * \param[out] lai48 caller-provided memory for output 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;
[PATCH] libosmocore[master]: gsm: add osmo_mnc_from_str(), osmo_mnc_cmp(), osmo_plmn_cmp(...
Review at https://gerrit.osmocom.org/6959 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 add osmo_plmn_cmp() Change-Id: I0910aee1e6be696002f37fe8d5c308cbd2bfc10b --- M include/osmocom/gsm/gsm48.h M src/gsm/gsm48.c M src/gsm/libosmogsm.map 3 files changed, 80 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/59/6959/1 diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index d3732f3..3364d53 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -64,3 +64,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/gsm48.c b/src/gsm/gsm48.c index 62f9277..8d31477 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -533,6 +533,78 @@ } } +/* 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_digitsResult 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) +{ + uint16_t _mnc = 0; + bool _mnc_3_digits = false; + char *endptr; + int rc = 0; + + if (!mnc_str || !isdigit(mnc_str[0])) { + /* 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, , 10); + if (errno) + rc = -errno; + else if (*endptr) + rc = -EINVAL; + _mnc_3_digits = strlen(mnc_str) > 2; + + if (mnc) + *mnc = _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); +} + /*! Encode TS 04.08 Location Area Identifier, legacy implementation. * Instead use osmo_generate_lai(), which is capable of three-digit MNC with leading zeros. * \param[out] lai48 caller-provided memory for output 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;