blob: 2021ed8279fab0ce82289a56689c0f75a3bc999f [file] [log] [blame]
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001/* Manage all MSC roles of a connected subscriber (MSC-A, MSC-I, MSC-T) */
2/*
3 * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: AGPL-3.0+
7 *
8 * Author: Neels Hofmeyr
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <osmocom/gsm/gsm48.h>
25
26#include <osmocom/msc/msub.h>
27#include <osmocom/msc/msc_roles.h>
28#include <osmocom/msc/msc_a.h>
29#include <osmocom/msc/msc_i.h>
30#include <osmocom/msc/msc_t.h>
31#include <osmocom/msc/vlr.h>
32#include <osmocom/msc/e_link.h>
33
34const struct value_string msc_role_names[] = {
35 { MSC_ROLE_A, "MSC-A" },
36 { MSC_ROLE_I, "MSC-I" },
37 { MSC_ROLE_T, "MSC-T" },
38 {}
39};
40
41LLIST_HEAD(msub_list);
42
43#define for_each_msub_role(msub, role_idx) \
44 for ((role_idx) = 0; (role_idx) < ARRAY_SIZE((msub)->role); (role_idx)++) \
45 if ((msub)->role[role_idx])
46
47enum msub_fsm_state {
48 MSUB_ST_ACTIVE,
49 MSUB_ST_TERMINATING,
50};
51
52enum msub_fsm_event {
53 MSUB_EV_ROLE_TERMINATED,
54};
55
56static void msub_check_for_release(struct osmo_fsm_inst *fi)
57{
58 struct msub *msub = fi->priv;
Harald Weltedb6855c2019-05-09 10:28:43 +020059 struct msc_role_common *msc_role_a_c = NULL;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010060 enum msc_role role_idx;
61 int role_present[MSC_ROLES_COUNT] = {};
62 struct osmo_fsm_inst *child;
63
64 /* See what child FSMs are still present. A caller might exchange roles by first allocating a new one as child
65 * of this FSM, and then exchanging the msub->role[] pointer. Even though the currently active role is removing
66 * itself from msub, we can still see whether another one is pending as a child of this msub. */
67 llist_for_each_entry(child, &fi->proc.children, proc.child) {
68 struct msc_role_common *c = child->priv;
69 role_present[c->role]++;
70 if (c->role == MSC_ROLE_A)
71 msc_role_a_c = c;
72 }
73
74 /* Log. */
75 for (role_idx = 0; role_idx < ARRAY_SIZE(role_present); role_idx++) {
76 if (!role_present[role_idx])
77 continue;
78 LOG_MSUB(msub, LOGL_DEBUG, "%d %s still active\n", role_present[role_idx], msc_role_name(role_idx));
79 }
80
81 /* To remain valid, there must be both an MSC-A role and one of MSC-I or MSC-T;
82 * except, SGs connections need no MSC-I or MSC-T. */
83 if (role_present[MSC_ROLE_A]
84 && (role_present[MSC_ROLE_I] || role_present[MSC_ROLE_T]
85 || (msc_role_a_c && msc_role_a_c->ran->type == OSMO_RAT_EUTRAN_SGS)))
86 return;
87
88 /* The subscriber has become invalid. Go to terminating state to clearly signal that this msub is definitely
89 * going now. */
90 osmo_fsm_inst_state_chg(fi, MSUB_ST_TERMINATING, 0, 0);
91}
92
93void msub_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
94{
95 struct msub *msub = fi->priv;
96 struct osmo_fsm_inst *role_fi;
97
98 switch (event) {
99 case MSUB_EV_ROLE_TERMINATED:
100 role_fi = data;
101 /* Role implementations are required to pass their own osmo_fsm_inst pointer to osmo_fsm_inst_term(). */
102 msub_remove_role(msub, role_fi);
103 msub_check_for_release(fi);
104 return;
105 default:
106 return;
107 }
108}
109
110void msub_fsm_terminating_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
111{
112 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
113}
114
115void msub_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
116{
117 struct msub *msub = fi->priv;
118 LOG_MSUB(msub, LOGL_DEBUG, "Free\n");
119 msub_set_vsub(msub, NULL);
120 llist_del(&msub->entry);
121}
122
123#define S(x) (1 << (x))
124
125static const struct osmo_fsm_state msub_fsm_states[] = {
126 [MSUB_ST_ACTIVE] = {
127 .name = "active",
128 .in_event_mask = S(MSUB_EV_ROLE_TERMINATED),
129 .out_state_mask = S(MSUB_ST_TERMINATING),
130 .action = msub_fsm_active,
131 },
132 [MSUB_ST_TERMINATING] = {
133 .name = "terminating",
134 .onenter = msub_fsm_terminating_onenter,
135 },
136};
137
138static const struct value_string msub_fsm_event_names[] = {
139 OSMO_VALUE_STRING(MSUB_EV_ROLE_TERMINATED),
140 {}
141};
142
143struct osmo_fsm msub_fsm = {
144 .name = "msub_fsm",
145 .states = msub_fsm_states,
146 .num_states = ARRAY_SIZE(msub_fsm_states),
147 .log_subsys = DMSC,
148 .event_names = msub_fsm_event_names,
149 .cleanup = msub_fsm_cleanup,
150};
151
152static __attribute__((constructor)) void msub_fsm_init()
153{
154 OSMO_ASSERT(osmo_fsm_register(&msub_fsm) == 0);
155}
156
157struct msc_role_common *_msub_role_alloc(struct msub *msub, enum msc_role role, struct osmo_fsm *role_fsm,
158 size_t struct_size, const char *struct_name, struct ran_infra *ran)
159{
160 struct osmo_fsm_inst *fi;
161 struct msc_role_common *c;
162
163 fi = osmo_fsm_inst_alloc_child(role_fsm, msub->fi, MSUB_EV_ROLE_TERMINATED);
164 OSMO_ASSERT(fi);
165
166 c = (struct msc_role_common*)talloc_named_const(fi, struct_size, struct_name);
167 OSMO_ASSERT(c);
168 memset(c, 0, struct_size);
169 fi->priv = c;
170
171 *c = (struct msc_role_common){
172 .role = role,
173 .fi = fi,
174 .ran = ran,
175 };
176
177 msub_set_role(msub, fi);
178 return c;
179}
180
181struct msub *msub_alloc(struct gsm_network *net)
182{
183 struct msub *msub;
184 struct osmo_fsm_inst *msub_fi = osmo_fsm_inst_alloc(&msub_fsm, net, NULL, LOGL_DEBUG, NULL);
185 OSMO_ASSERT(msub_fi);
186
187 msub = talloc(msub_fi, struct msub);
188 OSMO_ASSERT(msub);
189 msub_fi->priv = msub;
190 *msub = (struct msub){
191 .net = net,
192 .fi = msub_fi,
193 };
194
195 llist_add_tail(&msub->entry, &msub_list);
196 return msub;
197}
198
199/* Careful: the subscriber may not yet be authenticated, or may already be in release. Better use
200 * msc_a_for_vsub(for_vsub, true) to make sure you don't use an invalid conn. */
201struct msub *msub_for_vsub(const struct vlr_subscr *for_vsub)
202{
203 struct msub *msub;
204 if (!for_vsub)
205 return NULL;
206
207 llist_for_each_entry(msub, &msub_list, entry) {
208 if (msub->vsub == for_vsub)
209 return msub;
210 }
211
212 return NULL;
213}
214
215const char *msub_name(const struct msub *msub)
216{
217 return vlr_subscr_name(msub? msub->vsub : NULL);
218}
219
220void msub_set_role(struct msub *msub, struct osmo_fsm_inst *msc_role)
221{
222 struct osmo_fsm_inst *prev_role;
223 struct msc_role_common *c;
224
225 OSMO_ASSERT(msc_role);
226 c = msc_role->priv;
227
228 prev_role = msub->role[c->role];
229 if (prev_role)
230 LOGPFSML(prev_role, LOGL_DEBUG, "Replaced by another %s\n", msc_role_name(c->role));
231
232 c->msub = msub;
233 msub->role[c->role] = msc_role;
234 msub_update_id(msub);
235
236 if (prev_role) {
237 struct msc_role_common *prev_c = prev_role->priv;
238 switch (prev_c->role) {
239 case MSC_ROLE_I:
240 msc_i_clear(prev_role->priv);
241 break;
242 case MSC_ROLE_T:
243 msc_t_clear(prev_role->priv);
244 break;
245 default:
246 osmo_fsm_inst_term(prev_role, OSMO_FSM_TERM_REQUEST, prev_role);
247 break;
248 }
249 }
250}
251
252void msub_remove_role(struct msub *msub, struct osmo_fsm_inst *fi)
253{
254 enum msc_role idx;
255 struct msc_role_common *c;
256 if (!msub || !fi)
257 return;
258
259 c = fi->priv;
260 LOG_MSUB(msub, LOGL_DEBUG, "%s terminated\n", msc_role_name(c->role));
261
262 for_each_msub_role(msub, idx) {
263 if (msub->role[idx] == fi)
264 msub->role[idx] = NULL;
265 }
266}
267
268struct msc_a *msub_msc_a(const struct msub *msub)
269{
270 struct osmo_fsm_inst *fi;
271 if (!msub)
272 return NULL;
273 fi = msub->role[MSC_ROLE_A];
274 if (!fi)
275 return NULL;
276 return (struct msc_a*)fi->priv;
277}
278
279struct msc_i *msub_msc_i(const struct msub *msub)
280{
281 struct osmo_fsm_inst *fi;
282 if (!msub)
283 return NULL;
284 fi = msub->role[MSC_ROLE_I];
285 if (!fi)
286 return NULL;
287 return (struct msc_i*)fi->priv;
288}
289
290struct msc_t *msub_msc_t(const struct msub *msub)
291{
292 struct osmo_fsm_inst *fi;
293 if (!msub)
294 return NULL;
295 fi = msub->role[MSC_ROLE_T];
296 if (!fi)
297 return NULL;
298 return (struct msc_t*)fi->priv;
299}
300
301/* Return the ran_conn of the MSC-I role, if available. If the MSC-I role is handled by a remote MSC, return NULL. */
302struct ran_conn *msub_ran_conn(const struct msub *msub)
303{
304 struct msc_i *msc_i = msub_msc_i(msub);
305 if (!msc_i)
306 return NULL;
307 return msc_i->ran_conn;
308}
309
310static struct ran_infra *msub_ran(const struct msub *msub)
311{
312 int i;
313 struct msc_role_common *c;
314
315 for (i = 0; i < MSC_ROLES_COUNT; i++) {
316 if (!msub->role[i])
317 continue;
318 c = msub->role[i]->priv;
319 if (!c->ran)
320 continue;
321 return c->ran;
322 }
323
324 return &msc_ran_infra[OSMO_RAT_UNKNOWN];
325}
326
327const char *msub_ran_conn_name(const struct msub *msub)
328{
329 struct msc_i *msc_i = msub_msc_i(msub);
330 struct msc_t *msc_t = msub_msc_t(msub);
331 if (msc_i && msc_i->c.remote_to)
332 return e_link_name(msc_i->c.remote_to);
333 if (msc_i && msc_i->ran_conn)
334 return ran_conn_name(msc_i->ran_conn);
335 if (msc_t && msc_t->c.remote_to)
336 return e_link_name(msc_t->c.remote_to);
337 if (msc_t && msc_t->ran_conn)
338 return ran_conn_name(msc_t->ran_conn);
339 return osmo_rat_type_name(msub_ran(msub)->type);
340}
341
342int msub_set_vsub(struct msub *msub, struct vlr_subscr *vsub)
343{
344 OSMO_ASSERT(msub);
345 if (msub->vsub == vsub)
346 return 0;
347 if (msub->vsub && vsub) {
348 LOG_MSUB(msub, LOGL_ERROR,
349 "Changing a connection's VLR Subscriber is not allowed: not changing to %s\n",
350 vlr_subscr_name(vsub));
351 return -ENOTSUP;
352 }
353 if (vsub) {
354 struct msub *other_msub = msub_for_vsub(vsub);
355 if (other_msub) {
356 struct msc_a *msc_a = msub_msc_a(msub);
357 struct msc_a *other_msc_a = msub_msc_a(other_msub);
358 LOG_MSC_A(msc_a, LOGL_ERROR,
359 "Cannot associate with VLR subscr, another connection is already active%s%s\n",
360 other_msc_a ? " at " : "", other_msc_a ? other_msc_a->c.fi->id : "");
361 LOG_MSC_A(other_msc_a, LOGL_ERROR, "Attempt to associate a second subscriber connection%s%s\n",
362 msc_a ? " at " : "", msc_a ? msc_a->c.fi->id : "");
363 if (other_msc_a && msc_a_in_release(other_msc_a)) {
364 LOG_MSC_A(other_msc_a, LOGL_ERROR,
365 "Another connection for this subscriber is coming up, since this"
366 " is already in release, forcefully discarding it\n");
367 osmo_fsm_inst_term(other_msc_a->c.fi, OSMO_FSM_TERM_ERROR, other_msc_a->c.fi);
368 /* Count this as "recovered from duplicate connection" error and do associate. */
369 } else
370 return -EINVAL;
371 }
372 }
373 if (msub->vsub) {
374 vlr_subscr_put(msub->vsub, VSUB_USE_MSUB);
375 msub->vsub = NULL;
376 }
377 if (vsub) {
378 vlr_subscr_get(vsub, VSUB_USE_MSUB);
379 msub->vsub = vsub;
380 vsub->cs.attached_via_ran = msub_ran(msub)->type;
381 msub_update_id(msub);
382 }
383 return 0;
384}
385
386struct vlr_subscr *msub_vsub(const struct msub *msub)
387{
388 return msub ? msub->vsub : NULL;
389}
390
391struct gsm_network *msub_net(const struct msub *msub)
392{
393 OSMO_ASSERT(msub->net);
394 return msub->net;
395}
396
397int msub_role_to_role_event(struct msub *msub, enum msc_role from_role, enum msc_role to_role)
398{
399 switch (from_role) {
400 case MSC_ROLE_A:
401 switch (to_role) {
402 case MSC_ROLE_I:
403 return MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST;
404 case MSC_ROLE_T:
405 return MSC_T_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST;
406 default:
407 break;
408 }
409 break;
410
411 case MSC_ROLE_I:
412 switch (to_role) {
413 case MSC_ROLE_A:
414 return MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST;
415 default:
416 break;
417 }
418 break;
419
420 case MSC_ROLE_T:
421 switch (to_role) {
422 case MSC_ROLE_A:
423 return MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST;
424 default:
425 break;
426 }
427 break;
428
429 default:
430 break;
431 }
432
433 LOG_MSUB(msub, LOGL_ERROR, "Cannot tx DTAP from %s to %s\n", msc_role_name(from_role), msc_role_name(to_role));
434 return -1;
435}
436
437/* The caller retains ownership of the an_apdu_msg -- don't forget to msgb_free() it. */
438int _msub_role_dispatch(struct msub *msub, enum msc_role to_role, uint32_t to_role_event, const struct an_apdu *an_apdu,
439 const char *file, int line)
440{
441 struct osmo_fsm_inst *to_fi = msub->role[to_role];
442
443 if (!to_fi) {
444 LOG_MSUB_CAT_SRC(msub, DMSC, LOGL_ERROR, file, line,
445 "Cannot tx event to %s, no such role defined\n", msc_role_name(to_role));
446 return -EINVAL;
447 }
448
449 return _osmo_fsm_inst_dispatch(to_fi, to_role_event, (void*)an_apdu, file, line);
450}
451
452/* The caller retains ownership of the an_apdu_msg -- don't forget to msgb_free() it. */
453int msub_tx_an_apdu(struct msub *msub, enum msc_role from_role, enum msc_role to_role, struct an_apdu *an_apdu)
454{
455 int event = msub_role_to_role_event(msub, from_role, to_role);
456 if (event < 0)
457 return event;
458 return msub_role_dispatch(msub, to_role, event, an_apdu);
459}
460
461static void _msub_update_id(struct msub *msub, const char *subscr_name)
462{
463 enum msc_role idx;
464 struct msc_a *msc_a = msub_msc_a(msub);
465 struct vlr_subscr *vsub = msub_vsub(msub);
466 const char *compl_l3_name = NULL;
467 char id[128];
468
469 if (msc_a)
470 compl_l3_name = get_value_string_or_null(complete_layer3_type_names, msc_a->complete_layer3_type);
471 if (!compl_l3_name)
472 compl_l3_name = "no-compl-l3";
473
474 snprintf(id, sizeof(id), "%s:%s:%s", subscr_name, msub_ran_conn_name(msub), compl_l3_name);
475 osmo_identifier_sanitize_buf(id, NULL, '-');
476
477 for_each_msub_role(msub, idx) {
478 osmo_fsm_inst_update_id(msub->role[idx], id);
479 }
480 if (vsub) {
481 if (vsub->lu_fsm)
482 osmo_fsm_inst_update_id(vsub->lu_fsm, id);
483 if (vsub->auth_fsm)
484 osmo_fsm_inst_update_id(vsub->auth_fsm, id);
485 if (vsub->proc_arq_fsm)
486 osmo_fsm_inst_update_id(vsub->proc_arq_fsm, id);
487 }
488}
489
490/* Compose an ID almost like gsm48_mi_to_string(), but print the MI type along, and print a TMSI as hex. */
491void msub_update_id_from_mi(struct msub *msub, const uint8_t mi[], uint8_t mi_len)
492{
493 _msub_update_id(msub, osmo_mi_name(mi, mi_len));
494}
495
496/* Update msub->fi id string from current msub->vsub and msub->complete_layer3_type. */
497void msub_update_id(struct msub *msub)
498{
499 if (!msub)
500 return;
501 _msub_update_id(msub, vlr_subscr_name(msub->vsub));
502}
503
504/* Iterate all msub instances that are relevant for this subscriber, and update FSM ID strings for all of the FSM
505 * instances. */
506void msub_update_id_for_vsub(struct vlr_subscr *for_vsub)
507{
508 struct msub *msub;
509 if (!for_vsub)
510 return;
511
512 llist_for_each_entry(msub, &msub_list, entry) {
513 if (msub->vsub == for_vsub)
514 msub_update_id(msub);
515 }
516}
517
518void msc_role_forget_conn(struct osmo_fsm_inst *role, struct ran_conn *conn)
519{
520 struct msc_i *old_i = role->priv;
521 struct msc_t *old_t = role->priv;
522 struct msc_role_common *c = role->priv;
523 struct ran_conn **conn_p = NULL;
524
525 switch (c->role) {
526 case MSC_ROLE_I:
527 conn_p = &old_i->ran_conn;
528 break;
529
530 case MSC_ROLE_T:
531 conn_p = &old_t->ran_conn;
532 break;
533 default:
534 break;
535 }
536
537 if (!conn_p)
538 return;
539
540 if (*conn_p != conn)
541 return;
542
543 (*conn_p)->msc_role = NULL;
544 *conn_p = NULL;
545}
546
547struct msgb *msc_role_ran_encode(struct osmo_fsm_inst *fi, const struct ran_msg *ran_msg)
548{
549 struct msc_role_common *c = fi->priv;
550 struct msgb *msg;
551 if (!c->ran->ran_encode) {
552 LOGPFSML(fi, LOGL_ERROR, "Cannot encode %s: no NAS encoding function defined for RAN type %s\n",
553 ran_msg_type_name(ran_msg->msg_type), osmo_rat_type_name(c->ran->type));
554 return NULL;
555 }
556 msg = c->ran->ran_encode(fi, ran_msg);
557 if (!msg)
558 LOGPFSML(fi, LOGL_ERROR, "Failed to encode %s\n", ran_msg_type_name(ran_msg->msg_type));
559 return msg;
560}
561
562int msc_role_ran_decode(struct osmo_fsm_inst *fi, const struct an_apdu *an_apdu,
563 ran_decode_cb_t decode_cb, void *decode_cb_data)
564{
565 struct ran_dec ran_dec;
566 struct msc_role_common *c = fi->priv;
567 if (!an_apdu) {
568 LOGPFSML(fi, LOGL_ERROR, "NULL AN-APDU\n");
569 return -EINVAL;
570 }
571 if (an_apdu->an_proto != c->ran->an_proto) {
572 LOGPFSML(fi, LOGL_ERROR, "Unexpected AN-APDU protocol: %s\n", an_proto_name(an_apdu->an_proto));
573 return -EINVAL;
574 }
575 if (!an_apdu->msg) {
576 LOGPFSML(fi, LOGL_DEBUG, "No PDU in this AN-APDU\n");
577 return 0;
578 }
579 ran_dec = (struct ran_dec) {
580 .caller_fi = fi,
581 .caller_data = decode_cb_data,
582 .decode_cb = decode_cb,
583 };
584 if (!c->ran->ran_dec_l2) {
585 LOGPFSML(fi, LOGL_ERROR, "No ran_dec_l2() defined for RAN type %s\n",
586 osmo_rat_type_name(c->ran->type));
587 return -ENOTSUP;
588 }
589 return c->ran->ran_dec_l2(&ran_dec, an_apdu->msg);
590}