aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Engel <tobias@ccc.de>2012-03-22 15:07:29 +0100
committerTobias Engel <tobias@ccc.de>2012-03-22 15:16:17 +0100
commit7d8ff3113c466e40466a311163b0caf98f8c8f72 (patch)
tree66b38a3e9136dfa05fb5f0f9f5eed4014e6d6204
parent2f2be578cbda0f3cecaf72058502e5780ad2f4cb (diff)
Supplementary Services (de)activation and interrogation
These patches enhance the Supplementary Service (SS) processing from only being able to handle USSD to other SS, specifically activation, deactivation and interrogation of those SS. Registration is not yet implemented. The HLR db now includes a table SS_Status which contains fields for the SS code (GSM 09.02 17.7.5), basic service code (17.7.9 and 17.7.10) and SS status bits (17.7.4) and references the subscriber. db.c supports interrogating and setting the SS status with the functions db_ss_interrogate_status and db_ss_set_status. No automatic provisioning takes place. To do so, a record has to be added to the db referencing the subscriber and containing the desired SS code, BS code and having the 'P' bit in the SS status set to one. All occurrences of "ussd" have been replaced with "ss" where the corresponding file/function/variable deals not exclusively with USSD requests. ussd.c and ussd.h have been renamed to ss.c and ss.h. msgb_wrap_with_TL and msgb_push_TLV1 were removed from gsm_04_80.c and are now exported by libosmocore. gsm0480_send_ss_return_result has been added to gsm_04_80.c. It takes a msgb as an argument which has to already contain the ASN.1 formatted Return Result minus the operation code and invoke id. change_ss_activation and interrogate_ss have been added to ss.c (formerly ussd.c). Currently, (de)activation and interrogation of SS will always be handled as if it was requested for the Telephony teleservice, no matter what was requested by the subscriber. Also, sending a Return Error has not been implemented yet (Reject is used instead).
-rw-r--r--openbsc/include/openbsc/Makefile.am2
-rw-r--r--openbsc/include/openbsc/db.h4
-rw-r--r--openbsc/include/openbsc/gsm_04_80.h15
-rw-r--r--openbsc/include/openbsc/ss.h10
-rw-r--r--openbsc/include/openbsc/ussd.h10
-rw-r--r--openbsc/src/libmsc/Makefile.am2
-rw-r--r--openbsc/src/libmsc/db.c89
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c4
-rw-r--r--openbsc/src/libmsc/gsm_04_80.c65
-rw-r--r--openbsc/src/libmsc/ss.c173
-rw-r--r--openbsc/src/libmsc/ussd.c79
11 files changed, 328 insertions, 125 deletions
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 8e64ff8d3..8ff6be844 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -2,7 +2,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
gsm_subscriber.h gsm_04_11.h debug.h signal.h \
misdn.h chan_alloc.h paging.h \
trau_mux.h rs232.h openbscdefines.h rtp_proxy.h \
- bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \
+ bsc_rll.h mncc.h transaction.h ss.h gsm_04_80.h \
silent_call.h mgcp.h meas_rep.h rest_octets.h \
system_information.h handover.h mgcp_internal.h \
vty.h socket.h e1_config.h trau_upqueue.h token_auth.h \
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index d0c85ea30..e6b101f69 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -78,4 +78,8 @@ int db_store_counter(struct osmo_counter *ctr);
struct rate_ctr_group;
int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
+/* Supplementary Services */
+int db_ss_interrogate_status(struct gsm_subscriber *subscr, uint8_t ss_code, uint8_t bs_code, uint8_t *ss_status);
+int db_ss_set_status(struct gsm_subscriber *subscr, uint8_t ss_code, uint8_t bs_code, uint8_t ss_status);
+
#endif /* _DB_H */
diff --git a/openbsc/include/openbsc/gsm_04_80.h b/openbsc/include/openbsc/gsm_04_80.h
index 0a6065234..ea5033564 100644
--- a/openbsc/include/openbsc/gsm_04_80.h
+++ b/openbsc/include/openbsc/gsm_04_80.h
@@ -3,16 +3,21 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/protocol/gsm_04_80.h>
+#include <osmocom/gsm/protocol/gsm_09_02.h>
#include <osmocom/gsm/gsm0480.h>
struct gsm_subscriber_connection;
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
- const struct msgb *in_msg, const char* response_text,
- const struct ussd_request *req);
-int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
- const struct msgb *msg,
- const struct ussd_request *request);
+ const char* response_text,
+ const struct ss_request *req);
+int gsm0480_send_ss_return_result(struct gsm_subscriber_connection *conn,
+ const struct ss_request *req,
+ struct msgb *msg);
+int gsm0480_send_ss_reject(struct gsm_subscriber_connection *conn,
+ const struct ss_request *request,
+ uint8_t problem_category,
+ uint8_t problem_code);
int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text);
int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn);
diff --git a/openbsc/include/openbsc/ss.h b/openbsc/include/openbsc/ss.h
new file mode 100644
index 000000000..92ce913d3
--- /dev/null
+++ b/openbsc/include/openbsc/ss.h
@@ -0,0 +1,10 @@
+#ifndef _SS_H
+#define _SS_H
+
+/* Handler function for mobile-originated SS messages */
+
+#include <osmocom/core/msgb.h>
+
+int handle_rcv_ss(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+#endif
diff --git a/openbsc/include/openbsc/ussd.h b/openbsc/include/openbsc/ussd.h
deleted file mode 100644
index 266546811..000000000
--- a/openbsc/include/openbsc/ussd.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _USSD_H
-#define _USSD_H
-
-/* Handler function for mobile-originated USSD messages */
-
-#include <osmocom/core/msgb.h>
-
-int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
-
-#endif
diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am
index 4a1488df5..51cf131e7 100644
--- a/openbsc/src/libmsc/Makefile.am
+++ b/openbsc/src/libmsc/Makefile.am
@@ -13,7 +13,7 @@ libmsc_a_SOURCES = auth.c \
silent_call.c \
sms_queue.c \
token_auth.c \
- ussd.c \
+ ss.c \
vty_interface_layer3.c \
transaction.c \
osmo_msc.c
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index a7eeda4dc..a169b965f 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -38,6 +38,8 @@
#include <osmocom/core/statistics.h>
#include <osmocom/core/rate_ctr.h>
+#include <osmocom/gsm/protocol/gsm_09_02.h>
+
static char *db_basename = NULL;
static char *db_dirname = NULL;
static dbi_conn conn;
@@ -149,6 +151,15 @@ static char *create_stmts[] = {
"sres BLOB NOT NULL, "
"kc BLOB NOT NULL "
")",
+ "CREATE TABLE IF NOT EXISTS SS_Status ("
+ "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+ "subscriber INTEGER NOT NULL, "
+ "ss_code TINYINT UNSIGNED NOT NULL, "
+ "bs_code TINYINT UNSIGNED, "
+ "ss_status TINYINT UNSIGNED NOT NULL, "
+ "UNIQUE(subscriber, ss_code, bs_code), "
+ "FOREIGN KEY(subscriber) REFERENCES Subscriber (id) ON DELETE CASCADE ON UPDATE CASCADE "
+ ")",
};
void db_error_func(dbi_conn conn, void *data)
@@ -1299,3 +1310,81 @@ int db_store_rate_ctr_group(struct rate_ctr_group *ctrg)
return 0;
}
+
+int db_ss_interrogate_status(struct gsm_subscriber *subscr, uint8_t ss_code, uint8_t bs_code, uint8_t *ss_status)
+{
+ char buf[32];
+ dbi_result result;
+
+ /* Copy the id to a string as queryf with %llu is failing */
+ sprintf(buf, "%llu", subscr->id);
+ result = dbi_conn_queryf(conn,
+ "SELECT ss_status FROM SS_Status "
+ "WHERE subscriber = %s "
+ "AND ss_code = %i AND bs_code = %i",
+ buf, ss_code, bs_code);
+
+ if (!result) {
+ LOGP(DDB,
+ LOGL_ERROR,
+ "Failed to query ss_status for subscriber %llu, "
+ "ss code 0x%02X, bs code 0x%02X\n",
+ subscr->id, ss_code, bs_code);
+ return -EIO;
+ }
+ if (!dbi_result_next_row(result)) {
+ DEBUGP(DDB,
+ "Failed to find ss_status for subscriber %llu, "
+ "ss code 0x%02X, bs code 0x%02X\n",
+ subscr->id, ss_code, bs_code);
+ dbi_result_free(result);
+ return -ENOENT;
+ }
+
+ *ss_status = dbi_result_get_uint(result, "ss_status");
+ DEBUGP(DDB,
+ "Found ss_status for subscriber %llu, "
+ "ss code 0x%02X, bs code 0x%02X: P:%d R:%d A:%d Q:%d\n",
+ subscr->id, ss_code, bs_code,
+ (*ss_status & GSM0902_SS_STATUS_P_BIT) && 1,
+ (*ss_status & GSM0902_SS_STATUS_R_BIT) && 1,
+ (*ss_status & GSM0902_SS_STATUS_A_BIT) && 1,
+ (*ss_status & GSM0902_SS_STATUS_Q_BIT) && 1);
+
+ dbi_result_free(result);
+ return 0;
+}
+
+int db_ss_set_status(struct gsm_subscriber *subscr, uint8_t ss_code, uint8_t bs_code, uint8_t ss_status)
+{
+ char buf[32];
+ dbi_result result;
+
+ /* Copy the id to a string as queryf with %llu is failing */
+ sprintf(buf, "%llu", subscr->id);
+
+ result = dbi_conn_queryf(conn,
+ "UPDATE SS_Status SET ss_status = %i "
+ "WHERE subscriber = %s AND "
+ "ss_code = %i AND bs_code = %i",
+ ss_status, buf, ss_code, bs_code);
+
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to set ss_status for subscriber %llu\n",
+ subscr->id);
+ return -EIO;
+ }
+
+ DEBUGP(DDB,
+ "Set ss_status for subscriber %llu, "
+ "ss code 0x%02X, bs code 0x%02X: P:%d R:%d A:%d Q:%d\n",
+ subscr->id, ss_code, bs_code,
+ (ss_status & GSM0902_SS_STATUS_P_BIT) && 1,
+ (ss_status & GSM0902_SS_STATUS_R_BIT) && 1,
+ (ss_status & GSM0902_SS_STATUS_A_BIT) && 1,
+ (ss_status & GSM0902_SS_STATUS_Q_BIT) && 1);
+
+ dbi_result_free(result);
+ return 0;
+}
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 20a2cc502..0e18d0c1d 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -45,7 +45,7 @@
#include <openbsc/trau_mux.h>
#include <openbsc/rtp_proxy.h>
#include <openbsc/transaction.h>
-#include <openbsc/ussd.h>
+#include <openbsc/ss.h>
#include <openbsc/silent_call.h>
#include <openbsc/bsc_api.h>
#include <openbsc/osmo_msc.h>
@@ -3217,7 +3217,7 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
break;
case GSM48_PDISC_NC_SS:
release_anchor(conn);
- rc = handle_rcv_ussd(conn, msg);
+ rc = handle_rcv_ss(conn, msg);
break;
default:
LOGP(DRLL, LOGL_NOTICE, "Unknown "
diff --git a/openbsc/src/libmsc/gsm_04_80.c b/openbsc/src/libmsc/gsm_04_80.c
index 39738a5ee..85445dc59 100644
--- a/openbsc/src/libmsc/gsm_04_80.c
+++ b/openbsc/src/libmsc/gsm_04_80.c
@@ -39,31 +39,11 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
-static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
-{
- uint8_t *data = msgb_push(msgb, 2);
-
- data[0] = tag;
- data[1] = msgb->len - 2;
- return data;
-}
-
-static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
- uint8_t value)
-{
- uint8_t *data = msgb_push(msgb, 3);
-
- data[0] = tag;
- data[1] = 1;
- data[2] = value;
- return data;
-}
-
/* Send response to a mobile-originated ProcessUnstructuredSS-Request */
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
- const struct msgb *in_msg, const char *response_text,
- const struct ussd_request *req)
+ const char *response_text,
+ const struct ss_request *req)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
@@ -109,16 +89,47 @@ int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
return gsm0808_submit_dtap(conn, msg, 0, 0);
}
-int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
- const struct msgb *in_msg,
- const struct ussd_request *req)
+/* Send response to a mobile-originated Invoke */
+int gsm0480_send_ss_return_result(struct gsm_subscriber_connection *conn,
+ const struct ss_request *req,
+ struct msgb *msg)
+{
+ struct gsm48_hdr *gh;
+
+ /* Pre-pend the operation code */
+ msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode);
+
+ /* Wrap the contents as a sequence */
+ msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
+
+ /* Pre-pend the invoke ID */
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
+
+ /* Wrap this up as a Return Result component */
+ msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
+
+ /* Wrap the component in a Facility message */
+ msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
+
+ /* And finally pre-pend the L3 header */
+ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id
+ | (1<<7); /* TI direction = 1 */
+ gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
+
+ return gsm0808_submit_dtap(conn, msg, 0, 0);
+}
+
+int gsm0480_send_ss_reject(struct gsm_subscriber_connection *conn,
+ const struct ss_request *req,
+ uint8_t problem_category,
+ uint8_t problem_code)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
/* First insert the problem code */
- msgb_push_TLV1(msg, GSM_0480_PROBLEM_CODE_TAG_GENERAL,
- GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
+ msgb_push_TLV1(msg, problem_category, problem_code);
/* Before it insert the invoke ID */
msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
diff --git a/openbsc/src/libmsc/ss.c b/openbsc/src/libmsc/ss.c
new file mode 100644
index 000000000..44a01ec3a
--- /dev/null
+++ b/openbsc/src/libmsc/ss.c
@@ -0,0 +1,173 @@
+/* Network-specific handling of mobile-originated SSs. */
+
+/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
+ *
+ * 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/>.
+ *
+ */
+
+/* This module defines the network-specific handling of mobile-originated
+ SS messages. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <openbsc/db.h>
+#include <openbsc/gsm_04_80.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/debug.h>
+#include <openbsc/osmo_msc.h>
+
+/* Declarations of USSD strings to be recognised */
+const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
+
+/* Forward declarations of network-specific handler functions */
+static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ss_request *req);
+static int change_ss_activation(struct gsm_subscriber_connection *conn, uint8_t activate, const struct ss_request *req);
+static int interrogate_ss(struct gsm_subscriber_connection *conn, const struct ss_request *req);
+
+/* Entrypoint - handler function common to all mobile-originated SS */
+int handle_rcv_ss(struct gsm_subscriber_connection *conn, struct msgb *msg)
+{
+ int rc;
+ struct ss_request req;
+ struct gsm48_hdr *gh;
+ uint8_t activate;
+
+ memset(&req, 0, sizeof(req));
+ gh = msgb_l3(msg);
+ rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &req);
+
+ if (rc == 1) {
+
+ switch (req.opcode) {
+ case GSM0480_OP_CODE_PROCESS_USS_REQ:
+
+ if (req.ussd_text[0] == 0xFF) /* Release-Complete */
+ return 0;
+
+ if (!strcmp(USSD_TEXT_OWN_NUMBER,
+ (const char *)req.ussd_text)) {
+ DEBUGP(DMM, "USSD: Own number requested\n");
+ rc = send_own_number(conn, msg, &req);
+ } else {
+ DEBUGP(DMM, "Unhandled USSD %s\n", req.ussd_text);
+ rc = gsm0480_send_ss_reject(conn, &req,
+ GSM_0480_PROBLEM_CODE_TAG_INVOKE,
+ GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION);
+ }
+
+ break;
+
+ case GSM0480_OP_CODE_ACTIVATE_SS:
+ case GSM0480_OP_CODE_DEACTIVATE_SS:
+ activate = (req.opcode == GSM0480_OP_CODE_ACTIVATE_SS);
+ rc = change_ss_activation(conn, activate, &req);
+ break;
+ case GSM0480_OP_CODE_INTERROGATE_SS:
+ rc = interrogate_ss(conn, &req);
+ break;
+ default:
+ DEBUGP(DMM, "Unhandled SS opcode %d\n", req.opcode);
+ rc = gsm0480_send_ss_reject(conn, &req,
+ GSM_0480_PROBLEM_CODE_TAG_GENERAL,
+ GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
+ break;
+ }
+
+ } else {
+ rc = gsm0480_send_ss_reject(conn, &req,
+ GSM_0480_PROBLEM_CODE_TAG_GENERAL,
+ GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE);
+ }
+
+ /* check if we can release it */
+ msc_release_connection(conn);
+ return rc;
+}
+
+/* A network-specific handler function */
+static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ss_request *req)
+{
+ char *own_number = conn->subscr->extension;
+ char response_string[GSM_EXTENSION_LENGTH + 20];
+
+ /* Need trailing CR as EOT character */
+ snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
+ return gsm0480_send_ussd_response(conn, response_string, req);
+}
+
+static int change_ss_activation(struct gsm_subscriber_connection *conn, uint8_t activate, const struct ss_request *req)
+{
+ struct msgb *msg;
+ uint8_t ss_status;
+ int rc = db_ss_interrogate_status(conn->subscr,
+ req->ss_code,
+ GSM0902_TS_CODE_TELEPHONY,
+ &ss_status);
+
+ if(rc < 0 || !(ss_status & GSM0902_SS_STATUS_P_BIT)) {
+ DEBUGP(DMM, "SS 0x%02X not provisioned\n", req->ss_code);
+ return gsm0480_send_ss_reject(conn, req,
+ GSM_0480_PROBLEM_CODE_TAG_INVOKE,
+ GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION);
+ }
+
+ ss_status &= ~GSM0902_SS_STATUS_A_BIT;
+ ss_status |= (activate ? GSM0902_SS_STATUS_A_BIT : 0);
+
+ rc = db_ss_set_status(conn->subscr, req->ss_code,
+ GSM0902_TS_CODE_TELEPHONY, ss_status);
+ if(rc < 0)
+ return gsm0480_send_ss_reject(conn, req,
+ GSM_0480_PROBLEM_CODE_TAG_INVOKE,
+ GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION);
+
+ msg = gsm48_msgb_alloc();
+ /* First put the payload into the message */
+ msgb_push_TLV1(msg, GSM0902_SS_DATA_SS_STATUS_TAG, ss_status);
+ /* Then wrap it as a Sequence of type SS-Data */
+ msgb_wrap_with_TL(msg, GSM0902_SS_INFO_SS_DATA_TAG);
+
+ return gsm0480_send_ss_return_result(conn, req, msg);
+}
+
+static int interrogate_ss(struct gsm_subscriber_connection *conn, const struct ss_request *req)
+{
+ struct msgb *msg;
+ uint8_t ss_status;
+ int rc = db_ss_interrogate_status(conn->subscr,
+ req->ss_code,
+ GSM0902_TS_CODE_TELEPHONY,
+ &ss_status);
+
+ if(rc < 0 || !(ss_status & GSM0902_SS_STATUS_P_BIT)) {
+ DEBUGP(DMM, "SS 0x%02X not provisioned\n", req->ss_code);
+ return gsm0480_send_ss_reject(conn, req,
+ GSM_0480_PROBLEM_CODE_TAG_INVOKE,
+ GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION);
+ }
+
+ msg = gsm48_msgb_alloc();
+ /* Put the payload into the message */
+ msgb_push_TLV1(msg, GSM0902_SS_INTERR_SS_RES_SS_STATUS_TAG, ss_status);
+
+ return gsm0480_send_ss_return_result(conn, req, msg);
+}
diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c
deleted file mode 100644
index 76ee101a1..000000000
--- a/openbsc/src/libmsc/ussd.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Network-specific handling of mobile-originated USSDs. */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
- *
- * 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/>.
- *
- */
-
-/* This module defines the network-specific handling of mobile-originated
- USSD messages. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/osmo_msc.h>
-
-/* Declarations of USSD strings to be recognised */
-const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
-
-/* Forward declarations of network-specific handler functions */
-static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req);
-
-
-/* Entrypoint - handler function common to all mobile-originated USSDs */
-int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
- int rc;
- struct ussd_request req;
- struct gsm48_hdr *gh;
-
- memset(&req, 0, sizeof(req));
- gh = msgb_l3(msg);
- rc = gsm0480_decode_ussd_request(gh, msgb_l3len(msg), &req);
- if (req.text[0] == 0xFF) /* Release-Complete */
- return 0;
-
- if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.text)) {
- DEBUGP(DMM, "USSD: Own number requested\n");
- rc = send_own_number(conn, msg, &req);
- } else {
- DEBUGP(DMM, "Unhandled USSD %s\n", req.text);
- rc = gsm0480_send_ussd_reject(conn, msg, &req);
- }
-
- /* check if we can release it */
- msc_release_connection(conn);
- return rc;
-}
-
-/* A network-specific handler function */
-static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req)
-{
- char *own_number = conn->subscr->extension;
- char response_string[GSM_EXTENSION_LENGTH + 20];
-
- /* Need trailing CR as EOT character */
- snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
- return gsm0480_send_ussd_response(conn, msg, response_string, req);
-}