diff --git a/include/osmocom/msc/gsm_04_11_gsup.h b/include/osmocom/msc/gsm_04_11_gsup.h index 4034f5e19..9c8c7cf2a 100644 --- a/include/osmocom/msc/gsm_04_11_gsup.h +++ b/include/osmocom/msc/gsm_04_11_gsup.h @@ -12,8 +12,8 @@ int gsm411_gsup_mo_ready_for_sm_req(struct gsm_trans *trans, uint8_t sm_rp_mr); int gsm411_gsup_mo_fwd_sm_req(struct gsm_trans *trans, struct msgb *msg, uint8_t sm_rp_mr, uint8_t *sm_rp_da, uint8_t sm_rp_da_len); -int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr); +int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr, const uint8_t *ui_buf, uint8_t ui_len); int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans, - uint8_t sm_rp_mr, uint8_t cause); + uint8_t sm_rp_mr, uint8_t cause, const uint8_t *ui_buf, uint8_t ui_len); int gsm411_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg); diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c index 6536d0b84..b6d5f4a7b 100644 --- a/src/libmsc/gsm_04_11.c +++ b/src/libmsc/gsm_04_11.c @@ -852,7 +852,19 @@ static int gsm411_rx_rp_ack(struct gsm_trans *trans, if (trans->net->sms_over_gsup) { /* Forward towards SMSC via GSUP */ - return gsm411_gsup_mt_fwd_sm_res(trans, rph->msg_ref); + uint8_t ui_len = 0; + uint8_t *ui_buf = NULL; + /* check for: + * - sufficient size for tag, length and data + * - RP-User-Data tag + * - user data length is valid */ + if (rph->len > 2 && + rph->data[0] == GSM411_IE_RP_USER_DATA && + rph->data[1] <= (rph->len - 2)) { + ui_len = rph->data[1]; + ui_buf = &(rph->data[2]); + } + return gsm411_gsup_mt_fwd_sm_res(trans, rph->msg_ref, ui_buf, ui_len); } if (!sms) { @@ -893,7 +905,23 @@ static int gsm411_rx_rp_error(struct gsm_trans *trans, if (trans->net->sms_over_gsup) { /* Forward towards SMSC via GSUP */ - return gsm411_gsup_mt_fwd_sm_err(trans, rph->msg_ref, cause); + uint8_t ui_len = 0; + uint8_t *ui_buf = NULL; + uint8_t ui_tag_idx = cause_len + 1; + uint8_t ui_len_idx = ui_tag_idx + 1; + uint8_t ui_buf_idx = ui_len_idx + 1; + /* check for: + * - sufficient size for tag, length and data + * - RP-User-Data tag + * - user data length is valid */ + if (rph->len > ui_buf_idx && + rph->data[ui_tag_idx] == GSM411_IE_RP_USER_DATA && + rph->data[ui_len_idx] <= (rph->len - ui_buf_idx)) { + ui_len = rph->data[ui_len_idx]; + ui_buf = &(rph->data[ui_buf_idx]); + } + + return gsm411_gsup_mt_fwd_sm_err(trans, rph->msg_ref, cause, ui_buf, ui_len); } if (!sms) { diff --git a/src/libmsc/gsm_04_11_gsup.c b/src/libmsc/gsm_04_11_gsup.c index 96fdbc648..4dcc3026a 100644 --- a/src/libmsc/gsm_04_11_gsup.c +++ b/src/libmsc/gsm_04_11_gsup.c @@ -184,7 +184,7 @@ msg_error: return -EINVAL; } -int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr) +int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr, const uint8_t *ui_buf, uint8_t ui_len) { struct osmo_gsup_message gsup_msg; @@ -202,11 +202,17 @@ int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr) gsup_msg.destination_name_len = trans->sms.gsup_source_name_len; gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg); + /* include optional SM-RP-UI field if present */ + if (ui_len) { + gsup_msg.sm_rp_ui_len = ui_len; + gsup_msg.sm_rp_ui = ui_buf; + } + return gsup_client_mux_tx(trans->net->gcm, &gsup_msg); } int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans, - uint8_t sm_rp_mr, uint8_t cause) + uint8_t sm_rp_mr, uint8_t cause, const uint8_t *ui_buf, uint8_t ui_len) { struct osmo_gsup_message gsup_msg; @@ -227,7 +233,12 @@ int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans, /* SM-RP-Cause value */ gsup_msg.sm_rp_cause = &cause; - /* TODO: include optional SM-RP-UI field if present */ + /* include optional SM-RP-UI field if present */ + if (ui_len) { + gsup_msg.sm_rp_ui_len = ui_len; + gsup_msg.sm_rp_ui = ui_buf; + } + return gsup_client_mux_tx(trans->net->gcm, &gsup_msg); }