blob: 755f8aa9131b15bc0d9321cb8e138cba74d6083e [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 Hofmeyr90843962017-09-04 15:04:35 +020024#include <osmocom/msc/osmo_msc.h>
25#include <osmocom/msc/bsc_api.h>
26#include <osmocom/msc/debug.h>
27#include <osmocom/msc/transaction.h>
28#include <osmocom/msc/db.h>
29#include <osmocom/msc/vlr.h>
30#include <osmocom/msc/osmo_msc.h>
31#include <osmocom/msc/a_iface.h>
Max43b01b02017-09-15 11:22:30 +020032#include <osmocom/msc/gsm_04_08.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020033#include <osmocom/msc/gsm_04_11.h>
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080034
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020035#include "../../bscconfig.h"
36#ifdef BUILD_IU
37#include <osmocom/ranap/iu_client.h>
38#else
Neels Hofmeyr90843962017-09-04 15:04:35 +020039#include <osmocom/msc/iu_dummy.h>
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020040#endif
41
Harald Welte2483f1b2016-06-19 18:06:02 +020042/* Receive a SAPI-N-REJECT from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +020043void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080044{
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080045 int sapi = dlci & 0x7;
46
47 if (sapi == UM_SAPI_SMS)
48 gsm411_sapi_n_reject(conn);
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080049}
50
Harald Welte2483f1b2016-06-19 18:06:02 +020051static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
52{
53 if (!conn)
54 return;
55 if (!conn->conn_fsm)
56 return;
57 if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020058 || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING)) {
59 DEBUGP(DMM, "%s: bump: conn still being established (%s)\n",
60 vlr_subscr_name(conn->vsub),
61 osmo_fsm_inst_state_name(conn->conn_fsm));
Harald Welte2483f1b2016-06-19 18:06:02 +020062 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020063 }
Harald Welte2483f1b2016-06-19 18:06:02 +020064 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
65}
66
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020067/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
68 * MSC_CONN_REJECT */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020069int msc_compl_l3(struct gsm_subscriber_connection *conn,
70 struct msgb *msg, uint16_t chosen_channel)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080071{
Neels Hofmeyr6166f292017-11-22 14:33:12 +010072 msc_subscr_conn_get(conn, MSC_CONN_USE_COMPL_L3);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080073 gsm0408_dispatch(conn, msg);
74
Harald Welte2483f1b2016-06-19 18:06:02 +020075 /* Bump whether the conn wants to be closed */
76 subscr_conn_bump(conn);
77
78 /* If this should be kept, the conn->conn_fsm has placed a use_count */
Neels Hofmeyr6166f292017-11-22 14:33:12 +010079 msc_subscr_conn_put(conn, MSC_CONN_USE_COMPL_L3);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020080
81 /* Always return acceptance, because even if the conn was not accepted,
82 * we assumed ownership of it and the caller shall not interfere with
83 * that. We may even already have discarded the conn. */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020084 return MSC_CONN_ACCEPT;
Harald Welte2483f1b2016-06-19 18:06:02 +020085
86#if 0
Holger Hans Peter Freythere9f420d2016-02-10 10:42:20 +010087 /*
88 * If this is a silent call we want the channel to remain open as long as
89 * possible and this is why we accept this connection regardless of any
90 * pending transaction or ongoing operation.
91 */
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +010092 if (conn->silent_call)
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020093 return MSC_CONN_ACCEPT;
94 if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
95 return MSC_CONN_ACCEPT;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +010096 if (trans_has_conn(conn))
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020097 return MSC_CONN_ACCEPT;
Jacob Erlbeck8e68b562014-01-30 21:01:12 +010098
99 LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200100 return MSC_CONN_REJECT;
Harald Welte2483f1b2016-06-19 18:06:02 +0200101#endif
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800102}
103
Harald Welte2483f1b2016-06-19 18:06:02 +0200104/* Receive a DTAP message from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200105void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800106{
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100107 msc_subscr_conn_get(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800108 gsm0408_dispatch(conn, msg);
Harald Welte2483f1b2016-06-19 18:06:02 +0200109
110 /* Bump whether the conn wants to be closed */
111 subscr_conn_bump(conn);
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100112 msc_subscr_conn_put(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800113}
114
Harald Welte2483f1b2016-06-19 18:06:02 +0200115/* Receive an ASSIGNMENT COMPLETE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200116void msc_assign_compl(struct gsm_subscriber_connection *conn,
117 uint8_t rr_cause, uint8_t chosen_channel,
118 uint8_t encr_alg_id, uint8_t speec)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100119{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100120 LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100121}
122
Harald Welte2483f1b2016-06-19 18:06:02 +0200123/* Receive an ASSIGNMENT FAILURE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200124void msc_assign_fail(struct gsm_subscriber_connection *conn,
125 uint8_t cause, uint8_t *rr_cause)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100126{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100127 LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100128}
129
Harald Welte2483f1b2016-06-19 18:06:02 +0200130/* Receive a CLASSMARK CHANGE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200131void msc_classmark_chg(struct gsm_subscriber_connection *conn,
132 const uint8_t *cm2, uint8_t cm2_len,
133 const uint8_t *cm3, uint8_t cm3_len)
Harald Welte95e862c2012-01-23 10:28:35 +0100134{
Harald Welte2483f1b2016-06-19 18:06:02 +0200135 if (cm2 && cm2_len) {
136 if (cm2_len > sizeof(conn->classmark.classmark2)) {
137 LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
138 vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
139 cm2_len = sizeof(conn->classmark.classmark2);
Harald Welte95e862c2012-01-23 10:28:35 +0100140 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200141 conn->classmark.classmark2_len = cm2_len;
142 memcpy(conn->classmark.classmark2, cm2, cm2_len);
143 }
144 if (cm3 && cm3_len) {
145 if (cm3_len > sizeof(conn->classmark.classmark3)) {
146 LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
147 vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
148 cm3_len = sizeof(conn->classmark.classmark3);
149 }
150 conn->classmark.classmark3_len = cm3_len;
151 memcpy(conn->classmark.classmark3, cm3, cm3_len);
Harald Welte95e862c2012-01-23 10:28:35 +0100152 }
153}
154
Harald Welte2483f1b2016-06-19 18:06:02 +0200155/* Receive a CIPHERING MODE COMPLETE from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200156void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
157 struct msgb *msg, uint8_t alg_id)
Harald Weltecf149ee2012-01-23 16:40:24 +0100158{
Harald Welte2483f1b2016-06-19 18:06:02 +0200159 struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
Harald Weltecf149ee2012-01-23 16:40:24 +0100160
Harald Welte2483f1b2016-06-19 18:06:02 +0200161 if (!conn) {
Harald Welte284c39a2018-01-24 22:38:06 +0100162 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete on NULL conn\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200163 return;
164 }
165 if (!conn->vsub) {
Harald Welte284c39a2018-01-24 22:38:06 +0100166 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete for NULL subscr\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200167 return;
Harald Weltecf149ee2012-01-23 16:40:24 +0100168 }
169
Harald Welte284c39a2018-01-24 22:38:06 +0100170 DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n", vlr_subscr_name(conn->vsub));
Harald Welte2483f1b2016-06-19 18:06:02 +0200171
Harald Welte284c39a2018-01-24 22:38:06 +0100172 if (msg) {
173 struct gsm48_hdr *gh = msgb_l3(msg);
174 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
175 struct tlv_parsed tp;
176 uint8_t mi_type;
177 char imeisv[GSM48_MI_SIZE] = "";
Harald Welte2483f1b2016-06-19 18:06:02 +0200178
Harald Welte284c39a2018-01-24 22:38:06 +0100179 if (!gh) {
180 LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
181 return;
182 }
183
184 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
185
186 /* bearer capability */
187 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
188 mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
189 if (mi_type == GSM_MI_TYPE_IMEISV
190 && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
191 gsm48_mi_to_string(imeisv, sizeof(imeisv),
192 TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
193 TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
194 ciph_res.imeisv = imeisv;
195 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200196 }
197 }
198
199 ciph_res.cause = VLR_CIPH_COMPL;
200 vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
Harald Weltecf149ee2012-01-23 16:40:24 +0100201}
202
Harald Welte2483f1b2016-06-19 18:06:02 +0200203struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network)
204{
205 struct gsm_subscriber_connection *conn;
Harald Welte95e862c2012-01-23 10:28:35 +0100206
Harald Welte2483f1b2016-06-19 18:06:02 +0200207 conn = talloc_zero(network, struct gsm_subscriber_connection);
208 if (!conn)
209 return NULL;
Harald Welte95e862c2012-01-23 10:28:35 +0100210
Harald Welte2483f1b2016-06-19 18:06:02 +0200211 conn->network = network;
212 llist_add_tail(&conn->entry, &network->subscr_conns);
213 return conn;
214}
215
216void msc_subscr_cleanup(struct vlr_subscr *vsub)
217{
218 if (!vsub)
219 return;
220 vsub->lu_fsm = NULL;
221}
222
223void msc_subscr_con_cleanup(struct gsm_subscriber_connection *conn)
224{
225 if (!conn)
226 return;
227
228 if (conn->vsub) {
229 DEBUGP(DRLL, "subscr %s: Freeing subscriber connection\n",
230 vlr_subscr_name(conn->vsub));
231 msc_subscr_cleanup(conn->vsub);
232 vlr_subscr_put(conn->vsub);
233 conn->vsub = NULL;
234 } else
235 DEBUGP(DRLL, "Freeing subscriber connection"
236 " with NULL subscriber\n");
237
238 if (!conn->conn_fsm)
239 return;
240
241 osmo_fsm_inst_term(conn->conn_fsm,
242 (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED)
243 ? OSMO_FSM_TERM_REGULAR
244 : OSMO_FSM_TERM_ERROR,
245 NULL);
246}
247
248void msc_subscr_con_free(struct gsm_subscriber_connection *conn)
249{
250 if (!conn)
251 return;
252
253 msc_subscr_con_cleanup(conn);
254
255 llist_del(&conn->entry);
256 talloc_free(conn);
257}
258
259/* Receive a CLEAR REQUEST from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200260int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
Harald Welte2483f1b2016-06-19 18:06:02 +0200261{
262 msc_subscr_conn_close(conn, cause);
263 return 1;
264}
265
266/* MSC-level operations to be called by libbsc in NITB */
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800267static struct bsc_api msc_handler = {
268 .sapi_n_reject = msc_sapi_n_reject,
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800269 .compl_l3 = msc_compl_l3,
Neels Hofmeyrcc7db182016-12-18 23:52:38 +0100270 .dtap = msc_dtap,
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100271 .clear_request = msc_clear_request,
272 .assign_compl = msc_assign_compl,
273 .assign_fail = msc_assign_fail,
Harald Welte95e862c2012-01-23 10:28:35 +0100274 .classmark_chg = msc_classmark_chg,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200275 .cipher_mode_compl = msc_cipher_mode_compl,
Harald Welte2483f1b2016-06-19 18:06:02 +0200276 .conn_cleanup = msc_subscr_con_cleanup,
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +0800277};
278
279struct bsc_api *msc_bsc_api() {
280 return &msc_handler;
281}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800282
Harald Welte2483f1b2016-06-19 18:06:02 +0200283static void msc_subscr_conn_release_all(struct gsm_subscriber_connection *conn, uint32_t cause)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800284{
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800285 if (conn->in_release)
286 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200287 conn->in_release = true;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800288
Harald Welte2483f1b2016-06-19 18:06:02 +0200289 /* If we're closing in a middle of a trans, we need to clean up */
290 trans_conn_closed(conn);
291
292 switch (conn->via_ran) {
293 case RAN_UTRAN_IU:
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200294 ranap_iu_tx_release(conn->iu.ue_ctx, NULL);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200295 /* FIXME: keep the conn until the Iu Release Outcome is
296 * received from the UE, or a timeout expires. For now, the log
297 * says "unknown UE" for each release outcome. */
Harald Welte2483f1b2016-06-19 18:06:02 +0200298 break;
299 case RAN_GERAN_A:
Philipp Maierfbf66102017-04-09 12:32:51 +0200300 a_iface_tx_clear_cmd(conn);
Harald Welte2483f1b2016-06-19 18:06:02 +0200301 break;
302 default:
303 LOGP(DMM, LOGL_ERROR, "%s: Unknown RAN type, cannot tx release/clear\n",
304 vlr_subscr_name(conn->vsub));
305 break;
306 }
307}
308
309/* If the conn->conn_fsm is still present, dispatch SUBSCR_CONN_E_CN_CLOSE
310 * event to gracefully terminate the connection. If the conn_fsm is already
311 * cleared, call msc_subscr_conn_release_all() to take release actions.
312 * \param cause a GSM_CAUSE_* constant, e.g. GSM_CAUSE_AUTH_FAILED.
313 */
314void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
315 uint32_t cause)
316{
317 if (!conn)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800318 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200319 if (conn->in_release) {
320 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
321 " already dispatching release, ignore.\n",
322 vlr_subscr_name(conn->vsub), cause);
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800323 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200324 }
325 if (!conn->conn_fsm) {
326 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u): no conn fsm,"
327 " releasing directly without release event.\n",
328 vlr_subscr_name(conn->vsub), cause);
329 /* In case of an IMSI Detach, we don't have conn_fsm. Release
330 * anyway to ensure a timely Iu Release / BSSMAP Clear. */
331 msc_subscr_conn_release_all(conn, cause);
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100332 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200333 }
334 if (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED) {
335 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
336 " conn fsm already releasing, ignore.\n",
337 vlr_subscr_name(conn->vsub), cause);
338 return;
339 }
340 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
341}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800342
Harald Welte2483f1b2016-06-19 18:06:02 +0200343/* increment the ref-count. Needs to be called by every user */
344struct gsm_subscriber_connection *
345_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100346 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200347 const char *file, int line)
348{
349 OSMO_ASSERT(conn);
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200350
Harald Welte2483f1b2016-06-19 18:06:02 +0200351 if (conn->in_release)
Neels Hofmeyr785fadc2017-11-22 14:44:35 +0100352 LOGPSRC(DREF, LOGL_ERROR, file, line,
353 "%s: MSC conn use error: using conn that is already in release (%s)\n",
354 vlr_subscr_name(conn->vsub),
355 msc_subscr_conn_use_name(balance_token));
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200356
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100357 if (balance_token != MSC_CONN_USE_UNTRACKED) {
358 uint32_t flag = 1 << balance_token;
359 OSMO_ASSERT(balance_token < 32);
360 if (conn->use_tokens & flag)
361 LOGPSRC(DREF, LOGL_ERROR, file, line,
362 "%s: MSC conn use error: using an already used token: %s\n",
363 vlr_subscr_name(conn->vsub),
364 msc_subscr_conn_use_name(balance_token));
365 conn->use_tokens |= flag;
366 }
367
Harald Welte2483f1b2016-06-19 18:06:02 +0200368 conn->use_count++;
369 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100370 "%s: MSC conn use + %s == %u (0x%x)\n",
371 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
372 conn->use_count, conn->use_tokens);
Harald Welte2483f1b2016-06-19 18:06:02 +0200373
374 return conn;
375}
376
377/* decrement the ref-count. Once it reaches zero, we release */
378void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100379 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200380 const char *file, int line)
381{
382 OSMO_ASSERT(conn);
383
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100384 if (balance_token != MSC_CONN_USE_UNTRACKED) {
385 uint32_t flag = 1 << balance_token;
386 OSMO_ASSERT(balance_token < 32);
387 if (!(conn->use_tokens & flag))
388 LOGPSRC(DREF, LOGL_ERROR, file, line,
389 "%s: MSC conn use error: freeing an unused token: %s\n",
390 vlr_subscr_name(conn->vsub),
391 msc_subscr_conn_use_name(balance_token));
392 conn->use_tokens &= ~flag;
393 }
394
Harald Welte2483f1b2016-06-19 18:06:02 +0200395 if (conn->use_count == 0) {
396 LOGPSRC(DREF, LOGL_ERROR, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100397 "%s: MSC conn use - %s failed: is already 0\n",
398 vlr_subscr_name(conn->vsub),
399 msc_subscr_conn_use_name(balance_token));
Harald Welte2483f1b2016-06-19 18:06:02 +0200400 return;
401 }
402
403 conn->use_count--;
404 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100405 "%s: MSC conn use - %s == %u (0x%x)\n",
406 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
407 conn->use_count, conn->use_tokens);
Harald Welte2483f1b2016-06-19 18:06:02 +0200408
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200409 if (conn->use_count == 0)
410 msc_subscr_con_free(conn);
411}
412
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100413const struct value_string msc_subscr_conn_use_names[] = {
414 {MSC_CONN_USE_UNTRACKED, "UNTRACKED"},
415 {MSC_CONN_USE_COMPL_L3, "compl_l3"},
416 {MSC_CONN_USE_DTAP, "dtap"},
417 {MSC_CONN_USE_FSM, "fsm"},
418 {MSC_CONN_USE_TRANS_CC, "trans_cc"},
419 {MSC_CONN_USE_TRANS_SMS, "trans_sms"},
420 {MSC_CONN_USE_TRANS_USSD, "trans_ussd"},
421 {MSC_CONN_USE_SILENT_CALL, "silent_call"},
422 {0, NULL},
423};
424
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200425void msc_stop_paging(struct vlr_subscr *vsub)
426{
427 DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
428 /* tell BSCs and RNCs to stop paging? How? */
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800429}