blob: 62a7e8a22a60e86497471a14de6fb0f5d844b5cb [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>
Neels Hofmeyr90843962017-09-04 15:04:35 +020025#include <osmocom/msc/debug.h>
26#include <osmocom/msc/transaction.h>
27#include <osmocom/msc/db.h>
28#include <osmocom/msc/vlr.h>
29#include <osmocom/msc/osmo_msc.h>
30#include <osmocom/msc/a_iface.h>
Max43b01b02017-09-15 11:22:30 +020031#include <osmocom/msc/gsm_04_08.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020032#include <osmocom/msc/gsm_04_11.h>
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080033
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020034#include "../../bscconfig.h"
35#ifdef BUILD_IU
36#include <osmocom/ranap/iu_client.h>
37#else
Neels Hofmeyr90843962017-09-04 15:04:35 +020038#include <osmocom/msc/iu_dummy.h>
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020039#endif
40
Neels Hofmeyr55014d02018-03-22 16:43:40 +010041struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv)
42{
43 struct gsm_network *net;
44
45 net = talloc_zero(ctx, struct gsm_network);
46 if (!net)
47 return NULL;
48
49 net->plmn = (struct osmo_plmn_id){ .mcc=1, .mnc=1 };
50
51 /* Permit a compile-time default of A5/3 and A5/1 */
52 net->a5_encryption_mask = (1 << 3) | (1 << 1);
53
54 /* Use 30 min periodic update interval as sane default */
55 net->t3212 = 5;
56
57 net->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
58
59 INIT_LLIST_HEAD(&net->trans_list);
60 INIT_LLIST_HEAD(&net->upqueue);
61 INIT_LLIST_HEAD(&net->subscr_conns);
62
63 /* init statistics */
64 net->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, 0);
65 if (!net->msc_ctrs) {
66 talloc_free(net);
67 return NULL;
68 }
69 net->active_calls = osmo_counter_alloc("msc.active_calls");
70
71 net->mncc_recv = mncc_recv;
72
73 INIT_LLIST_HEAD(&net->a.bscs);
74
75 return net;
76}
77
Harald Welte2483f1b2016-06-19 18:06:02 +020078/* Receive a SAPI-N-REJECT from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +020079void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080080{
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080081 int sapi = dlci & 0x7;
82
83 if (sapi == UM_SAPI_SMS)
84 gsm411_sapi_n_reject(conn);
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080085}
86
Neels Hofmeyrd6a769b2018-03-12 23:59:07 +010087void subscr_conn_release_when_unused(struct gsm_subscriber_connection *conn)
Harald Welte2483f1b2016-06-19 18:06:02 +020088{
89 if (!conn)
90 return;
91 if (!conn->conn_fsm)
92 return;
93 if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020094 || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING)) {
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +010095 DEBUGP(DMM, "%s: %s: conn still being established (%s)\n",
96 vlr_subscr_name(conn->vsub), __func__,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020097 osmo_fsm_inst_state_name(conn->conn_fsm));
Harald Welte2483f1b2016-06-19 18:06:02 +020098 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020099 }
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100100 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_RELEASE_WHEN_UNUSED, NULL);
Harald Welte2483f1b2016-06-19 18:06:02 +0200101}
102
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200103/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
104 * MSC_CONN_REJECT */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200105int msc_compl_l3(struct gsm_subscriber_connection *conn,
106 struct msgb *msg, uint16_t chosen_channel)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800107{
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100108 msc_subscr_conn_get(conn, MSC_CONN_USE_COMPL_L3);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800109 gsm0408_dispatch(conn, msg);
110
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100111 subscr_conn_release_when_unused(conn);
Harald Welte2483f1b2016-06-19 18:06:02 +0200112
113 /* If this should be kept, the conn->conn_fsm has placed a use_count */
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100114 msc_subscr_conn_put(conn, MSC_CONN_USE_COMPL_L3);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200115
116 /* Always return acceptance, because even if the conn was not accepted,
117 * we assumed ownership of it and the caller shall not interfere with
118 * that. We may even already have discarded the conn. */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200119 return MSC_CONN_ACCEPT;
Harald Welte2483f1b2016-06-19 18:06:02 +0200120
121#if 0
Holger Hans Peter Freythere9f420d2016-02-10 10:42:20 +0100122 /*
123 * If this is a silent call we want the channel to remain open as long as
124 * possible and this is why we accept this connection regardless of any
125 * pending transaction or ongoing operation.
126 */
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100127 if (conn->silent_call)
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200128 return MSC_CONN_ACCEPT;
129 if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
130 return MSC_CONN_ACCEPT;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100131 if (trans_has_conn(conn))
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200132 return MSC_CONN_ACCEPT;
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100133
134 LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200135 return MSC_CONN_REJECT;
Harald Welte2483f1b2016-06-19 18:06:02 +0200136#endif
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800137}
138
Harald Welte2483f1b2016-06-19 18:06:02 +0200139/* Receive a DTAP message from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200140void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800141{
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100142 msc_subscr_conn_get(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800143 gsm0408_dispatch(conn, msg);
Harald Welte2483f1b2016-06-19 18:06:02 +0200144
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100145 subscr_conn_release_when_unused(conn);
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100146 msc_subscr_conn_put(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800147}
148
Harald Welte2483f1b2016-06-19 18:06:02 +0200149/* Receive an ASSIGNMENT COMPLETE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200150void msc_assign_compl(struct gsm_subscriber_connection *conn,
151 uint8_t rr_cause, uint8_t chosen_channel,
152 uint8_t encr_alg_id, uint8_t speec)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100153{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100154 LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100155}
156
Harald Welte2483f1b2016-06-19 18:06:02 +0200157/* Receive an ASSIGNMENT FAILURE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200158void msc_assign_fail(struct gsm_subscriber_connection *conn,
159 uint8_t cause, uint8_t *rr_cause)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100160{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100161 LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100162}
163
Harald Welte2483f1b2016-06-19 18:06:02 +0200164/* Receive a CLASSMARK CHANGE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200165void msc_classmark_chg(struct gsm_subscriber_connection *conn,
166 const uint8_t *cm2, uint8_t cm2_len,
167 const uint8_t *cm3, uint8_t cm3_len)
Harald Welte95e862c2012-01-23 10:28:35 +0100168{
Harald Welte2483f1b2016-06-19 18:06:02 +0200169 if (cm2 && cm2_len) {
170 if (cm2_len > sizeof(conn->classmark.classmark2)) {
171 LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
172 vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
173 cm2_len = sizeof(conn->classmark.classmark2);
Harald Welte95e862c2012-01-23 10:28:35 +0100174 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200175 conn->classmark.classmark2_len = cm2_len;
176 memcpy(conn->classmark.classmark2, cm2, cm2_len);
177 }
178 if (cm3 && cm3_len) {
179 if (cm3_len > sizeof(conn->classmark.classmark3)) {
180 LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
181 vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
182 cm3_len = sizeof(conn->classmark.classmark3);
183 }
184 conn->classmark.classmark3_len = cm3_len;
185 memcpy(conn->classmark.classmark3, cm3, cm3_len);
Harald Welte95e862c2012-01-23 10:28:35 +0100186 }
187}
188
Harald Welte2483f1b2016-06-19 18:06:02 +0200189/* Receive a CIPHERING MODE COMPLETE from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200190void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
191 struct msgb *msg, uint8_t alg_id)
Harald Weltecf149ee2012-01-23 16:40:24 +0100192{
Harald Welte2483f1b2016-06-19 18:06:02 +0200193 struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
Harald Weltecf149ee2012-01-23 16:40:24 +0100194
Harald Welte2483f1b2016-06-19 18:06:02 +0200195 if (!conn) {
Harald Welte284c39a2018-01-24 22:38:06 +0100196 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete on NULL conn\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200197 return;
198 }
199 if (!conn->vsub) {
Harald Welte284c39a2018-01-24 22:38:06 +0100200 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete for NULL subscr\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200201 return;
Harald Weltecf149ee2012-01-23 16:40:24 +0100202 }
203
Harald Welte284c39a2018-01-24 22:38:06 +0100204 DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n", vlr_subscr_name(conn->vsub));
Harald Welte2483f1b2016-06-19 18:06:02 +0200205
Harald Welte284c39a2018-01-24 22:38:06 +0100206 if (msg) {
207 struct gsm48_hdr *gh = msgb_l3(msg);
208 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
209 struct tlv_parsed tp;
210 uint8_t mi_type;
Harald Welte2483f1b2016-06-19 18:06:02 +0200211
Harald Welte284c39a2018-01-24 22:38:06 +0100212 if (!gh) {
213 LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
214 return;
215 }
216
217 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
218
219 /* bearer capability */
220 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
221 mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
222 if (mi_type == GSM_MI_TYPE_IMEISV
223 && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +0100224 gsm48_mi_to_string(ciph_res.imeisv, sizeof(ciph_res.imeisv),
Harald Welte284c39a2018-01-24 22:38:06 +0100225 TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
226 TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
Harald Welte284c39a2018-01-24 22:38:06 +0100227 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200228 }
229 }
230
231 ciph_res.cause = VLR_CIPH_COMPL;
232 vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
Harald Weltecf149ee2012-01-23 16:40:24 +0100233}
234
Harald Welte2483f1b2016-06-19 18:06:02 +0200235struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network)
236{
237 struct gsm_subscriber_connection *conn;
Harald Welte95e862c2012-01-23 10:28:35 +0100238
Harald Welte2483f1b2016-06-19 18:06:02 +0200239 conn = talloc_zero(network, struct gsm_subscriber_connection);
240 if (!conn)
241 return NULL;
Harald Welte95e862c2012-01-23 10:28:35 +0100242
Harald Welte2483f1b2016-06-19 18:06:02 +0200243 conn->network = network;
244 llist_add_tail(&conn->entry, &network->subscr_conns);
245 return conn;
246}
247
248void msc_subscr_cleanup(struct vlr_subscr *vsub)
249{
250 if (!vsub)
251 return;
252 vsub->lu_fsm = NULL;
253}
254
255void msc_subscr_con_cleanup(struct gsm_subscriber_connection *conn)
256{
257 if (!conn)
258 return;
259
260 if (conn->vsub) {
261 DEBUGP(DRLL, "subscr %s: Freeing subscriber connection\n",
262 vlr_subscr_name(conn->vsub));
263 msc_subscr_cleanup(conn->vsub);
Neels Hofmeyr1db394f2018-03-09 17:04:53 +0100264 conn->vsub->msc_conn_ref = NULL;
Harald Welte2483f1b2016-06-19 18:06:02 +0200265 vlr_subscr_put(conn->vsub);
266 conn->vsub = NULL;
267 } else
268 DEBUGP(DRLL, "Freeing subscriber connection"
269 " with NULL subscriber\n");
270
271 if (!conn->conn_fsm)
272 return;
273
274 osmo_fsm_inst_term(conn->conn_fsm,
275 (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED)
276 ? OSMO_FSM_TERM_REGULAR
277 : OSMO_FSM_TERM_ERROR,
278 NULL);
279}
280
281void msc_subscr_con_free(struct gsm_subscriber_connection *conn)
282{
283 if (!conn)
284 return;
285
286 msc_subscr_con_cleanup(conn);
287
288 llist_del(&conn->entry);
289 talloc_free(conn);
290}
291
292/* Receive a CLEAR REQUEST from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200293int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
Harald Welte2483f1b2016-06-19 18:06:02 +0200294{
295 msc_subscr_conn_close(conn, cause);
296 return 1;
297}
298
Harald Welte2483f1b2016-06-19 18:06:02 +0200299static void msc_subscr_conn_release_all(struct gsm_subscriber_connection *conn, uint32_t cause)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800300{
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800301 if (conn->in_release)
302 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200303 conn->in_release = true;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800304
Harald Welte2483f1b2016-06-19 18:06:02 +0200305 /* If we're closing in a middle of a trans, we need to clean up */
306 trans_conn_closed(conn);
307
308 switch (conn->via_ran) {
309 case RAN_UTRAN_IU:
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200310 ranap_iu_tx_release(conn->iu.ue_ctx, NULL);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200311 /* FIXME: keep the conn until the Iu Release Outcome is
312 * received from the UE, or a timeout expires. For now, the log
313 * says "unknown UE" for each release outcome. */
Harald Welte2483f1b2016-06-19 18:06:02 +0200314 break;
315 case RAN_GERAN_A:
Philipp Maierfbf66102017-04-09 12:32:51 +0200316 a_iface_tx_clear_cmd(conn);
Harald Welte2483f1b2016-06-19 18:06:02 +0200317 break;
318 default:
319 LOGP(DMM, LOGL_ERROR, "%s: Unknown RAN type, cannot tx release/clear\n",
320 vlr_subscr_name(conn->vsub));
321 break;
322 }
323}
324
325/* If the conn->conn_fsm is still present, dispatch SUBSCR_CONN_E_CN_CLOSE
326 * event to gracefully terminate the connection. If the conn_fsm is already
327 * cleared, call msc_subscr_conn_release_all() to take release actions.
328 * \param cause a GSM_CAUSE_* constant, e.g. GSM_CAUSE_AUTH_FAILED.
329 */
330void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
331 uint32_t cause)
332{
333 if (!conn)
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800334 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200335 if (conn->in_release) {
336 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
337 " already dispatching release, ignore.\n",
338 vlr_subscr_name(conn->vsub), cause);
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800339 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200340 }
341 if (!conn->conn_fsm) {
342 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u): no conn fsm,"
343 " releasing directly without release event.\n",
344 vlr_subscr_name(conn->vsub), cause);
345 /* In case of an IMSI Detach, we don't have conn_fsm. Release
346 * anyway to ensure a timely Iu Release / BSSMAP Clear. */
347 msc_subscr_conn_release_all(conn, cause);
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100348 return;
Harald Welte2483f1b2016-06-19 18:06:02 +0200349 }
350 if (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED) {
351 DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
352 " conn fsm already releasing, ignore.\n",
353 vlr_subscr_name(conn->vsub), cause);
354 return;
355 }
356 osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
357}
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800358
Harald Welte2483f1b2016-06-19 18:06:02 +0200359/* increment the ref-count. Needs to be called by every user */
360struct gsm_subscriber_connection *
361_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100362 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200363 const char *file, int line)
364{
365 OSMO_ASSERT(conn);
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200366
Harald Welte2483f1b2016-06-19 18:06:02 +0200367 if (conn->in_release)
Neels Hofmeyr785fadc2017-11-22 14:44:35 +0100368 LOGPSRC(DREF, LOGL_ERROR, file, line,
369 "%s: MSC conn use error: using conn that is already in release (%s)\n",
370 vlr_subscr_name(conn->vsub),
371 msc_subscr_conn_use_name(balance_token));
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200372
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100373 if (balance_token != MSC_CONN_USE_UNTRACKED) {
374 uint32_t flag = 1 << balance_token;
375 OSMO_ASSERT(balance_token < 32);
376 if (conn->use_tokens & flag)
377 LOGPSRC(DREF, LOGL_ERROR, file, line,
378 "%s: MSC conn use error: using an already used token: %s\n",
379 vlr_subscr_name(conn->vsub),
380 msc_subscr_conn_use_name(balance_token));
381 conn->use_tokens |= flag;
382 }
383
Harald Welte2483f1b2016-06-19 18:06:02 +0200384 conn->use_count++;
385 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100386 "%s: MSC conn use + %s == %u (0x%x)\n",
387 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
388 conn->use_count, conn->use_tokens);
Harald Welte2483f1b2016-06-19 18:06:02 +0200389
390 return conn;
391}
392
393/* decrement the ref-count. Once it reaches zero, we release */
394void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100395 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200396 const char *file, int line)
397{
398 OSMO_ASSERT(conn);
399
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100400 if (balance_token != MSC_CONN_USE_UNTRACKED) {
401 uint32_t flag = 1 << balance_token;
402 OSMO_ASSERT(balance_token < 32);
403 if (!(conn->use_tokens & flag))
404 LOGPSRC(DREF, LOGL_ERROR, file, line,
405 "%s: MSC conn use error: freeing an unused token: %s\n",
406 vlr_subscr_name(conn->vsub),
407 msc_subscr_conn_use_name(balance_token));
408 conn->use_tokens &= ~flag;
409 }
410
Harald Welte2483f1b2016-06-19 18:06:02 +0200411 if (conn->use_count == 0) {
412 LOGPSRC(DREF, LOGL_ERROR, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100413 "%s: MSC conn use - %s failed: is already 0\n",
414 vlr_subscr_name(conn->vsub),
415 msc_subscr_conn_use_name(balance_token));
Harald Welte2483f1b2016-06-19 18:06:02 +0200416 return;
417 }
418
419 conn->use_count--;
420 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100421 "%s: MSC conn use - %s == %u (0x%x)\n",
422 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
423 conn->use_count, conn->use_tokens);
Harald Welte2483f1b2016-06-19 18:06:02 +0200424
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200425 if (conn->use_count == 0)
426 msc_subscr_con_free(conn);
427}
428
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100429const struct value_string msc_subscr_conn_use_names[] = {
430 {MSC_CONN_USE_UNTRACKED, "UNTRACKED"},
431 {MSC_CONN_USE_COMPL_L3, "compl_l3"},
432 {MSC_CONN_USE_DTAP, "dtap"},
433 {MSC_CONN_USE_FSM, "fsm"},
434 {MSC_CONN_USE_TRANS_CC, "trans_cc"},
435 {MSC_CONN_USE_TRANS_SMS, "trans_sms"},
436 {MSC_CONN_USE_TRANS_USSD, "trans_ussd"},
437 {MSC_CONN_USE_SILENT_CALL, "silent_call"},
438 {0, NULL},
439};
440
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200441void msc_stop_paging(struct vlr_subscr *vsub)
442{
443 DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
444 /* tell BSCs and RNCs to stop paging? How? */
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800445}