diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2020-09-18 18:00:50 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2020-10-07 15:37:50 +0200 |
commit | 5b214e2847cb8264e42494e7474f3e3d350aaab7 (patch) | |
tree | 6e181795bdc3f436a83d8f513acdc822ae9ba8ef /src/gsm/gsm0808.c | |
parent | 02de87bd5c8ed02e26ade44d07e78b541d3b62d1 (diff) |
add BSSMAP coding for Location Services
BSSMAP: add A-interface messages between MSC and BSC:
- Perform Location Request
- Perform Location Response
- Perform Location Abort
Change-Id: I4d7302a4853518916b6b425e710c10568eb2ffe5
Diffstat (limited to 'src/gsm/gsm0808.c')
-rw-r--r-- | src/gsm/gsm0808.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 53220617..971d9625 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -26,9 +26,11 @@ #include <osmocom/core/byteswap.h> #include <osmocom/core/endian.h> #include <osmocom/gsm/gsm0808.h> +#include <osmocom/gsm/gsm0808_lcs.h> #include <osmocom/gsm/gsm0808_utils.h> #include <osmocom/gsm/protocol/gsm_08_08.h> #include <osmocom/gsm/gsm48.h> +#include <osmocom/gsm/gad.h> /*! \addtogroup gsm0808 * @{ @@ -1341,6 +1343,106 @@ struct msgb *gsm0808_create_dtap(struct msgb *msg_l3, uint8_t link_id) return msg; } +struct msgb *gsm0808_create_perform_location_request(const struct gsm0808_perform_location_request *params) +{ + struct msgb *msg; + uint8_t *out; + int rc; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-REQUEST"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_RQST); + + /* Location Type 3.2.2.63 */ + osmo_bssmap_le_ie_enc_location_type(msg, ¶ms->location_type); + + if (params->imsi.type == GSM_MI_TYPE_IMSI) { + /* IMSI 3.2.2.6 */ + out = msgb_tl_put(msg, GSM0808_IE_IMSI); + rc = osmo_mobile_identity_encode_msgb(msg, ¶ms->imsi, false); + if (rc < 0) { + msgb_free(msg); + return NULL; + } + /* write the MI value length */ + *out = rc; + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +struct msgb *gsm0808_create_perform_location_response(const struct gsm0808_perform_location_response *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-RESPONSE"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE); + + if (params->location_estimate_present) { + uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LOCATION_ESTIMATE); + int rc = osmo_gad_raw_write(msg, ¶ms->location_estimate); + if (rc < 0) { + msgb_free(msg); + return NULL; + } + *l = rc; + } + + if (params->lcs_cause.present) { + uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LCS_CAUSE); + int rc = osmo_lcs_cause_enc(msg, ¶ms->lcs_cause); + if (rc < 0) { + msgb_free(msg); + return NULL; + } + *l = rc; + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +int gsm0808_enc_lcs_cause(struct msgb *msg, const struct lcs_cause_ie *lcs_cause) +{ + uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LCS_CAUSE); + int rc = osmo_lcs_cause_enc(msg, lcs_cause); + if (rc <= 0) + return rc; + *l = rc; + return rc + 2; +} + +struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lcs_cause) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-ABORT"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_ABORT); + + gsm0808_enc_lcs_cause(msg, lcs_cause); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + /* As per 3GPP TS 48.008 version 11.7.0 Release 11 */ static const struct tlv_definition bss_att_tlvdef = { .def = { |