blob: c847b78f14caac0735f703857d82e24628acd1b2 [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>
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080031
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080032#include <openbsc/gsm_04_11.h>
33
Harald Welte2483f1b2016-06-19 18:06:02 +020034/* Receive a SAPI-N-REJECT from BSC */
Holger Hans Peter Freytheradb6e1c2010-09-18 06:44:24 +080035static void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080036{
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080037 int sapi = dlci & 0x7;
38
39 if (sapi == UM_SAPI_SMS)
40 gsm411_sapi_n_reject(conn);
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080041}
42
Harald Welte2483f1b2016-06-19 18:06:02 +020043static bool keep_conn(struct gsm_subscriber_connection *conn)
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +080044{
Harald Welte2483f1b2016-06-19 18:06:02 +020045 /* TODO: what about a silent call? */
46
47 if (!conn->conn_fsm) {
48 DEBUGP(DMM, "No conn_fsm, release conn\n");
49 return false;
50 }
51
52 switch (conn->conn_fsm->state) {
53 case SUBSCR_CONN_S_NEW:
54 case SUBSCR_CONN_S_ACCEPTED:
55 return true;
56 default:
57 return false;
58 }
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +080059}
60
Harald Welte2483f1b2016-06-19 18:06:02 +020061static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
62{
63 if (!conn)
64 return;
65 if (!conn->conn_fsm)
66 return;
67 if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
68 || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING))
69 return;
70 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
71}
72
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020073/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
74 * MSC_CONN_REJECT */
75static int msc_compl_l3(struct gsm_subscriber_connection *conn,
76 struct msgb *msg, uint16_t chosen_channel)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080077{
Harald Welte2483f1b2016-06-19 18:06:02 +020078 /* Ownership of the gsm_subscriber_connection is still a bit mucky
79 * between libbsc and libmsc. In libmsc, we use ref counting, but not
80 * in libbsc. This will become simpler with the MSCSPLIT. */
81
82 /* reserve for the duration of this function */
83 msc_subscr_conn_get(conn);
84
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080085 gsm0408_dispatch(conn, msg);
86
Harald Welte2483f1b2016-06-19 18:06:02 +020087 if (!keep_conn(conn)) {
88 DEBUGP(DMM, "compl_l3: Discarding conn\n");
89 /* keep the use_count reserved, libbsc will discard. If we
90 * released the ref count and discarded here, libbsc would
91 * double-free. And we will not change bsc_api semantics. */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020092 return MSC_CONN_REJECT;
Harald Welte2483f1b2016-06-19 18:06:02 +020093 }
94 DEBUGP(DMM, "compl_l3: Keeping conn\n");
95
96 /* Bump whether the conn wants to be closed */
97 subscr_conn_bump(conn);
98
99 /* If this should be kept, the conn->conn_fsm has placed a use_count */
100 msc_subscr_conn_put(conn);
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200101 return MSC_CONN_ACCEPT;
Harald Welte2483f1b2016-06-19 18:06:02 +0200102
103#if 0
Holger Hans Peter Freythere9f420d2016-02-10 10:42:20 +0100104 /*
105 * If this is a silent call we want the channel to remain open as long as
106 * possible and this is why we accept this connection regardless of any
107 * pending transaction or ongoing operation.
108 */
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100109 if (conn->silent_call)
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200110 return MSC_CONN_ACCEPT;
111 if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
112 return MSC_CONN_ACCEPT;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100113 if (trans_has_conn(conn))
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200114 return MSC_CONN_ACCEPT;
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100115
116 LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200117 return MSC_CONN_REJECT;
Harald Welte2483f1b2016-06-19 18:06:02 +0200118#endif
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800119}
120
Harald Welte2483f1b2016-06-19 18:06:02 +0200121/* Receive a DTAP message from BSC */
Holger Hans Peter Freyther46caa302010-11-04 12:18:00 +0100122static void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800123{
Harald Welte2483f1b2016-06-19 18:06:02 +0200124 msc_subscr_conn_get(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800125 gsm0408_dispatch(conn, msg);
Harald Welte2483f1b2016-06-19 18:06:02 +0200126
127 /* Bump whether the conn wants to be closed */
128 subscr_conn_bump(conn);
129 msc_subscr_conn_put(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800130}
131
Harald Welte2483f1b2016-06-19 18:06:02 +0200132/* Receive an ASSIGNMENT COMPLETE from BSC */
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100133static void msc_assign_compl(struct gsm_subscriber_connection *conn,
134 uint8_t rr_cause, uint8_t chosen_channel,
135 uint8_t encr_alg_id, uint8_t speec)
136{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100137 LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100138}
139
Harald Welte2483f1b2016-06-19 18:06:02 +0200140/* Receive an ASSIGNMENT FAILURE from BSC */
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100141static void msc_assign_fail(struct gsm_subscriber_connection *conn,
142 uint8_t cause, uint8_t *rr_cause)
143{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100144 LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100145}
146
Harald Welte2483f1b2016-06-19 18:06:02 +0200147/* Receive a CLASSMARK CHANGE from BSC */
Harald Welte95e862c2012-01-23 10:28:35 +0100148static void msc_classmark_chg(struct gsm_subscriber_connection *conn,
149 const uint8_t *cm2, uint8_t cm2_len,
150 const uint8_t *cm3, uint8_t cm3_len)
151{
Harald Welte2483f1b2016-06-19 18:06:02 +0200152 if (cm2 && cm2_len) {
153 if (cm2_len > sizeof(conn->classmark.classmark2)) {
154 LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
155 vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
156 cm2_len = sizeof(conn->classmark.classmark2);
Harald Welte95e862c2012-01-23 10:28:35 +0100157 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200158 conn->classmark.classmark2_len = cm2_len;
159 memcpy(conn->classmark.classmark2, cm2, cm2_len);
160 }
161 if (cm3 && cm3_len) {
162 if (cm3_len > sizeof(conn->classmark.classmark3)) {
163 LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
164 vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
165 cm3_len = sizeof(conn->classmark.classmark3);
166 }
167 conn->classmark.classmark3_len = cm3_len;
168 memcpy(conn->classmark.classmark3, cm3, cm3_len);
Harald Welte95e862c2012-01-23 10:28:35 +0100169 }
170}
171
Harald Welte2483f1b2016-06-19 18:06:02 +0200172/* Receive a CIPHERING MODE COMPLETE from BSC */
Harald Weltecf149ee2012-01-23 16:40:24 +0100173static void msc_ciph_m_compl(struct gsm_subscriber_connection *conn,
174 struct msgb *msg, uint8_t alg_id)
175{
Harald Welte2483f1b2016-06-19 18:06:02 +0200176 struct gsm48_hdr *gh = msgb_l3(msg);
177 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
178 struct tlv_parsed tp;
179 uint8_t mi_type;
180 char imeisv[GSM48_MI_SIZE] = "";
181 struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
Harald Weltecf149ee2012-01-23 16:40:24 +0100182
Harald Welte2483f1b2016-06-19 18:06:02 +0200183 if (!gh) {
184 LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
Harald Weltecf149ee2012-01-23 16:40:24 +0100185 return;
186 }
187
Harald Welte2483f1b2016-06-19 18:06:02 +0200188 if (!conn) {
189 LOGP(DRR, LOGL_ERROR,
190 "invalid: rx Ciphering Mode Complete on NULL conn\n");
191 return;
192 }
193 if (!conn->vsub) {
194 LOGP(DRR, LOGL_ERROR,
195 "invalid: rx Ciphering Mode Complete for NULL subscr\n");
196 return;
Harald Weltecf149ee2012-01-23 16:40:24 +0100197 }
198
Harald Welte2483f1b2016-06-19 18:06:02 +0200199 DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n",
200 vlr_subscr_name(conn->vsub));
201
202 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
203
204 /* bearer capability */
205 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
206 mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
207 if (mi_type == GSM_MI_TYPE_IMEISV
208 && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
209 gsm48_mi_to_string(imeisv, sizeof(imeisv),
210 TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
211 TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
212 ciph_res.imeisv = imeisv;
213 }
214 }
215
216 ciph_res.cause = VLR_CIPH_COMPL;
217 vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
Harald Weltecf149ee2012-01-23 16:40:24 +0100218}
219
Harald Welte2483f1b2016-06-19 18:06:02 +0200220struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network)
221{
222 struct gsm_subscriber_connection *conn;
Harald Welte95e862c2012-01-23 10:28:35 +0100223
Harald Welte2483f1b2016-06-19 18:06:02 +0200224 conn = talloc_zero(network, struct gsm_subscriber_connection);
225 if (!conn)
226 return NULL;
Harald Welte95e862c2012-01-23 10:28:35 +0100227
Harald Welte2483f1b2016-06-19 18:06:02 +0200228 conn->network = network;
229 llist_add_tail(&conn->entry, &network->subscr_conns);
230 return conn;
231}
232
233void msc_subscr_cleanup(struct vlr_subscr *vsub)
234{
235 if (!vsub)
236 return;
237 vsub->lu_fsm = NULL;
238}
239
240void msc_subscr_con_cleanup(struct gsm_subscriber_connection *conn)
241{
242 if (!conn)
243 return;
244
245 if (conn->vsub) {
246 DEBUGP(DRLL, "subscr %s: Freeing subscriber connection\n",
247 vlr_subscr_name(conn->vsub));
248 msc_subscr_cleanup(conn->vsub);
249 vlr_subscr_put(conn->vsub);
250 conn->vsub = NULL;
251 } else
252 DEBUGP(DRLL, "Freeing subscriber connection"
253 " with NULL subscriber\n");
254
255 if (!conn->conn_fsm)
256 return;
257
258 osmo_fsm_inst_term(conn->conn_fsm,
259 (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED)
260 ? OSMO_FSM_TERM_REGULAR
261 : OSMO_FSM_TERM_ERROR,
262 NULL);
263}
264
265void msc_subscr_con_free(struct gsm_subscriber_connection *conn)
266{
267 if (!conn)
268 return;
269
270 msc_subscr_con_cleanup(conn);
271
272 llist_del(&conn->entry);
273 talloc_free(conn);
274}
275
276/* Receive a CLEAR REQUEST from BSC */
277static int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
278{
279 msc_subscr_conn_close(conn, cause);
280 return 1;
281}
282
283/* MSC-level operations to be called by libbsc in NITB */
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800284static struct bsc_api msc_handler = {
285 .sapi_n_reject = msc_sapi_n_reject,
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800286 .compl_l3 = msc_compl_l3,
Neels Hofmeyrcc7db182016-12-18 23:52:38 +0100287 .dtap = msc_dtap,
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100288 .clear_request = msc_clear_request,
289 .assign_compl = msc_assign_compl,
290 .assign_fail = msc_assign_fail,
Harald Welte95e862c2012-01-23 10:28:35 +0100291 .classmark_chg = msc_classmark_chg,
Harald Weltecf149ee2012-01-23 16:40:24 +0100292 .cipher_mode_compl = msc_ciph_m_compl,
Harald Welte2483f1b2016-06-19 18:06:02 +0200293 .conn_cleanup = msc_subscr_con_cleanup,
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800294};
295
296struct bsc_api *msc_bsc_api() {
297 return &msc_handler;
298}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800299
Harald Welte2483f1b2016-06-19 18:06:02 +0200300static void msc_subscr_conn_release_all(struct gsm_subscriber_connection *conn, uint32_t cause)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800301{
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800302 if (conn->in_release)
303 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200304 conn->in_release = true;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800305
Harald Welte2483f1b2016-06-19 18:06:02 +0200306 /* If we're closing in a middle of a trans, we need to clean up */
307 trans_conn_closed(conn);
308
309 switch (conn->via_ran) {
310 case RAN_UTRAN_IU:
311 /* future: iu_tx_release(conn->iu.ue_ctx, NULL); */
312 break;
313 case RAN_GERAN_A:
314 /* future: a_iface_tx_clear_cmd(conn); */
315 break;
316 default:
317 LOGP(DMM, LOGL_ERROR, "%s: Unknown RAN type, cannot tx release/clear\n",
318 vlr_subscr_name(conn->vsub));
319 break;
320 }
321}
322
323/* If the conn->conn_fsm is still present, dispatch SUBSCR_CONN_E_CN_CLOSE
324 * event to gracefully terminate the connection. If the conn_fsm is already
325 * cleared, call msc_subscr_conn_release_all() to take release actions.
326 * \param cause a GSM_CAUSE_* constant, e.g. GSM_CAUSE_AUTH_FAILED.
327 */
328void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
329 uint32_t cause)
330{
331 if (!conn)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800332 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200333 if (conn->in_release) {
334 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
335 " already dispatching release, ignore.\n",
336 vlr_subscr_name(conn->vsub), cause);
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800337 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200338 }
339 if (!conn->conn_fsm) {
340 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u): no conn fsm,"
341 " releasing directly without release event.\n",
342 vlr_subscr_name(conn->vsub), cause);
343 /* In case of an IMSI Detach, we don't have conn_fsm. Release
344 * anyway to ensure a timely Iu Release / BSSMAP Clear. */
345 msc_subscr_conn_release_all(conn, cause);
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100346 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200347 }
348 if (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED) {
349 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
350 " conn fsm already releasing, ignore.\n",
351 vlr_subscr_name(conn->vsub), cause);
352 return;
353 }
354 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
355}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800356
Harald Welte2483f1b2016-06-19 18:06:02 +0200357/* increment the ref-count. Needs to be called by every user */
358struct gsm_subscriber_connection *
359_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
360 const char *file, int line)
361{
362 OSMO_ASSERT(conn);
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200363
Harald Welte2483f1b2016-06-19 18:06:02 +0200364 if (conn->in_release)
365 return NULL;
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200366
Harald Welte2483f1b2016-06-19 18:06:02 +0200367 conn->use_count++;
368 LOGPSRC(DREF, LOGL_DEBUG, file, line,
369 "%s: MSC conn use + 1 == %u\n",
370 vlr_subscr_name(conn->vsub), conn->use_count);
371
372 return conn;
373}
374
375/* decrement the ref-count. Once it reaches zero, we release */
376void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
377 const char *file, int line)
378{
379 OSMO_ASSERT(conn);
380
381 if (conn->use_count == 0) {
382 LOGPSRC(DREF, LOGL_ERROR, file, line,
383 "%s: MSC conn use - 1 failed: is already 0\n",
384 vlr_subscr_name(conn->vsub));
385 return;
386 }
387
388 conn->use_count--;
389 LOGPSRC(DREF, LOGL_DEBUG, file, line,
390 "%s: MSC conn use - 1 == %u\n",
391 vlr_subscr_name(conn->vsub), conn->use_count);
392
393 if (conn->use_count == 0) {
394 gsm0808_clear(conn);
395 bsc_subscr_con_free(conn);
396 }
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800397}