diff options
author | Oliver Smith <osmith@sysmocom.de> | 2019-02-01 11:35:10 +0100 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2019-04-26 20:36:39 +0200 |
commit | affbb2064669a58aea4a18f773eed90b15dffcf9 (patch) | |
tree | 3468f76002d782cbb69b1a897205d9478eb58764 /src | |
parent | 3d6ffd8c9c9e8e97df37bf989ede58e61c7d9a05 (diff) |
GSUP: add inter-MSC handover related msgs and IEs
Based on a draft created by Neels, which is the result of reading a MAP
trace of two MSCs negotiating inter-MSC handovers, and of reading the
TS 29.002, TS 29.010 and related specs:
https://lists.osmocom.org/pipermail/openbsc/2019-January/012653.html
I figured out that the "Handover Number" mentioned in the specifications
is the same as the MSISDN IE that we already have, so we can use that
instead of creating a new IE (example usage in tests/gsup/gsup_test.c).
Create a new OSMO_GSUP_MSGT_E_ROUTING_ERROR message type, which the GSUP
server uses to tell a client that its message could not be forwarded to
the destination (see [1]). MAP has no related message.
[1]: Change-Id: Ia4f345abc877baaf0a8f73b8988e6514d9589bf5 (osmo-hlr.git)
Related: OS#3774
Change-Id: Ic00b0601eacff6d72927cea51767801142ee75db
Diffstat (limited to 'src')
-rw-r--r-- | src/gsm/gsup.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/gsm/gsup.c b/src/gsm/gsup.c index 71dbbe18..a3d9eef5 100644 --- a/src/gsm/gsup.c +++ b/src/gsm/gsup.c @@ -83,6 +83,26 @@ const struct value_string osmo_gsup_message_type_names[] = { OSMO_VALUE_STRING(OSMO_GSUP_MSGT_CHECK_IMEI_ERROR), OSMO_VALUE_STRING(OSMO_GSUP_MSGT_CHECK_IMEI_RESULT), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT), + + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_ERROR), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT), + + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_ERROR), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT), + + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST), + + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_CLOSE), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_ABORT), + + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_E_ROUTING_ERROR), + { 0, NULL } }; @@ -247,6 +267,26 @@ parse_error: return -1; } +/*! Decode AN-apdu (see 3GPP TS 29.002 7.6.9.1). + * \param[out] gsup_msg abstract GSUP message structure + * \param[in] data pointer to the raw IE payload + * \param[in] data_len length of IE pointed by \ref data + * \returns 0 in case of success, negative in case of error + */ +int osmo_gsup_decode_an_apdu(struct osmo_gsup_message *gsup_msg, const uint8_t *data, size_t data_len) +{ + if (data_len < 1) { + LOGP(DLGSUP, LOGL_ERROR, "Corrupted an_apdu message (length must be >= 1)\n"); + return -EINVAL; + } + + gsup_msg->an_apdu.access_network_proto = data[0]; + gsup_msg->an_apdu.data_len = data_len -1; + gsup_msg->an_apdu.data = data + 1; + + return 0; +} + /*! Decode (parse) a GSUP message * \param[in] const_data input data to be parsed * \param[in] data_len length of input (\a const_data) @@ -481,6 +521,36 @@ int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, gsup_msg->message_class = value[0]; break; + case OSMO_GSUP_SOURCE_NAME_IE: + gsup_msg->source_name = value; + gsup_msg->source_name_len = value_len; + break; + + case OSMO_GSUP_DESTINATION_NAME_IE: + gsup_msg->destination_name = value; + gsup_msg->destination_name_len = value_len; + break; + + case OSMO_GSUP_AN_APDU_IE: + rc = osmo_gsup_decode_an_apdu(gsup_msg, value, value_len); + if (rc) + return rc; + break; + + case OSMO_GSUP_CAUSE_RR_IE: + gsup_msg->cause_rr = value[0]; + gsup_msg->cause_rr_set = true; + break; + + case OSMO_GSUP_CAUSE_BSSAP_IE: + gsup_msg->cause_bssap = value[0]; + gsup_msg->cause_bssap_set = true; + break; + + case OSMO_GSUP_CAUSE_SM_IE: + gsup_msg->cause_sm = value[0]; + break; + default: LOGP(DLGSUP, LOGL_NOTICE, "GSUP IE type %d unknown\n", iei); @@ -568,6 +638,35 @@ static void encode_auth_info(struct msgb *msg, enum osmo_gsup_iei iei, *len_field = msgb_length(msg) - old_len; } +/*! Encode AN-apdu (see 3GPP TS 29.002 7.6.9.1). + * \param[out] msg target message buffer (caller-allocated) + * \param[in] gsup_msg abstract GSUP message structure + * \returns 0 in case of success, negative in case of error + */ +int osmo_gsup_encode_an_apdu(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) +{ + const struct osmo_gsup_an_apdu an_apdu = gsup_msg->an_apdu; + + if (msgb_tailroom(msg) < 2 + an_apdu.data_len) { + LOGP(DLGSUP, LOGL_ERROR, "Not enough tailroom in msg to encode an_apdu:" + " IE header (2) + an_apdu.data_len (%zu) == %zu, msgb tailroom == %d\n", + an_apdu.data_len, an_apdu.data_len + 2, msgb_tailroom(msg)); + return -ENOMEM; + } + + /* Tag and total length */ + msgb_tv_put(msg, OSMO_GSUP_AN_APDU_IE, 1 + an_apdu.data_len); + + /* Put access_network_proto */ + msgb_v_put(msg, an_apdu.access_network_proto); + + /* Put data */ + uint8_t *buf = msgb_put(msg, an_apdu.data_len); + memcpy(buf, an_apdu.data, an_apdu.data_len); + + return 0; +} + /*! Encode a GSUP message * \param[out] msg message buffer to which encoded message is written * \param[in] gsup_msg \ref osmo_gsup_message data to be encoded @@ -727,6 +826,34 @@ int osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) msgb_tlv_put(msg, OSMO_GSUP_MESSAGE_CLASS_IE, sizeof(u8), &u8); } + if (gsup_msg->source_name) + msgb_tlv_put(msg, OSMO_GSUP_SOURCE_NAME_IE, gsup_msg->source_name_len, gsup_msg->source_name); + + if (gsup_msg->destination_name) + msgb_tlv_put(msg, OSMO_GSUP_DESTINATION_NAME_IE, gsup_msg->destination_name_len, + gsup_msg->destination_name); + + if (gsup_msg->an_apdu.access_network_proto || gsup_msg->an_apdu.data_len) { + rc = osmo_gsup_encode_an_apdu(msg, gsup_msg); + if (rc) { + LOGP(DLGSUP, LOGL_ERROR, "Failed to encode AN-apdu IE \n"); + return -EINVAL; + } + } + + if (gsup_msg->cause_rr_set) { + u8 = gsup_msg->cause_rr; + msgb_tlv_put(msg, OSMO_GSUP_CAUSE_RR_IE, sizeof(u8), &u8); + } + + if (gsup_msg->cause_bssap_set) { + u8 = gsup_msg->cause_bssap; + msgb_tlv_put(msg, OSMO_GSUP_CAUSE_BSSAP_IE, sizeof(u8), &u8); + } + + if ((u8 = gsup_msg->cause_sm)) + msgb_tlv_put(msg, OSMO_GSUP_CAUSE_SM_IE, sizeof(u8), &u8); + return 0; } |