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
This commit is contained in:
Pau Espin 2023-05-25 18:39:25 +02:00
parent 770ed7fc24
commit 1576144542
3 changed files with 62 additions and 0 deletions

View File

@ -88,6 +88,10 @@ struct gprs_gmm_entity {
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 @@ int gprs_gmm_submit_llgmm_assing_req(const struct gprs_gmm_entity *gmme);
/* 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, \

View File

@ -1240,6 +1240,33 @@ static int gprs_gmm_rx_status(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh
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 @@ int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int
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",

View File

@ -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 @@ uint8_t gprs_gmm_secs_to_gprs_tmr_floor(int secs)
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;
}