blob: 866cfbd07b364e90c9b75a20685385e915205a43 [file] [log] [blame]
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +08001/* main MSC management code... */
2
3/*
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +02004 * (C) 2010,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freyther85531cc2010-10-06 20:37:09 +08005 * (C) 2010 by On-Waves
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +08006 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080021 *
22 */
23
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020024#include <openbsc/osmo_msc.h>
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080025#include <openbsc/bsc_api.h>
26#include <openbsc/debug.h>
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +080027#include <openbsc/transaction.h>
Harald Welte95e862c2012-01-23 10:28:35 +010028#include <openbsc/db.h>
Harald Welte2483f1b2016-06-19 18:06:02 +020029#include <openbsc/vlr.h>
30#include <openbsc/osmo_msc.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020031#include <openbsc/iu.h>
Philipp Maierfbf66102017-04-09 12:32:51 +020032#include <openbsc/a_iface.h>
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080033
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080034#include <openbsc/gsm_04_11.h>
35
Harald Welte2483f1b2016-06-19 18:06:02 +020036/* Receive a SAPI-N-REJECT from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +020037void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080038{
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080039 int sapi = dlci & 0x7;
40
41 if (sapi == UM_SAPI_SMS)
42 gsm411_sapi_n_reject(conn);
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080043}
44
Harald Welte2483f1b2016-06-19 18:06:02 +020045static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
46{
47 if (!conn)
48 return;
49 if (!conn->conn_fsm)
50 return;
51 if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020052 || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING)) {
53 DEBUGP(DMM, "%s: bump: conn still being established (%s)\n",
54 vlr_subscr_name(conn->vsub),
55 osmo_fsm_inst_state_name(conn->conn_fsm));
Harald Welte2483f1b2016-06-19 18:06:02 +020056 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020057 }
Harald Welte2483f1b2016-06-19 18:06:02 +020058 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
59}
60
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020061/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
62 * MSC_CONN_REJECT */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020063int msc_compl_l3(struct gsm_subscriber_connection *conn,
64 struct msgb *msg, uint16_t chosen_channel)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080065{
Harald Welte2483f1b2016-06-19 18:06:02 +020066 msc_subscr_conn_get(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080067 gsm0408_dispatch(conn, msg);
68
Harald Welte2483f1b2016-06-19 18:06:02 +020069 /* Bump whether the conn wants to be closed */
70 subscr_conn_bump(conn);
71
72 /* If this should be kept, the conn->conn_fsm has placed a use_count */
73 msc_subscr_conn_put(conn);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020074
75 /* Always return acceptance, because even if the conn was not accepted,
76 * we assumed ownership of it and the caller shall not interfere with
77 * that. We may even already have discarded the conn. */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020078 return MSC_CONN_ACCEPT;
Harald Welte2483f1b2016-06-19 18:06:02 +020079
80#if 0
Holger Hans Peter Freythere9f420d2016-02-10 10:42:20 +010081 /*
82 * If this is a silent call we want the channel to remain open as long as
83 * possible and this is why we accept this connection regardless of any
84 * pending transaction or ongoing operation.
85 */
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +010086 if (conn->silent_call)
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020087 return MSC_CONN_ACCEPT;
88 if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
89 return MSC_CONN_ACCEPT;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +010090 if (trans_has_conn(conn))
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020091 return MSC_CONN_ACCEPT;
Jacob Erlbeck8e68b562014-01-30 21:01:12 +010092
93 LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020094 return MSC_CONN_REJECT;
Harald Welte2483f1b2016-06-19 18:06:02 +020095#endif
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080096}
97
Harald Welte2483f1b2016-06-19 18:06:02 +020098/* Receive a DTAP message from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020099void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800100{
Harald Welte2483f1b2016-06-19 18:06:02 +0200101 msc_subscr_conn_get(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800102 gsm0408_dispatch(conn, msg);
Harald Welte2483f1b2016-06-19 18:06:02 +0200103
104 /* Bump whether the conn wants to be closed */
105 subscr_conn_bump(conn);
106 msc_subscr_conn_put(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800107}
108
Harald Welte2483f1b2016-06-19 18:06:02 +0200109/* Receive an ASSIGNMENT COMPLETE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200110void msc_assign_compl(struct gsm_subscriber_connection *conn,
111 uint8_t rr_cause, uint8_t chosen_channel,
112 uint8_t encr_alg_id, uint8_t speec)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100113{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100114 LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100115}
116
Harald Welte2483f1b2016-06-19 18:06:02 +0200117/* Receive an ASSIGNMENT FAILURE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200118void msc_assign_fail(struct gsm_subscriber_connection *conn,
119 uint8_t cause, uint8_t *rr_cause)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100120{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100121 LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100122}
123
Harald Welte2483f1b2016-06-19 18:06:02 +0200124/* Receive a CLASSMARK CHANGE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200125void msc_classmark_chg(struct gsm_subscriber_connection *conn,
126 const uint8_t *cm2, uint8_t cm2_len,
127 const uint8_t *cm3, uint8_t cm3_len)
Harald Welte95e862c2012-01-23 10:28:35 +0100128{
Harald Welte2483f1b2016-06-19 18:06:02 +0200129 if (cm2 && cm2_len) {
130 if (cm2_len > sizeof(conn->classmark.classmark2)) {
131 LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
132 vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
133 cm2_len = sizeof(conn->classmark.classmark2);
Harald Welte95e862c2012-01-23 10:28:35 +0100134 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200135 conn->classmark.classmark2_len = cm2_len;
136 memcpy(conn->classmark.classmark2, cm2, cm2_len);
137 }
138 if (cm3 && cm3_len) {
139 if (cm3_len > sizeof(conn->classmark.classmark3)) {
140 LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
141 vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
142 cm3_len = sizeof(conn->classmark.classmark3);
143 }
144 conn->classmark.classmark3_len = cm3_len;
145 memcpy(conn->classmark.classmark3, cm3, cm3_len);
Harald Welte95e862c2012-01-23 10:28:35 +0100146 }
147}
148
Harald Welte2483f1b2016-06-19 18:06:02 +0200149/* Receive a CIPHERING MODE COMPLETE from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200150void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
151 struct msgb *msg, uint8_t alg_id)
Harald Weltecf149ee2012-01-23 16:40:24 +0100152{
Harald Welte2483f1b2016-06-19 18:06:02 +0200153 struct gsm48_hdr *gh = msgb_l3(msg);
154 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
155 struct tlv_parsed tp;
156 uint8_t mi_type;
157 char imeisv[GSM48_MI_SIZE] = "";
158 struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
Harald Weltecf149ee2012-01-23 16:40:24 +0100159
Harald Welte2483f1b2016-06-19 18:06:02 +0200160 if (!gh) {
161 LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
Harald Weltecf149ee2012-01-23 16:40:24 +0100162 return;
163 }
164
Harald Welte2483f1b2016-06-19 18:06:02 +0200165 if (!conn) {
166 LOGP(DRR, LOGL_ERROR,
167 "invalid: rx Ciphering Mode Complete on NULL conn\n");
168 return;
169 }
170 if (!conn->vsub) {
171 LOGP(DRR, LOGL_ERROR,
172 "invalid: rx Ciphering Mode Complete for NULL subscr\n");
173 return;
Harald Weltecf149ee2012-01-23 16:40:24 +0100174 }
175
Harald Welte2483f1b2016-06-19 18:06:02 +0200176 DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n",
177 vlr_subscr_name(conn->vsub));
178
179 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
180
181 /* bearer capability */
182 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
183 mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
184 if (mi_type == GSM_MI_TYPE_IMEISV
185 && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
186 gsm48_mi_to_string(imeisv, sizeof(imeisv),
187 TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
188 TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
189 ciph_res.imeisv = imeisv;
190 }
191 }
192
193 ciph_res.cause = VLR_CIPH_COMPL;
194 vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
Harald Weltecf149ee2012-01-23 16:40:24 +0100195}
196
Harald Welte2483f1b2016-06-19 18:06:02 +0200197struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network)
198{
199 struct gsm_subscriber_connection *conn;
Harald Welte95e862c2012-01-23 10:28:35 +0100200
Harald Welte2483f1b2016-06-19 18:06:02 +0200201 conn = talloc_zero(network, struct gsm_subscriber_connection);
202 if (!conn)
203 return NULL;
Harald Welte95e862c2012-01-23 10:28:35 +0100204
Harald Welte2483f1b2016-06-19 18:06:02 +0200205 conn->network = network;
206 llist_add_tail(&conn->entry, &network->subscr_conns);
207 return conn;
208}
209
210void msc_subscr_cleanup(struct vlr_subscr *vsub)
211{
212 if (!vsub)
213 return;
214 vsub->lu_fsm = NULL;
215}
216
217void msc_subscr_con_cleanup(struct gsm_subscriber_connection *conn)
218{
219 if (!conn)
220 return;
221
222 if (conn->vsub) {
223 DEBUGP(DRLL, "subscr %s: Freeing subscriber connection\n",
224 vlr_subscr_name(conn->vsub));
225 msc_subscr_cleanup(conn->vsub);
226 vlr_subscr_put(conn->vsub);
227 conn->vsub = NULL;
228 } else
229 DEBUGP(DRLL, "Freeing subscriber connection"
230 " with NULL subscriber\n");
231
232 if (!conn->conn_fsm)
233 return;
234
235 osmo_fsm_inst_term(conn->conn_fsm,
236 (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED)
237 ? OSMO_FSM_TERM_REGULAR
238 : OSMO_FSM_TERM_ERROR,
239 NULL);
240}
241
242void msc_subscr_con_free(struct gsm_subscriber_connection *conn)
243{
244 if (!conn)
245 return;
246
247 msc_subscr_con_cleanup(conn);
248
249 llist_del(&conn->entry);
250 talloc_free(conn);
251}
252
253/* Receive a CLEAR REQUEST from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200254int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
Harald Welte2483f1b2016-06-19 18:06:02 +0200255{
256 msc_subscr_conn_close(conn, cause);
257 return 1;
258}
259
260/* MSC-level operations to be called by libbsc in NITB */
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800261static struct bsc_api msc_handler = {
262 .sapi_n_reject = msc_sapi_n_reject,
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800263 .compl_l3 = msc_compl_l3,
Neels Hofmeyrcc7db182016-12-18 23:52:38 +0100264 .dtap = msc_dtap,
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100265 .clear_request = msc_clear_request,
266 .assign_compl = msc_assign_compl,
267 .assign_fail = msc_assign_fail,
Harald Welte95e862c2012-01-23 10:28:35 +0100268 .classmark_chg = msc_classmark_chg,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200269 .cipher_mode_compl = msc_cipher_mode_compl,
Harald Welte2483f1b2016-06-19 18:06:02 +0200270 .conn_cleanup = msc_subscr_con_cleanup,
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800271};
272
273struct bsc_api *msc_bsc_api() {
274 return &msc_handler;
275}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800276
Harald Welte2483f1b2016-06-19 18:06:02 +0200277static void msc_subscr_conn_release_all(struct gsm_subscriber_connection *conn, uint32_t cause)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800278{
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800279 if (conn->in_release)
280 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200281 conn->in_release = true;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800282
Harald Welte2483f1b2016-06-19 18:06:02 +0200283 /* If we're closing in a middle of a trans, we need to clean up */
284 trans_conn_closed(conn);
285
286 switch (conn->via_ran) {
287 case RAN_UTRAN_IU:
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200288 iu_tx_release(conn->iu.ue_ctx, NULL);
289 /* FIXME: keep the conn until the Iu Release Outcome is
290 * received from the UE, or a timeout expires. For now, the log
291 * says "unknown UE" for each release outcome. */
Harald Welte2483f1b2016-06-19 18:06:02 +0200292 break;
293 case RAN_GERAN_A:
Philipp Maierfbf66102017-04-09 12:32:51 +0200294 a_iface_tx_clear_cmd(conn);
Harald Welte2483f1b2016-06-19 18:06:02 +0200295 break;
296 default:
297 LOGP(DMM, LOGL_ERROR, "%s: Unknown RAN type, cannot tx release/clear\n",
298 vlr_subscr_name(conn->vsub));
299 break;
300 }
301}
302
303/* If the conn->conn_fsm is still present, dispatch SUBSCR_CONN_E_CN_CLOSE
304 * event to gracefully terminate the connection. If the conn_fsm is already
305 * cleared, call msc_subscr_conn_release_all() to take release actions.
306 * \param cause a GSM_CAUSE_* constant, e.g. GSM_CAUSE_AUTH_FAILED.
307 */
308void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
309 uint32_t cause)
310{
311 if (!conn)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800312 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200313 if (conn->in_release) {
314 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
315 " already dispatching release, ignore.\n",
316 vlr_subscr_name(conn->vsub), cause);
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800317 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200318 }
319 if (!conn->conn_fsm) {
320 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u): no conn fsm,"
321 " releasing directly without release event.\n",
322 vlr_subscr_name(conn->vsub), cause);
323 /* In case of an IMSI Detach, we don't have conn_fsm. Release
324 * anyway to ensure a timely Iu Release / BSSMAP Clear. */
325 msc_subscr_conn_release_all(conn, cause);
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100326 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200327 }
328 if (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED) {
329 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
330 " conn fsm already releasing, ignore.\n",
331 vlr_subscr_name(conn->vsub), cause);
332 return;
333 }
334 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
335}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800336
Harald Welte2483f1b2016-06-19 18:06:02 +0200337/* increment the ref-count. Needs to be called by every user */
338struct gsm_subscriber_connection *
339_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
340 const char *file, int line)
341{
342 OSMO_ASSERT(conn);
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200343
Harald Welte2483f1b2016-06-19 18:06:02 +0200344 if (conn->in_release)
345 return NULL;
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200346
Harald Welte2483f1b2016-06-19 18:06:02 +0200347 conn->use_count++;
348 LOGPSRC(DREF, LOGL_DEBUG, file, line,
349 "%s: MSC conn use + 1 == %u\n",
350 vlr_subscr_name(conn->vsub), conn->use_count);
351
352 return conn;
353}
354
355/* decrement the ref-count. Once it reaches zero, we release */
356void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
357 const char *file, int line)
358{
359 OSMO_ASSERT(conn);
360
361 if (conn->use_count == 0) {
362 LOGPSRC(DREF, LOGL_ERROR, file, line,
363 "%s: MSC conn use - 1 failed: is already 0\n",
364 vlr_subscr_name(conn->vsub));
365 return;
366 }
367
368 conn->use_count--;
369 LOGPSRC(DREF, LOGL_DEBUG, file, line,
370 "%s: MSC conn use - 1 == %u\n",
371 vlr_subscr_name(conn->vsub), conn->use_count);
372
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200373 if (conn->use_count == 0)
374 msc_subscr_con_free(conn);
375}
376
377void msc_stop_paging(struct vlr_subscr *vsub)
378{
379 DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
380 /* tell BSCs and RNCs to stop paging? How? */
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800381}