diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libmsc/gsm_04_08.c | 5 | ||||
-rw-r--r-- | src/libmsc/gsm_04_11.c | 57 | ||||
-rw-r--r-- | src/libmsc/gsm_04_11_gsup.c | 96 |
3 files changed, 154 insertions, 4 deletions
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index 7ff868140..686194fc8 100644 --- a/src/libmsc/gsm_04_08.c +++ b/src/libmsc/gsm_04_08.c @@ -1810,6 +1810,11 @@ static int msc_vlr_route_gsup_msg(struct vlr_subscr *vsub, DEBUGP(DMSC, "Routed to GSM 04.11 MO handler\n"); return gsm411_gsup_mo_handler(vsub, gsup_msg); + /* GSM 04.11 code implementing MT SMS */ + case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST: + DEBUGP(DMSC, "Routed to GSM 04.11 MT handler\n"); + return gsm411_gsup_mt_handler(vsub, gsup_msg); + default: LOGP(DMM, LOGL_ERROR, "No handler found for %s, dropping message...\n", osmo_gsup_message_type_name(gsup_msg->message_type)); diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c index 788a0a946..15a92d487 100644 --- a/src/libmsc/gsm_04_11.c +++ b/src/libmsc/gsm_04_11.c @@ -158,10 +158,13 @@ static int paging_cb_mmsms_est_req(unsigned int hooknum, unsigned int event, gsm411_smc_recv(&trans->sms.smc_inst, GSM411_MMSMS_REL_IND, NULL, 0); - /* Notify the SMSqueue and free stored SMS */ - send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event); - trans->sms.sms = NULL; - sms_free(sms); + /* gsm411_send_rp_data() doesn't set trans->sms.sms */ + if (sms != NULL) { + /* Notify the SMSqueue and free stored SMS */ + send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event); + trans->sms.sms = NULL; + sms_free(sms); + } /* Destroy this transaction */ trans_free(trans); @@ -794,6 +797,11 @@ static int gsm411_rx_rp_ack(struct gsm_trans *trans, * successfully received a SMS. We can now safely mark it as * transmitted */ + if (trans->net->sms_over_gsup) { + /* Forward towards SMSC via GSUP */ + return gsm411_gsup_mt_fwd_sm_res(trans, rph->msg_ref); + } + if (!sms) { LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n"); return gsm411_send_rp_error(trans, rph->msg_ref, @@ -830,6 +838,11 @@ static int gsm411_rx_rp_error(struct gsm_trans *trans, vlr_subscr_name(trans->conn->vsub), cause_len, cause, get_value_string(gsm411_rp_cause_strs, cause)); + if (trans->net->sms_over_gsup) { + /* Forward towards SMSC via GSUP */ + return gsm411_gsup_mt_fwd_sm_err(trans, rph->msg_ref, cause); + } + if (!sms) { LOGP(DLSMS, LOGL_ERROR, "RX RP-ERR, but no sms in transaction?!?\n"); @@ -1112,6 +1125,42 @@ int gsm411_send_sms(struct gsm_network *net, GSM411_SM_RL_DATA_REQ); } +/* Low-level function to send raw RP-DATA to a given subscriber */ +int gsm411_send_rp_data(struct gsm_network *net, struct vlr_subscr *vsub, + size_t sm_rp_oa_len, const uint8_t *sm_rp_oa, + size_t sm_rp_ud_len, const uint8_t *sm_rp_ud) +{ + struct gsm_trans *trans; + struct msgb *msg; + + /* Allocate a new transaction for MT SMS */ + trans = gsm411_alloc_mt_trans(net, vsub); + if (!trans) + return -ENOMEM; + + /* Allocate a message buffer for to be encoded SMS */ + msg = gsm411_msgb_alloc(); + if (!msg) { + trans_free(trans); + return -ENOMEM; + } + + /* Encode SM-RP-OA (SMSC address) */ + msgb_lv_put(msg, sm_rp_oa_len, sm_rp_oa); + + /* Encode SM-RP-DA (shall be empty, len=0) */ + msgb_v_put(msg, 0x00); + + /* Encode RP-UD itself (SM TPDU) */ + msgb_lv_put(msg, sm_rp_ud_len, sm_rp_ud); + + rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED]); + + return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg, + GSM411_MT_RP_DATA_MT, trans->sms.sm_rp_mr, + GSM411_SM_RL_DATA_REQ); +} + /* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */ int gsm0411_rcv_sms(struct ran_conn *conn, struct msgb *msg) diff --git a/src/libmsc/gsm_04_11_gsup.c b/src/libmsc/gsm_04_11_gsup.c index 5c0107245..f2de95f70 100644 --- a/src/libmsc/gsm_04_11_gsup.c +++ b/src/libmsc/gsm_04_11_gsup.c @@ -201,3 +201,99 @@ msg_error: msg_name, msg_is_err ? "Err" : "Res"); return -EINVAL; } + +int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr) +{ + struct osmo_gsup_message gsup_msg; + + /* Associate logging messages with this subscriber */ + log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub); + + LOGP(DLSMS, LOGL_DEBUG, "TX MT-forwardSM-Res\n"); + + /* Initialize a new GSUP message */ + gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT, + trans->vsub->imsi, &sm_rp_mr); + + return osmo_gsup_client_enc_send(trans->net->vlr->gsup_client, &gsup_msg); +} + +int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans, + uint8_t sm_rp_mr, uint8_t cause) +{ + struct osmo_gsup_message gsup_msg; + + /* Associate logging messages with this subscriber */ + log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub); + + LOGP(DLSMS, LOGL_DEBUG, "TX MT-forwardSM-Err\n"); + + /* Initialize a new GSUP message */ + gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR, + trans->vsub->imsi, &sm_rp_mr); + + /* SM-RP-Cause value */ + gsup_msg.sm_rp_cause = &cause; + + /* TODO: include optional SM-RP-UI field if present */ + return osmo_gsup_client_enc_send(trans->net->vlr->gsup_client, &gsup_msg); +} + +/* Handles MT SMS (and triggers Paging Request if required) */ +int gsm411_gsup_mt_handler(struct vlr_subscr *vsub, + struct osmo_gsup_message *gsup_msg) +{ + struct vlr_instance *vlr; + struct gsm_network *net; + int rc; + + /* Obtain required pointers */ + vlr = vsub->vlr; + net = (struct gsm_network *) vlr->user_ctx; + + /* Associate logging messages with this subscriber */ + log_set_context(LOG_CTX_VLR_SUBSCR, vsub); + + LOGP(DLSMS, LOGL_DEBUG, "RX MT-forwardSM-Req\n"); + + /* Make sure that 'SMS over GSUP' is expected */ + if (!net->sms_over_gsup) { + LOGP(DLSMS, LOGL_NOTICE, "Unexpected MT SMS over GSUP, " + "ignoring message...\n"); + /* TODO: notify sender about that? */ + return -EIO; + } + + /** + * Verify GSUP message + * + * FIXME: SM-RP-MR is not known yet (to be assigned by MSC) + * NOTE: SM-RP-DA is out of our interest + */ + if (!gsup_msg->sm_rp_mr) + goto msg_error; + if (!gsup_msg->sm_rp_ui) + goto msg_error; + + /* SM-RP-OA shall contain SMSC address */ + if (gsup_msg->sm_rp_oa_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR) + goto msg_error; + + /* Send RP-DATA */ + rc = gsm411_send_rp_data(net, vsub, + gsup_msg->sm_rp_oa_len, gsup_msg->sm_rp_oa, + gsup_msg->sm_rp_ui_len, gsup_msg->sm_rp_ui); + if (rc) { + LOGP(DLSMS, LOGL_NOTICE, "Failed to send MT SMS, " + "ignoring MT-forwardSM-Req message...\n"); + /* TODO: notify sender about that? */ + return rc; + } + + return 0; + +msg_error: + /* TODO: notify sender about that? */ + LOGP(DLSMS, LOGL_NOTICE, "RX malformed MT-forwardSM-Req\n"); + return -EINVAL; +} |