blob: a6618c093265aa0857f0b01ba6bd977411a25f2e [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");
Vadim Yanitskiyad64e2a2018-06-26 18:27:25 +070070 net->active_nc_ss = osmo_counter_alloc("msc.active_nc_ss");
Neels Hofmeyr55014d02018-03-22 16:43:40 +010071
72 net->mncc_recv = mncc_recv;
73
74 INIT_LLIST_HEAD(&net->a.bscs);
75
76 return net;
77}
78
Harald Welte2483f1b2016-06-19 18:06:02 +020079/* Receive a SAPI-N-REJECT from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +020080void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080081{
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +080082 int sapi = dlci & 0x7;
83
84 if (sapi == UM_SAPI_SMS)
85 gsm411_sapi_n_reject(conn);
Holger Hans Peter Freyther43b09092010-06-15 11:52:51 +080086}
87
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020088/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
89 * MSC_CONN_REJECT */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020090int msc_compl_l3(struct gsm_subscriber_connection *conn,
91 struct msgb *msg, uint16_t chosen_channel)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080092{
Neels Hofmeyr6166f292017-11-22 14:33:12 +010093 msc_subscr_conn_get(conn, MSC_CONN_USE_COMPL_L3);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +080094 gsm0408_dispatch(conn, msg);
95
Neels Hofmeyr6166f292017-11-22 14:33:12 +010096 msc_subscr_conn_put(conn, MSC_CONN_USE_COMPL_L3);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020097
98 /* Always return acceptance, because even if the conn was not accepted,
99 * we assumed ownership of it and the caller shall not interfere with
100 * that. We may even already have discarded the 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 */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200122void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800123{
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100124 msc_subscr_conn_get(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800125 gsm0408_dispatch(conn, msg);
Harald Welte2483f1b2016-06-19 18:06:02 +0200126
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100127 msc_subscr_conn_put(conn, MSC_CONN_USE_DTAP);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800128}
129
Harald Welte2483f1b2016-06-19 18:06:02 +0200130/* Receive an ASSIGNMENT COMPLETE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200131void msc_assign_compl(struct gsm_subscriber_connection *conn,
132 uint8_t rr_cause, uint8_t chosen_channel,
133 uint8_t encr_alg_id, uint8_t speec)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100134{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100135 LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100136}
137
Harald Welte2483f1b2016-06-19 18:06:02 +0200138/* Receive an ASSIGNMENT FAILURE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200139void msc_assign_fail(struct gsm_subscriber_connection *conn,
140 uint8_t cause, uint8_t *rr_cause)
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100141{
Jacob Erlbeck8e68b562014-01-30 21:01:12 +0100142 LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
Holger Hans Peter Freyther40aac3f2011-12-27 12:31:02 +0100143}
144
Harald Welte2483f1b2016-06-19 18:06:02 +0200145/* Receive a CLASSMARK CHANGE from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200146void msc_classmark_chg(struct gsm_subscriber_connection *conn,
147 const uint8_t *cm2, uint8_t cm2_len,
148 const uint8_t *cm3, uint8_t cm3_len)
Harald Welte95e862c2012-01-23 10:28:35 +0100149{
Harald Welte2483f1b2016-06-19 18:06:02 +0200150 if (cm2 && cm2_len) {
151 if (cm2_len > sizeof(conn->classmark.classmark2)) {
152 LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
153 vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
154 cm2_len = sizeof(conn->classmark.classmark2);
Harald Welte95e862c2012-01-23 10:28:35 +0100155 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200156 conn->classmark.classmark2_len = cm2_len;
157 memcpy(conn->classmark.classmark2, cm2, cm2_len);
158 }
159 if (cm3 && cm3_len) {
160 if (cm3_len > sizeof(conn->classmark.classmark3)) {
161 LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
162 vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
163 cm3_len = sizeof(conn->classmark.classmark3);
164 }
165 conn->classmark.classmark3_len = cm3_len;
166 memcpy(conn->classmark.classmark3, cm3, cm3_len);
Harald Welte95e862c2012-01-23 10:28:35 +0100167 }
168}
169
Harald Welte2483f1b2016-06-19 18:06:02 +0200170/* Receive a CIPHERING MODE COMPLETE from BSC */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200171void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
172 struct msgb *msg, uint8_t alg_id)
Harald Weltecf149ee2012-01-23 16:40:24 +0100173{
Harald Welte2483f1b2016-06-19 18:06:02 +0200174 struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
Harald Weltecf149ee2012-01-23 16:40:24 +0100175
Harald Welte2483f1b2016-06-19 18:06:02 +0200176 if (!conn) {
Harald Welte284c39a2018-01-24 22:38:06 +0100177 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete on NULL conn\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200178 return;
179 }
180 if (!conn->vsub) {
Harald Welte284c39a2018-01-24 22:38:06 +0100181 LOGP(DRR, LOGL_ERROR, "invalid: rx Ciphering Mode Complete for NULL subscr\n");
Harald Welte2483f1b2016-06-19 18:06:02 +0200182 return;
Harald Weltecf149ee2012-01-23 16:40:24 +0100183 }
184
Harald Welte284c39a2018-01-24 22:38:06 +0100185 DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n", vlr_subscr_name(conn->vsub));
Harald Welte2483f1b2016-06-19 18:06:02 +0200186
Harald Welte284c39a2018-01-24 22:38:06 +0100187 if (msg) {
188 struct gsm48_hdr *gh = msgb_l3(msg);
189 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
190 struct tlv_parsed tp;
191 uint8_t mi_type;
Harald Welte2483f1b2016-06-19 18:06:02 +0200192
Harald Welte284c39a2018-01-24 22:38:06 +0100193 if (!gh) {
194 LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
195 return;
196 }
197
198 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
199
200 /* bearer capability */
201 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
202 mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
203 if (mi_type == GSM_MI_TYPE_IMEISV
204 && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +0100205 gsm48_mi_to_string(ciph_res.imeisv, sizeof(ciph_res.imeisv),
Harald Welte284c39a2018-01-24 22:38:06 +0100206 TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
207 TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
Harald Welte284c39a2018-01-24 22:38:06 +0100208 }
Harald Welte2483f1b2016-06-19 18:06:02 +0200209 }
210 }
211
212 ciph_res.cause = VLR_CIPH_COMPL;
213 vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
Harald Weltecf149ee2012-01-23 16:40:24 +0100214}
215
Harald Welte2483f1b2016-06-19 18:06:02 +0200216/* Receive a CLEAR REQUEST from BSC */
Philipp Maierfbf66102017-04-09 12:32:51 +0200217int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
Harald Welte2483f1b2016-06-19 18:06:02 +0200218{
219 msc_subscr_conn_close(conn, cause);
220 return 1;
221}
222
Neels Hofmeyr99a8d232018-04-09 20:44:56 +0200223static const char *used_ref_counts_str(struct gsm_subscriber_connection *conn)
224{
225 static char buf[256];
226 int bit_nr;
227 char *pos = buf;
228 *pos = '\0';
229
230 if (conn->use_tokens < 0)
231 return "invalid";
232
233#define APPEND_STR(fmt, args...) do { \
234 int remain = sizeof(buf) - (pos - buf) - 1; \
235 int l = -1; \
236 if (remain > 0) \
237 l = snprintf(pos, remain, "%s" fmt, (pos == buf? "" : ","), ##args); \
238 if (l < 0 || l > remain) { \
239 buf[sizeof(buf) - 1] = '\0'; \
240 return buf; \
241 } \
242 pos += l; \
243 } while(0)
244
245 for (bit_nr = 0; (1 << bit_nr) <= conn->use_tokens; bit_nr++) {
246 if (conn->use_tokens & (1 << bit_nr)) {
247 APPEND_STR("%s", get_value_string(msc_subscr_conn_use_names, bit_nr));
248 }
249 }
250 return buf;
251#undef APPEND_STR
252}
253
Harald Welte2483f1b2016-06-19 18:06:02 +0200254/* increment the ref-count. Needs to be called by every user */
255struct gsm_subscriber_connection *
256_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100257 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200258 const char *file, int line)
259{
260 OSMO_ASSERT(conn);
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200261
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100262 if (balance_token != MSC_CONN_USE_UNTRACKED) {
263 uint32_t flag = 1 << balance_token;
264 OSMO_ASSERT(balance_token < 32);
265 if (conn->use_tokens & flag)
266 LOGPSRC(DREF, LOGL_ERROR, file, line,
267 "%s: MSC conn use error: using an already used token: %s\n",
268 vlr_subscr_name(conn->vsub),
269 msc_subscr_conn_use_name(balance_token));
270 conn->use_tokens |= flag;
271 }
272
Harald Welte2483f1b2016-06-19 18:06:02 +0200273 conn->use_count++;
274 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr99a8d232018-04-09 20:44:56 +0200275 "%s: MSC conn use + %s == %u (0x%x: %s)\n",
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100276 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
Neels Hofmeyr99a8d232018-04-09 20:44:56 +0200277 conn->use_count, conn->use_tokens, used_ref_counts_str(conn));
Harald Welte2483f1b2016-06-19 18:06:02 +0200278
279 return conn;
280}
281
282/* decrement the ref-count. Once it reaches zero, we release */
283void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100284 enum msc_subscr_conn_use balance_token,
Harald Welte2483f1b2016-06-19 18:06:02 +0200285 const char *file, int line)
286{
287 OSMO_ASSERT(conn);
288
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100289 if (balance_token != MSC_CONN_USE_UNTRACKED) {
290 uint32_t flag = 1 << balance_token;
291 OSMO_ASSERT(balance_token < 32);
292 if (!(conn->use_tokens & flag))
293 LOGPSRC(DREF, LOGL_ERROR, file, line,
294 "%s: MSC conn use error: freeing an unused token: %s\n",
295 vlr_subscr_name(conn->vsub),
296 msc_subscr_conn_use_name(balance_token));
297 conn->use_tokens &= ~flag;
298 }
299
Harald Welte2483f1b2016-06-19 18:06:02 +0200300 if (conn->use_count == 0) {
301 LOGPSRC(DREF, LOGL_ERROR, file, line,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100302 "%s: MSC conn use - %s failed: is already 0\n",
303 vlr_subscr_name(conn->vsub),
304 msc_subscr_conn_use_name(balance_token));
Harald Welte2483f1b2016-06-19 18:06:02 +0200305 return;
306 }
307
308 conn->use_count--;
309 LOGPSRC(DREF, LOGL_DEBUG, file, line,
Neels Hofmeyr99a8d232018-04-09 20:44:56 +0200310 "%s: MSC conn use - %s == %u (0x%x: %s)\n",
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100311 vlr_subscr_name(conn->vsub), msc_subscr_conn_use_name(balance_token),
Neels Hofmeyr99a8d232018-04-09 20:44:56 +0200312 conn->use_count, conn->use_tokens, used_ref_counts_str(conn));
Harald Welte2483f1b2016-06-19 18:06:02 +0200313
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200314 if (conn->use_count == 0)
Neels Hofmeyre3d3dc62018-03-31 00:02:14 +0200315 osmo_fsm_inst_dispatch(conn->fi, SUBSCR_CONN_E_UNUSED, NULL);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200316}
317
Neels Hofmeyr4068ab22018-04-01 20:55:54 +0200318bool msc_subscr_conn_used_by(struct gsm_subscriber_connection *conn, enum msc_subscr_conn_use token)
319{
320 return conn && (conn->use_tokens & (1 << token));
321}
322
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100323const struct value_string msc_subscr_conn_use_names[] = {
324 {MSC_CONN_USE_UNTRACKED, "UNTRACKED"},
325 {MSC_CONN_USE_COMPL_L3, "compl_l3"},
326 {MSC_CONN_USE_DTAP, "dtap"},
Neels Hofmeyre3d3dc62018-03-31 00:02:14 +0200327 {MSC_CONN_USE_AUTH_CIPH, "auth+ciph"},
328 {MSC_CONN_USE_CM_SERVICE, "cm_service"},
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100329 {MSC_CONN_USE_TRANS_CC, "trans_cc"},
330 {MSC_CONN_USE_TRANS_SMS, "trans_sms"},
Vadim Yanitskiy846efcb2018-06-10 22:22:49 +0700331 {MSC_CONN_USE_TRANS_NC_SS, "trans_nc_ss"},
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100332 {MSC_CONN_USE_SILENT_CALL, "silent_call"},
Neels Hofmeyre3d3dc62018-03-31 00:02:14 +0200333 {MSC_CONN_USE_RELEASE, "release"},
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100334 {0, NULL},
335};
336
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200337void msc_stop_paging(struct vlr_subscr *vsub)
338{
339 DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
340 /* tell BSCs and RNCs to stop paging? How? */
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800341}