blob: 25fe4aa8316606c95df42b3e027f5ea507a040d0 [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>
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070049#include <osmocom/msc/msc_ifaces.h>
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070050
51/* FIXME: choose a proper range */
52static uint32_t new_callref = 0x20000001;
Harald Welte6eafe912009-10-16 08:32:58 +020053
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070054static void ncss_session_timeout_handler(void *_trans)
55{
56 struct gsm_trans *trans = (struct gsm_trans *) _trans;
57 struct osmo_gsup_message gsup_msg = { 0 };
58
59 /* The timeout might be disabled from the VTY */
60 if (trans->net->ncss_guard_timeout == 0)
61 return;
62
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010063 LOG_TRANS(trans, LOGL_NOTICE, "SS/USSD session timeout, releasing\n");
Vadim Yanitskiy64623e12018-11-28 23:05:51 +070064
65 /* Indicate connection release to subscriber (if active) */
66 if (trans->conn != NULL) {
67 /* This pair of cause location and value is used by commercial networks */
68 msc_send_ussd_release_complete_cause(trans->conn, trans->transaction_id,
69 GSM48_CAUSE_LOC_PUN_S_LU, GSM48_CC_CAUSE_NORMAL_UNSPEC);
70 }
71
72 /* Terminate GSUP session with EUSE */
73 gsup_msg.message_type = OSMO_GSUP_MSGT_PROC_SS_ERROR;
74 OSMO_STRLCPY_ARRAY(gsup_msg.imsi, trans->vsub->imsi);
75
76 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END;
77 gsup_msg.session_id = trans->callref;
78 gsup_msg.cause = GMM_CAUSE_NET_FAIL;
79
80 osmo_gsup_client_enc_send(trans->net->vlr->gsup_client, &gsup_msg);
81
82 /* Finally, release this transaction */
83 trans_free(trans);
84}
85
Vadim Yanitskiy5b860fa2018-06-12 05:24:52 +070086/* Entry point for call independent MO SS messages */
Neels Hofmeyrc036b792018-11-29 22:37:51 +010087int gsm0911_rcv_nc_ss(struct ran_conn *conn, struct msgb *msg)
Harald Welte6eafe912009-10-16 08:32:58 +020088{
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070089 struct gsm48_hdr *gh = msgb_l3(msg);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070090 struct osmo_gsup_message gsup_msg;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070091 struct gsm_trans *trans;
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +070092 struct msgb *gsup_msgb;
93 uint16_t facility_ie_len;
94 uint8_t *facility_ie;
Max4a5cfa52019-01-10 17:41:05 +010095 uint8_t tid;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070096 uint8_t msg_type;
97 int rc;
Harald Welte6eafe912009-10-16 08:32:58 +020098
Vadim Yanitskiy10c64192018-04-17 19:17:11 +070099 msg_type = gsm48_hdr_msg_type(gh);
100 tid = gsm48_hdr_trans_id_flip_ti(gh);
Harald Welte2483f1b2016-06-19 18:06:02 +0200101
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700102 /* Associate logging messages with this subscriber */
103 log_set_context(LOG_CTX_VLR_SUBSCR, conn->vsub);
104
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700105 /* Reuse existing transaction, or create a new one */
Max4a5cfa52019-01-10 17:41:05 +0100106 trans = trans_find_by_id(conn, GSM48_PDISC_NC_SS, tid);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700107 if (!trans) {
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700108 /* Count MS-initiated attempts to establish a NC SS/USSD session */
109 rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS]);
110
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700111 /**
112 * According to GSM TS 04.80, section 2.4.2 "Register
113 * (mobile station to network direction)", the REGISTER
114 * message is sent by the mobile station to the network
115 * to assign a new transaction identifier for call independent
116 * supplementary service control and to request or acknowledge
117 * a supplementary service.
118 */
119 if (msg_type != GSM0480_MTYPE_REGISTER) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100120 LOG_TRANS(trans, LOGL_ERROR, "Rx wrong SS/USSD message type for new transaction: %s\n",
121 gsm48_pdisc_msgtype_name(GSM48_PDISC_NC_SS, msg_type));
Vadim Yanitskiy9aec25e2018-06-12 06:26:28 +0700122 gsm48_tx_simple(conn,
123 GSM48_PDISC_NC_SS | (tid << 4),
124 GSM0480_MTYPE_RELEASE_COMPLETE);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700125 return -EINVAL;
126 }
127
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700128 trans = trans_alloc(conn->network, conn->vsub,
Max4a5cfa52019-01-10 17:41:05 +0100129 GSM48_PDISC_NC_SS, tid, new_callref++);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700130 if (!trans) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100131 LOG_TRANS(trans, LOGL_ERROR, " -> No memory for trans\n");
Vadim Yanitskiy9aec25e2018-06-12 06:26:28 +0700132 gsm48_tx_simple(conn,
133 GSM48_PDISC_NC_SS | (tid << 4),
134 GSM0480_MTYPE_RELEASE_COMPLETE);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700135 return -ENOMEM;
136 }
137
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700138 /* Init inactivity timer */
139 osmo_timer_setup(&trans->ss.timer_guard,
140 ncss_session_timeout_handler, trans);
141
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700142 /* Count active NC SS/USSD sessions */
143 osmo_counter_inc(conn->network->active_nc_ss);
144
Neels Hofmeyr3c20a5e2018-11-30 01:08:36 +0100145 trans->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_NC_SS);
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700146 trans->dlci = OMSC_LINKID_CB(msg);
147 cm_service_request_concludes(conn, msg);
148 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200149
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100150 LOG_TRANS(trans, LOGL_DEBUG, "Received SS/USSD msg %s\n",
151 gsm48_pdisc_msgtype_name(GSM48_PDISC_NC_SS, msg_type));
152
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700153 /* (Re)schedule the inactivity timer */
154 if (conn->network->ncss_guard_timeout > 0) {
155 osmo_timer_schedule(&trans->ss.timer_guard,
156 conn->network->ncss_guard_timeout, 0);
157 }
158
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700159 /* Attempt to extract Facility IE */
160 rc = gsm0480_extract_ie_by_tag(gh, msgb_l3len(msg),
161 &facility_ie, &facility_ie_len, GSM0480_IE_FACILITY);
162 if (rc) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100163 LOG_TRANS(trans, LOGL_ERROR, "GSM 04.80 message parsing error, couldn't extract Facility IE\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700164 goto error;
Tobias Engelea730322013-12-28 17:03:14 +0100165 }
166
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700167 /* Facility IE is optional for RELEASE COMPLETE */
168 if (msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
169 if (!facility_ie || facility_ie_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100170 LOG_TRANS(trans, LOGL_ERROR, "GSM 04.80 message parsing error,"
171 " missing mandatory Facility IE\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700172 rc = -EINVAL;
173 goto error;
Holger Hans Peter Freyther5085e0b2016-07-12 17:53:26 +0200174 }
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700175 }
176
177 /* Compose a mew GSUP message */
178 memset(&gsup_msg, 0x00, sizeof(gsup_msg));
179 gsup_msg.message_type = OSMO_GSUP_MSGT_PROC_SS_REQUEST;
180 gsup_msg.session_id = trans->callref;
181
182 /**
183 * Perform A-interface to GSUP-interface mapping,
184 * according to GSM TS 09.11, table 4.2.
185 */
186 switch (msg_type) {
187 case GSM0480_MTYPE_REGISTER:
188 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_BEGIN;
189 break;
190 case GSM0480_MTYPE_FACILITY:
191 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_CONTINUE;
192 break;
193 case GSM0480_MTYPE_RELEASE_COMPLETE:
194 gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END;
195 break;
196 }
197
198 /* Fill in the (optional) message payload */
199 if (facility_ie) {
200 gsup_msg.ss_info_len = facility_ie_len;
201 gsup_msg.ss_info = facility_ie;
202 }
203
204 /* Fill in subscriber's IMSI */
205 OSMO_STRLCPY_ARRAY(gsup_msg.imsi, conn->vsub->imsi);
206
207 /* Allocate GSUP message buffer */
Harald Welte1ea6baf2018-07-31 19:40:52 +0200208 gsup_msgb = osmo_gsup_client_msgb_alloc();
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700209 if (!gsup_msgb) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100210 LOG_TRANS(trans, LOGL_ERROR, "Couldn't allocate GSUP message\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700211 rc = -ENOMEM;
212 goto error;
213 }
214
215 /* Encode GSUP message */
216 rc = osmo_gsup_encode(gsup_msgb, &gsup_msg);
217 if (rc) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100218 LOG_TRANS(trans, LOGL_ERROR, "Couldn't encode GSUP message\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700219 goto error;
220 }
221
222 /* Finally send */
Harald Welte1ea6baf2018-07-31 19:40:52 +0200223 rc = osmo_gsup_client_send(conn->network->vlr->gsup_client, gsup_msgb);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700224 if (rc) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100225 LOG_TRANS(trans, LOGL_ERROR, "Couldn't send GSUP message\n");
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700226 goto error;
227 }
228
Vadim Yanitskiyfcc24ed2018-06-21 17:55:56 +0700229 /* Should we release connection? Or wait for response? */
230 if (msg_type == GSM0480_MTYPE_RELEASE_COMPLETE)
231 trans_free(trans);
232 else
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100233 ran_conn_communicating(conn);
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700234
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700235 /* Count established MS-initiated NC SS/USSD sessions */
236 if (msg_type == GSM0480_MTYPE_REGISTER)
237 rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED]);
238
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700239 return 0;
240
241error:
242 /* Abort transaction on DTAP-interface */
Vadim Yanitskiy0622ef52018-08-03 04:39:04 +0700243 msc_send_ussd_reject(conn, tid, -1,
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700244 GSM_0480_PROBLEM_CODE_TAG_GENERAL,
245 GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
246 if (trans)
247 trans_free(trans);
248
249 /* TODO: abort transaction on GSUP interface if any */
250 return rc;
251}
252
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700253/* Call-back from paging the B-end of the connection */
254static int handle_paging_event(unsigned int hooknum, unsigned int event,
255 struct msgb *msg, void *_conn, void *_transt)
256{
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100257 struct ran_conn *conn = _conn;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700258 enum gsm_paging_event paging_event = event;
259 struct gsm_trans *transt = _transt;
260 struct gsm48_hdr *gh;
261 struct msgb *ss_msg;
262
263 OSMO_ASSERT(!transt->conn);
264 OSMO_ASSERT(transt->ss.msg);
265
266 switch (paging_event) {
267 case GSM_PAGING_SUCCEEDED:
268 DEBUGP(DMM, "Paging subscr %s succeeded!\n",
269 vlr_subscr_msisdn_or_name(transt->vsub));
270
271 /* Assign connection */
Neels Hofmeyr3c20a5e2018-11-30 01:08:36 +0100272 transt->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_NC_SS);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700273 transt->paging_request = NULL;
274
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700275 /* (Re)schedule the inactivity timer */
276 if (conn->network->ncss_guard_timeout > 0) {
277 osmo_timer_schedule(&transt->ss.timer_guard,
278 conn->network->ncss_guard_timeout, 0);
279 }
280
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700281 /* Send stored message */
282 ss_msg = transt->ss.msg;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700283 gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));
284 gh->proto_discr = GSM48_PDISC_NC_SS;
285 gh->proto_discr |= transt->transaction_id << 4;
286 gh->msg_type = GSM0480_MTYPE_REGISTER;
287
288 /* Sent to the MS, give ownership of ss_msg */
289 msc_tx_dtap(transt->conn, ss_msg);
290 transt->ss.msg = NULL;
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700291
292 /* Count established network-initiated NC SS/USSD sessions */
293 rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED]);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700294 break;
295 case GSM_PAGING_EXPIRED:
296 case GSM_PAGING_BUSY:
297 DEBUGP(DMM, "Paging subscr %s %s!\n",
298 vlr_subscr_msisdn_or_name(transt->vsub),
299 paging_event == GSM_PAGING_EXPIRED ? "expired" : "busy");
300
301 /* TODO: inform HLR about this failure */
302
303 msgb_free(transt->ss.msg);
304 transt->ss.msg = NULL;
305
306 transt->callref = 0;
307 transt->paging_request = NULL;
308 trans_free(transt);
309 break;
310 }
311
312 return 0;
313}
314
315static struct gsm_trans *establish_nc_ss_trans(struct gsm_network *net,
316 struct vlr_subscr *vsub, struct osmo_gsup_message *gsup_msg)
317{
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100318 struct ran_conn *conn;
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700319 struct gsm_trans *trans, *transt;
320 int tid;
321
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100322 /* Allocate transaction first, for log context */
323 trans = trans_alloc(net, vsub, GSM48_PDISC_NC_SS,
324 TRANS_ID_UNASSIGNED, gsup_msg->session_id);
325
326 if (!trans) {
327 LOG_TRANS(trans, LOGL_ERROR, " -> No memory for trans\n");
328 return NULL;
329 }
330
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700331 if (gsup_msg->session_state != OSMO_GSUP_SESSION_STATE_BEGIN) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100332 LOG_TRANS(trans, LOGL_ERROR, "Received non-BEGIN message "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700333 "for non-existing transaction\n");
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100334 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700335 return NULL;
336 }
337
338 if (!gsup_msg->ss_info || gsup_msg->ss_info_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100339 LOG_TRANS(trans, LOGL_ERROR, "Missing mandatory Facility IE\n");
340 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700341 return NULL;
342 }
343
344 /* If subscriber is not "attached" */
Max7d41d872018-12-19 11:48:33 +0100345 if (!vsub->cgi.lai.lac) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100346 LOG_TRANS(trans, LOGL_ERROR, "Network-originated session "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700347 "rejected - subscriber is not attached\n");
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100348 trans_free(trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700349 return NULL;
350 }
351
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100352 LOG_TRANS(trans, LOGL_DEBUG, "Establishing network-originated session\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700353
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +0700354 /* Count active NC SS/USSD sessions */
355 osmo_counter_inc(net->active_nc_ss);
356
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700357 /* Assign transaction ID */
Max30fb97a2019-01-10 17:25:33 +0100358 tid = trans_assign_trans_id(trans->net, trans->vsub, GSM48_PDISC_NC_SS);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700359 if (tid < 0) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100360 LOG_TRANS(trans, LOGL_ERROR, "No free transaction ID\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700361 /* TODO: inform HLR about this */
362 /* TODO: release connection with subscriber */
363 trans->callref = 0;
364 trans_free(trans);
365 return NULL;
366 }
367 trans->transaction_id = tid;
368
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700369 /* Init inactivity timer */
370 osmo_timer_setup(&trans->ss.timer_guard,
371 ncss_session_timeout_handler, trans);
372
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700373 /* Attempt to find connection */
374 conn = connection_for_subscr(vsub);
375 if (conn) {
376 /* Assign connection */
Neels Hofmeyr3c20a5e2018-11-30 01:08:36 +0100377 trans->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_NC_SS);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700378 trans->dlci = 0x00; /* SAPI=0, not SACCH */
379 return trans;
380 }
381
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100382 LOG_TRANS(trans, LOGL_DEBUG, "Triggering Paging Request\n");
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700383
384 /* Find transaction with this subscriber already paging */
385 llist_for_each_entry(transt, &net->trans_list, entry) {
386 /* Transaction of our conn? */
387 if (transt == trans || transt->vsub != vsub)
388 continue;
389
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100390 LOG_TRANS(trans, LOGL_ERROR, "Paging already started, "
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700391 "rejecting message...\n");
392 trans_free(trans);
393 return NULL;
394 }
395
396 /* Trigger Paging Request */
397 trans->paging_request = subscr_request_conn(vsub,
Harald Welte0df904d2018-12-03 11:00:04 +0100398 &handle_paging_event, trans, "GSM 09.11 SS/USSD",
399 SGSAP_SERV_IND_CS_CALL);
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
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700434int gsm0911_gsup_handler(struct vlr_subscr *vsub,
435 struct osmo_gsup_message *gsup_msg)
436{
437 struct vlr_instance *vlr;
438 struct gsm_network *net;
439 struct gsm_trans *trans;
440 struct gsm48_hdr *gh;
441 struct msgb *ss_msg;
442 bool trans_end;
443
444 /* Associate logging messages with this subscriber */
445 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
446
447 /* Obtain pointer to vlr_instance */
448 vlr = vsub->vlr;
449 OSMO_ASSERT(vlr);
450
451 /* Obtain pointer to gsm_network */
452 net = (struct gsm_network *) vlr->user_ctx;
453 OSMO_ASSERT(net);
454
455 /* Handle errors */
456 if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
457 /* FIXME: handle this error somehow! */
Harald Welte6307b852009-10-16 08:41:51 +0200458 return 0;
Holger Hans Peter Freyther5085e0b2016-07-12 17:53:26 +0200459 }
Harald Welte6eafe912009-10-16 08:32:58 +0200460
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700461 /* Attempt to find DTAP-transaction */
462 trans = trans_find_by_callref(net, gsup_msg->session_id);
463 if (!trans) {
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700464 /* Count network-initiated attempts to establish a NC SS/USSD session */
465 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS]);
466
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700467 /* Attempt to establish a new transaction */
468 trans = establish_nc_ss_trans(net, vsub, gsup_msg);
469 if (!trans) {
470 /* FIXME: send ERROR back to the HLR */
471 return -EINVAL;
472 }
473
474 /* Wait for Paging Response */
475 if (trans->paging_request)
476 return 0;
Harald Welte6eafe912009-10-16 08:32:58 +0200477 }
Holger Hans Peter Freyther24866632010-06-30 12:15:19 +0800478
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700479 /* (Re)schedule the inactivity timer */
480 if (net->ncss_guard_timeout > 0) {
481 osmo_timer_schedule(&trans->ss.timer_guard,
482 net->ncss_guard_timeout, 0);
483 }
484
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700485 /* Allocate and prepare a new MT message */
486 ss_msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD");
487 gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));
488 gh->proto_discr = GSM48_PDISC_NC_SS;
489 gh->proto_discr |= trans->transaction_id << 4;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700490
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700491 /**
492 * Perform GSUP-interface to A-interface mapping,
493 * according to GSM TS 09.11, table 4.1.
494 *
495 * TODO: see (note 3), both CONTINUE and END may
496 * be also mapped to REGISTER if a new transaction
497 * has to be established.
498 */
499 switch (gsup_msg->session_state) {
500 case OSMO_GSUP_SESSION_STATE_BEGIN:
501 gh->msg_type = GSM0480_MTYPE_REGISTER;
502 break;
503 case OSMO_GSUP_SESSION_STATE_CONTINUE:
504 gh->msg_type = GSM0480_MTYPE_FACILITY;
505 break;
506 case OSMO_GSUP_SESSION_STATE_END:
507 gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
508 break;
509
510 /* Missing or incorrect session state */
511 case OSMO_GSUP_SESSION_STATE_NONE:
512 default:
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100513 LOG_TRANS(trans, LOGL_ERROR, "Unexpected session state %d\n",
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700514 gsup_msg->session_state);
515 /* FIXME: send ERROR back to the HLR */
516 msgb_free(ss_msg);
517 return -EINVAL;
518 }
519
520 /* Facility IE is optional only for RELEASE COMPLETE */
521 if (gh->msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
522 if (!gsup_msg->ss_info || gsup_msg->ss_info_len < 2) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100523 LOG_TRANS(trans, LOGL_ERROR, "Missing mandatory Facility IE "
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700524 "for mapped 0x%02x message\n", gh->msg_type);
525 /* FIXME: send ERROR back to the HLR */
526 msgb_free(ss_msg);
527 return -EINVAL;
528 }
529 }
530
531 /* Append Facility IE if preset */
532 if (gsup_msg->ss_info && gsup_msg->ss_info_len > 2) {
533 /* Facility IE carries LV, others carry TLV */
534 if (gh->msg_type == GSM0480_MTYPE_FACILITY)
535 msgb_lv_put(ss_msg, gsup_msg->ss_info_len, gsup_msg->ss_info);
536 else
537 msgb_tlv_put(ss_msg, GSM0480_IE_FACILITY,
538 gsup_msg->ss_info_len, gsup_msg->ss_info);
539 }
540
541 /* Should we release the transaction? */
542 trans_end = (gh->msg_type == GSM0480_MTYPE_RELEASE_COMPLETE);
543
544 /* Sent to the MS, give ownership of ss_msg */
545 msc_tx_dtap(trans->conn, ss_msg);
546
547 /* Release transaction if required */
548 if (trans_end)
549 trans_free(trans);
550
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +0700551 /* Count established network-initiated NC SS/USSD sessions */
552 if (gsup_msg->session_state == OSMO_GSUP_SESSION_STATE_BEGIN)
553 rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED]);
554
Vadim Yanitskiy8a6ef552018-06-12 08:21:20 +0700555 return 0;
Harald Welte6eafe912009-10-16 08:32:58 +0200556}