blob: 32e8e23e09bb63d1354dfef4685a802c815cf292 [file] [log] [blame]
Harald Welte8c8f7912009-10-26 20:42:55 +01001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
Harald Welte6eafe912009-10-16 08:32:58 +02002 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther680833e2010-07-25 18:08:53 +08005 * (C) 2008, 2009, 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte6eafe912009-10-16 08:32:58 +02006 * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
7 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +010011 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
Harald Welte6eafe912009-10-16 08:32:58 +020013 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * GNU Affero General Public License for more details.
Harald Welte6eafe912009-10-16 08:32:58 +020019 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010020 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte6eafe912009-10-16 08:32:58 +020022 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30
Neels Hofmeyr90843962017-09-04 15:04:35 +020031#include <osmocom/msc/debug.h>
32#include <osmocom/msc/gsm_data.h>
33#include <osmocom/msc/gsm_04_08.h>
34#include <osmocom/msc/gsm_04_80.h>
35#include <osmocom/msc/msc_ifaces.h>
Harald Welte6eafe912009-10-16 08:32:58 +020036
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010037#include <osmocom/gsm/gsm0480.h>
38#include <osmocom/gsm/gsm_utils.h>
39#include <osmocom/core/msgb.h>
40#include <osmocom/gsm/tlv.h>
Holger Hans Peter Freytherc0714b82010-09-30 18:48:28 +080041
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020042static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
Harald Welte6eafe912009-10-16 08:32:58 +020043{
Holger Hans Peter Freytherac30cc82010-07-26 19:08:59 +080044 uint8_t *data = msgb_push(msgb, 2);
45
46 data[0] = tag;
Holger Hans Peter Freythere6373b72010-07-27 01:25:59 +080047 data[1] = msgb->len - 2;
Holger Hans Peter Freytherac30cc82010-07-26 19:08:59 +080048 return data;
Harald Welte6eafe912009-10-16 08:32:58 +020049}
50
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020051static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
52 uint8_t value)
Harald Welte6eafe912009-10-16 08:32:58 +020053{
Holger Hans Peter Freytherac30cc82010-07-26 19:08:59 +080054 uint8_t *data = msgb_push(msgb, 3);
55
56 data[0] = tag;
57 data[1] = 1;
58 data[2] = value;
59 return data;
Harald Welte6eafe912009-10-16 08:32:58 +020060}
61
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +070062static inline unsigned char *msgb_push_NULL(struct msgb *msgb)
63{
64 uint8_t *data = msgb_push(msgb, 2);
Harald Welte6eafe912009-10-16 08:32:58 +020065
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +070066 data[0] = ASN1_NULL_TYPE_TAG;
67 data[1] = 0;
68 return data;
69}
70
71
72/*! Send a MT RELEASE COMPLETE message with USSD-response,
73 * wrapped into the ReturnResult component (see section 3.6.1).
74 *
75 * \param[in] conn Active subscriber connection
76 * \param[in] transaction_id Transaction ID with TI flag set
77 * \param[in] invoke_id InvokeID of the request
78 * \param[in] response_text The response text
79 * \return result of \ref msc_tx_dtap
80 */
Holger Hans Peter Freytherd42c3f22010-06-17 17:35:57 +080081int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +070082 uint8_t transaction_id, uint8_t invoke_id,
83 const char *response_text)
Harald Welte6eafe912009-10-16 08:32:58 +020084{
Holger Hans Peter Freyther8239e062016-01-25 22:03:25 +010085 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP");
Harald Welte6eafe912009-10-16 08:32:58 +020086 struct gsm48_hdr *gh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020087 uint8_t *ptr8;
Harald Welte6eafe912009-10-16 08:32:58 +020088 int response_len;
89
Harald Welte6eafe912009-10-16 08:32:58 +020090 /* First put the payload text into the message */
Holger Hans Peter Freytherba81ab32010-07-26 17:56:55 +080091 ptr8 = msgb_put(msg, 0);
Holger Hans Peter Freyther1f229b32013-12-26 22:17:45 +010092 gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), response_text, &response_len);
Holger Hans Peter Freytherba81ab32010-07-26 17:56:55 +080093 msgb_put(msg, response_len);
Harald Welte6eafe912009-10-16 08:32:58 +020094
95 /* Then wrap it as an Octet String */
96 msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG);
97
98 /* Pre-pend the DCS octet string */
99 msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F);
100
101 /* Then wrap these as a Sequence */
102 msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
103
104 /* Pre-pend the operation code */
Harald Welte6307b852009-10-16 08:41:51 +0200105 msgb_push_TLV1(msg, GSM0480_OPERATION_CODE,
106 GSM0480_OP_CODE_PROCESS_USS_REQ);
Harald Welte6eafe912009-10-16 08:32:58 +0200107
108 /* Wrap the operation code and IA5 string as a sequence */
109 msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
110
111 /* Pre-pend the invoke ID */
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700112 msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
Harald Welte6eafe912009-10-16 08:32:58 +0200113
114 /* Wrap this up as a Return Result component */
115 msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
116
117 /* Wrap the component in a Facility message */
118 msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
119
120 /* And finally pre-pend the L3 header */
121 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700122 gh->proto_discr = GSM48_PDISC_NC_SS;
123 gh->proto_discr |= transaction_id << 4;
Harald Welte6eafe912009-10-16 08:32:58 +0200124 gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
125
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200126 return msc_tx_dtap(conn, msg);
Harald Welte6eafe912009-10-16 08:32:58 +0200127}
128
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700129/*! Send a MT RELEASE COMPLETE message with ReturnError component
130 * (see section 3.6.1) and given error code (see section 3.6.6).
131 *
132 * \param[in] conn Active subscriber connection
133 * \param[in] transaction_id Transaction ID with TI flag set
134 * \param[in] invoke_id InvokeID of the request
135 * \param[in] error_code Error code (section 4.5)
136 * \return result of \ref msc_tx_dtap
137 */
Vadim Yanitskiy635f98c2018-06-08 17:13:44 +0700138int gsm0480_send_ussd_return_error(struct gsm_subscriber_connection *conn,
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700139 uint8_t transaction_id, uint8_t invoke_id, uint8_t error_code)
Vadim Yanitskiy635f98c2018-06-08 17:13:44 +0700140{
141 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD ERR");
142 struct gsm48_hdr *gh;
143
144 /* First insert the problem code */
145 msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code);
146
147 /* Before it insert the invoke ID */
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700148 msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
Vadim Yanitskiy635f98c2018-06-08 17:13:44 +0700149
150 /* Wrap this up as a Reject component */
151 msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_ERROR);
152
153 /* Wrap the component in a Facility message */
154 msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
155
156 /* And finally pre-pend the L3 header */
157 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700158 gh->proto_discr = GSM48_PDISC_NC_SS;
159 gh->proto_discr |= transaction_id << 4;
Vadim Yanitskiy635f98c2018-06-08 17:13:44 +0700160 gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
161
162 return msc_tx_dtap(conn, msg);
163}
164
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700165/*! Send a MT RELEASE COMPLETE message with Reject component
166 * (see section 3.6.1) and given error code (see section 3.6.7).
167 *
168 * \param[in] conn Active subscriber connection
169 * \param[in] transaction_id Transaction ID with TI flag set
170 * \param[in] invoke_id InvokeID of the request
171 * \param[in] problem_tag Problem code tag (table 3.13)
172 * \param[in] problem_code Problem code (tables 3.14-17)
173 * \return result of \ref msc_tx_dtap
174 *
175 * Note: if InvokeID is not available, e.g. when message parsing
176 * failed, any incorrect value can be passed (0x00 > x > 0xff), so
177 * the universal NULL-tag (see table 3.6) will be used instead.
178 */
Holger Hans Peter Freytherd42c3f22010-06-17 17:35:57 +0800179int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700180 uint8_t transaction_id, int invoke_id,
181 uint8_t problem_tag, uint8_t problem_code)
Harald Welte6eafe912009-10-16 08:32:58 +0200182{
Holger Hans Peter Freyther8239e062016-01-25 22:03:25 +0100183 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ");
Harald Welte6eafe912009-10-16 08:32:58 +0200184 struct gsm48_hdr *gh;
185
Harald Welte6eafe912009-10-16 08:32:58 +0200186 /* First insert the problem code */
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700187 msgb_push_TLV1(msg, problem_tag, problem_code);
Harald Welte6eafe912009-10-16 08:32:58 +0200188
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700189 /**
190 * If the Invoke ID is not available, Universal Null
191 * (table 3.9) with length = 0 shall be used.
192 */
193 if (invoke_id < 0 || invoke_id > 255)
194 msgb_push_NULL(msg);
195 else
196 msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
Harald Welte6eafe912009-10-16 08:32:58 +0200197
198 /* Wrap this up as a Reject component */
199 msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT);
200
201 /* Wrap the component in a Facility message */
202 msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
203
204 /* And finally pre-pend the L3 header */
205 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
Vadim Yanitskiy5df4e4d2018-06-12 08:03:53 +0700206 gh->proto_discr = GSM48_PDISC_NC_SS;
207 gh->proto_discr |= transaction_id << 4;
Harald Welte6eafe912009-10-16 08:32:58 +0200208 gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
209
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200210 return msc_tx_dtap(conn, msg);
Harald Welte6eafe912009-10-16 08:32:58 +0200211}
Holger Hans Peter Freytherdaf75342010-07-26 20:01:07 +0800212
Neels Hofmeyr43273c62016-05-10 12:50:31 +0200213int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level, const char *text)
Holger Hans Peter Freytherdaf75342010-07-26 20:01:07 +0800214{
Neels Hofmeyr43273c62016-05-10 12:50:31 +0200215 struct msgb *msg = gsm0480_create_ussd_notify(level, text);
Holger Hans Peter Freytherdaf75342010-07-26 20:01:07 +0800216 if (!msg)
217 return -1;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200218 return msc_tx_dtap(conn, msg);
Holger Hans Peter Freytherdaf75342010-07-26 20:01:07 +0800219}
Holger Hans Peter Freyther68d26792010-07-27 03:31:50 +0800220
Neels Hofmeyr43273c62016-05-10 12:50:31 +0200221int msc_send_ussd_release_complete(struct gsm_subscriber_connection *conn)
Holger Hans Peter Freyther68d26792010-07-27 03:31:50 +0800222{
Neels Hofmeyr43273c62016-05-10 12:50:31 +0200223 struct msgb *msg = gsm0480_create_ussd_release_complete();
Holger Hans Peter Freyther68d26792010-07-27 03:31:50 +0800224 if (!msg)
225 return -1;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200226 return msc_tx_dtap(conn, msg);
Holger Hans Peter Freyther68d26792010-07-27 03:31:50 +0800227}