blob: ea7529eb3c4d4f326e3012f651b8cc00b6500ba5 [file] [log] [blame]
Harald Welteb8b85a12016-06-17 00:06:42 +02001/* Osmocom Visitor Location Register (VLR): Location Update FSMs */
2
3/* (C) 2016 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <osmocom/core/fsm.h>
Max43b01b02017-09-15 11:22:30 +020023#include <osmocom/gsm/gsm48.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020024#include <osmocom/gsm/gsup.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020025#include <osmocom/msc/vlr.h>
26#include <osmocom/msc/debug.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020027
28#include "vlr_core.h"
29#include "vlr_auth_fsm.h"
30#include "vlr_lu_fsm.h"
31
32#define S(x) (1 << (x))
33
34#define LU_TIMEOUT_LONG 30
35
36enum vlr_fsm_result {
37 VLR_FSM_RESULT_NONE,
38 VLR_FSM_RESULT_SUCCESS,
39 VLR_FSM_RESULT_FAILURE,
40};
41
42
43/***********************************************************************
44 * Update_HLR_VLR, TS 23.012 Chapter 4.1.2.4
45 ***********************************************************************/
46
47enum upd_hlr_vlr_state {
48 UPD_HLR_VLR_S_INIT,
49 UPD_HLR_VLR_S_WAIT_FOR_DATA,
50 UPD_HLR_VLR_S_DONE,
51};
52
53enum upd_hlr_vlr_evt {
54 UPD_HLR_VLR_E_START,
55 UPD_HLR_VLR_E_INS_SUB_DATA,
56 UPD_HLR_VLR_E_ACT_TRACE_MODE,
57 UPD_HLR_VLR_E_FW_CHECK_SS_IND,
58 UPD_HLR_VLR_E_UPD_LOC_ACK,
59 UPD_HLR_VLR_E_UPD_LOC_NACK,
60};
61
62static const struct value_string upd_hlr_vlr_event_names[] = {
63 OSMO_VALUE_STRING(UPD_HLR_VLR_E_START),
64 OSMO_VALUE_STRING(UPD_HLR_VLR_E_INS_SUB_DATA),
65 OSMO_VALUE_STRING(UPD_HLR_VLR_E_ACT_TRACE_MODE),
66 OSMO_VALUE_STRING(UPD_HLR_VLR_E_FW_CHECK_SS_IND),
67 OSMO_VALUE_STRING(UPD_HLR_VLR_E_UPD_LOC_ACK),
68 OSMO_VALUE_STRING(UPD_HLR_VLR_E_UPD_LOC_NACK),
69 { 0, NULL }
70};
71
72static void upd_hlr_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
73 void *data)
74{
75 struct vlr_subscr *vsub = fi->priv;
76
77 OSMO_ASSERT(event == UPD_HLR_VLR_E_START);
78
79 /* Send UpdateLocation to HLR */
80 vlr_subscr_req_lu(vsub, vsub->vlr->cfg.is_ps);
81 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_WAIT_FOR_DATA,
82 LU_TIMEOUT_LONG, 0);
83}
84
85static void upd_hlr_vlr_fsm_wait_data(struct osmo_fsm_inst *fi, uint32_t event,
86 void *data)
87{
88 struct vlr_subscr *vsub = fi->priv;
89
90 switch (event) {
91 case UPD_HLR_VLR_E_INS_SUB_DATA:
92 /* FIXME: Insert_Subscr_Data_VLR */
93 break;
94 case UPD_HLR_VLR_E_ACT_TRACE_MODE:
95 /* TODO: Activate_Tracing_VLR */
96 break;
97 case UPD_HLR_VLR_E_FW_CHECK_SS_IND:
98 /* TODO: Forward Check SS Ind to MSC */
99 break;
100 case UPD_HLR_VLR_E_UPD_LOC_ACK:
101 /* Inside Update_HLR_VLR after UpdateLocationAck */
102 vsub->sub_dataconf_by_hlr_ind = true;
103 vsub->loc_conf_in_hlr_ind = true;
104 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
105 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
106 break;
107 case UPD_HLR_VLR_E_UPD_LOC_NACK:
108 /* Inside Update_HLR_VLR after UpdateLocationNack */
109 /* TODO: Check_User_Error_In_Serving_Network_Entity */
110 vsub->sub_dataconf_by_hlr_ind = false;
111 vsub->loc_conf_in_hlr_ind = false;
112 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
113 /* Data is a pointer to a gsm48_gmm_cause which we
114 * simply pass through */
115 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, data);
116 break;
117 }
118}
119
120static const struct osmo_fsm_state upd_hlr_vlr_states[] = {
121 [UPD_HLR_VLR_S_INIT] = {
122 .in_event_mask = S(UPD_HLR_VLR_E_START),
123 .out_state_mask = S(UPD_HLR_VLR_S_WAIT_FOR_DATA),
124 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_INIT),
125 .action = upd_hlr_vlr_fsm_init,
126 },
127 [UPD_HLR_VLR_S_WAIT_FOR_DATA] = {
128 .in_event_mask = S(UPD_HLR_VLR_E_INS_SUB_DATA) |
129 S(UPD_HLR_VLR_E_ACT_TRACE_MODE) |
130 S(UPD_HLR_VLR_E_FW_CHECK_SS_IND) |
131 S(UPD_HLR_VLR_E_UPD_LOC_ACK) |
132 S(UPD_HLR_VLR_E_UPD_LOC_NACK),
133 .out_state_mask = S(UPD_HLR_VLR_S_DONE),
134 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_WAIT_FOR_DATA),
135 .action = upd_hlr_vlr_fsm_wait_data,
136 },
137 [UPD_HLR_VLR_S_DONE] = {
138 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_DONE),
139 },
140};
141
142static struct osmo_fsm upd_hlr_vlr_fsm = {
143 .name = "upd_hlr_vlr_fsm",
144 .states = upd_hlr_vlr_states,
145 .num_states = ARRAY_SIZE(upd_hlr_vlr_states),
146 .allstate_event_mask = 0,
147 .allstate_action = NULL,
148 .log_subsys = DVLR,
149 .event_names = upd_hlr_vlr_event_names,
150};
151
152struct osmo_fsm_inst *
153upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
154 struct vlr_subscr *vsub,
155 uint32_t parent_event)
156{
157 struct osmo_fsm_inst *fi;
158
159 fi = osmo_fsm_inst_alloc_child(&upd_hlr_vlr_fsm, parent,
160 parent_event);
161 if (!fi)
162 return NULL;
163
164 fi->priv = vsub;
165 osmo_fsm_inst_dispatch(fi, UPD_HLR_VLR_E_START, NULL);
166
167 return fi;
168}
169
170
171/***********************************************************************
172 * Subscriber_Present_VLR, TS 29.002 Chapter 25.10.1
173 ***********************************************************************/
174
175enum sub_pres_vlr_state {
176 SUB_PRES_VLR_S_INIT,
177 SUB_PRES_VLR_S_WAIT_FOR_HLR,
178 SUB_PRES_VLR_S_DONE,
179};
180
181enum sub_pres_vlr_event {
182 SUB_PRES_VLR_E_START,
183 SUB_PRES_VLR_E_READY_SM_CNF,
184 SUB_PRES_VLR_E_READY_SM_ERR,
185};
186
187static const struct value_string sub_pres_vlr_event_names[] = {
188 OSMO_VALUE_STRING(SUB_PRES_VLR_E_START),
189 OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_CNF),
190 OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_ERR),
191 { 0, NULL }
192};
193
194static void sub_pres_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
195 void *data)
196{
197 struct vlr_subscr *vsub = fi->priv;
198 OSMO_ASSERT(event == SUB_PRES_VLR_E_START);
199
200 if (!vsub->ms_not_reachable_flag) {
201 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
202 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
203 return;
204 }
205 /* FIXME: Send READY_FOR_SM via GSUP */
206 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_WAIT_FOR_HLR,
207 LU_TIMEOUT_LONG, 0);
208}
209
210static void sub_pres_vlr_fsm_wait_hlr(struct osmo_fsm_inst *fi, uint32_t event,
211 void *data)
212{
213 struct vlr_subscr *vsub = fi->priv;
214
215 switch (event) {
216 case SUB_PRES_VLR_E_READY_SM_CNF:
217 vsub->ms_not_reachable_flag = false;
218 break;
219 case SUB_PRES_VLR_E_READY_SM_ERR:
220 break;
221 }
222 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
223 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
224}
225
226static const struct osmo_fsm_state sub_pres_vlr_states[] = {
227 [SUB_PRES_VLR_S_INIT] = {
228 .in_event_mask = S(SUB_PRES_VLR_E_START),
229 .out_state_mask = S(SUB_PRES_VLR_S_WAIT_FOR_HLR) |
230 S(SUB_PRES_VLR_S_DONE),
231 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_INIT),
232 .action = sub_pres_vlr_fsm_init,
233 },
234 [SUB_PRES_VLR_S_WAIT_FOR_HLR] = {
235 .in_event_mask = S(SUB_PRES_VLR_E_READY_SM_CNF) |
236 S(SUB_PRES_VLR_E_READY_SM_ERR),
237 .out_state_mask = S(SUB_PRES_VLR_S_DONE),
238 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_WAIT_FOR_HLR),
239 .action = sub_pres_vlr_fsm_wait_hlr,
240 },
241 [SUB_PRES_VLR_S_DONE] = {
242 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_DONE),
243 },
244};
245
246static struct osmo_fsm sub_pres_vlr_fsm = {
247 .name = "sub_pres_vlr_fsm",
248 .states = sub_pres_vlr_states,
249 .num_states = ARRAY_SIZE(sub_pres_vlr_states),
250 .allstate_event_mask = 0,
251 .allstate_action = NULL,
252 .log_subsys = DVLR,
253 .event_names = sub_pres_vlr_event_names,
254};
255
256struct osmo_fsm_inst *sub_pres_vlr_fsm_start(struct osmo_fsm_inst *parent,
257 struct vlr_subscr *vsub,
258 uint32_t term_event)
259{
260 struct osmo_fsm_inst *fi;
261
262 fi = osmo_fsm_inst_alloc_child(&sub_pres_vlr_fsm, parent,
263 term_event);
264 if (!fi)
265 return NULL;
266
267 fi->priv = vsub;
268 osmo_fsm_inst_dispatch(fi, SUB_PRES_VLR_E_START, NULL);
269
270 return fi;
271}
272
273/***********************************************************************
274 * Location_Update_Completion_VLR, TS 23.012 Chapter 4.1.2.3
275 ***********************************************************************/
276
277enum lu_compl_vlr_state {
278 LU_COMPL_VLR_S_INIT,
279 LU_COMPL_VLR_S_WAIT_SUB_PRES,
280 LU_COMPL_VLR_S_WAIT_IMEI,
281 LU_COMPL_VLR_S_WAIT_IMEI_TMSI,
282 LU_COMPL_VLR_S_WAIT_TMSI_CNF,
283 LU_COMPL_VLR_S_DONE,
284};
285
286enum lu_compl_vlr_event {
287 LU_COMPL_VLR_E_START,
288 LU_COMPL_VLR_E_SUB_PRES_COMPL,
289 LU_COMPL_VLR_E_IMEI_CHECK_ACK,
290 LU_COMPL_VLR_E_IMEI_CHECK_NACK,
291 LU_COMPL_VLR_E_NEW_TMSI_ACK,
292};
293
294static const struct value_string lu_compl_vlr_event_names[] = {
295 OSMO_VALUE_STRING(LU_COMPL_VLR_E_START),
296 OSMO_VALUE_STRING(LU_COMPL_VLR_E_SUB_PRES_COMPL),
297 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_ACK),
298 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
299 OSMO_VALUE_STRING(LU_COMPL_VLR_E_NEW_TMSI_ACK),
300 { 0, NULL }
301};
302
303struct lu_compl_vlr_priv {
304 struct vlr_subscr *vsub;
305 void *msc_conn_ref;
306 struct osmo_fsm_inst *sub_pres_vlr_fsm;
307 uint32_t parent_event_success;
308 uint32_t parent_event_failure;
309 void *parent_event_data;
310 enum vlr_fsm_result result;
311 uint8_t cause;
312 bool assign_tmsi;
313};
314
315static void _vlr_lu_compl_fsm_done(struct osmo_fsm_inst *fi,
316 enum vlr_fsm_result result,
317 uint8_t cause)
318{
319 struct lu_compl_vlr_priv *lcvp = fi->priv;
320 lcvp->result = result;
321 lcvp->cause = cause;
322 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_DONE, 0, 0);
323}
324
325static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi)
326{
327 struct lu_compl_vlr_priv *lcvp = fi->priv;
328 struct vlr_subscr *vsub = lcvp->vsub;
329 if (!vsub->lu_complete) {
330 vsub->lu_complete = true;
331 /* Balanced by vlr_subscr_rx_imsi_detach() */
332 vlr_subscr_get(vsub);
333 }
334 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0);
335}
336
337static void vlr_lu_compl_fsm_failure(struct osmo_fsm_inst *fi, uint8_t cause)
338{
339 struct lu_compl_vlr_priv *lcvp = fi->priv;
340 lcvp->vsub->vlr->ops.tx_lu_rej(lcvp->msc_conn_ref, cause);
341 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_FAILURE, cause);
342}
343
344static void vlr_lu_compl_fsm_dispatch_result(struct osmo_fsm_inst *fi,
345 uint32_t prev_state)
346{
347 struct lu_compl_vlr_priv *lcvp = fi->priv;
348 if (!fi->proc.parent) {
349 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
350 return;
351 }
352 osmo_fsm_inst_dispatch(fi->proc.parent,
353 (lcvp->result == VLR_FSM_RESULT_SUCCESS)
354 ? lcvp->parent_event_success
355 : lcvp->parent_event_failure,
356 &lcvp->cause);
357}
358
359static void lu_compl_vlr_init(struct osmo_fsm_inst *fi, uint32_t event,
360 void *data)
361{
362 struct lu_compl_vlr_priv *lcvp = fi->priv;
363 struct vlr_subscr *vsub = lcvp->vsub;
364 struct vlr_instance *vlr;
365 OSMO_ASSERT(vsub);
366 vlr = vsub->vlr;
367 OSMO_ASSERT(vlr);
368
369 OSMO_ASSERT(event == LU_COMPL_VLR_E_START);
370
371 /* TODO: National Roaming restrictions? */
372 /* TODO: Roaming restriction due to unsupported feature in subscriber
373 * data? */
374 /* TODO: Regional subscription restriction? */
375 /* TODO: Administrative restriction of subscribres' access feature? */
376 /* TODO: AccessRestrictuionData parameter available? */
377 /* TODO: AccessRestrictionData permits RAT? */
378 /* Node 1 */
379 /* TODO: Autonomous CSG supported in VPLMN and allowed by HPLMN? */
380 /* TODO: Hybrid Cel / CSG Cell */
381 /* Node 2 */
382 vsub->la_allowed = true;
383 vsub->imsi_detached_flag = false;
384 /* Start Subscriber_Present_VLR Procedure */
385 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_SUB_PRES,
386 LU_TIMEOUT_LONG, 0);
387
388 lcvp->sub_pres_vlr_fsm = sub_pres_vlr_fsm_start(fi, vsub,
389 LU_COMPL_VLR_E_SUB_PRES_COMPL);
390
391}
392
393static void lu_compl_vlr_new_tmsi(struct osmo_fsm_inst *fi)
394{
395 struct lu_compl_vlr_priv *lcvp = fi->priv;
396 struct vlr_subscr *vsub = lcvp->vsub;
397 struct vlr_instance *vlr = vsub->vlr;
398
399 LOGPFSM(fi, "%s()\n", __func__);
400
401 if (vlr_subscr_alloc_tmsi(vsub)) {
402 vlr_lu_compl_fsm_failure(fi,
403 GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
404 return;
405 }
406
407 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF,
408 vlr_timer(vlr, 3250), 3250);
409
410 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new);
411}
412
413/* After completion of Subscriber_Present_VLR */
414static void lu_compl_vlr_wait_subscr_pres(struct osmo_fsm_inst *fi,
415 uint32_t event,
416 void *data)
417{
418 struct lu_compl_vlr_priv *lcvp = fi->priv;
419 struct vlr_subscr *vsub = lcvp->vsub;
420 struct vlr_instance *vlr = vsub->vlr;
421
422 OSMO_ASSERT(event == LU_COMPL_VLR_E_SUB_PRES_COMPL);
423
424 lcvp->sub_pres_vlr_fsm = NULL;
425
426 /* TODO: Trace_Subscriber_Activity_VLR */
427
428 if (vlr->cfg.check_imei_rqd) {
429 /* Check IMEI VLR */
430 osmo_fsm_inst_state_chg(fi,
431 lcvp->assign_tmsi ?
432 LU_COMPL_VLR_S_WAIT_IMEI_TMSI
433 : LU_COMPL_VLR_S_WAIT_IMEI,
434 vlr_timer(vlr, 3270), 3270);
435 vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI);
436 return;
437 }
438
439 /* Do we need to allocate a TMSI? */
440 if (lcvp->assign_tmsi) {
441 lu_compl_vlr_new_tmsi(fi);
442 return;
443 }
444
445 /* Location Updating Accept */
446 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
447 vlr_lu_compl_fsm_success(fi);
448}
449
450/* Waiting for completion of CHECK_IMEI_VLR */
451static void lu_compl_vlr_wait_imei(struct osmo_fsm_inst *fi, uint32_t event,
452 void *data)
453{
454 struct lu_compl_vlr_priv *lcvp = fi->priv;
455 struct vlr_subscr *vsub = lcvp->vsub;
456 struct vlr_instance *vlr = vsub->vlr;
457
458 switch (event) {
459 case LU_COMPL_VLR_E_IMEI_CHECK_ACK:
460 if (!vsub->imei[0]) {
461 /* Abort: Do nothing */
462 vlr_lu_compl_fsm_failure(fi,
463 GSM48_REJECT_PROTOCOL_ERROR);
464 return;
465 }
466 /* Pass */
467 break;
468
469 case LU_COMPL_VLR_E_IMEI_CHECK_NACK:
470 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_ILLEGAL_ME);
471 /* FIXME: IMEI Check Fail to VLR Application (Detach IMSI VLR) */
472 return;
473 }
474
475 /* IMEI is available. Allocate TMSI if needed. */
476 if (lcvp->assign_tmsi) {
477 if (fi->state != LU_COMPL_VLR_S_WAIT_IMEI_TMSI)
478 LOGPFSML(fi, LOGL_ERROR,
479 "TMSI required, expected to be in state"
480 " LU_COMPL_VLR_S_WAIT_IMEI_TMSI,"
481 " am in %s instead\n",
482 osmo_fsm_state_name(fi->fsm, fi->state));
483 /* Logged an error, continue anyway. */
484
485 lu_compl_vlr_new_tmsi(fi);
486
487 /* Wait for TMSI ack */
488 return;
489 }
490
491 /* No TMSI needed, accept now. */
492 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
493 vlr_lu_compl_fsm_success(fi);
494}
495
496/* Waiting for TMSI confirmation */
497static void lu_compl_vlr_wait_tmsi(struct osmo_fsm_inst *fi, uint32_t event,
498 void *data)
499{
500 struct lu_compl_vlr_priv *lcvp = fi->priv;
501 struct vlr_subscr *vsub = lcvp->vsub;
502
503 OSMO_ASSERT(event == LU_COMPL_VLR_E_NEW_TMSI_ACK);
504
505 if (!vsub || vsub->tmsi_new == GSM_RESERVED_TMSI) {
506 LOGPFSML(fi, LOGL_ERROR, "TMSI Realloc Compl implies that"
507 " the subscriber has a new TMSI allocated, but"
508 " the new TMSI is unset.\n");
509 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
510 return;
511 }
512
513 vsub->tmsi = vsub->tmsi_new;
514 vsub->tmsi_new = GSM_RESERVED_TMSI;
515
516 vlr_lu_compl_fsm_success(fi);
517}
518
519static const struct osmo_fsm_state lu_compl_vlr_states[] = {
520 [LU_COMPL_VLR_S_INIT] = {
521 .in_event_mask = S(LU_COMPL_VLR_E_START),
522 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
523 S(LU_COMPL_VLR_S_WAIT_SUB_PRES) |
524 S(LU_COMPL_VLR_S_WAIT_IMEI),
525 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_INIT),
526 .action = lu_compl_vlr_init,
527 },
528 [LU_COMPL_VLR_S_WAIT_SUB_PRES] = {
529 .in_event_mask = S(LU_COMPL_VLR_E_SUB_PRES_COMPL),
530 .out_state_mask = S(LU_COMPL_VLR_S_WAIT_IMEI) |
531 S(LU_COMPL_VLR_S_WAIT_IMEI_TMSI) |
532 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF) |
533 S(LU_COMPL_VLR_S_DONE),
534 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_SUB_PRES),
535 .action = lu_compl_vlr_wait_subscr_pres,
536 },
537 [LU_COMPL_VLR_S_WAIT_IMEI] = {
538 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
539 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
540 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
541 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI),
542 .action = lu_compl_vlr_wait_imei,
543 },
544 [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = {
545 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
546 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
547 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
548 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
549 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI_TMSI),
550 .action = lu_compl_vlr_wait_imei,
551 },
552 [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = {
553 .in_event_mask = S(LU_COMPL_VLR_E_NEW_TMSI_ACK),
554 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
555 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
556 .action = lu_compl_vlr_wait_tmsi,
557 },
558 [LU_COMPL_VLR_S_DONE] = {
559 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_DONE),
560 .onenter = vlr_lu_compl_fsm_dispatch_result,
561 },
562};
563
564static struct osmo_fsm lu_compl_vlr_fsm = {
565 .name = "lu_compl_vlr_fsm",
566 .states = lu_compl_vlr_states,
567 .num_states = ARRAY_SIZE(lu_compl_vlr_states),
568 .allstate_event_mask = 0,
569 .allstate_action = NULL,
570 .log_subsys = DVLR,
571 .event_names = lu_compl_vlr_event_names,
572};
573
574struct osmo_fsm_inst *
575lu_compl_vlr_proc_alloc(struct osmo_fsm_inst *parent,
576 struct vlr_subscr *vsub,
577 void *msc_conn_ref,
578 uint32_t parent_event_success,
579 uint32_t parent_event_failure,
580 bool assign_tmsi)
581{
582 struct osmo_fsm_inst *fi;
583 struct lu_compl_vlr_priv *lcvp;
584
585 fi = osmo_fsm_inst_alloc_child(&lu_compl_vlr_fsm, parent,
586 parent_event_failure);
587 if (!fi)
588 return NULL;
589
590 lcvp = talloc_zero(fi, struct lu_compl_vlr_priv);
591 lcvp->vsub = vsub;
592 lcvp->msc_conn_ref = msc_conn_ref;
593 lcvp->parent_event_success = parent_event_success;
594 lcvp->parent_event_failure = parent_event_failure;
595 lcvp->assign_tmsi = assign_tmsi;
596 fi->priv = lcvp;
597
598 return fi;
599}
600
601
602/***********************************************************************
603 * Update_Location_Area_VLR, TS 23.012 Chapter 4.1.2.1
604 ***********************************************************************/
605
606static const struct value_string fsm_lu_event_names[] = {
607 OSMO_VALUE_STRING(VLR_ULA_E_UPDATE_LA),
608 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK),
609 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK),
610 OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES),
611 OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES),
612 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI),
613 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI),
614 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEISV),
615 OSMO_VALUE_STRING(VLR_ULA_E_HLR_LU_RES),
616 OSMO_VALUE_STRING(VLR_ULA_E_UPD_HLR_COMPL),
617 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_SUCCESS),
618 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_FAILURE),
619 OSMO_VALUE_STRING(VLR_ULA_E_NEW_TMSI_ACK),
620 { 0, NULL }
621};
622
623struct lu_fsm_priv {
624 struct vlr_instance *vlr;
625 struct vlr_subscr *vsub;
626 void *msc_conn_ref;
627 struct osmo_fsm_inst *upd_hlr_vlr_fsm;
628 struct osmo_fsm_inst *lu_compl_vlr_fsm;
629 uint32_t parent_event_success;
630 uint32_t parent_event_failure;
631 void *parent_event_data;
632 enum vlr_fsm_result result;
633 uint8_t rej_cause;
634
635 enum vlr_lu_type type;
636 bool lu_by_tmsi;
637 char imsi[16];
638 uint32_t tmsi;
639 struct osmo_location_area_id old_lai;
640 struct osmo_location_area_id new_lai;
641 bool authentication_required;
642 enum vlr_ciph ciphering_required;
643 bool is_r99;
644 bool is_utran;
645 bool assign_tmsi;
646};
647
648
649/* Determine if given location area is served by this VLR */
650static bool lai_in_this_vlr(struct vlr_instance *vlr,
651 const struct osmo_location_area_id *lai)
652{
653 /* TODO: VLR needs to keep a locally configued list of LAIs */
654 return true;
655}
656
657/* Determine if authentication is required */
658static bool is_auth_required(struct lu_fsm_priv *lfp)
659{
660 /* The cases where the authentication procedure should be used
661 * are defined in 3GPP TS 33.102 */
662 /* For now we use a default value passed in to vlr_lu_fsm(). */
663 return lfp->authentication_required
664 || (lfp->ciphering_required != VLR_CIPH_NONE);
665}
666
667/* Determine if ciphering is required */
668static bool is_ciph_required(struct lu_fsm_priv *lfp)
669{
670 return lfp->ciphering_required != VLR_CIPH_NONE;
671}
672
673/* Determine if a HLR Update is required */
674static bool hlr_update_needed(struct vlr_subscr *vsub)
675{
676 /* TODO: properly decide this, rather than always assuming we
677 * need to update the HLR. */
678 return true;
679}
680
681static void lu_fsm_dispatch_result(struct osmo_fsm_inst *fi,
682 uint32_t prev_state)
683{
684 struct lu_fsm_priv *lfp = fi->priv;
685 if (!fi->proc.parent) {
686 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
687 return;
688 }
689 osmo_fsm_inst_dispatch(fi->proc.parent,
690 (lfp->result == VLR_FSM_RESULT_SUCCESS)
691 ? lfp->parent_event_success
692 : lfp->parent_event_failure,
693 lfp->parent_event_data);
694}
695
696static void _lu_fsm_done(struct osmo_fsm_inst *fi,
697 enum vlr_fsm_result result)
698{
699 struct lu_fsm_priv *lfp = fi->priv;
700 lfp->result = result;
701 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_DONE, 0, 0);
702}
703
704static void lu_fsm_success(struct osmo_fsm_inst *fi)
705{
706 _lu_fsm_done(fi, VLR_FSM_RESULT_SUCCESS);
707}
708
709static void lu_fsm_failure(struct osmo_fsm_inst *fi, uint8_t rej_cause)
710{
711 struct lu_fsm_priv *lfp = fi->priv;
712 if (rej_cause)
713 lfp->vlr->ops.tx_lu_rej(lfp->msc_conn_ref, rej_cause);
714 _lu_fsm_done(fi, VLR_FSM_RESULT_FAILURE);
715}
716
717static void vlr_loc_upd_start_lu_compl_fsm(struct osmo_fsm_inst *fi)
718{
719 struct lu_fsm_priv *lfp = fi->priv;
720 lfp->lu_compl_vlr_fsm =
721 lu_compl_vlr_proc_alloc(fi, lfp->vsub, lfp->msc_conn_ref,
722 VLR_ULA_E_LU_COMPL_SUCCESS,
723 VLR_ULA_E_LU_COMPL_FAILURE,
724 lfp->assign_tmsi);
725
726 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, LU_COMPL_VLR_E_START, NULL);
727}
728
729static void lu_fsm_discard_lu_compl_fsm(struct osmo_fsm_inst *fi)
730{
731 struct lu_fsm_priv *lfp = fi->priv;
732 if (!lfp->lu_compl_vlr_fsm)
733 return;
734 osmo_fsm_inst_term(lfp->lu_compl_vlr_fsm, OSMO_FSM_TERM_PARENT, NULL);
735}
736
737/* 4.1.2.1 Node 4 */
738static void vlr_loc_upd_node_4(struct osmo_fsm_inst *fi)
739{
740 struct lu_fsm_priv *lfp = fi->priv;
741 struct vlr_subscr *vsub = lfp->vsub;
742 bool hlr_unknown = false;
743
744 LOGPFSM(fi, "%s()\n", __func__);
745
746 if (hlr_unknown) {
747 /* FIXME: Delete subscriber record */
748 /* LU REJ: Roaming not allowed */
749 lu_fsm_failure(fi, GSM48_REJECT_ROAMING_NOT_ALLOWED);
750 } else {
751 /* Update_HLR_VLR */
752 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_UPD,
753 LU_TIMEOUT_LONG, 0);
754 lfp->upd_hlr_vlr_fsm =
755 upd_hlr_vlr_proc_start(fi, vsub, VLR_ULA_E_UPD_HLR_COMPL);
756 }
757}
758
759/* 4.1.2.1 Node B */
760static void vlr_loc_upd_node_b(struct osmo_fsm_inst *fi)
761{
762 LOGPFSM(fi, "%s()\n", __func__);
763
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200764 /* OsmoHLR does not support PgA, neither stores the IMEISV, so we have no need to update the HLR
765 * with either. TODO: depend on actual HLR configuration. See 3GPP TS 23.012 Release 14, process
766 * Update_Location_Area_VLR (ULA_VLR2). */
Harald Welteb8b85a12016-06-17 00:06:42 +0200767 if (0) { /* IMEISV or PgA to send */
768 vlr_loc_upd_node_4(fi);
769 } else {
770 /* Location_Update_Completion */
771 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
772 LU_TIMEOUT_LONG, 0);
773 vlr_loc_upd_start_lu_compl_fsm(fi);
774 }
775}
776
777/* Non-standard: after Ciphering Mode Complete (or no ciph required) */
778static void vlr_loc_upd_post_ciph(struct osmo_fsm_inst *fi)
779{
780 struct lu_fsm_priv *lfp = fi->priv;
781 struct vlr_subscr *vsub = lfp->vsub;
782
783 LOGPFSM(fi, "%s()\n", __func__);
784
785 OSMO_ASSERT(vsub);
786
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200787 if (lfp->is_utran) {
788 int rc;
789 rc = lfp->vlr->ops.tx_common_id(lfp->msc_conn_ref);
790 if (rc)
791 LOGPFSML(fi, LOGL_ERROR,
792 "Error while sending Common ID (%d)\n", rc);
793 }
794
Harald Welteb8b85a12016-06-17 00:06:42 +0200795 vsub->conf_by_radio_contact_ind = true;
796 /* Update LAI */
797 vsub->cgi.lai = lfp->new_lai;
798 vsub->dormant_ind = false;
799 vsub->cancel_loc_rx = false;
800 if (hlr_update_needed(vsub)) {
801 vlr_loc_upd_node_4(fi);
802 } else {
803 /* TODO: ADD Support */
804 /* TODO: Node A: PgA Support */
805 vlr_loc_upd_node_b(fi);
806 }
807}
808
809/* 4.1.2.1 after Authentication successful (or no auth rqd) */
810static void vlr_loc_upd_post_auth(struct osmo_fsm_inst *fi)
811{
812 struct lu_fsm_priv *lfp = fi->priv;
813 struct vlr_subscr *vsub = lfp->vsub;
814
815 LOGPFSM(fi, "%s()\n", __func__);
816
817 OSMO_ASSERT(vsub);
818
819 if (!is_ciph_required(lfp)) {
820 vlr_loc_upd_post_ciph(fi);
821 return;
822 }
823
824 if (vlr_set_ciph_mode(vsub->vlr, fi, lfp->msc_conn_ref,
825 lfp->ciphering_required,
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200826 vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200827 LOGPFSML(fi, LOGL_ERROR,
828 "Failed to send Ciphering Mode Command\n");
829 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
830 return;
831 }
832
833 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_CIPH, LU_TIMEOUT_LONG, 0);
834}
835
836static void vlr_loc_upd_node1(struct osmo_fsm_inst *fi)
837{
838 struct lu_fsm_priv *lfp = fi->priv;
839 struct vlr_subscr *vsub = lfp->vsub;
840
841 LOGPFSM(fi, "%s()\n", __func__);
842
843 OSMO_ASSERT(vsub);
844
845 if (is_auth_required(lfp)) {
846 /* Authenticate_VLR */
847 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH,
848 LU_TIMEOUT_LONG, 0);
849 vsub->auth_fsm = auth_fsm_start(lfp->vsub, fi->log_level,
850 fi, VLR_ULA_E_AUTH_RES,
851 lfp->is_r99,
852 lfp->is_utran);
853 } else {
854 /* no need for authentication */
855 vlr_loc_upd_post_auth(fi);
856 }
857}
858
859static void vlr_loc_upd_want_imsi(struct osmo_fsm_inst *fi)
860{
861 struct lu_fsm_priv *lfp = fi->priv;
862 struct vlr_instance *vlr = lfp->vlr;
863
864 LOGPFSM(fi, "%s()\n", __func__);
865
866 OSMO_ASSERT(lfp->vsub);
867
868 /* Obtain_IMSI_VLR */
869 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI,
870 vlr_timer(vlr, 3270), 3270);
871 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI);
872 /* will continue at vlr_loc_upd_node1() once IMSI arrives */
873}
874
875static int assoc_lfp_with_sub(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
876{
877 struct lu_fsm_priv *lfp = fi->priv;
878 struct vlr_instance *vlr = lfp->vlr;
879
880 if (vsub->lu_fsm) {
881 LOGPFSML(fi, LOGL_ERROR,
882 "A Location Updating process is already pending for"
883 " this subscriber. Aborting.\n");
884 /* Also get rid of the other pending LU attempt? */
885 /*lu_fsm_failure(vsub->lu_fsm, GSM48_REJECT_CONGESTION);*/
886 lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
887 return -EINVAL;
888 }
889 vsub->lu_fsm = fi;
890 vsub->msc_conn_ref = lfp->msc_conn_ref;
891 /* FIXME: send new LAC to HLR? */
892 vsub->lac = lfp->new_lai.lac;
893 lfp->vsub = vsub;
894 /* Tell MSC to associate this subscriber with the given
895 * connection */
896 vlr->ops.subscr_assoc(lfp->msc_conn_ref, lfp->vsub);
897 return 0;
898}
899
900static const char *lai_name(struct osmo_location_area_id *lai)
901{
902 static char buf[64];
903 snprintf(buf, sizeof(buf),"MCC:%u, MNC:%u, LAC:%u",
904 lai->plmn.mcc, lai->plmn.mnc, lai->lac);
905 return buf;
906}
907
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200908static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi)
909{
910 struct lu_fsm_priv *lfp = fi->priv;
911 struct vlr_instance *vlr = lfp->vlr;
912 struct vlr_subscr *vsub = NULL;
913
914 if (!lfp->imsi[0]) {
915 /* TMSI was used */
916 lfp->lu_by_tmsi = true;
917 /* TMSI clash: if a different subscriber already has this TMSI,
918 * we will find that other subscriber in the VLR. So the IMSIs
919 * would mismatch, but we don't know about it. Theoretically,
920 * an authentication process would thwart any attempt to use
921 * someone else's TMSI.
922 * TODO: Otherwise we can ask for the IMSI and verify that it
923 * matches the IMSI on record. */
924 vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, NULL);
925
926 if (!vsub) {
927 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
928 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
929 return -1;
930 }
931
932 vsub->sub_dataconf_by_hlr_ind = false;
933 if (assoc_lfp_with_sub(fi, vsub)) {
934 vlr_subscr_put(vsub);
935 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
936 }
937 vlr_subscr_put(vsub);
938 } else {
939 /* IMSI was used */
940 vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, NULL);
941
942 if (!vsub) {
943 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
944 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
945 vlr_subscr_put(vsub);
946 return -1;
947 }
948
949 vsub->sub_dataconf_by_hlr_ind = false;
950 if (assoc_lfp_with_sub(fi, vsub)) {
951 vlr_subscr_put(vsub);
952 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
953 }
954 vlr_subscr_put(vsub);
955 }
956 return 0;
957}
958
Harald Welteb8b85a12016-06-17 00:06:42 +0200959/* 4.1.2.1: Subscriber (via MSC/SGSN) requests location update */
960static void _start_lu_main(struct osmo_fsm_inst *fi)
961{
962 struct lu_fsm_priv *lfp = fi->priv;
963 struct vlr_instance *vlr = lfp->vlr;
Harald Welteb8b85a12016-06-17 00:06:42 +0200964
965 /* TODO: PUESBINE related handling */
966
967 /* Is previous LAI in this VLR? */
968 if (!lai_in_this_vlr(vlr, &lfp->old_lai)) {
969#if 0
970 /* FIXME: check previous VLR, (3) */
971 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_PVLR,
972 LU_TIMEOUT_LONG, 0);
973 return;
974#endif
975 LOGPFSML(fi, LOGL_NOTICE, "LAI change from %s,"
976 " but checking previous VLR not implemented\n",
977 lai_name(&lfp->old_lai));
978 }
979
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200980 /* If this is a TMSI based LU, we may not have the IMSI. Make sure that
981 * we know the IMSI, either on record, or request it. */
982 if (!lfp->vsub->imsi[0])
983 vlr_loc_upd_want_imsi(fi);
984 else
Harald Welteb8b85a12016-06-17 00:06:42 +0200985 vlr_loc_upd_node1(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200986}
987
Harald Welteb8b85a12016-06-17 00:06:42 +0200988static void lu_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event,
989 void *data)
990{
991 struct lu_fsm_priv *lfp = fi->priv;
992 struct vlr_instance *vlr = lfp->vlr;
993
994 OSMO_ASSERT(event == VLR_ULA_E_UPDATE_LA);
995
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200996 if (_lu_fsm_associate_vsub(fi))
997 return; /* error. FSM already terminated. */
998
999 OSMO_ASSERT(lfp->vsub);
1000
1001 /* See 3GPP TS 23.012, procedure Retrieve_IMEISV_If_Required */
1002 if ((!vlr->cfg.retrieve_imeisv_early)
1003 || (lfp->type == VLR_LU_TYPE_PERIODIC && lfp->vsub->imeisv[0])) {
Harald Welteb8b85a12016-06-17 00:06:42 +02001004 /* R_IMEISV_IR1 passed */
1005 _start_lu_main(fi);
1006 } else {
1007 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMEISV);
1008 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV,
1009 vlr_timer(vlr, 3270), 3270);
1010 }
1011}
1012
1013static void lu_fsm_wait_imeisv(struct osmo_fsm_inst *fi, uint32_t event,
1014 void *data)
1015{
1016 switch (event) {
1017 case VLR_ULA_E_ID_IMEISV:
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001018 /* IMEISV was copied in vlr_subscr_rx_id_resp(), and that's
1019 * where we received this event from. */
Harald Welteb8b85a12016-06-17 00:06:42 +02001020 _start_lu_main(fi);
1021 break;
1022 default:
1023 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1024 osmo_fsm_event_name(fi->fsm, event));
1025 break;
1026 }
1027}
1028
1029/* Wait for response from Send_Identification to PVLR */
1030static void lu_fsm_wait_pvlr(struct osmo_fsm_inst *fi, uint32_t event,
1031 void *data)
1032{
1033 switch (event) {
1034 case VLR_ULA_E_SEND_ID_ACK:
1035 vlr_loc_upd_node1(fi);
1036 break;
1037 case VLR_ULA_E_SEND_ID_NACK:
1038 vlr_loc_upd_want_imsi(fi);
1039 break;
1040 default:
1041 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1042 osmo_fsm_event_name(fi->fsm, event));
1043 break;
1044 }
1045}
1046
1047/* Wait for result of Authenticate_VLR procedure */
1048static void lu_fsm_wait_auth(struct osmo_fsm_inst *fi, uint32_t event,
1049 void *data)
1050{
1051 struct lu_fsm_priv *lfp = fi->priv;
1052 enum vlr_auth_fsm_result *res = data;
1053 uint8_t rej_cause = 0;
1054
1055 OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES);
1056
1057 lfp->upd_hlr_vlr_fsm = NULL;
1058
1059 if (res) {
1060 switch (*res) {
1061 case VLR_AUTH_RES_PASSED:
1062 /* Result == Pass */
1063 vlr_loc_upd_post_auth(fi);
1064 return;
1065 case VLR_AUTH_RES_ABORTED:
1066 /* go to Idle with no response */
1067 rej_cause = 0;
1068 break;
1069 case VLR_AUTH_RES_UNKNOWN_SUBSCR:
1070 /* FIXME: delete subscribe record */
1071 rej_cause = GSM48_REJECT_IMSI_UNKNOWN_IN_HLR;
1072 break;
1073 case VLR_AUTH_RES_AUTH_FAILED:
1074 /* cause = illegal subscriber */
1075 rej_cause = GSM48_REJECT_ILLEGAL_MS;
1076 break;
1077 case VLR_AUTH_RES_PROC_ERR:
1078 /* cause = system failure */
1079 rej_cause = GSM48_REJECT_NETWORK_FAILURE;
1080 break;
1081 default:
1082 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1083 osmo_fsm_event_name(fi->fsm, event));
1084 break;
1085 }
1086 } else
1087 rej_cause = GSM48_REJECT_NETWORK_FAILURE;
1088
1089 lu_fsm_failure(fi, rej_cause);
1090}
1091
1092static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event,
1093 void *data)
1094{
1095 struct lu_fsm_priv *lfp = fi->priv;
1096 struct vlr_subscr *vsub = lfp->vsub;
1097 struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
1098
1099 OSMO_ASSERT(event == VLR_ULA_E_CIPH_RES);
1100
1101 if (!data)
1102 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
1103 else
1104 res = *(struct vlr_ciph_result*)data;
1105
1106 switch (res.cause) {
1107 case VLR_CIPH_COMPL:
1108 break;
1109 case VLR_CIPH_REJECT:
1110 LOGPFSM(fi, "ciphering rejected\n");
1111 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1112 return;
1113 default:
1114 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
1115 res.cause);
1116 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1117 return;
1118 }
1119
1120 if (res.imeisv) {
1121 LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
1122 vlr_subscr_set_imeisv(vsub, res.imeisv);
1123 }
1124 vlr_loc_upd_post_ciph(fi);
1125}
1126
1127static void lu_fsm_wait_imsi(struct osmo_fsm_inst *fi, uint32_t event,
1128 void *data)
1129{
1130 struct lu_fsm_priv *lfp = fi->priv;
1131 struct vlr_subscr *vsub = lfp->vsub;
1132 char *mi_string = data;
1133
1134 switch (event) {
1135 case VLR_ULA_E_ID_IMSI:
1136 vlr_subscr_set_imsi(vsub, mi_string);
1137 vlr_loc_upd_node1(fi);
1138 break;
1139 default:
1140 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1141 osmo_fsm_event_name(fi->fsm, event));
1142 break;
1143 }
1144}
1145
1146/* At the end of Update_HLR_VLR */
1147static void lu_fsm_wait_hlr_ul_res(struct osmo_fsm_inst *fi, uint32_t event,
1148 void *data)
1149{
1150 struct lu_fsm_priv *lfp = fi->priv;
1151
1152 switch (event) {
1153 case VLR_ULA_E_HLR_LU_RES:
1154 /* pass-through this event to Update_HLR_VLR */
1155 if (data == NULL)
1156 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_ACK, NULL);
1157 else
1158 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_NACK, data);
1159 break;
1160 case VLR_ULA_E_UPD_HLR_COMPL:
1161 if (data == NULL) {
1162 /* successful case */
1163 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
1164 LU_TIMEOUT_LONG, 0);
1165 vlr_loc_upd_start_lu_compl_fsm(fi);
1166 /* continue in MSC ?!? */
1167 } else {
1168 /* unsuccessful case */
1169 enum gsm48_gmm_cause cause =
1170 *(enum gsm48_gmm_cause *)data;
Neels Hofmeyref9126c2017-07-18 15:38:39 +02001171 /* Ignoring standalone mode for now. */
Harald Welteb8b85a12016-06-17 00:06:42 +02001172 if (0 /* procedure_error && vlr->cfg.standalone_mode */) {
1173 osmo_fsm_inst_state_chg(fi,
1174 VLR_ULA_S_WAIT_LU_COMPL_STANDALONE,
1175 LU_TIMEOUT_LONG, 0);
1176 vlr_loc_upd_start_lu_compl_fsm(fi);
1177 } else {
1178 lu_fsm_failure(fi, cause);
1179 }
1180 }
1181 break;
1182 default:
1183 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1184 osmo_fsm_event_name(fi->fsm, event));
1185 break;
1186 }
1187}
1188
1189/* Wait for end of Location_Update_Completion_VLR */
1190static void lu_fsm_wait_lu_compl(struct osmo_fsm_inst *fi, uint32_t event,
1191 void *data)
1192{
1193 struct lu_fsm_priv *lfp = fi->priv;
1194 uint8_t cause;
1195
1196 switch (event) {
1197 case VLR_ULA_E_NEW_TMSI_ACK:
1198 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1199 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1200 break;
1201 case VLR_ULA_E_ID_IMEI:
1202 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1203 LU_COMPL_VLR_E_IMEI_CHECK_ACK, NULL);
1204 break;
1205 case VLR_ULA_E_LU_COMPL_SUCCESS:
1206 lu_fsm_discard_lu_compl_fsm(fi);
1207
1208 /* Update Register */
1209 /* TODO: Set_Notification_Type 23.078 */
1210 /* TODO: Notify_gsmSCF 23.078 */
1211 /* TODO: Authenticated Radio Contact Established -> ARC */
1212 lu_fsm_success(fi);
1213 break;
1214 case VLR_ULA_E_LU_COMPL_FAILURE:
1215 cause = GSM48_REJECT_NETWORK_FAILURE;
1216 if (data)
1217 cause = *(uint8_t*)data;
1218 lu_fsm_discard_lu_compl_fsm(fi);
1219 lu_fsm_failure(fi, cause);
1220 break;
1221 default:
1222 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1223 osmo_fsm_event_name(fi->fsm, event));
1224 break;
1225 }
1226}
1227
1228/* Wait for end of Location_Update_Completion_VLR (standalone case) */
1229static void lu_fsm_wait_lu_compl_standalone(struct osmo_fsm_inst *fi,
1230 uint32_t event, void *data)
1231{
1232 struct lu_fsm_priv *lfp = fi->priv;
1233 struct vlr_subscr *vsub = lfp->vsub;
1234 uint8_t cause;
1235
1236 switch (event) {
1237 case VLR_ULA_E_NEW_TMSI_ACK:
1238 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1239 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1240 break;
1241 case VLR_ULA_E_LU_COMPL_SUCCESS:
1242 lu_fsm_discard_lu_compl_fsm(fi);
1243 vsub->sub_dataconf_by_hlr_ind = false;
1244 lu_fsm_success(fi);
1245 break;
1246 case VLR_ULA_E_LU_COMPL_FAILURE:
1247 vsub->sub_dataconf_by_hlr_ind = false;
1248 cause = GSM48_REJECT_NETWORK_FAILURE;
1249 if (data)
1250 cause = *(uint8_t*)data;
1251 lu_fsm_discard_lu_compl_fsm(fi);
1252 lu_fsm_failure(fi, cause);
1253 break;
1254 default:
1255 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1256 osmo_fsm_event_name(fi->fsm, event));
1257 break;
1258 }
1259}
1260
1261static const struct osmo_fsm_state vlr_lu_fsm_states[] = {
1262 [VLR_ULA_S_IDLE] = {
1263 .in_event_mask = S(VLR_ULA_E_UPDATE_LA),
1264 .out_state_mask = S(VLR_ULA_S_WAIT_IMEISV) |
1265 S(VLR_ULA_S_WAIT_PVLR) |
1266 S(VLR_ULA_S_WAIT_IMSI) |
1267 S(VLR_ULA_S_WAIT_AUTH) |
1268 S(VLR_ULA_S_WAIT_HLR_UPD) |
1269 S(VLR_ULA_S_DONE),
1270 .name = OSMO_STRINGIFY(VLR_ULA_S_IDLE),
1271 .action = lu_fsm_idle,
1272 },
1273 [VLR_ULA_S_WAIT_IMEISV] = {
1274 .in_event_mask = S(VLR_ULA_E_ID_IMEISV),
1275 .out_state_mask = S(VLR_ULA_S_WAIT_PVLR) |
1276 S(VLR_ULA_S_WAIT_IMSI) |
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001277 S(VLR_ULA_S_WAIT_AUTH) |
1278 S(VLR_ULA_S_WAIT_HLR_UPD) |
Harald Welteb8b85a12016-06-17 00:06:42 +02001279 S(VLR_ULA_S_DONE),
1280 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMEISV),
1281 .action = lu_fsm_wait_imeisv,
1282 },
1283 [VLR_ULA_S_WAIT_PVLR] = {
1284 .in_event_mask = S(VLR_ULA_E_SEND_ID_ACK) |
1285 S(VLR_ULA_E_SEND_ID_NACK),
1286 .out_state_mask = S(VLR_ULA_S_WAIT_IMSI) |
1287 S(VLR_ULA_S_WAIT_AUTH) |
1288 S(VLR_ULA_S_DONE),
1289 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_PVLR),
1290 .action = lu_fsm_wait_pvlr,
1291 },
1292 [VLR_ULA_S_WAIT_AUTH] = {
1293 .in_event_mask = S(VLR_ULA_E_AUTH_RES),
1294 .out_state_mask = S(VLR_ULA_S_WAIT_CIPH) |
1295 S(VLR_ULA_S_WAIT_LU_COMPL) |
1296 S(VLR_ULA_S_WAIT_HLR_UPD) |
1297 S(VLR_ULA_S_DONE),
1298 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_AUTH),
1299 .action = lu_fsm_wait_auth,
1300 },
1301 [VLR_ULA_S_WAIT_CIPH] = {
1302 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_CIPH),
1303 .in_event_mask = S(VLR_ULA_E_CIPH_RES),
1304 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1305 S(VLR_ULA_S_WAIT_HLR_UPD) |
1306 S(VLR_ULA_S_DONE),
1307 .action = lu_fsm_wait_ciph,
1308 },
1309 [VLR_ULA_S_WAIT_IMSI] = {
1310 .in_event_mask = S(VLR_ULA_E_ID_IMSI),
1311 .out_state_mask = S(VLR_ULA_S_WAIT_AUTH) |
1312 S(VLR_ULA_S_WAIT_HLR_UPD) |
1313 S(VLR_ULA_S_DONE),
1314 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMSI),
1315 .action = lu_fsm_wait_imsi,
1316 },
1317 [VLR_ULA_S_WAIT_HLR_UPD] = {
1318 .in_event_mask = S(VLR_ULA_E_HLR_LU_RES) |
1319 S(VLR_ULA_E_UPD_HLR_COMPL),
1320 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1321 S(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE) |
1322 S(VLR_ULA_S_DONE),
1323 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_HLR_UPD),
1324 .action = lu_fsm_wait_hlr_ul_res,
1325 },
1326 [VLR_ULA_S_WAIT_LU_COMPL] = {
1327 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1328 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1329 S(VLR_ULA_E_NEW_TMSI_ACK) |
1330 S(VLR_ULA_E_ID_IMEI) |
1331 S(VLR_ULA_E_ID_IMEISV),
1332 .out_state_mask = S(VLR_ULA_S_DONE),
1333 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL),
1334 .action = lu_fsm_wait_lu_compl,
1335 },
1336 [VLR_ULA_S_WAIT_LU_COMPL_STANDALONE] = {
1337 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1338 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1339 S(VLR_ULA_E_NEW_TMSI_ACK),
1340 .out_state_mask = S(VLR_ULA_S_DONE),
1341 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE),
1342 .action = lu_fsm_wait_lu_compl_standalone,
1343 },
1344 [VLR_ULA_S_DONE] = {
1345 .name = OSMO_STRINGIFY(VLR_ULA_S_DONE),
1346 .onenter = lu_fsm_dispatch_result,
1347 },
1348};
1349
1350static void fsm_lu_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
1351{
1352 struct lu_fsm_priv *lfp = fi->priv;
1353 struct vlr_subscr *vsub = lfp->vsub;
1354
1355 LOGPFSM(fi, "fsm_lu_cleanup called with cause %s\n",
1356 osmo_fsm_term_cause_name(cause));
1357 if (vsub && vsub->lu_fsm == fi)
1358 vsub->lu_fsm = NULL;
1359}
1360
1361static struct osmo_fsm vlr_lu_fsm = {
1362 .name = "vlr_lu_fsm",
1363 .states = vlr_lu_fsm_states,
1364 .num_states = ARRAY_SIZE(vlr_lu_fsm_states),
1365 .allstate_event_mask = 0,
1366 .allstate_action = NULL,
1367 .log_subsys = DVLR,
1368 .event_names = fsm_lu_event_names,
1369 .cleanup = fsm_lu_cleanup,
1370};
1371
1372struct osmo_fsm_inst *
1373vlr_loc_update(struct osmo_fsm_inst *parent,
1374 uint32_t parent_event_success,
1375 uint32_t parent_event_failure,
1376 void *parent_event_data,
1377 struct vlr_instance *vlr, void *msc_conn_ref,
1378 enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
1379 const struct osmo_location_area_id *old_lai,
1380 const struct osmo_location_area_id *new_lai,
1381 bool authentication_required,
1382 enum vlr_ciph ciphering_required,
1383 bool is_r99, bool is_utran,
1384 bool assign_tmsi)
1385{
1386 struct osmo_fsm_inst *fi;
1387 struct lu_fsm_priv *lfp;
1388
1389 fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure);
1390 if (!fi)
1391 return NULL;
1392
1393 lfp = talloc_zero(fi, struct lu_fsm_priv);
1394 lfp->vlr = vlr;
1395 lfp->msc_conn_ref = msc_conn_ref;
1396 lfp->tmsi = tmsi;
1397 lfp->type = type;
1398 lfp->old_lai = *old_lai;
1399 lfp->new_lai = *new_lai;
1400 lfp->lu_by_tmsi = true;
1401 lfp->parent_event_success = parent_event_success;
1402 lfp->parent_event_failure = parent_event_failure;
1403 lfp->parent_event_data = parent_event_data;
1404 lfp->authentication_required = authentication_required;
1405 lfp->ciphering_required = ciphering_required;
1406 lfp->is_r99 = is_r99;
1407 lfp->is_utran = is_utran;
1408 lfp->assign_tmsi = assign_tmsi;
1409 if (imsi) {
1410 strncpy(lfp->imsi, imsi, sizeof(lfp->imsi)-1);
1411 lfp->imsi[sizeof(lfp->imsi)-1] = '\0';
1412 lfp->lu_by_tmsi = false;
1413 }
1414 fi->priv = lfp;
1415
1416 LOGPFSM(fi, "rev=%s net=%s%s%s\n",
1417 is_r99 ? "R99" : "GSM",
1418 is_utran ? "UTRAN" : "GERAN",
1419 (authentication_required || ciphering_required)?
1420 " Auth" : " (no Auth)",
1421 (authentication_required || ciphering_required)?
1422 (ciphering_required? "+Ciph" : " (no Ciph)")
1423 : "");
1424
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001425 if (is_utran && !authentication_required)
1426 LOGPFSML(fi, LOGL_ERROR,
1427 "Authentication off on UTRAN network. Good luck.\n");
1428
Harald Welteb8b85a12016-06-17 00:06:42 +02001429 osmo_fsm_inst_dispatch(fi, VLR_ULA_E_UPDATE_LA, NULL);
1430
1431 return fi;
1432}
1433
1434/* Gracefully terminate an FSM created by vlr_loc_update() in case of external
1435 * timeout (i.e. from MSC). */
1436void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi)
1437{
1438 if (!fi || fi->state == VLR_ULA_S_DONE)
1439 return;
1440 LOGPFSM(fi, "Connection timed out\n");
1441 lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
1442}
1443
1444void vlr_lu_fsm_init(void)
1445{
1446 osmo_fsm_register(&vlr_lu_fsm);
1447 osmo_fsm_register(&upd_hlr_vlr_fsm);
1448 osmo_fsm_register(&sub_pres_vlr_fsm);
1449 osmo_fsm_register(&lu_compl_vlr_fsm);
1450}