osmo-msc/src/libmsc/gsm_04_11.c

1298 lines
34 KiB
C
Raw Normal View History

/* Point-to-Point (PP) Short Message Service (SMS)
* Support on Mobile Radio Interface
* 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <netinet/in.h>
#include "bscconfig.h"
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/gsm0411_utils.h>
#include <osmocom/gsm/protocol/gsm_04_11.h>
#include <osmocom/msc/debug.h>
#include <osmocom/msc/gsm_data.h>
#include <osmocom/msc/db.h>
#include <osmocom/msc/gsm_subscriber.h>
#include <osmocom/msc/gsm_04_08.h>
#include <osmocom/msc/signal.h>
#include <osmocom/msc/db.h>
#include <osmocom/msc/transaction.h>
#include <osmocom/msc/msc_ifaces.h>
#include <osmocom/msc/vlr.h>
#ifdef BUILD_SMPP
#include "smpp_smsc.h"
#endif
void *tall_gsms_ctx;
static uint32_t new_callref = 0x40000001;
struct gsm_sms *sms_alloc(void)
{
return talloc_zero(tall_gsms_ctx, struct gsm_sms);
}
void sms_free(struct gsm_sms *sms)
{
/* drop references to subscriber structure */
if (sms->receiver)
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
vlr_subscr_put(sms->receiver);
#ifdef BUILD_SMPP
if (sms->smpp.esme)
smpp_esme_put(sms->smpp.esme);
#endif
talloc_free(sms);
}
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
struct gsm_sms *sms_from_text(struct vlr_subscr *receiver,
const char *sender_msisdn,
int dcs, const char *text)
{
struct gsm_sms *sms = sms_alloc();
if (!sms)
return NULL;
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
sms->receiver = vlr_subscr_get(receiver);
OSMO_STRLCPY_ARRAY(sms->text, text);
OSMO_STRLCPY_ARRAY(sms->src.addr, sender_msisdn);
sms->reply_path_req = 0;
sms->status_rep_req = 0;
sms->ud_hdr_ind = 0;
sms->protocol_id = 0; /* implicit */
sms->data_coding_scheme = dcs;
OSMO_STRLCPY_ARRAY(sms->dst.addr, receiver->msisdn);
/* Generate user_data */
sms->user_data_len = gsm_7bit_encode_n(sms->user_data, sizeof(sms->user_data),
sms->text, NULL);
return sms;
}
static void send_signal(int sig_no,
struct gsm_trans *trans,
struct gsm_sms *sms,
int paging_result)
{
struct sms_signal_data sig;
sig.trans = trans;
sig.sms = sms;
sig.paging_result = paging_result;
osmo_signal_dispatch(SS_SMS, sig_no, &sig);
}
static int gsm411_sendmsg(struct ran_conn *conn, struct msgb *msg)
2008-12-29 01:54:02 +00:00
{
DEBUGP(DLSMS, "GSM4.11 TX %s\n", msgb_hexdump(msg));
msg->l3h = msg->data;
return msc_tx_dtap(conn, msg);
2008-12-29 01:54:02 +00:00
}
/* Paging callback for MT SMS (Paging is triggered by SMC) */
static int paging_cb_mmsms_est_req(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *_conn, void *_trans)
{
struct ran_conn *conn = _conn;
struct gsm_trans *trans = _trans;
struct gsm_sms *sms = trans->sms.sms;
int rc = 0;
DEBUGP(DLSMS, "paging_cb_mmsms_est_req(hooknum=%u, event=%u, "
"conn=%p, trans=%p)\n", hooknum, event, conn, trans);
if (hooknum != GSM_HOOK_RR_PAGING)
return -EINVAL;
/* Paging procedure has finished */
trans->paging_request = NULL;
switch (event) {
case GSM_PAGING_SUCCEEDED:
/* Associate transaction with established connection */
trans->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_SMS);
/* Confirm successful connection establishment */
gsm411_smc_recv(&trans->sms.smc_inst,
GSM411_MMSMS_EST_CNF, NULL, 0);
break;
case GSM_PAGING_EXPIRED:
case GSM_PAGING_BUSY:
/* Inform SMC about channel establishment failure */
gsm411_smc_recv(&trans->sms.smc_inst,
GSM411_MMSMS_REL_IND, NULL, 0);
/* 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);
rc = -ETIMEDOUT;
break;
default:
LOGP(DLSMS, LOGL_ERROR, "Unhandled paging event: %d\n", event);
}
return rc;
}
static int gsm411_mmsms_est_req(struct gsm_trans *trans)
{
/* Subscriber's data shall be associated */
OSMO_ASSERT(trans->vsub != NULL);
/* Check if connection is already established */
if (trans->conn != NULL) {
LOGP(DLSMS, LOGL_DEBUG, "Using an existing connection "
"for %s\n", vlr_subscr_name(trans->vsub));
return gsm411_smc_recv(&trans->sms.smc_inst,
GSM411_MMSMS_EST_CNF, NULL, 0);
}
/* Initiate Paging procedure */
LOGP(DLSMS, LOGL_DEBUG, "Initiating Paging procedure "
"for %s due to MMSMS_EST_REQ\n", vlr_subscr_name(trans->vsub));
trans->paging_request = subscr_request_conn(trans->vsub,
paging_cb_mmsms_est_req, trans, "MT SMS");
if (!trans->paging_request) {
LOGP(DLSMS, LOGL_ERROR, "Failed to initiate Paging "
"procedure for %s\n", vlr_subscr_name(trans->vsub));
/* Inform SMC about channel establishment failure */
gsm411_smc_recv(&trans->sms.smc_inst,
GSM411_MMSMS_REL_IND, NULL, 0);
trans_free(trans);
return -EIO;
}
return 0;
}
/* Prefix msg with a 04.08/04.11 CP header */
static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
uint8_t msg_type)
{
struct gsm48_hdr *gh;
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
/* Outgoing needs the highest bit set */
gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
gh->msg_type = msg_type;
OMSC_LINKID_CB(msg) = trans->dlci;
DEBUGP(DLSMS, "sending CP message (trans=%x)\n", trans->transaction_id);
return gsm411_sendmsg(trans->conn, msg);
}
/* mm_send: receive MMCCSMS sap message from SMC */
static int gsm411_mm_send(struct gsm411_smc_inst *inst, int msg_type,
struct msgb *msg, int cp_msg_type)
{
struct gsm_trans *trans =
container_of(inst, struct gsm_trans, sms.smc_inst);
int rc = 0;
switch (msg_type) {
case GSM411_MMSMS_EST_REQ:
rc = gsm411_mmsms_est_req(trans);
msgb_free(msg); /* upper layer does not free msg */
2009-08-14 08:42:43 +00:00
break;
case GSM411_MMSMS_DATA_REQ:
rc = gsm411_cp_sendmsg(msg, trans, cp_msg_type);
2009-08-14 08:42:43 +00:00
break;
case GSM411_MMSMS_REL_REQ:
DEBUGP(DLSMS, "Got MMSMS_REL_REQ, destroying transaction.\n");
msgb_free(msg);
trans_free(trans);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Unhandled MMCCSMS msg 0x%x\n", msg_type);
msgb_free(msg);
rc = -EINVAL;
}
return rc;
}
/* mm_send: receive MNCCSMS sap message from SMR */
int gsm411_mn_send(struct gsm411_smr_inst *inst, int msg_type,
struct msgb *msg)
{
struct gsm_trans *trans =
container_of(inst, struct gsm_trans, sms.smr_inst);
/* forward to SMC */
return gsm411_smc_send(&trans->sms.smc_inst, msg_type, msg);
}
static int gsm340_rx_sms_submit(struct gsm_sms *gsms)
{
if (db_sms_store(gsms) != 0) {
LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
/* dispatch a signal to tell higher level about it */
send_signal(S_SMS_SUBMITTED, NULL, gsms, 0);
2009-08-17 07:39:55 +00:00
return 0;
}
/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
static int gsm340_gen_oa_sub(uint8_t *oa, unsigned int oa_len,
const struct gsm_sms_addr *src)
{
/* network specific, private numbering plan */
return gsm340_gen_oa(oa, oa_len, src->ton, src->npi, src->addr);
}
/* generate a msgb containing an 03.40 9.2.2.1 SMS-DELIVER TPDU derived from
* struct gsm_sms, returns total size of TPDU */
static int gsm340_gen_sms_deliver_tpdu(struct msgb *msg, struct gsm_sms *sms)
{
uint8_t *smsp;
uint8_t oa[12]; /* max len per 03.40 */
uint8_t octet_len;
unsigned int old_msg_len = msg->len;
int oa_len;
/* generate first octet with masked bits */
smsp = msgb_put(msg, 1);
/* TP-MTI (message type indicator) */
*smsp = GSM340_SMS_DELIVER_SC2MS;
/* TP-MMS (more messages to send) */
if (0 /* FIXME */)
*smsp |= 0x04;
/* TP-SRI(deliver)/SRR(submit) */
if (sms->status_rep_req)
*smsp |= 0x20;
/* TP-UDHI (indicating TP-UD contains a header) */
if (sms->ud_hdr_ind)
*smsp |= 0x40;
/* generate originator address */
oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
if (oa_len < 0)
return -ENOSPC;
smsp = msgb_put(msg, oa_len);
memcpy(smsp, oa, oa_len);
/* generate TP-PID */
smsp = msgb_put(msg, 1);
*smsp = sms->protocol_id;
/* generate TP-DCS */
smsp = msgb_put(msg, 1);
*smsp = sms->data_coding_scheme;
/* generate TP-SCTS */
smsp = msgb_put(msg, 7);
gsm340_gen_scts(smsp, time(NULL));
/* generate TP-UDL */
smsp = msgb_put(msg, 1);
*smsp = sms->user_data_len;
/* generate TP-UD */
switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
case DCS_7BIT_DEFAULT:
octet_len = sms->user_data_len*7/8;
if (sms->user_data_len*7%8 != 0)
octet_len++;
/* Warning, user_data_len indicates the amount of septets
* (characters), we need amount of octets occupied */
smsp = msgb_put(msg, octet_len);
memcpy(smsp, sms->user_data, octet_len);
break;
case DCS_UCS2:
case DCS_8BIT_DATA:
smsp = msgb_put(msg, sms->user_data_len);
memcpy(smsp, sms->user_data, sms->user_data_len);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
sms->data_coding_scheme);
break;
}
return msg->len - old_msg_len;
}
/* As defined by GSM 03.40, Section 9.2.2.3. */
static int gsm340_gen_sms_status_report_tpdu(struct msgb *msg,
struct gsm_sms *sms)
{
unsigned int old_msg_len = msg->len;
uint8_t oa[12]; /* max len per 03.40 */
uint8_t *smsp;
int oa_len;
/* generate first octet with masked bits */
smsp = msgb_put(msg, 1);
/* TP-MTI (message type indicator) */
*smsp = GSM340_SMS_STATUS_REP_SC2MS;
/* TP-MMS (more messages to send) */
if (0 /* FIXME */)
*smsp |= 0x04;
/* TP-MR (message reference) */
smsp = msgb_put(msg, 1);
*smsp = sms->msg_ref;
/* generate recipient address */
oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
if (oa_len < 0)
return -ENOSPC;
smsp = msgb_put(msg, oa_len);
memcpy(smsp, oa, oa_len);
/* generate TP-SCTS (Service centre timestamp) */
smsp = msgb_put(msg, 7);
gsm340_gen_scts(smsp, sms->created);
/* generate TP-DT (Discharge time, in TP-SCTS format). */
smsp = msgb_put(msg, 7);
gsm340_gen_scts(smsp, sms->created);
/* TP-ST (status) */
smsp = msgb_put(msg, 1);
/* From GSM 03.40, Section 9.2.3.15, 0x00 means OK. */
*smsp = 0x00;
LOGP(DLSMS, LOGL_INFO, "sending status report for SMS reference %x\n",
sms->msg_ref);
return msg->len - old_msg_len;
}
static int sms_route_mt_sms(struct ran_conn *conn,
struct gsm_sms *gsms)
{
int rc;
#ifdef BUILD_SMPP
int smpp_first = smpp_route_smpp_first(gsms, conn);
/*
* Route through SMPP first before going to the local database. In case
* of a unroutable message and no local subscriber, SMPP will be tried
* twice. In case of an unknown subscriber continue with the normal
* delivery of the SMS.
*/
if (smpp_first) {
rc = smpp_try_deliver(gsms, conn);
if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED)
/* unknown subscriber, try local */
goto try_local;
if (rc < 0) {
LOGP(DLSMS, LOGL_ERROR, "%s: SMS delivery error: %d.",
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
vlr_subscr_name(conn->vsub), rc);
rc = GSM411_RP_CAUSE_MO_TEMP_FAIL;
/* rc will be logged by gsm411_send_rp_error() */
rate_ctr_inc(&conn->network->msc_ctrs->ctr[
MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR]);
}
return rc;
}
try_local:
#endif
/* determine gsms->receiver based on dialled number */
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
gsms->receiver = vlr_subscr_find_by_msisdn(conn->network->vlr,
gsms->dst.addr);
if (!gsms->receiver) {
#ifdef BUILD_SMPP
/* Avoid a second look-up */
if (smpp_first) {
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
}
rc = smpp_try_deliver(gsms, conn);
if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED) {
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
} else if (rc < 0) {
LOGP(DLSMS, LOGL_ERROR, "%s: SMS delivery error: %d.",
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
vlr_subscr_name(conn->vsub), rc);
rc = GSM411_RP_CAUSE_MO_TEMP_FAIL;
/* rc will be logged by gsm411_send_rp_error() */
rate_ctr_inc(&conn->network->msc_ctrs->ctr[
MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR]);
}
#else
rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
#endif
} else
rc = 0;
return rc;
}
/* process an incoming TPDU (called from RP-DATA)
* return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we can route this sms somewhere we can reach indeed. After this change, the conversation looks like this: MS GSM 03.40 SMSC SMPP 3.4 ESME | | | | SMS-SUBMIT | | |------------------->| | | | DELIVER-SM | | |---------------->| | | | | | DELIVER-SM-RESP | | |<----------------| | GSM 04.11 RP-ACK | | |<-------------------| | | | | Before this patch, the RP-ACK was sent back straight forward to the MS, no matter if the sms can be route by the ESME or not. Thus, the user ends up getting a misleading "message delivered" in their phone screen, when the message may just be unroutable by the ESME hence silently dropped. If we get no reply from the ESME, there is a hardcoded timer that will expire to send back an RP-ERROR to the MS indicating that network is out-of-order. Currently this timer is arbitrarily set to 5 seconds. I found no specific good default value on the SMPP 3.4 specs, section 7.2, where the response_timer is described. There must be a place that describes a better default value for this. We could also expose this timer through VTY for configurability reasons, to be done later. Given all this needs to happen asyncronously, ie. block the SMSC, this patch extends the gsm_sms structure with two new fields to annotate useful information to send the RP-ACK/RP-ERROR back to the MS of origin. These new fields are: * the GSM 04.07 transaction id, to look up for the gsm_trans object. * the GSM 04.11 message reference so the MS of origin can correlate this response to its original request. Tested here using python-libsmpp script that replies with DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see here on my motorola C155 that message cannot be delivered. I have tested with the success status code in the SMPP DELIVER_SM_RESP too. Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
static int gsm340_rx_tpdu(struct gsm_trans *trans, struct msgb *msg,
uint32_t gsm411_msg_ref)
2008-12-29 00:44:41 +00:00
{
struct ran_conn *conn = trans->conn;
uint8_t *smsp = msgb_sms(msg);
struct gsm_sms *gsms;
unsigned int sms_alphabet;
uint8_t sms_mti, sms_vpf;
uint8_t *sms_vp;
uint8_t da_len_bytes;
uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
int rc = 0;
2008-12-29 00:44:41 +00:00
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED]);
gsms = sms_alloc();
if (!gsms)
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
/* invert those fields where 0 means active/present */
sms_mti = *smsp & 0x03;
sms_vpf = (*smsp & 0x18) >> 3;
gsms->status_rep_req = (*smsp & 0x20) >> 5;
gsms->ud_hdr_ind = (*smsp & 0x40);
/*
* Not evaluating MMS (More Messages to Send) because the
* lchan stays open anyway.
* Not evaluating RP (Reply Path) because we're not aware of its
* benefits.
*/
2008-12-29 00:44:41 +00:00
smsp++;
gsms->msg_ref = *smsp++;
2008-12-29 00:44:41 +00:00
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we can route this sms somewhere we can reach indeed. After this change, the conversation looks like this: MS GSM 03.40 SMSC SMPP 3.4 ESME | | | | SMS-SUBMIT | | |------------------->| | | | DELIVER-SM | | |---------------->| | | | | | DELIVER-SM-RESP | | |<----------------| | GSM 04.11 RP-ACK | | |<-------------------| | | | | Before this patch, the RP-ACK was sent back straight forward to the MS, no matter if the sms can be route by the ESME or not. Thus, the user ends up getting a misleading "message delivered" in their phone screen, when the message may just be unroutable by the ESME hence silently dropped. If we get no reply from the ESME, there is a hardcoded timer that will expire to send back an RP-ERROR to the MS indicating that network is out-of-order. Currently this timer is arbitrarily set to 5 seconds. I found no specific good default value on the SMPP 3.4 specs, section 7.2, where the response_timer is described. There must be a place that describes a better default value for this. We could also expose this timer through VTY for configurability reasons, to be done later. Given all this needs to happen asyncronously, ie. block the SMSC, this patch extends the gsm_sms structure with two new fields to annotate useful information to send the RP-ACK/RP-ERROR back to the MS of origin. These new fields are: * the GSM 04.07 transaction id, to look up for the gsm_trans object. * the GSM 04.11 message reference so the MS of origin can correlate this response to its original request. Tested here using python-libsmpp script that replies with DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see here on my motorola C155 that message cannot be delivered. I have tested with the success status code in the SMPP DELIVER_SM_RESP too. Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
gsms->gsm411.transaction_id = trans->transaction_id;
gsms->gsm411.msg_ref = gsm411_msg_ref;
/* length in bytes of the destination address */
da_len_bytes = 2 + *smsp/2 + *smsp%2;
if (da_len_bytes > 12) {
LOGP(DLSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
goto out;
} else if (da_len_bytes < 4) {
LOGP(DLSMS, LOGL_ERROR, "Destination Address < 4 bytes ?!?\n");
rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
goto out;
}
memset(address_lv, 0, sizeof(address_lv));
memcpy(address_lv, smsp, da_len_bytes);
/* mangle first byte to reflect length in bytes, not digits */
address_lv[0] = da_len_bytes - 1;
gsms->dst.ton = (address_lv[1] >> 4) & 7;
gsms->dst.npi = address_lv[1] & 0xF;
/* convert to real number */
gsm48_decode_bcd_number(gsms->dst.addr,
sizeof(gsms->dst.addr), address_lv, 1);
smsp += da_len_bytes;
2008-12-29 00:44:41 +00:00
gsms->protocol_id = *smsp++;
gsms->data_coding_scheme = *smsp++;
sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
if (sms_alphabet == 0xffffffff) {
rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
goto out;
}
switch (sms_vpf) {
case GSM340_TP_VPF_RELATIVE:
sms_vp = smsp++;
break;
case GSM340_TP_VPF_ABSOLUTE:
case GSM340_TP_VPF_ENHANCED:
sms_vp = smsp;
/* the additional functionality indicator... */
if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
smsp++;
smsp += 7;
2008-12-29 00:44:41 +00:00
break;
case GSM340_TP_VPF_NONE:
sms_vp = 0;
break;
2008-12-29 00:44:41 +00:00
default:
LOGP(DLSMS, LOGL_NOTICE,
"SMS Validity period not implemented: 0x%02x\n", sms_vpf);
rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
goto out;
2008-12-29 00:44:41 +00:00
}
gsms->user_data_len = *smsp++;
if (gsms->user_data_len) {
memcpy(gsms->user_data, smsp, gsms->user_data_len);
switch (sms_alphabet) {
case DCS_7BIT_DEFAULT:
gsm_7bit_decode_n(gsms->text, sizeof(gsms->text), smsp,
gsms->user_data_len);
break;
case DCS_8BIT_DATA:
case DCS_UCS2:
case DCS_NONE:
break;
}
}
2008-12-29 00:44:41 +00:00
OSMO_STRLCPY_ARRAY(gsms->src.addr, conn->vsub->msisdn);
LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
"MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
"UserDataLength: 0x%02x, UserData: \"%s\"\n",
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
vlr_subscr_name(conn->vsub), sms_mti, sms_vpf, gsms->msg_ref,
gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr,
gsms->user_data_len,
sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
osmo_hexdump(gsms->user_data, gsms->user_data_len));
gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
/* FIXME: This looks very wrong */
send_signal(0, NULL, gsms, 0);
rc = sms_route_mt_sms(conn, gsms);
/*
* This SMS got routed through SMPP or no receiver exists.
* In any case, we store it in the database for further processing.
*/
switch (sms_mti) {
case GSM340_SMS_SUBMIT_MS2SC:
/* MS is submitting a SMS */
rc = gsm340_rx_sms_submit(gsms);
break;
case GSM340_SMS_COMMAND_MS2SC:
case GSM340_SMS_DELIVER_REP_MS2SC:
LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
}
out:
sms_free(gsms);
2008-12-29 00:44:41 +00:00
return rc;
2008-12-29 00:44:41 +00:00
}
/* Prefix msg with a RP-DATA header and send as SMR DATA */
static int gsm411_rp_sendmsg(struct gsm411_smr_inst *inst, struct msgb *msg,
uint8_t rp_msg_type, uint8_t rp_msg_ref,
int rl_msg_type)
{
struct gsm411_rp_hdr *rp;
uint8_t len = msg->len;
/* GSM 04.11 RP-DATA header */
rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
rp->len = len + 2;
rp->msg_type = rp_msg_type;
rp->msg_ref = rp_msg_ref;
return gsm411_smr_send(inst, rl_msg_type, msg);
}
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we can route this sms somewhere we can reach indeed. After this change, the conversation looks like this: MS GSM 03.40 SMSC SMPP 3.4 ESME | | | | SMS-SUBMIT | | |------------------->| | | | DELIVER-SM | | |---------------->| | | | | | DELIVER-SM-RESP | | |<----------------| | GSM 04.11 RP-ACK | | |<-------------------| | | | | Before this patch, the RP-ACK was sent back straight forward to the MS, no matter if the sms can be route by the ESME or not. Thus, the user ends up getting a misleading "message delivered" in their phone screen, when the message may just be unroutable by the ESME hence silently dropped. If we get no reply from the ESME, there is a hardcoded timer that will expire to send back an RP-ERROR to the MS indicating that network is out-of-order. Currently this timer is arbitrarily set to 5 seconds. I found no specific good default value on the SMPP 3.4 specs, section 7.2, where the response_timer is described. There must be a place that describes a better default value for this. We could also expose this timer through VTY for configurability reasons, to be done later. Given all this needs to happen asyncronously, ie. block the SMSC, this patch extends the gsm_sms structure with two new fields to annotate useful information to send the RP-ACK/RP-ERROR back to the MS of origin. These new fields are: * the GSM 04.07 transaction id, to look up for the gsm_trans object. * the GSM 04.11 message reference so the MS of origin can correlate this response to its original request. Tested here using python-libsmpp script that replies with DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see here on my motorola C155 that message cannot be delivered. I have tested with the success status code in the SMPP DELIVER_SM_RESP too. Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
2008-12-29 01:54:02 +00:00
{
struct msgb *msg = gsm411_msgb_alloc();
DEBUGP(DLSMS, "TX: SMS RP ACK\n");
2008-12-29 01:54:02 +00:00
return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg, GSM411_MT_RP_ACK_MT,
msg_ref, GSM411_SM_RL_REPORT_REQ);
2008-12-29 01:54:02 +00:00
}
libmsc: send RP-ACK to MS after ESME sends SMPP DELIVER-SM-RESP Hold on with the GSM 04.11 RP-ACK/RP-ERROR that we send to the MS until we get a confirmation from the ESME, via SMPP DELIVER-SM-RESP, that we can route this sms somewhere we can reach indeed. After this change, the conversation looks like this: MS GSM 03.40 SMSC SMPP 3.4 ESME | | | | SMS-SUBMIT | | |------------------->| | | | DELIVER-SM | | |---------------->| | | | | | DELIVER-SM-RESP | | |<----------------| | GSM 04.11 RP-ACK | | |<-------------------| | | | | Before this patch, the RP-ACK was sent back straight forward to the MS, no matter if the sms can be route by the ESME or not. Thus, the user ends up getting a misleading "message delivered" in their phone screen, when the message may just be unroutable by the ESME hence silently dropped. If we get no reply from the ESME, there is a hardcoded timer that will expire to send back an RP-ERROR to the MS indicating that network is out-of-order. Currently this timer is arbitrarily set to 5 seconds. I found no specific good default value on the SMPP 3.4 specs, section 7.2, where the response_timer is described. There must be a place that describes a better default value for this. We could also expose this timer through VTY for configurability reasons, to be done later. Given all this needs to happen asyncronously, ie. block the SMSC, this patch extends the gsm_sms structure with two new fields to annotate useful information to send the RP-ACK/RP-ERROR back to the MS of origin. These new fields are: * the GSM 04.07 transaction id, to look up for the gsm_trans object. * the GSM 04.11 message reference so the MS of origin can correlate this response to its original request. Tested here using python-libsmpp script that replies with DELIVER_SM_RESP and status code 0x0b (Invalid Destination). I can see here on my motorola C155 that message cannot be delivered. I have tested with the success status code in the SMPP DELIVER_SM_RESP too. Change-Id: I0d5bd5693fed6d4f4bd2951711c7888712507bfd
2017-05-04 16:44:22 +00:00
int gsm411_send_rp_error(struct gsm_trans *trans, uint8_t msg_ref,
uint8_t cause)
2008-12-29 01:54:02 +00:00
{
struct msgb *msg = gsm411_msgb_alloc();
msgb_tv_put(msg, 1, cause);
2008-12-29 01:54:02 +00:00
LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
get_value_string(gsm411_rp_cause_strs, cause));
2008-12-29 01:54:02 +00:00
return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg,
GSM411_MT_RP_ERROR_MT, msg_ref, GSM411_SM_RL_REPORT_REQ);
2008-12-29 01:54:02 +00:00
}
/* Receive a 04.11 TPDU inside RP-DATA / user data */
static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph,
uint8_t *dst, uint8_t dst_len)
{
int rc = 0;
if (trans->net->sms_over_gsup) {
/* RP-ACK or RP-ERROR is triggered as soon as we get the response */
rc = gsm411_gsup_mo_fwd_sm_req(trans, msg, rph->msg_ref, dst, dst_len);
if (rc) /* GSUP message sending error */
return gsm411_send_rp_error(trans, rph->msg_ref, rc);
return 0;
}
rc = gsm340_rx_tpdu(trans, msg, rph->msg_ref);
if (rc == 0)
return gsm411_send_rp_ack(trans, rph->msg_ref);
else if (rc > 0)
return gsm411_send_rp_error(trans, rph->msg_ref, rc);
else
return rc;
}
/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
uint8_t src_len, dst_len, rpud_len;
uint8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
/* in the MO case, this should always be zero length */
src_len = rph->data[0];
if (src_len)
src = &rph->data[1];
dst_len = rph->data[1+src_len];
if (dst_len)
dst = &rph->data[1+src_len+1];
rpud_len = rph->data[1+src_len+1+dst_len];
if (rpud_len)
rp_ud = &rph->data[1+src_len+1+dst_len+1];
DEBUGP(DLSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
src_len, dst_len, rpud_len);
if (src_len && src)
LOGP(DLSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
if (!dst_len || !dst || !rpud_len || !rp_ud) {
LOGP(DLSMS, LOGL_ERROR,
"RP-DATA (MO) without DST or TPDU ?!?\n");
gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_INV_MAND_INF);
return -EIO;
}
msg->l4h = rp_ud;
DEBUGP(DLSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
return gsm411_rx_rp_ud(msg, trans, rph, dst, dst_len);
}
static struct gsm_sms *sms_report_alloc(struct gsm_sms *sms)
{
struct gsm_sms *sms_report;
int len;
sms_report = sms_alloc();
OSMO_ASSERT(sms_report);
sms_report->msg_ref = sms->msg_ref;
sms_report->protocol_id = sms->protocol_id;
sms_report->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
/* Invert address to send status report back to origin. */
sms_report->src = sms->dst;
sms_report->dst = sms->src;
/* As specified by Appendix B. Delivery Receipt Format.
* TODO: Many fields in this string are just set with dummy values,
* revisit this.
*/
len = snprintf((char *)sms_report->user_data,
sizeof(sms_report->user_data),
"id:%.08llu sub:000 dlvrd:000 submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DELIVRD err:000 text:%.20s",
sms->id, sms->text);
sms_report->user_data_len = len;
LOGP(DLSMS, LOGL_NOTICE, "%s\n", sms_report->user_data);
/* This represents a sms report. */
sms_report->is_report = true;
return sms_report;
}
static void sms_status_report(struct gsm_sms *gsms,
struct ran_conn *conn)
{
struct gsm_sms *sms_report;
int rc;
sms_report = sms_report_alloc(gsms);
rc = sms_route_mt_sms(conn, sms_report);
if (rc < 0) {
LOGP(DLSMS, LOGL_ERROR,
"Failed to send status report! err=%d\n", rc);
}
/* No route via SMPP, send the GSM 03.40 status-report now. */
if (sms_report->receiver)
gsm340_rx_sms_submit(sms_report);
LOGP(DLSMS, LOGL_NOTICE, "Status report has been sent\n");
sms_free(sms_report);
}
/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
static int gsm411_rx_rp_ack(struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
struct gsm_sms *sms = trans->sms.sms;
/* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
* 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,
GSM411_RP_CAUSE_PROTOCOL_ERR);
}
/* mark this SMS as sent in database */
db_sms_mark_delivered(sms);
send_signal(S_SMS_DELIVERED, trans, sms, 0);
if (sms->status_rep_req)
sms_status_report(sms, trans->conn);
sms_free(sms);
trans->sms.sms = NULL;
return 0;
}
static int gsm411_rx_rp_error(struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
struct gsm_network *net = trans->conn->network;
struct gsm_sms *sms = trans->sms.sms;
uint8_t cause_len = rph->data[0];
uint8_t cause = rph->data[1];
/* Error in response to MT RP_DATA, i.e. the MS did not
* successfully receive the SMS. We need to investigate
* the cause and take action depending on it */
LOGP(DLSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
vlr_subscr_name(trans->conn->vsub), cause_len, cause,
get_value_string(gsm411_rp_cause_strs, cause));
2009-07-09 21:52:59 +00:00
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");
2009-08-17 07:39:55 +00:00
return -EINVAL;
#if 0
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_PROTOCOL_ERR);
2009-08-17 07:39:55 +00:00
#endif
}
if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
/* MS has not enough memory to store the message. We need
2010-12-23 21:23:15 +00:00
* to store this in our database and wait for a SMMA message */
/* FIXME */
send_signal(S_SMS_MEM_EXCEEDED, trans, sms, 0);
rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM]);
} else {
send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER]);
}
sms_free(sms);
trans->sms.sms = NULL;
return 0;
}
static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
int rc;
if (trans->net->sms_over_gsup) {
/* RP-ACK or RP-ERROR is triggered as soon as we get the response */
rc = gsm411_gsup_mo_ready_for_sm_req(trans, rph->msg_ref);
if (rc) /* GSUP message sending error */
return gsm411_send_rp_error(trans, rph->msg_ref, rc);
return 0;
}
rc = gsm411_send_rp_ack(trans, rph->msg_ref);
/* MS tells us that it has memory for more SMS, we need
* to check if we have any pending messages for it and then
* transfer those */
send_signal(S_SMS_SMMA, trans, NULL, 0);
return rc;
}
/* receive RL DATA */
static int gsm411_rx_rl_data(struct msgb *msg, struct gsm48_hdr *gh,
struct gsm_trans *trans)
{
2008-12-29 01:54:02 +00:00
struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
uint8_t msg_type = rp_data->msg_type & 0x07;
int rc = 0;
switch (msg_type) {
case GSM411_MT_RP_DATA_MO:
DEBUGP(DLSMS, "RX SMS RP-DATA (MO)\n");
rc = gsm411_rx_rp_data(msg, trans, rp_data);
break;
case GSM411_MT_RP_SMMA_MO:
DEBUGP(DLSMS, "RX SMS RP-SMMA\n");
rc = gsm411_rx_rp_smma(msg, trans, rp_data);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
rc = -EINVAL;
break;
}
return rc;
}
/* receive RL REPORT */
static int gsm411_rx_rl_report(struct msgb *msg, struct gsm48_hdr *gh,
struct gsm_trans *trans)
{
struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
uint8_t msg_type = rp_data->msg_type & 0x07;
int rc = 0;
switch (msg_type) {
case GSM411_MT_RP_ACK_MO:
DEBUGP(DLSMS, "RX SMS RP-ACK (MO)\n");
rc = gsm411_rx_rp_ack(trans, rp_data);
break;
case GSM411_MT_RP_ERROR_MO:
DEBUGP(DLSMS, "RX SMS RP-ERROR (MO)\n");
rc = gsm411_rx_rp_error(trans, rp_data);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
rc = -EINVAL;
break;
}
return rc;
}
/* receive SM-RL sap message from SMR
* NOTE: Message is freed by sender
*/
int gsm411_rl_recv(struct gsm411_smr_inst *inst, int msg_type,
struct msgb *msg)
{
struct gsm_trans *trans =
container_of(inst, struct gsm_trans, sms.smr_inst);
struct gsm48_hdr *gh = msgb_l3(msg);
int rc = 0;
switch (msg_type) {
case GSM411_SM_RL_DATA_IND:
rc = gsm411_rx_rl_data(msg, gh, trans);
break;
case GSM411_SM_RL_REPORT_IND:
if (gh)
rc = gsm411_rx_rl_report(msg, gh, trans);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Unhandled SM-RL message 0x%x\n", msg_type);
rc = -EINVAL;
}
return rc;
}
/* receive MNCCSMS sap message from SMC
* NOTE: Message is freed by sender
*/
static int gsm411_mn_recv(struct gsm411_smc_inst *inst, int msg_type,
struct msgb *msg)
{
struct gsm_trans *trans =
container_of(inst, struct gsm_trans, sms.smc_inst);
struct gsm48_hdr *gh = msgb_l3(msg);
int rc = 0;
switch (msg_type) {
case GSM411_MNSMS_EST_IND:
case GSM411_MNSMS_DATA_IND:
DEBUGP(DLSMS, "MNSMS-DATA/EST-IND\n");
rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
break;
case GSM411_MNSMS_ERROR_IND:
if (gh)
DEBUGP(DLSMS, "MNSMS-ERROR-IND, cause %d (%s)\n",
gh->data[0],
get_value_string(gsm411_cp_cause_strs,
gh->data[0]));
else
DEBUGP(DLSMS, "MNSMS-ERROR-IND, no cause\n");
rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
break;
default:
LOGP(DLSMS, LOGL_NOTICE, "Unhandled MNCCSMS msg 0x%x\n", msg_type);
rc = -EINVAL;
}
return rc;
}
static struct gsm_trans *gsm411_alloc_mt_trans(struct gsm_network *net,
struct vlr_subscr *vsub)
{
struct ran_conn *conn;
struct gsm_trans *trans;
int tid;
LOGP(DLSMS, LOGL_INFO, "Going to send a MT SMS\n");
/* Generate a new transaction ID */
tid = trans_assign_trans_id(net, vsub, GSM48_PDISC_SMS, 0);
if (tid == -1) {
LOGP(DLSMS, LOGL_ERROR, "No available transaction IDs\n");
return NULL;
}
/* Allocate a new transaction */
trans = trans_alloc(net, vsub, GSM48_PDISC_SMS, tid, new_callref++);
if (!trans) {
LOGP(DLSMS, LOGL_ERROR, "No memory for trans\n");
return NULL;
}
/* Init both SMC and SMR state machines */
gsm411_smc_init(&trans->sms.smc_inst, 0, 1,
gsm411_mn_recv, gsm411_mm_send);
gsm411_smr_init(&trans->sms.smr_inst, 0, 1,
gsm411_rl_recv, gsm411_mn_send);
/* Attempt to find an existing connection */
conn = connection_for_subscr(vsub);
if (conn) {
/* Associate transaction with connection */
trans->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_SMS);
/* Generate unique RP Message Reference */
trans->sms.sm_rp_mr = conn->next_rp_ref++;
}
/* Use SAPI 3 (see GSM 04.11, section 2.3) */
trans->dlci = UM_SAPI_SMS;
return trans;
}
/* High-level function to send an SMS to a given subscriber */
int gsm411_send_sms(struct gsm_network *net,
struct vlr_subscr *vsub,
struct gsm_sms *sms)
{
uint8_t *data, *rp_ud_len;
struct gsm_trans *trans;
struct msgb *msg;
int rc;
/* Allocate a new transaction for MT SMS */
trans = gsm411_alloc_mt_trans(net, vsub);
if (!trans) {
send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
sms_free(sms);
return -ENOMEM;
}
/* Allocate a message buffer for to be encoded SMS */
msg = gsm411_msgb_alloc();
if (!msg) {
send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
trans_free(trans);
sms_free(sms);
return -ENOMEM;
}
/* Hardcode SMSC Originating Address for now */
data = (uint8_t *)msgb_put(msg, 8);
data[0] = 0x07; /* originator length == 7 */
data[1] = 0x91; /* type of number: international, ISDN */
data[2] = 0x44; /* 447785016005 */
data[3] = 0x77;
data[4] = 0x58;
data[5] = 0x10;
data[6] = 0x06;
data[7] = 0x50;
/* Hardcoded Destination Address */
data = (uint8_t *)msgb_put(msg, 1);
data[0] = 0; /* destination length == 0 */
/* obtain a pointer for the rp_ud_len, so we can fill it later */
rp_ud_len = (uint8_t *)msgb_put(msg, 1);
if (sms->is_report) {
/* generate the 03.40 SMS-STATUS-REPORT TPDU */
rc = gsm340_gen_sms_status_report_tpdu(msg, sms);
} else {
/* generate the 03.40 SMS-DELIVER TPDU */
rc = gsm340_gen_sms_deliver_tpdu(msg, sms);
}
if (rc < 0) {
send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
sms_free(sms);
trans_free(trans);
msgb_free(msg);
return rc;
}
*rp_ud_len = rc;
/* Store a pointer to abstract SMS representation */
trans->sms.sms = sms;
rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED]);
db_sms_inc_deliver_attempts(trans->sms.sms);
return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg,
GSM411_MT_RP_DATA_MT, trans->sms.sm_rp_mr,
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)
{
struct gsm48_hdr *gh = msgb_l3(msg);
uint8_t msg_type = gh->msg_type;
uint8_t transaction_id = gsm48_hdr_trans_id_flip_ti(gh);
struct gsm_trans *trans;
int new_trans = 0;
int rc = 0;
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
if (!conn->vsub)
return -EIO;
/* FIXME: send some error message */
DEBUGP(DLSMS, "receiving data (trans_id=%x, msg_type=%s)\n", transaction_id,
gsm48_pdisc_msgtype_name(gsm48_hdr_pdisc(gh), gsm48_hdr_msg_type(gh)));
trans = trans_find_by_id(conn, GSM48_PDISC_SMS, transaction_id);
/*
* A transaction we created but don't know about?
*/
if (!trans && (transaction_id & 0x8) == 0) {
LOGP(DLSMS, LOGL_ERROR, "trans_id=%x allocated by us but known "
"to us anymore. We are ignoring it, maybe a CP-ERROR "
"from a MS?\n",
transaction_id);
return -EINVAL;
}
if (!trans) {
DEBUGP(DLSMS, " -> (new transaction)\n");
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
trans = trans_alloc(conn->network, conn->vsub,
GSM48_PDISC_SMS,
transaction_id, new_callref++);
if (!trans) {
DEBUGP(DLSMS, " -> No memory for trans\n");
/* FIXME: send some error message */
return -ENOMEM;
}
gsm411_smc_init(&trans->sms.smc_inst, 0, 1,
gsm411_mn_recv, gsm411_mm_send);
gsm411_smr_init(&trans->sms.smr_inst, 0, 1,
gsm411_rl_recv, gsm411_mn_send);
trans->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_SMS);
trans->dlci = OMSC_LINKID_CB(msg); /* DLCI as received from BSC */
new_trans = 1;
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
cm_service_request_concludes(conn, msg);
}
/* 5.4: For MO, if a CP-DATA is received for a new
* transaction, equals reception of an implicit
* last CP-ACK for previous transaction */
if (trans->sms.smc_inst.cp_state == GSM411_CPS_IDLE
&& msg_type == GSM411_MT_CP_DATA) {
int i;
struct gsm_trans *ptrans;
/* Scan through all remote initiated transactions */
for (i=8; i<15; i++) {
if (i == transaction_id)
continue;
ptrans = trans_find_by_id(conn, GSM48_PDISC_SMS, i);
if (!ptrans)
continue;
DEBUGP(DLSMS, "Implicit CP-ACK for trans_id=%x\n", i);
/* Finish it for good */
trans_free(ptrans);
}
}
ran_conn_communicating(conn);
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
gsm411_smc_recv(&trans->sms.smc_inst,
(new_trans) ? GSM411_MMSMS_EST_IND : GSM411_MMSMS_DATA_IND,
msg, msg_type);
return rc;
}
void _gsm411_sms_trans_free(struct gsm_trans *trans)
{
/* cleanup SMS instance */
gsm411_smr_clear(&trans->sms.smr_inst);
trans->sms.smr_inst.rl_recv = NULL;
trans->sms.smr_inst.mn_send = NULL;
gsm411_smc_clear(&trans->sms.smc_inst);
trans->sms.smc_inst.mn_recv = NULL;
trans->sms.smc_inst.mm_send = NULL;
if (trans->sms.sms) {
LOGP(DLSMS, LOGL_ERROR, "Transaction contains SMS.\n");
send_signal(S_SMS_UNKNOWN_ERROR, trans, trans->sms.sms, 0);
sms_free(trans->sms.sms);
trans->sms.sms = NULL;
}
}
Use libvlr in libmsc (large refactoring) Original libvlr code is by Harald Welte <laforge@gnumonks.org>, polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>. This is a long series of trial-and-error development collapsed in one patch. This may be split in smaller commits if reviewers prefer that. If we can keep it as one, we have saved ourselves the additional separation work. SMS: The SQL based lookup of SMS for attached subscribers no longer works since the SQL database no longer has the subscriber data. Replace with a round-robin on the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the subscriber is currently attached. If there are many SMS for not-attached subscribers in the SMS database, this will become inefficient: a DB hit returns a pending SMS, the RAM lookup will reveal that the subscriber is not attached, after which the DB is hit for the next SMS. It would become more efficient e.g. by having an MSISDN based hash list for the VLR subscribers and by marking non-attached SMS recipients in the SMS database so that they can be excluded with the SQL query already. There is a sanity limit to do at most 100 db hits per attempt to find a pending SMS. So if there are more than 100 stored SMS waiting for their recipients to actually attach to the MSC, it may take more than one SMS queue trigger to deliver SMS for subscribers that are actually attached. This is not very beautiful, but is merely intended to carry us over to a time when we have a proper separate SMSC entity. Introduce gsm_subscriber_connection ref-counting in libmsc. Remove/Disable VTY and CTRL commands to create subscribers, which is now a task of the OsmoHLR. Adjust the python tests accordingly. Remove VTY cmd subscriber-keep-in-ram. Use OSMO_GSUP_PORT = 4222 instead of 2222. See I4222e21686c823985be8ff1f16b1182be8ad6175. So far use the LAC from conn->bts, will be replaced by conn->lac in Id3705236350d5f69e447046b0a764bbabc3d493c. Related: OS#1592 OS#1974 Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2016-06-19 16:06:02 +00:00
/* Process incoming SAPI N-REJECT from BSC */
void gsm411_sapi_n_reject(struct ran_conn *conn)
{
struct gsm_network *net;
struct gsm_trans *trans, *tmp;
net = conn->network;
sms: Fix crash on RLL Establish Request timeouts with active call Sylvain pointed out that in the current crash log the transaction we try to read the SMS from is actually a transaction for Call Control. On AMD64 the struct layout is different and that leads to a crash when the CC transaction is in front of the SMS transaction. Look at the trans->protocol to fix the crash. The issue got introduced in 6a3d765bf97349535602ed5b2b55d2093aa18d71 (2010) when I added the SAPI N Reject handling. #0 smpp_sms_cb (subsys=1, signal=4, handler_data=0xbb8270, signal_data=0x7fff33574ea0) at smpp_openbsc.c:284 284 if (sms->source != SMS_SOURCE_SMPP) (gdb) bt #0 smpp_sms_cb (subsys=1, signal=4, handler_data=0xbb8270, signal_data=0x7fff33574ea0) at smpp_openbsc.c:284 #1 0x00007f424e4a094c in osmo_signal_dispatch (subsys=1, signal=4, signal_data=0x7fff33574ea0) at signal.c:105 #2 0x000000000042b070 in send_signal (sig_no=<optimized out>, trans=<optimized out>, sms=<optimized out>, paging_result=<optimized out>) at gsm_04_11.c:125 #3 0x000000000042ccd2 in gsm411_sapi_n_reject (conn=0xec6790) at gsm_04_11.c:1000 #4 0x0000000000408983 in send_sapi_reject (link_id=<optimized out>, conn=<optimized out>) at bsc_api.c:733 #5 rll_ind_cb (_data=<optimized out>, lchan=<optimized out>, link_id=<optimized out>, rllr_ind=<optimized out>) at bsc_api.c:755 #6 rll_ind_cb (lchan=<optimized out>, link_id=<optimized out>, _data=<optimized out>, rllr_ind=<optimized out>) at bsc_api.c:736 #7 0x000000000041f8d2 in complete_rllr (rllr=<optimized out>, type=<optimized out>) at bsc_rll.c:55 #8 0x00007f424e4a03bc in osmo_timers_update () at timer.c:243 #9 0x00007f424e4a069b in osmo_select_main (polling=0) at select.c:133 #10 0x0000000000407394 in main (argc=<optimized out>, argv=0x7fff33575238) at bsc_hack.c:346 (gdb) frame 3 #3 0x000000000042ccd2 in gsm411_sapi_n_reject (conn=0xec6790) at gsm_04_11.c:1000 1000 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0); (gdb) p trans $1 = (struct gsm_trans *) 0xedba80 (gdb) p *trans .... data = 0x1}}, sms = 0x3439323400000003}}} (gdb) p trans->protocol $4 = 3 '\003'
2013-12-27 21:47:09 +00:00
llist_for_each_entry_safe(trans, tmp, &net->trans_list, entry) {
struct gsm_sms *sms;
if (trans->conn != conn)
continue;
if (trans->protocol != GSM48_PDISC_SMS)
continue;
sms = trans->sms.sms;
if (!sms) {
LOGP(DLSMS, LOGL_ERROR, "SAPI Reject but no SMS.\n");
continue;
}
sms: Fix crash on RLL Establish Request timeouts with active call Sylvain pointed out that in the current crash log the transaction we try to read the SMS from is actually a transaction for Call Control. On AMD64 the struct layout is different and that leads to a crash when the CC transaction is in front of the SMS transaction. Look at the trans->protocol to fix the crash. The issue got introduced in 6a3d765bf97349535602ed5b2b55d2093aa18d71 (2010) when I added the SAPI N Reject handling. #0 smpp_sms_cb (subsys=1, signal=4, handler_data=0xbb8270, signal_data=0x7fff33574ea0) at smpp_openbsc.c:284 284 if (sms->source != SMS_SOURCE_SMPP) (gdb) bt #0 smpp_sms_cb (subsys=1, signal=4, handler_data=0xbb8270, signal_data=0x7fff33574ea0) at smpp_openbsc.c:284 #1 0x00007f424e4a094c in osmo_signal_dispatch (subsys=1, signal=4, signal_data=0x7fff33574ea0) at signal.c:105 #2 0x000000000042b070 in send_signal (sig_no=<optimized out>, trans=<optimized out>, sms=<optimized out>, paging_result=<optimized out>) at gsm_04_11.c:125 #3 0x000000000042ccd2 in gsm411_sapi_n_reject (conn=0xec6790) at gsm_04_11.c:1000 #4 0x0000000000408983 in send_sapi_reject (link_id=<optimized out>, conn=<optimized out>) at bsc_api.c:733 #5 rll_ind_cb (_data=<optimized out>, lchan=<optimized out>, link_id=<optimized out>, rllr_ind=<optimized out>) at bsc_api.c:755 #6 rll_ind_cb (lchan=<optimized out>, link_id=<optimized out>, _data=<optimized out>, rllr_ind=<optimized out>) at bsc_api.c:736 #7 0x000000000041f8d2 in complete_rllr (rllr=<optimized out>, type=<optimized out>) at bsc_rll.c:55 #8 0x00007f424e4a03bc in osmo_timers_update () at timer.c:243 #9 0x00007f424e4a069b in osmo_select_main (polling=0) at select.c:133 #10 0x0000000000407394 in main (argc=<optimized out>, argv=0x7fff33575238) at bsc_hack.c:346 (gdb) frame 3 #3 0x000000000042ccd2 in gsm411_sapi_n_reject (conn=0xec6790) at gsm_04_11.c:1000 1000 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0); (gdb) p trans $1 = (struct gsm_trans *) 0xedba80 (gdb) p *trans .... data = 0x1}}, sms = 0x3439323400000003}}} (gdb) p trans->protocol $4 = 3 '\003'
2013-12-27 21:47:09 +00:00
send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
sms_free(sms);
trans->sms.sms = NULL;
trans_free(trans);
}
}