blob: 6558272a86d43d03820ea4378604bf67d70c2dfd [file] [log] [blame]
Harald Welte6eafe912009-10-16 08:32:58 +02001/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
2 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +07004 * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
Harald Welte6eafe912009-10-16 08:32:58 +02005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Welte6eafe912009-10-16 08:32:58 +020011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Welte6eafe912009-10-16 08:32:58 +020017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte6eafe912009-10-16 08:32:58 +020020 *
21 */
22
Vadim Yanitskiy5b860fa2018-06-12 05:24:52 +070023/**
24 * MSC-specific handling of call independent Supplementary
25 * Services messages (NC_SS) according to GSM TS 09.11
26 * "Signalling interworking for supplementary services".
27 */
Harald Welte6eafe912009-10-16 08:32:58 +020028
29#include <stdio.h>
Harald Welte6eafe912009-10-16 08:32:58 +020030#include <errno.h>
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070031#include <stdbool.h>
32
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +070033#include <osmocom/core/linuxlist.h>
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +070034#include <osmocom/core/rate_ctr.h>
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070035#include <osmocom/core/utils.h>
36#include <osmocom/core/msgb.h>
Vadim Yanitskiy0622ef52018-08-03 04:39:04 +070037
38#include <osmocom/gsm/protocol/gsm_04_80.h>
39#include <osmocom/gsm/gsm0480.h>
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070040#include <osmocom/gsm/tlv.h>
Harald Welte6eafe912009-10-16 08:32:58 +020041
Neels Hofmeyr90843962017-09-04 15:04:35 +020042#include <osmocom/msc/gsm_04_80.h>
43#include <osmocom/msc/gsm_subscriber.h>
44#include <osmocom/msc/debug.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020045#include <osmocom/msc/vlr.h>
Max43b01b02017-09-15 11:22:30 +020046#include <osmocom/msc/gsm_04_08.h>
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070047#include <osmocom/msc/transaction.h>
Harald Welte1ea6baf2018-07-31 19:40:52 +020048#include <osmocom/gsupclient/gsup_client.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010049#include <osmocom/msc/msc_a.h>
50#include <osmocom/msc/msub.h>
51#include <osmocom/msc/paging.h>
52#include <osmocom/msc/gsup_client_mux.h>
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070053
54/* FIXME: choose a proper range */
55static uint32_t new_callref = 0x20000001;
Harald Welte6eafe912009-10-16 08:32:58 +020056
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070057static void ncss_session_timeout_handler(void *_trans)
58{
59 struct gsm_trans *trans = (struct gsm_trans *) _trans;
60 struct osmo_gsup_message gsup_msg = { 0 };
61
62 /* The timeout might be disabled from the VTY */
63 if (trans->net->ncss_guard_timeout == 0)
64 return;
65
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010066 LOG_TRANS(trans, LOGL_NOTICE, "SS/USSD session timeout, releasing\n");
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070067
68 /* Indicate connection release to subscriber (if active) */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010069 if (trans->msc_a != NULL) {
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070070 /* This pair of cause location and value is used by commercial networks */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010071 msc_send_ussd_release_complete_cause(trans->msc_a, trans->transaction_id,
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070072 GSM48_CAUSE_LOC_PUN_S_LU, GSM48_CC_CAUSE_NORMAL_UNSPEC);
73 }
74
75 /* Terminate GSUP session with EUSE */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010076 gsup_msg = (struct osmo_gsup_message){
77 .message_type = OSMO_GSUP_MSGT_PROC_SS_ERROR,
78
79 .session_state = OSMO_GSUP_SESSION_STATE_END,
80 .session_id = trans->callref,
81 .cause = GMM_CAUSE_NET_FAIL,
82
83 .message_class = OSMO_GSUP_MESSAGE_CLASS_USSD,
84 };
85
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070086 OSMO_STRLCPY_ARRAY(gsup_msg.imsi, trans->vsub->imsi);
87
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010088 gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070089
90 /* Finally, release this transaction */
91 trans_free(trans);
92}
93
Vadim Yanitskiy5b860fa2018-06-12 05:24:52 +070094/* Entry point for call independent MO SS messages */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010095int gsm0911_rcv_nc_ss(struct msc_a *msc_a, struct msgb *msg)
Harald Welte6eafe912009-10-16 08:32:58 +020096{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010097 struct gsm_network *net;
98 struct vlr_subscr *vsub;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070099 struct gsm48_hdr *gh = msgb_l3(msg);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700100 struct osmo_gsup_message gsup_msg;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700101 struct gsm_trans *trans;
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700102 uint16_t facility_ie_len;
103 uint8_t *facility_ie;
Max4a5cfa52019-01-10 17:41:05 +0100104 uint8_t tid;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700105 uint8_t msg_type;
106 int rc;
Harald Welte6eafe912009-10-16 08:32:58 +0200107
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100108 net = msc_a_net(msc_a);
109 OSMO_ASSERT(net);
110
111 vsub = msc_a_vsub(msc_a);
112 if (!vsub) {
113 LOG_MSC_A(msc_a, LOGL_ERROR, "No vlr_subscr set for this conn\n");
114 return -EINVAL;
115 }
116
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700117 msg_type = gsm48_hdr_msg_type(gh);
118 tid = gsm48_hdr_trans_id_flip_ti(gh);
Harald Welte2483f1b2016-06-19 18:06:02 +0200119
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700120 /* Associate logging messages with this subscriber */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100121 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700122
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700123 /* Reuse existing transaction, or create a new one */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100124 trans = trans_find_by_id(msc_a, TRANS_USSD, tid);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700125 if (!trans) {
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700126 /* Count MS-initiated attempts to establish a NC SS/USSD session */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100127 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS]);
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700128
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700129 /**
130 * According to GSM TS 04.80, section 2.4.2 "Register
131 * (mobile station to network direction)", the REGISTER
132 * message is sent by the mobile station to the network
133 * to assign a new transaction identifier for call independent
134 * supplementary service control and to request or acknowledge
135 * a supplementary service.
136 */
137 if (msg_type != GSM0480_MTYPE_REGISTER) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100138 LOG_TRANS(trans, LOGL_ERROR, "Rx wrong SS/USSD message type for new transaction: %s\n",
139 gsm48_pdisc_msgtype_name(GSM48_PDISC_NC_SS, msg_type));
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100140 gsm48_tx_simple(msc_a,
Vadim Yanitskiy9aec25e2018-06-12 06:26:28 +0700141 GSM48_PDISC_NC_SS | (tid << 4),
142 GSM0480_MTYPE_RELEASE_COMPLETE);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700143 return -EINVAL;
144 }
145
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100146 trans = trans_alloc(net, vsub, TRANS_USSD, tid, new_callref++);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700147 if (!trans) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100148 LOG_TRANS(trans, LOGL_ERROR, " -> No memory for trans\n");
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100149 gsm48_tx_simple(msc_a,
Vadim Yanitskiy9aec25e2018-06-12 06:26:28 +0700150 GSM48_PDISC_NC_SS | (tid << 4),
151 GSM0480_MTYPE_RELEASE_COMPLETE);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700152 return -ENOMEM;
153 }
154
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700155 /* Init inactivity timer */
156 osmo_timer_setup(&trans->ss.timer_guard,
157 ncss_session_timeout_handler, trans);
158
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700159 /* Count active NC SS/USSD sessions */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100160 osmo_counter_inc(net->active_nc_ss);
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700161
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700162 trans->dlci = OMSC_LINKID_CB(msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100163 trans->msc_a = msc_a;
164 msc_a_get(msc_a, MSC_A_USE_NC_SS);
165
166 osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_A_EV_TRANSACTION_ACCEPTED, trans);
167
168 /* An earlier CM Service Request for this SS message now has concluded */
169 if (!osmo_use_count_by(&msc_a->use_count, MSC_A_USE_CM_SERVICE_SS))
170 LOG_MSC_A(msc_a, LOGL_ERROR,
171 "Creating new MO SS transaction without prior CM Service Request\n");
172 else
173 msc_a_put(msc_a, MSC_A_USE_CM_SERVICE_SS);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700174 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200175
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100176 LOG_TRANS(trans, LOGL_DEBUG, "Received SS/USSD msg %s\n",
177 gsm48_pdisc_msgtype_name(GSM48_PDISC_NC_SS, msg_type));
178
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700179 /* (Re)schedule the inactivity timer */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100180 if (net->ncss_guard_timeout > 0) {
181 osmo_timer_schedule(&trans->ss.timer_guard, net->ncss_guard_timeout, 0);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700182 }
183
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700184 /* Attempt to extract Facility IE */
185 rc = gsm0480_extract_ie_by_tag(gh, msgb_l3len(msg),
186 &facility_ie, &facility_ie_len, GSM0480_IE_FACILITY);
187 if (rc) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100188 LOG_TRANS(trans, LOGL_ERROR, "GSM 04.80 message parsing error, couldn't extract Facility IE\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700189 goto error;
Tobias Engelea730322013-12-28 17:03:14 +0100190 }
191
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700192 /* Facility IE is optional for RELEASE COMPLETE */
193 if (msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
194 if (!facility_ie || facility_ie_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100195 LOG_TRANS(trans, LOGL_ERROR, "GSM 04.80 message parsing error,"
196 " missing mandatory Facility IE\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700197 rc = -EINVAL;
198 goto error;
Holger Hans Peter Freyther5085e0b2016-07-12 17:53:26 +0200199 }
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700200 }
201
202 /* Compose a mew GSUP message */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100203 gsup_msg = (struct osmo_gsup_message){
204 .message_type = OSMO_GSUP_MSGT_PROC_SS_REQUEST,
205 .session_id = trans->callref,
206 .message_class = OSMO_GSUP_MESSAGE_CLASS_USSD,
207 };
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700208
209 /**
210 * Perform A-interface to GSUP-interface mapping,
211 * according to GSM TS 09.11, table 4.2.
212 */
213 switch (msg_type) {
214 case GSM0480_MTYPE_REGISTER:
215 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_BEGIN;
216 break;
217 case GSM0480_MTYPE_FACILITY:
218 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_CONTINUE;
219 break;
220 case GSM0480_MTYPE_RELEASE_COMPLETE:
221 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END;
222 break;
223 }
224
225 /* Fill in the (optional) message payload */
226 if (facility_ie) {
227 gsup_msg.ss_info_len = facility_ie_len;
228 gsup_msg.ss_info = facility_ie;
229 }
230
231 /* Fill in subscriber's IMSI */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100232 OSMO_STRLCPY_ARRAY(gsup_msg.imsi, vsub->imsi);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700233
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100234 rc = gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700235
Vadim Yanitskiyfcc24ed2018-06-21 17:55:56 +0700236 /* Should we release connection? Or wait for response? */
237 if (msg_type == GSM0480_MTYPE_RELEASE_COMPLETE)
238 trans_free(trans);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700239
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700240 /* Count established MS-initiated NC SS/USSD sessions */
241 if (msg_type == GSM0480_MTYPE_REGISTER)
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100242 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED]);
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700243
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700244 return 0;
245
246error:
247 /* Abort transaction on DTAP-interface */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100248 msc_send_ussd_reject(msc_a, tid, -1,
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700249 GSM_0480_PROBLEM_CODE_TAG_GENERAL,
250 GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
251 if (trans)
252 trans_free(trans);
253
254 /* TODO: abort transaction on GSUP interface if any */
255 return rc;
256}
257
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700258/* Call-back from paging the B-end of the connection */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100259static void ss_paging_cb(struct msc_a *msc_a, struct gsm_trans *trans)
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700260{
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700261 struct gsm48_hdr *gh;
262 struct msgb *ss_msg;
263
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100264 if (trans->msc_a) {
265 LOG_MSC_A_CAT(msc_a, DPAG, LOGL_ERROR,
266 "Handle paging error: transaction already associated with subsciber,"
267 " apparently it was already handled. Skip.\n");
268 return;
269 }
270 OSMO_ASSERT(trans->ss.msg);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700271
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100272 if (msc_a) {
273 struct gsm_network *net = msc_a_net(msc_a);
Neels Hofmeyr979b0572019-05-09 15:24:49 +0200274 LOG_MSC_A_CAT(msc_a, DSS, LOGL_DEBUG, "Paging succeeded\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700275
276 /* Assign connection */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100277 msc_a_get(msc_a, MSC_A_USE_NC_SS);
278 trans->msc_a = msc_a;
279 trans->paging_request = NULL;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700280
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700281 /* (Re)schedule the inactivity timer */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100282 if (net->ncss_guard_timeout > 0) {
283 osmo_timer_schedule(&trans->ss.timer_guard, net->ncss_guard_timeout, 0);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700284 }
285
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700286 /* Send stored message */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100287 ss_msg = trans->ss.msg;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700288 gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));
289 gh->proto_discr = GSM48_PDISC_NC_SS;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100290 gh->proto_discr |= trans->transaction_id << 4;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700291 gh->msg_type = GSM0480_MTYPE_REGISTER;
292
293 /* Sent to the MS, give ownership of ss_msg */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100294 msc_a_tx_dtap_to_i(msc_a, ss_msg);
295 trans->ss.msg = NULL;
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700296
297 /* Count established network-initiated NC SS/USSD sessions */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100298 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED]);
299 } else {
Neels Hofmeyr979b0572019-05-09 15:24:49 +0200300 LOG_MSC_A_CAT(msc_a, DSS, LOGL_DEBUG, "Paging expired\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700301
302 /* TODO: inform HLR about this failure */
303
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100304 msgb_free(trans->ss.msg);
305 trans->ss.msg = NULL;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700306
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100307 trans->callref = 0;
308 trans->paging_request = NULL;
309 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700310 }
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700311}
312
313static struct gsm_trans *establish_nc_ss_trans(struct gsm_network *net,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100314 struct vlr_subscr *vsub, const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700315{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100316 struct msc_a *msc_a;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700317 struct gsm_trans *trans, *transt;
318 int tid;
319
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100320 /* Allocate transaction first, for log context */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100321 trans = trans_alloc(net, vsub, TRANS_USSD,
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100322 TRANS_ID_UNASSIGNED, gsup_msg->session_id);
323
324 if (!trans) {
325 LOG_TRANS(trans, LOGL_ERROR, " -> No memory for trans\n");
326 return NULL;
327 }
328
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700329 if (gsup_msg->session_state != OSMO_GSUP_SESSION_STATE_BEGIN) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100330 LOG_TRANS(trans, LOGL_ERROR, "Received non-BEGIN message "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700331 "for non-existing transaction\n");
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100332 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700333 return NULL;
334 }
335
336 if (!gsup_msg->ss_info || gsup_msg->ss_info_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100337 LOG_TRANS(trans, LOGL_ERROR, "Missing mandatory Facility IE\n");
338 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700339 return NULL;
340 }
341
342 /* If subscriber is not "attached" */
Max7d41d872018-12-19 11:48:33 +0100343 if (!vsub->cgi.lai.lac) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100344 LOG_TRANS(trans, LOGL_ERROR, "Network-originated session "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700345 "rejected - subscriber is not attached\n");
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100346 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700347 return NULL;
348 }
349
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100350 LOG_TRANS(trans, LOGL_DEBUG, "Establishing network-originated session\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700351
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700352 /* Count active NC SS/USSD sessions */
353 osmo_counter_inc(net->active_nc_ss);
354
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700355 /* Assign transaction ID */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100356 tid = trans_assign_trans_id(trans->net, trans->vsub, TRANS_USSD);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700357 if (tid < 0) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100358 LOG_TRANS(trans, LOGL_ERROR, "No free transaction ID\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700359 /* TODO: inform HLR about this */
360 /* TODO: release connection with subscriber */
361 trans->callref = 0;
362 trans_free(trans);
363 return NULL;
364 }
365 trans->transaction_id = tid;
366
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700367 /* Init inactivity timer */
368 osmo_timer_setup(&trans->ss.timer_guard,
369 ncss_session_timeout_handler, trans);
370
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700371 /* Attempt to find connection */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100372 msc_a = msc_a_for_vsub(vsub, true);
373 if (msc_a) {
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700374 /* Assign connection */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100375 msc_a_get(msc_a, MSC_A_USE_NC_SS);
376 trans->msc_a = msc_a;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700377 trans->dlci = 0x00; /* SAPI=0, not SACCH */
378 return trans;
379 }
380
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100381 LOG_TRANS(trans, LOGL_DEBUG, "Triggering Paging Request\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700382
383 /* Find transaction with this subscriber already paging */
384 llist_for_each_entry(transt, &net->trans_list, entry) {
385 /* Transaction of our conn? */
386 if (transt == trans || transt->vsub != vsub)
387 continue;
388
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100389 LOG_TRANS(trans, LOGL_ERROR, "Paging already started, "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700390 "rejecting message...\n");
391 trans_free(trans);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100392 /* FIXME: WTF IS THIS!? This is completely insane. Presence of a trans doesn't indicate Paging, and even
393 * if, why drop the current request??? */
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700394 return NULL;
395 }
396
397 /* Trigger Paging Request */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100398 trans->paging_request = paging_request_start(vsub, PAGING_CAUSE_SIGNALLING_HIGH_PRIO,
399 ss_paging_cb, trans, "GSM 09.11 SS/USSD");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700400 if (!trans->paging_request) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100401 LOG_TRANS(trans, LOGL_ERROR, "Failed to allocate paging token\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700402 trans_free(trans);
403 return NULL;
404 }
405
406 /* Store the Facility IE to be sent */
407 OSMO_ASSERT(trans->ss.msg == NULL);
408 trans->ss.msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD");
409 msgb_tlv_put(trans->ss.msg, GSM0480_IE_FACILITY,
410 gsup_msg->ss_info_len, gsup_msg->ss_info);
411
412 return NULL;
413}
414
415/* NC SS specific transaction release.
416 * Gets called by trans_free, DO NOT CALL YOURSELF! */
417void _gsm911_nc_ss_trans_free(struct gsm_trans *trans)
418{
419 /**
420 * TODO: if transaction wasn't properly terminated,
421 * we need to do it here by releasing the subscriber
422 * connection and sending notification via GSUP...
423 */
424 if (trans->ss.msg != NULL)
425 msgb_free(trans->ss.msg);
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700426
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700427 /* Stop inactivity timer */
428 osmo_timer_del(&trans->ss.timer_guard);
429
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700430 /* One session less */
431 osmo_counter_dec(trans->net->active_nc_ss);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700432}
433
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100434int gsm0911_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700435{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100436 struct vlr_instance *vlr = data;
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700437 struct gsm_network *net;
438 struct gsm_trans *trans;
439 struct gsm48_hdr *gh;
440 struct msgb *ss_msg;
441 bool trans_end;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100442 struct msc_a *msc_a;
443 struct vlr_subscr *vsub = vlr_subscr_find_by_imsi(vlr, gsup_msg->imsi, __func__);
444
445 if (!vsub) {
446 gsup_client_mux_tx_error_reply(gcm, gsup_msg, GMM_CAUSE_IMSI_UNKNOWN);
447 return -GMM_CAUSE_IMSI_UNKNOWN;
448 }
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700449
450 /* Associate logging messages with this subscriber */
451 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
452
453 /* Obtain pointer to vlr_instance */
454 vlr = vsub->vlr;
455 OSMO_ASSERT(vlr);
456
457 /* Obtain pointer to gsm_network */
458 net = (struct gsm_network *) vlr->user_ctx;
459 OSMO_ASSERT(net);
460
461 /* Handle errors */
462 if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
463 /* FIXME: handle this error somehow! */
Harald Welte6307b852009-10-16 08:41:51 +0200464 return 0;
Holger Hans Peter Freyther5085e0b2016-07-12 17:53:26 +0200465 }
Harald Welte6eafe912009-10-16 08:32:58 +0200466
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700467 /* Attempt to find DTAP-transaction */
468 trans = trans_find_by_callref(net, gsup_msg->session_id);
469 if (!trans) {
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700470 /* Count network-initiated attempts to establish a NC SS/USSD session */
471 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS]);
472
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700473 /* Attempt to establish a new transaction */
474 trans = establish_nc_ss_trans(net, vsub, gsup_msg);
475 if (!trans) {
476 /* FIXME: send ERROR back to the HLR */
477 return -EINVAL;
478 }
479
480 /* Wait for Paging Response */
481 if (trans->paging_request)
482 return 0;
Harald Welte6eafe912009-10-16 08:32:58 +0200483 }
Holger Hans Peter Freyther24866632010-06-30 12:15:19 +0800484
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700485 /* (Re)schedule the inactivity timer */
486 if (net->ncss_guard_timeout > 0) {
487 osmo_timer_schedule(&trans->ss.timer_guard,
488 net->ncss_guard_timeout, 0);
489 }
490
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700491 /* Allocate and prepare a new MT message */
492 ss_msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD");
493 gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));
494 gh->proto_discr = GSM48_PDISC_NC_SS;
495 gh->proto_discr |= trans->transaction_id << 4;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700496
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700497 /**
498 * Perform GSUP-interface to A-interface mapping,
499 * according to GSM TS 09.11, table 4.1.
500 *
501 * TODO: see (note 3), both CONTINUE and END may
502 * be also mapped to REGISTER if a new transaction
503 * has to be established.
504 */
505 switch (gsup_msg->session_state) {
506 case OSMO_GSUP_SESSION_STATE_BEGIN:
507 gh->msg_type = GSM0480_MTYPE_REGISTER;
508 break;
509 case OSMO_GSUP_SESSION_STATE_CONTINUE:
510 gh->msg_type = GSM0480_MTYPE_FACILITY;
511 break;
512 case OSMO_GSUP_SESSION_STATE_END:
513 gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
514 break;
515
516 /* Missing or incorrect session state */
517 case OSMO_GSUP_SESSION_STATE_NONE:
518 default:
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100519 LOG_TRANS(trans, LOGL_ERROR, "Unexpected session state %d\n",
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700520 gsup_msg->session_state);
521 /* FIXME: send ERROR back to the HLR */
522 msgb_free(ss_msg);
523 return -EINVAL;
524 }
525
526 /* Facility IE is optional only for RELEASE COMPLETE */
527 if (gh->msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
528 if (!gsup_msg->ss_info || gsup_msg->ss_info_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100529 LOG_TRANS(trans, LOGL_ERROR, "Missing mandatory Facility IE "
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700530 "for mapped 0x%02x message\n", gh->msg_type);
531 /* FIXME: send ERROR back to the HLR */
532 msgb_free(ss_msg);
533 return -EINVAL;
534 }
535 }
536
537 /* Append Facility IE if preset */
538 if (gsup_msg->ss_info && gsup_msg->ss_info_len > 2) {
539 /* Facility IE carries LV, others carry TLV */
540 if (gh->msg_type == GSM0480_MTYPE_FACILITY)
541 msgb_lv_put(ss_msg, gsup_msg->ss_info_len, gsup_msg->ss_info);
542 else
543 msgb_tlv_put(ss_msg, GSM0480_IE_FACILITY,
544 gsup_msg->ss_info_len, gsup_msg->ss_info);
545 }
546
547 /* Should we release the transaction? */
548 trans_end = (gh->msg_type == GSM0480_MTYPE_RELEASE_COMPLETE);
549
550 /* Sent to the MS, give ownership of ss_msg */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100551 msc_a = trans->msc_a;
552 if (!msc_a) {
553 LOG_TRANS(trans, LOGL_ERROR, "Cannot send SS message, no local MSC-A role defined for subscriber\n");
554 msgb_free(ss_msg);
555 return -EINVAL;
556 }
557 msc_a_tx_dtap_to_i(msc_a, ss_msg);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700558
559 /* Release transaction if required */
560 if (trans_end)
561 trans_free(trans);
562
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700563 /* Count established network-initiated NC SS/USSD sessions */
564 if (gsup_msg->session_state == OSMO_GSUP_SESSION_STATE_BEGIN)
565 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED]);
566
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700567 return 0;
Harald Welte6eafe912009-10-16 08:32:58 +0200568}