bsc/ussd: Send faked CM Service Accept before sending USSD

The MS do not show the USSD messages yet. This patch modifies the
implementation to insert a CM Service Accept before the ussdNotify
to finish the establishment of the MM connection according to
3GPP TS 04.10/3.2.1.

This fix has been tested with a Blackberry phone that has shown
an ussd_grace_txt after rf_locked has been set to '1'. Without this
patch, that message wasn't shown. The phone has sent a CC Setup
and other messages before processing the channel release message sent
by the BSC, but these messages have not been forwarded to the MSC (as
expected).

Ticket: OW#957
Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2013-10-31 10:47:02 +01:00 committed by Holger Hans Peter Freyther
parent 6e919dbb65
commit 61bd965b04
4 changed files with 20 additions and 10 deletions

View File

@ -39,6 +39,9 @@ void gsm_net_update_ctype(struct gsm_network *net);
int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn); int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq); int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq);
int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn); int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn);
int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
enum gsm48_reject_value value);
int gsm48_send_rr_release(struct gsm_lchan *lchan); int gsm48_send_rr_release(struct gsm_lchan *lchan);
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id, int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id,

View File

@ -804,14 +804,14 @@ int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn)
return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ); return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
} }
static int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
{ {
DEBUGP(DMM, "-> CM SERVICE ACK\n"); DEBUGP(DMM, "-> CM SERVICE ACK\n");
return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC); return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
} }
/* 9.2.6 CM service reject */ /* 9.2.6 CM service reject */
static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
enum gsm48_reject_value value) enum gsm48_reject_value value)
{ {
struct msgb *msg; struct msgb *msg;

View File

@ -16,5 +16,7 @@ osmo_bsc_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
$(top_builddir)/src/libcommon/libcommon.a \ $(top_builddir)/src/libcommon/libcommon.a \
$(top_builddir)/src/libctrl/libctrl.a \ $(top_builddir)/src/libctrl/libctrl.a \
$(top_builddir)/src/libcommon/libcommon.a \ $(top_builddir)/src/libcommon/libcommon.a \
$(LIBOSMOSCCP_LIBS) $(LIBOSMOCORE_LIBS) \ -ldbi -ldl $(LIBOSMOSCCP_LIBS) \
$(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS) $(LIBOSMOABIS_LIBS) $(LIBSMPP34_LIBS) $(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS) \
$(LIBOSMOABIS_LIBS)

View File

@ -87,8 +87,8 @@ static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
queue_msg_or_return(resp); queue_msg_or_return(resp);
} }
static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn, static void bsc_send_ussd_no_srv(struct gsm_subscriber_connection *conn,
struct msgb *msg, const char *text) struct msgb *msg, const char *text)
{ {
struct gsm48_hdr *gh; struct gsm48_hdr *gh;
int8_t pdisc; int8_t pdisc;
@ -119,10 +119,14 @@ static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn,
} }
if (drop_message) { if (drop_message) {
LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n", text); LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n",
text);
return; return;
} }
LOGP(DMSC, LOGL_INFO, "Sending CM Service Accept\n");
gsm48_tx_mm_serv_ack(conn);
LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text); LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text);
gsm0480_send_ussdNotify(conn, 1, text); gsm0480_send_ussdNotify(conn, 1, text);
gsm0480_send_releaseComplete(conn); gsm0480_send_releaseComplete(conn);
@ -143,7 +147,8 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
msc = bsc_find_msc(conn, msg); msc = bsc_find_msc(conn, msg);
if (!msc) { if (!msc) {
LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n"); LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n");
bsc_send_ussd_notification(conn, msg, conn->bts->network->bsc_data->ussd_no_msc_txt); bsc_send_ussd_no_srv(conn, msg,
conn->bts->network->bsc_data->ussd_no_msc_txt);
return -1; return -1;
} }
@ -164,9 +169,9 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
if (ret != BSC_CON_SUCCESS) { if (ret != BSC_CON_SUCCESS) {
/* allocation has failed */ /* allocation has failed */
if (ret == BSC_CON_REJECT_NO_LINK) if (ret == BSC_CON_REJECT_NO_LINK)
bsc_send_ussd_notification(conn, msg, msc->ussd_msc_lost_txt); bsc_send_ussd_no_srv(conn, msg, msc->ussd_msc_lost_txt);
else if (ret == BSC_CON_REJECT_RF_GRACE) else if (ret == BSC_CON_REJECT_RF_GRACE)
bsc_send_ussd_notification(conn, msg, msc->ussd_grace_txt); bsc_send_ussd_no_srv(conn, msg, msc->ussd_grace_txt);
return BSC_API_CONN_POL_REJECT; return BSC_API_CONN_POL_REJECT;
} }