aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/osmo_bsc.h11
-rw-r--r--openbsc/include/openbsc/osmo_msc_data.h6
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_api.c58
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sccp.c14
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_vty.c73
-rw-r--r--openbsc/tests/vty_test_runner.py35
6 files changed, 184 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/osmo_bsc.h b/openbsc/include/openbsc/osmo_bsc.h
index 1d216ac25..1032daa69 100644
--- a/openbsc/include/openbsc/osmo_bsc.h
+++ b/openbsc/include/openbsc/osmo_bsc.h
@@ -7,6 +7,13 @@
#define BSS_SEND_USSD 1
+enum bsc_con {
+ BSC_CON_SUCCESS,
+ BSC_CON_REJECT_NO_LINK,
+ BSC_CON_REJECT_RF_GRACE,
+ BSC_CON_NO_MEM,
+};
+
struct sccp_connection;
struct osmo_msc_data;
struct bsc_msc_connection;
@@ -34,8 +41,8 @@ struct bsc_api *osmo_bsc_api();
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
-int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
- struct osmo_msc_data *msc);
+enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
+ struct osmo_msc_data *msc);
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *);
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index 86b4a8455..9c312ca8d 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -86,6 +86,9 @@ struct osmo_msc_data {
/* ussd msc connection lost text */
char *ussd_msc_lost_txt;
+
+ /* ussd text when MSC has entered the grace period */
+ char *ussd_grace_txt;
};
/*
@@ -103,6 +106,9 @@ struct osmo_bsc_data {
char *rf_ctrl_name;
struct osmo_bsc_rf *rf_ctrl;
int auto_off_timeout;
+
+ /* ussd text when there is no MSC available */
+ char *ussd_no_msc_txt;
};
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index df8c0444f..675bbb20e 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -21,6 +21,8 @@
#include <openbsc/osmo_msc_data.h>
#include <openbsc/debug.h>
+#include <openbsc/gsm_04_80.h>
+
#include <osmocom/gsm/protocol/gsm_08_08.h>
#include <osmocom/gsm/gsm0808.h>
@@ -85,6 +87,47 @@ static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
queue_msg_or_return(resp);
}
+static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, const char *text)
+{
+ struct gsm48_hdr *gh;
+ int8_t pdisc;
+ uint8_t mtype;
+ int drop_message = 1;
+
+ if (!text)
+ return;
+
+ if (!msg || msgb_l3len(msg) < sizeof(*gh))
+ return;
+
+ gh = msgb_l3(msg);
+ pdisc = gh->proto_discr & 0x0f;
+ mtype = gh->msg_type & 0xbf;
+
+ /* Is CM service request? */
+ if (pdisc == GSM48_PDISC_MM && mtype == GSM48_MT_MM_CM_SERV_REQ) {
+ struct gsm48_service_request *cm;
+
+ cm = (struct gsm48_service_request *) &gh->data[0];
+
+ /* Is type SMS or call? */
+ if (cm->cm_service_type == GSM48_CMSERV_SMS)
+ drop_message = 0;
+ else if (cm->cm_service_type == GSM48_CMSERV_MO_CALL_PACKET)
+ drop_message = 0;
+ }
+
+ if (drop_message) {
+ LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n", text);
+ return;
+ }
+
+ LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text);
+ gsm0480_send_ussdNotify(conn, 1, text);
+ gsm0480_send_releaseComplete(conn);
+}
+
/*
* Instruct to reserve data for a new connectiom, create the complete
* layer three message, send it to open the connection.
@@ -100,6 +143,7 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
msc = bsc_find_msc(conn, msg);
if (!msc) {
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);
return -1;
}
@@ -112,10 +156,22 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
struct msgb *resp;
uint16_t network_code;
uint16_t country_code;
+ enum bsc_con ret;
/* allocate resource for a new connection */
- if (bsc_create_new_connection(conn, msc) != 0)
+ ret = bsc_create_new_connection(conn, msc);
+
+ if (ret != BSC_CON_SUCCESS) {
+ /* allocation has failed */
+ if (ret == BSC_CON_REJECT_NO_LINK)
+ bsc_send_ussd_notification(conn, msg, msc->ussd_msc_lost_txt);
+ else if (ret == BSC_CON_REJECT_RF_GRACE)
+ bsc_send_ussd_notification(conn, msg, msc->ussd_grace_txt);
+
return BSC_API_CONN_POL_REJECT;
+ }
+
+ /* check return value, if failed check msg for and send USSD */
network_code = get_network_code_for_msc(conn->sccp_con->msc);
country_code = get_country_code_for_msc(conn->sccp_con->msc);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
index 87f415e0b..aa8c79ca6 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
@@ -188,35 +188,35 @@ int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
return 0;
}
-int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
+enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
struct osmo_msc_data *msc)
{
struct osmo_bsc_sccp_con *bsc_con;
struct sccp_connection *sccp;
/* This should not trigger */
- if (!msc->msc_con->is_authenticated) {
+ if (!msc || !msc->msc_con->is_authenticated) {
LOGP(DMSC, LOGL_ERROR,
"How did this happen? MSC is not connected. Dropping.\n");
- return -1;
+ return BSC_CON_REJECT_NO_LINK;
}
if (!bsc_grace_allow_new_connection(conn->bts->network, conn->bts)) {
LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
- return -1;
+ return BSC_CON_REJECT_RF_GRACE;
}
sccp = sccp_connection_socket();
if (!sccp) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate memory.\n");
- return -ENOMEM;
+ return BSC_CON_NO_MEM;
}
bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
if (!bsc_con) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate.\n");
sccp_connection_free(sccp);
- return -1;
+ return BSC_CON_NO_MEM;
}
/* callbacks */
@@ -237,7 +237,7 @@ int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
bsc_con->conn = conn;
llist_add_tail(&bsc_con->entry, &active_connections);
conn->sccp_con = bsc_con;
- return 0;
+ return BSC_CON_SUCCESS;
}
int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 90b0a0cd8..fceaa4ad6 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -122,6 +122,11 @@ static void write_msc(struct vty *vty, struct osmo_msc_data *msc)
else
vty_out(vty, " no bsc-msc-lost-text%s", VTY_NEWLINE);
+ if (msc->ussd_grace_txt && msc->ussd_grace_txt[0])
+ vty_out(vty, " bsc-grace-text %s%s", msc->ussd_grace_txt, VTY_NEWLINE);
+ else
+ vty_out(vty, " no bsc-grace-text%s", VTY_NEWLINE);
+
if (msc->audio_length != 0) {
int i;
@@ -182,6 +187,11 @@ static int config_write_bsc(struct vty *vty)
vty_out(vty, " bsc-auto-rf-off %d%s",
bsc->auto_off_timeout, VTY_NEWLINE);
+ if (bsc->ussd_no_msc_txt && bsc->ussd_no_msc_txt[0])
+ vty_out(vty, " missing-msc-text %s%s", bsc->ussd_no_msc_txt, VTY_NEWLINE);
+ else
+ vty_out(vty, " no missing-msc-text%s", VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -384,7 +394,7 @@ DEFUN(cfg_net_msc_no_welcome_ussd,
struct osmo_msc_data *data = osmo_msc_data(vty);
talloc_free(data->ussd_welcome_txt);
- data->ussd_welcome_txt = 0;
+ data->ussd_welcome_txt = NULL;
return CMD_SUCCESS;
}
@@ -417,6 +427,63 @@ DEFUN(cfg_net_msc_no_lost_ussd,
return CMD_SUCCESS;
}
+DEFUN(cfg_net_msc_grace_ussd,
+ cfg_net_msc_grace_ussd_cmd,
+ "bsc-grace-text .TEXT",
+ "Set the USSD notification to be sent when the MSC has entered the grace period\n" "Text to be sent\n")
+{
+ struct osmo_msc_data *data = osmo_msc_data(vty);
+ char *str = argv_concat(argv, argc, 0);
+ if (!str)
+ return CMD_WARNING;
+
+ bsc_replace_string(osmo_bsc_data(vty), &data->ussd_grace_txt, str);
+ talloc_free(str);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_msc_no_grace_ussd,
+ cfg_net_msc_no_grace_ussd_cmd,
+ "no bsc-grace-text",
+ NO_STR "Clear the USSD notification to be sent when the MSC has entered the grace period\n")
+{
+ struct osmo_msc_data *data = osmo_msc_data(vty);
+
+ talloc_free(data->ussd_grace_txt);
+ data->ussd_grace_txt = NULL;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_bsc_missing_msc_ussd,
+ cfg_net_bsc_missing_msc_ussd_cmd,
+ "missing-msc-text .TEXT",
+ "Set the USSD notification to be send when a MSC has not been found.\n" "Text to be sent\n")
+{
+ struct osmo_bsc_data *data = osmo_bsc_data(vty);
+ char *txt = argv_concat(argv, argc, 0);
+ if (!txt)
+ return CMD_WARNING;
+
+ bsc_replace_string(data, &data->ussd_no_msc_txt, txt);
+ talloc_free(txt);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_bsc_no_missing_msc_text,
+ cfg_net_bsc_no_missing_msc_text_cmd,
+ "no missing-msc-text",
+ NO_STR "Clear the USSD notification to be send when a MSC has not been found.\n")
+{
+ struct osmo_bsc_data *data = osmo_bsc_data(vty);
+
+ talloc_free(data->ussd_no_msc_txt);
+ data->ussd_no_msc_txt = 0;
+
+ return CMD_SUCCESS;
+}
+
+
DEFUN(cfg_net_msc_type,
cfg_net_msc_type_cmd,
"type (normal|local)",
@@ -615,6 +682,8 @@ int bsc_vty_init_extra(void)
install_element(BSC_NODE, &cfg_net_rf_socket_cmd);
install_element(BSC_NODE, &cfg_net_rf_off_time_cmd);
install_element(BSC_NODE, &cfg_net_no_rf_off_time_cmd);
+ install_element(BSC_NODE, &cfg_net_bsc_missing_msc_ussd_cmd);
+ install_element(BSC_NODE, &cfg_net_bsc_no_missing_msc_text_cmd);
install_node(&msc_node, config_write_msc);
bsc_install_default(MSC_NODE);
@@ -631,6 +700,8 @@ int bsc_vty_init_extra(void)
install_element(MSC_NODE, &cfg_net_msc_no_welcome_ussd_cmd);
install_element(MSC_NODE, &cfg_net_msc_lost_ussd_cmd);
install_element(MSC_NODE, &cfg_net_msc_no_lost_ussd_cmd);
+ install_element(MSC_NODE, &cfg_net_msc_grace_ussd_cmd);
+ install_element(MSC_NODE, &cfg_net_msc_no_grace_ussd_cmd);
install_element(MSC_NODE, &cfg_net_msc_type_cmd);
install_element(MSC_NODE, &cfg_net_msc_emerg_cmd);
install_element(MSC_NODE, &cfg_net_msc_local_prefix_cmd);
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index ab9670ce0..460b70e77 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -207,7 +207,7 @@ class TestVTYBSC(TestVTYGenericBSC):
self.vty.command("msc 0")
self.assertEquals(self.vty.node(), 'config-msc')
- def testUssdNotifications(self):
+ def testUssdNotificationsMsc(self):
self.vty.enable()
self.vty.command("configure terminal")
self.vty.command("msc")
@@ -215,10 +215,12 @@ class TestVTYBSC(TestVTYGenericBSC):
# Test invalid input
self.vty.verify("bsc-msc-lost-text", ['% Command incomplete.'])
self.vty.verify("bsc-welcome-text", ['% Command incomplete.'])
+ self.vty.verify("bsc-grace-text", ['% Command incomplete.'])
# Enable USSD notifications
self.vty.verify("bsc-msc-lost-text MSC disconnected", [''])
self.vty.verify("bsc-welcome-text Hello MS", [''])
+ self.vty.verify("bsc-grace-text In grace period", [''])
# Verify settings
res = self.vty.command("write terminal")
@@ -226,17 +228,46 @@ class TestVTYBSC(TestVTYGenericBSC):
self.assertEquals(res.find('no bsc-msc-lost-text'), -1)
self.assert_(res.find('bsc-welcome-text Hello MS') > 0)
self.assertEquals(res.find('no bsc-welcome-text'), -1)
+ self.assert_(res.find('bsc-grace-text In grace period') > 0)
+ self.assertEquals(res.find('no bsc-grace-text'), -1)
# Now disable it..
self.vty.verify("no bsc-msc-lost-text", [''])
self.vty.verify("no bsc-welcome-text", [''])
+ self.vty.verify("no bsc-grace-text", [''])
# Verify settings
res = self.vty.command("write terminal")
self.assertEquals(res.find('bsc-msc-lost-text MSC disconnected'), -1)
self.assert_(res.find('no bsc-msc-lost-text') > 0)
- self.assert_(res.find('no bsc-welcome-text') > 0)
self.assertEquals(res.find('bsc-welcome-text Hello MS'), -1)
+ self.assert_(res.find('no bsc-welcome-text') > 0)
+ self.assertEquals(res.find('bsc-grace-text In grace period'), -1)
+ self.assert_(res.find('no bsc-grace-text') > 0)
+
+ def testUssdNotificationsBsc(self):
+ self.vty.enable()
+ self.vty.command("configure terminal")
+ self.vty.command("bsc")
+
+ # Test invalid input
+ self.vty.verify("missing-msc-text", ['% Command incomplete.'])
+
+ # Enable USSD notifications
+ self.vty.verify("missing-msc-text No MSC found", [''])
+
+ # Verify settings
+ res = self.vty.command("write terminal")
+ self.assert_(res.find('missing-msc-text No MSC found') > 0)
+ self.assertEquals(res.find('no missing-msc-text'), -1)
+
+ # Now disable it..
+ self.vty.verify("no missing-msc-text", [''])
+
+ # Verify settings
+ res = self.vty.command("write terminal")
+ self.assertEquals(res.find('missing-msc-text No MSC found'), -1)
+ self.assert_(res.find('no missing-msc-text') > 0)
class TestVTYNAT(TestVTYGenericBSC):