pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/33002 )
Change subject: gmm: Initial implementation of rx GMM Information msg ......................................................................
gmm: Initial implementation of rx GMM Information msg
Basic implementation of gprs_gmm_decode_network_name() was cherry-picked from osmocom-bb 2dfa84e73dca455900e6522f61f5c610077783b7 decode_network_name().
Change-Id: I9b81f8f9113a95cc75666dac5ff9e315d0845fcb --- M include/osmocom/gprs/gmm/gmm_private.h M src/gmm/gmm.c M src/gmm/misc.c 3 files changed, 75 insertions(+), 0 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/gmm/gmm_private.h b/include/osmocom/gprs/gmm/gmm_private.h index df3f496..48068d9 100644 --- a/include/osmocom/gprs/gmm/gmm_private.h +++ b/include/osmocom/gprs/gmm/gmm_private.h @@ -88,6 +88,10 @@ unsigned long t3314_assigned_sec; /* value assigned by the network */ struct osmo_timer_list t3312; /* periodic RAU, in seconds */ unsigned long t3312_assigned_sec; /* value assigned by the network */ + + /* network name */ + char name_long[32]; + char name_short[32]; };
/* gmm_prim.c: */ @@ -137,6 +141,7 @@ /* misc.c */ int gprs_gmm_gprs_tmr_to_secs(uint8_t gprs_tmr); uint8_t gprs_gmm_secs_to_gprs_tmr_floor(int secs); +int gprs_gmm_decode_network_name(char *name, int name_len, const uint8_t *lv);
#define LOGGMME(gmme, level, fmt, args...) \ LOGGMM(level, "GMME(IMSI-%s:PTMSI-%08x:TLLI-%08x) " fmt, \ diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c index f4fdd6c..a99fe57 100644 --- a/src/gmm/gmm.c +++ b/src/gmm/gmm.c @@ -1240,6 +1240,33 @@ return 0; }
+/* Rx GMM Information, 9.4.19 */ +static int gprs_gmm_rx_information(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + struct tlv_parsed tp; + int rc; + + if (len <= sizeof(struct gsm48_hdr)) /* no Optional IEs, empty msg */ + return 0; + + rc = gprs_gmm_tlv_parse(&tp, &gh->data[0], + len - sizeof(*gh)); + if (rc < 0) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM INFORMATION: failed to parse TLVs %d\n", rc); + return -EINVAL; + } + + if (TLVP_PRESENT(&tp, GSM48_IE_GSM_NAME_FULL)) + gprs_gmm_decode_network_name(gmme->name_long, sizeof(gmme->name_long), + TLVP_VAL(&tp, GSM48_IE_GSM_NAME_FULL)-1); + + if (TLVP_PRESENT(&tp, GSM48_IE_GSM_NAME_SHORT)) + gprs_gmm_decode_network_name(gmme->name_short, sizeof(gmme->name_short), + TLVP_VAL(&tp, GSM48_IE_GSM_NAME_SHORT)-1); + + return 0; +} + /* Rx GPRS Mobility Management. */ int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) { @@ -1270,6 +1297,9 @@ case GSM48_MT_GMM_STATUS: rc = gprs_gmm_rx_status(gmme, gh, len); break; + case GSM48_MT_GMM_INFO: + rc = gprs_gmm_rx_information(gmme, gh, len); + break; default: LOGGMME(gmme, LOGL_ERROR, "Rx GMM message not implemented! type=%u len=%u\n", diff --git a/src/gmm/misc.c b/src/gmm/misc.c index c54bf3c..18ed8c6 100644 --- a/src/gmm/misc.c +++ b/src/gmm/misc.c @@ -20,6 +20,7 @@
#include <osmocom/core/logging.h> #include <osmocom/core/utils.h> +#include <osmocom/gsm/gsm_utils.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gprs/gmm/gmm.h> @@ -79,3 +80,29 @@
return GPRS_TMR_6MINUTE | GPRS_TMR_FACT_MASK; } + + +/* Decode TS 24.008 10.5.3.5a "Network name". + * FIXME: This should be improved & moved to libosmocore at some point, since it is also used in CS MM. + */ +int gprs_gmm_decode_network_name(char *name, int name_len, const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + int length, padding; + + name[0] = '\0'; + if (in_len < 1) + return -EINVAL; + + /* must be CB encoded */ + if ((lv[1] & 0x70) != 0x00) + return -ENOTSUP; + + padding = lv[1] & 0x03; + length = ((in_len - 1) * 8 - padding) / 7; + if (length <= 0) + return 0; + gsm_7bit_decode_n(name, name_len, lv + 2, length); + + return length; +}