From ef7be49a3217827fd48e3a90899bfa475b1185ff Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 3 May 2019 21:01:13 +0200 Subject: gsm0808_utils: Add gsm0808_decode_cell_id_u() This function parses a single Cell ID list element into a 'union gsm0808_cell_id_u'. This function is going to be used by the upcoming CBSP support. Related: OS#3537 Change-Id: I08b33881667aa32f01e53ccb70d44d5b79c7c986 --- include/osmocom/gsm/gsm0808_utils.h | 1 + src/gsm/gsm0808_utils.c | 69 +++++++++++++++++++++++++++++++------ src/gsm/libosmogsm.map | 1 + 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 9cfaea68..76db2b6d 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -94,6 +94,7 @@ void gsm0808_cell_id_from_cgi(struct gsm0808_cell_id *cid, enum CELL_IDENT id_di const struct osmo_cell_global_id *cgi); int gsm0808_cell_id_to_cgi(struct osmo_cell_global_id *cgi, const struct gsm0808_cell_id *cid); void gsm0808_msgb_put_cell_id_u(struct msgb *msg, enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u); +int gsm0808_decode_cell_id_u(union gsm0808_cell_id_u *out, enum CELL_IDENT discr, const uint8_t *buf, unsigned int len); uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause); uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg, diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 70eed15e..afff59aa 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -193,6 +193,17 @@ int gsm0808_dec_osmux_cid(uint8_t *cid, const uint8_t *elem, uint8_t len) #endif /* HAVE_SYS_SOCKET_H */ +/* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC. */ +static void decode_lai(const uint8_t *data, struct osmo_location_area_id *decoded) +{ + struct gsm48_loc_area_id lai; + + /* Copy data to stack to prevent unaligned access in gsm48_decode_lai2(). */ + memcpy(&lai, data, sizeof(lai)); /* don't byte swap yet */ + + gsm48_decode_lai2(&lai, decoded); +} + /* Helper function for gsm0808_enc_speech_codec() * and gsm0808_enc_speech_codec_list() */ static uint8_t enc_speech_codec(struct msgb *msg, @@ -756,6 +767,53 @@ int gsm0808_dec_encrypt_info(struct gsm0808_encrypt_info *ei, return (int)(elem - old_elem); } +/*! Decode a single GSM 08.08 Cell ID list element payload + * \param[out] out caller-provided output union + * \param[in] discr Cell ID discriminator describing type to be decoded + * \param[in] buf User-provided input buffer containing binary Cell ID list element + * \param[in] len Length of buf + * \returns 0 on success; negative on error */ +int gsm0808_decode_cell_id_u(union gsm0808_cell_id_u *out, enum CELL_IDENT discr, const uint8_t *buf, unsigned int len) +{ + switch (discr) { + case CELL_IDENT_WHOLE_GLOBAL: + if (len < 7) + return -EINVAL; + decode_lai(buf, &out->global.lai); + out->global.cell_identity = osmo_load16be(buf + sizeof(struct gsm48_loc_area_id)); + break; + case CELL_IDENT_LAC_AND_CI: + if (len < 4) + return -EINVAL; + out->lac_and_ci.lac = osmo_load16be(buf); + out->lac_and_ci.ci = osmo_load16be(buf + sizeof(uint16_t)); + break; + case CELL_IDENT_CI: + if (len < 2) + return -EINVAL; + out->ci = osmo_load16be(buf); + break; + case CELL_IDENT_LAI_AND_LAC: + if (len < 5) + return -EINVAL; + decode_lai(buf, &out->lai_and_lac); + break; + case CELL_IDENT_LAC: + if (len < 2) + return -EINVAL; + out->lac = osmo_load16be(buf); + break; + case CELL_IDENT_BSS: + case CELL_IDENT_NO_CELL: + /* Does not have any list items */ + break; + default: + /* Remaining cell identification types are not implemented. */ + return -EINVAL; + } + return 0; +} + void gsm0808_msgb_put_cell_id_u(struct msgb *msg, enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u) { switch (id_discr) { @@ -865,17 +923,6 @@ uint8_t gsm0808_enc_cell_id_list(struct msgb *msg, return *tlv_len + 2; } -/* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC. */ -static void decode_lai(const uint8_t *data, struct osmo_location_area_id *decoded) -{ - struct gsm48_loc_area_id lai; - - /* Copy data to stack to prevent unaligned access in gsm48_decode_lai2(). */ - memcpy(&lai, data, sizeof(lai)); /* don't byte swap yet */ - - gsm48_decode_lai2(&lai, decoded); -} - static int parse_cell_id_global_list(struct gsm0808_cell_id_list2 *cil, const uint8_t *data, size_t remain, size_t *consumed) { diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index d49401d8..9aa9683a 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -244,6 +244,7 @@ gsm0808_lcls_status_names; gsm0808_enc_lcls; gsm0808_dec_lcls; gsm0808_msgb_put_cell_id_u; +gsm0808_decode_cell_id_u; gsm29118_msgb_alloc; gsm29118_create_alert_req; -- cgit v1.2.3