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