aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Engel <tobias@ccc.de>2012-03-22 15:07:29 +0100
committerHarald Welte <laforge@gnumonks.org>2015-01-01 14:34:34 +0100
commit33bc1716f435e81d837268cbb04ddf7487f14a32 (patch)
tree4da9bb8878ef5f91ecaffc588c2682ed9a84f8af
parentc83f0276b3d0e58b3c2187923f481026952b113b (diff)
SS: 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. 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.h35
-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.c66
-rw-r--r--openbsc/src/libmsc/ss.c173
-rw-r--r--openbsc/src/libmsc/ussd.c87
11 files changed, 348 insertions, 134 deletions
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 70365f2b3..3b0f2bcc9 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 ctrl.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 6699a8600..73c061bc7 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -79,4 +79,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..dc1c91120 100644
--- a/openbsc/include/openbsc/gsm_04_80.h
+++ b/openbsc/include/openbsc/gsm_04_80.h
@@ -3,16 +3,41 @@
#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>
+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;
+}
+
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 aa7d8ae99..de0ce66fe 100644
--- a/openbsc/src/libmsc/Makefile.am
+++ b/openbsc/src/libmsc/Makefile.am
@@ -16,7 +16,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 ctrl_commands.c meas_feed.c
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index bdecbb436..4acd76566 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>
+
/* Semi-Private-Interface (SPI) for the subscriber code */
void subscr_direct_free(struct gsm_subscriber *subscr);
@@ -174,6 +176,15 @@ static const 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)
@@ -1724,3 +1735,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 ce87ca025..037afb263 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -47,7 +47,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>
@@ -3357,7 +3357,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 b30f9ee5f..43c909bd9 100644
--- a/openbsc/src/libmsc/gsm_04_80.c
+++ b/openbsc/src/libmsc/gsm_04_80.c
@@ -39,31 +39,10 @@
#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 +88,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 7f01eae71..000000000
--- a/openbsc/src/libmsc/ussd.c
+++ /dev/null
@@ -1,87 +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 (!rc) {
- DEBUGP(DMM, "Unhandled SS\n");
- rc = gsm0480_send_ussd_reject(conn, msg, &req);
- msc_release_connection(conn);
- return rc;
- }
-
- /* Release-Complete */
- if (req.text[0] == '\0')
- 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);
-}