This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Max max.suraev at fairwaves.coSigned-off-by: Max <max.suraev at fairwaves.co> --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/db.h | 4 + openbsc/include/openbsc/gsm_04_80.h | 36 ++++++-- openbsc/include/openbsc/ss.h | 10 +++ openbsc/include/openbsc/ussd.h | 10 --- openbsc/src/libmsc/Makefile.am | 2 +- openbsc/src/libmsc/db.c | 89 +++++++++++++++++++ openbsc/src/libmsc/gsm_04_08.c | 4 +- openbsc/src/libmsc/gsm_04_80.c | 65 ++++++++------ openbsc/src/libmsc/ss.c | 173 ++++++++++++++++++++++++++++++++++++ openbsc/src/libmsc/ussd.c | 87 ------------------ 11 files changed, 349 insertions(+), 133 deletions(-) create mode 100644 openbsc/include/openbsc/ss.h delete mode 100644 openbsc/include/openbsc/ussd.h create mode 100644 openbsc/src/libmsc/ss.c delete mode 100644 openbsc/src/libmsc/ussd.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 254f43d..b19c413 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 6699a86..73c061b 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 0a60652..7139f95 100644 --- a/openbsc/include/openbsc/gsm_04_80.h +++ b/openbsc/include/openbsc/gsm_04_80.h @@ -3,16 +3,42 @@ #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; +/* FIXME: replace with libosmocore functions */ +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; +} + 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 0000000..92ce913 --- /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 2665468..0000000 --- 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 aa7d8ae..de0ce66 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 428f99b..25dd00e 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -41,6 +41,8 @@ /* Semi-Private-Interface (SPI) for the subscriber code */ void subscr_direct_free(struct gsm_subscriber *subscr); +#include <osmocom/gsm/protocol/gsm_09_02.h> + static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; @@ -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 29ab2ba..01f8f32 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> @@ -3340,7 +3340,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 b30f9ee..b20521a 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 0000000..44a01ec --- /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 at gnumonks.org> + * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke at selfish.org> + * (C) 2009 by Mike Haben <michael.haben at 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 7f01eae..0000000 --- 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 at gnumonks.org> - * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke at selfish.org> - * (C) 2009 by Mike Haben <michael.haben at 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); -} -- 2.1.4