blob: 94bea560f28801c8217558ffe71bb69d42a276d7 [file] [log] [blame]
Harald Weltea183a6e2016-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>
23#include <osmocom/gsm/gsup.h>
24#include <openbsc/vlr.h>
25#include <openbsc/debug.h>
26
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
255struct osmo_fsm_inst *sub_pres_vlr_fsm_start(struct osmo_fsm_inst *parent,
256 struct vlr_subscr *vsub,
257 uint32_t term_event)
258{
259 struct osmo_fsm_inst *fi;
260
261 fi = osmo_fsm_inst_alloc_child(&sub_pres_vlr_fsm, parent,
262 term_event);
263 if (!fi)
264 return NULL;
265
266 fi->priv = vsub;
267 osmo_fsm_inst_dispatch(fi, SUB_PRES_VLR_E_START, NULL);
268
269 return fi;
270}
271
272/***********************************************************************
273 * Location_Update_Completion_VLR, TS 23.012 Chapter 4.1.2.3
274 ***********************************************************************/
275
276enum lu_compl_vlr_state {
277 LU_COMPL_VLR_S_INIT,
278 LU_COMPL_VLR_S_WAIT_SUB_PRES,
279 LU_COMPL_VLR_S_WAIT_IMEI,
280 LU_COMPL_VLR_S_WAIT_IMEI_TMSI,
281 LU_COMPL_VLR_S_WAIT_TMSI_CNF,
282 LU_COMPL_VLR_S_DONE,
283};
284
285enum lu_compl_vlr_event {
286 LU_COMPL_VLR_E_START,
287 LU_COMPL_VLR_E_SUB_PRES_COMPL,
288 LU_COMPL_VLR_E_IMEI_CHECK_ACK,
289 LU_COMPL_VLR_E_IMEI_CHECK_NACK,
290 LU_COMPL_VLR_E_NEW_TMSI_ACK,
291};
292
293static const struct value_string lu_compl_vlr_event_names[] = {
294 OSMO_VALUE_STRING(LU_COMPL_VLR_E_START),
295 OSMO_VALUE_STRING(LU_COMPL_VLR_E_SUB_PRES_COMPL),
296 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_ACK),
297 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
298 OSMO_VALUE_STRING(LU_COMPL_VLR_E_NEW_TMSI_ACK),
299 { 0, NULL }
300};
301
302struct lu_compl_vlr_priv {
303 struct vlr_subscr *vsub;
304 void *msc_conn_ref;
305 struct osmo_fsm_inst *sub_pres_vlr_fsm;
306 uint32_t parent_event_success;
307 uint32_t parent_event_failure;
308 void *parent_event_data;
309 enum vlr_fsm_result result;
310 uint8_t cause;
311 bool assign_tmsi;
312};
313
314static void _vlr_lu_compl_fsm_done(struct osmo_fsm_inst *fi,
315 enum vlr_fsm_result result,
316 uint8_t cause)
317{
318 struct lu_compl_vlr_priv *lcvp = fi->priv;
319 lcvp->result = result;
320 lcvp->cause = cause;
321 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_DONE, 0, 0);
322}
323
324static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi)
325{
326 struct lu_compl_vlr_priv *lcvp = fi->priv;
327 struct vlr_subscr *vsub = lcvp->vsub;
328 if (!vsub->lu_complete) {
329 vsub->lu_complete = true;
330 /* Balanced by vlr_subscr_rx_imsi_detach() */
331 vlr_subscr_get(vsub);
332 }
333 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0);
334}
335
336static void vlr_lu_compl_fsm_failure(struct osmo_fsm_inst *fi, uint8_t cause)
337{
338 struct lu_compl_vlr_priv *lcvp = fi->priv;
339 lcvp->vsub->vlr->ops.tx_lu_rej(lcvp->msc_conn_ref, cause);
340 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_FAILURE, cause);
341}
342
343static void vlr_lu_compl_fsm_dispatch_result(struct osmo_fsm_inst *fi,
344 uint32_t prev_state)
345{
346 struct lu_compl_vlr_priv *lcvp = fi->priv;
347 if (!fi->proc.parent) {
348 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
349 return;
350 }
351 osmo_fsm_inst_dispatch(fi->proc.parent,
352 (lcvp->result == VLR_FSM_RESULT_SUCCESS)
353 ? lcvp->parent_event_success
354 : lcvp->parent_event_failure,
355 &lcvp->cause);
356}
357
358static void lu_compl_vlr_init(struct osmo_fsm_inst *fi, uint32_t event,
359 void *data)
360{
361 struct lu_compl_vlr_priv *lcvp = fi->priv;
362 struct vlr_subscr *vsub = lcvp->vsub;
363 struct vlr_instance *vlr;
364 OSMO_ASSERT(vsub);
365 vlr = vsub->vlr;
366 OSMO_ASSERT(vlr);
367
368 OSMO_ASSERT(event == LU_COMPL_VLR_E_START);
369
370 /* TODO: National Roaming restrictions? */
371 /* TODO: Roaming restriction due to unsupported feature in subscriber
372 * data? */
373 /* TODO: Regional subscription restriction? */
374 /* TODO: Administrative restriction of subscribres' access feature? */
375 /* TODO: AccessRestrictuionData parameter available? */
376 /* TODO: AccessRestrictionData permits RAT? */
377 /* Node 1 */
378 /* TODO: Autonomous CSG supported in VPLMN and allowed by HPLMN? */
379 /* TODO: Hybrid Cel / CSG Cell */
380 /* Node 2 */
381 vsub->la_allowed = true;
382 vsub->imsi_detached_flag = false;
383 /* Start Subscriber_Present_VLR Procedure */
384 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_SUB_PRES,
385 LU_TIMEOUT_LONG, 0);
386
387 lcvp->sub_pres_vlr_fsm = sub_pres_vlr_fsm_start(fi, vsub,
388 LU_COMPL_VLR_E_SUB_PRES_COMPL);
389
390}
391
392static void lu_compl_vlr_new_tmsi(struct osmo_fsm_inst *fi)
393{
394 struct lu_compl_vlr_priv *lcvp = fi->priv;
395 struct vlr_subscr *vsub = lcvp->vsub;
396 struct vlr_instance *vlr = vsub->vlr;
397
398 LOGPFSM(fi, "%s()\n", __func__);
399
400 if (vlr_subscr_alloc_tmsi(vsub)) {
401 vlr_lu_compl_fsm_failure(fi,
402 GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
403 return;
404 }
405
406 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF,
407 vlr_timer(vlr, 3250), 3250);
408
409 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new);
410}
411
412/* After completion of Subscriber_Present_VLR */
413static void lu_compl_vlr_wait_subscr_pres(struct osmo_fsm_inst *fi,
414 uint32_t event,
415 void *data)
416{
417 struct lu_compl_vlr_priv *lcvp = fi->priv;
418 struct vlr_subscr *vsub = lcvp->vsub;
419 struct vlr_instance *vlr = vsub->vlr;
420
421 OSMO_ASSERT(event == LU_COMPL_VLR_E_SUB_PRES_COMPL);
422
423 lcvp->sub_pres_vlr_fsm = NULL;
424
425 /* TODO: Trace_Subscriber_Activity_VLR */
426
427 if (vlr->cfg.check_imei_rqd) {
428 /* Check IMEI VLR */
429 osmo_fsm_inst_state_chg(fi,
430 lcvp->assign_tmsi ?
431 LU_COMPL_VLR_S_WAIT_IMEI_TMSI
432 : LU_COMPL_VLR_S_WAIT_IMEI,
433 vlr_timer(vlr, 3270), 3270);
434 vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI);
435 return;
436 }
437
438 /* Do we need to allocate a TMSI? */
439 if (lcvp->assign_tmsi) {
440 lu_compl_vlr_new_tmsi(fi);
441 return;
442 }
443
444 /* Location Updating Accept */
445 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
446 vlr_lu_compl_fsm_success(fi);
447}
448
449/* Waiting for completion of CHECK_IMEI_VLR */
450static void lu_compl_vlr_wait_imei(struct osmo_fsm_inst *fi, uint32_t event,
451 void *data)
452{
453 struct lu_compl_vlr_priv *lcvp = fi->priv;
454 struct vlr_subscr *vsub = lcvp->vsub;
455 struct vlr_instance *vlr = vsub->vlr;
456
457 switch (event) {
458 case LU_COMPL_VLR_E_IMEI_CHECK_ACK:
459 if (!vsub->imei[0]) {
460 /* Abort: Do nothing */
461 vlr_lu_compl_fsm_failure(fi,
462 GSM48_REJECT_PROTOCOL_ERROR);
463 return;
464 }
465 /* Pass */
466 break;
467
468 case LU_COMPL_VLR_E_IMEI_CHECK_NACK:
469 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_ILLEGAL_ME);
470 /* FIXME: IMEI Check Fail to VLR Application (Detach IMSI VLR) */
471 return;
472 }
473
474 /* IMEI is available. Allocate TMSI if needed. */
475 if (lcvp->assign_tmsi) {
476 if (fi->state != LU_COMPL_VLR_S_WAIT_IMEI_TMSI)
477 LOGPFSML(fi, LOGL_ERROR,
478 "TMSI required, expected to be in state"
479 " LU_COMPL_VLR_S_WAIT_IMEI_TMSI,"
480 " am in %s instead\n",
481 osmo_fsm_state_name(fi->fsm, fi->state));
482 /* Logged an error, continue anyway. */
483
484 lu_compl_vlr_new_tmsi(fi);
485
486 /* Wait for TMSI ack */
487 return;
488 }
489
490 /* No TMSI needed, accept now. */
491 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
492 vlr_lu_compl_fsm_success(fi);
493}
494
495/* Waiting for TMSI confirmation */
496static void lu_compl_vlr_wait_tmsi(struct osmo_fsm_inst *fi, uint32_t event,
497 void *data)
498{
499 struct lu_compl_vlr_priv *lcvp = fi->priv;
500 struct vlr_subscr *vsub = lcvp->vsub;
501
502 OSMO_ASSERT(event == LU_COMPL_VLR_E_NEW_TMSI_ACK);
503
504 if (!vsub || vsub->tmsi_new == GSM_RESERVED_TMSI) {
505 LOGPFSML(fi, LOGL_ERROR, "TMSI Realloc Compl implies that"
506 " the subscriber has a new TMSI allocated, but"
507 " the new TMSI is unset.\n");
508 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
509 return;
510 }
511
512 vsub->tmsi = vsub->tmsi_new;
513 vsub->tmsi_new = GSM_RESERVED_TMSI;
514
515 vlr_lu_compl_fsm_success(fi);
516}
517
518static const struct osmo_fsm_state lu_compl_vlr_states[] = {
519 [LU_COMPL_VLR_S_INIT] = {
520 .in_event_mask = S(LU_COMPL_VLR_E_START),
521 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
522 S(LU_COMPL_VLR_S_WAIT_SUB_PRES) |
523 S(LU_COMPL_VLR_S_WAIT_IMEI),
524 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_INIT),
525 .action = lu_compl_vlr_init,
526 },
527 [LU_COMPL_VLR_S_WAIT_SUB_PRES] = {
528 .in_event_mask = S(LU_COMPL_VLR_E_SUB_PRES_COMPL),
529 .out_state_mask = S(LU_COMPL_VLR_S_WAIT_IMEI) |
530 S(LU_COMPL_VLR_S_WAIT_IMEI_TMSI) |
531 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF) |
532 S(LU_COMPL_VLR_S_DONE),
533 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_SUB_PRES),
534 .action = lu_compl_vlr_wait_subscr_pres,
535 },
536 [LU_COMPL_VLR_S_WAIT_IMEI] = {
537 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
538 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
539 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
540 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI),
541 .action = lu_compl_vlr_wait_imei,
542 },
543 [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = {
544 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
545 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
546 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
547 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
548 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI_TMSI),
549 .action = lu_compl_vlr_wait_imei,
550 },
551 [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = {
552 .in_event_mask = S(LU_COMPL_VLR_E_NEW_TMSI_ACK),
553 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
554 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
555 .action = lu_compl_vlr_wait_tmsi,
556 },
557 [LU_COMPL_VLR_S_DONE] = {
558 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_DONE),
559 .onenter = vlr_lu_compl_fsm_dispatch_result,
560 },
561};
562
563static struct osmo_fsm lu_compl_vlr_fsm = {
564 .name = "lu_compl_vlr_fsm",
565 .states = lu_compl_vlr_states,
566 .num_states = ARRAY_SIZE(lu_compl_vlr_states),
567 .allstate_event_mask = 0,
568 .allstate_action = NULL,
569 .log_subsys = DVLR,
570 .event_names = lu_compl_vlr_event_names,
571};
572
573struct osmo_fsm_inst *
574lu_compl_vlr_proc_alloc(struct osmo_fsm_inst *parent,
575 struct vlr_subscr *vsub,
576 void *msc_conn_ref,
577 uint32_t parent_event_success,
578 uint32_t parent_event_failure,
579 bool assign_tmsi)
580{
581 struct osmo_fsm_inst *fi;
582 struct lu_compl_vlr_priv *lcvp;
583
584 fi = osmo_fsm_inst_alloc_child(&lu_compl_vlr_fsm, parent,
585 parent_event_failure);
586 if (!fi)
587 return NULL;
588
589 lcvp = talloc_zero(fi, struct lu_compl_vlr_priv);
590 lcvp->vsub = vsub;
591 lcvp->msc_conn_ref = msc_conn_ref;
592 lcvp->parent_event_success = parent_event_success;
593 lcvp->parent_event_failure = parent_event_failure;
594 lcvp->assign_tmsi = assign_tmsi;
595 fi->priv = lcvp;
596
597 return fi;
598}
599
600
601/***********************************************************************
602 * Update_Location_Area_VLR, TS 23.012 Chapter 4.1.2.1
603 ***********************************************************************/
604
605static const struct value_string fsm_lu_event_names[] = {
606 OSMO_VALUE_STRING(VLR_ULA_E_UPDATE_LA),
607 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK),
608 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK),
609 OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES),
610 OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES),
611 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI),
612 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI),
613 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEISV),
614 OSMO_VALUE_STRING(VLR_ULA_E_HLR_LU_RES),
615 OSMO_VALUE_STRING(VLR_ULA_E_UPD_HLR_COMPL),
616 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_SUCCESS),
617 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_FAILURE),
618 OSMO_VALUE_STRING(VLR_ULA_E_NEW_TMSI_ACK),
619 { 0, NULL }
620};
621
622struct lu_fsm_priv {
623 struct vlr_instance *vlr;
624 struct vlr_subscr *vsub;
625 void *msc_conn_ref;
626 struct osmo_fsm_inst *upd_hlr_vlr_fsm;
627 struct osmo_fsm_inst *lu_compl_vlr_fsm;
628 uint32_t parent_event_success;
629 uint32_t parent_event_failure;
630 void *parent_event_data;
631 enum vlr_fsm_result result;
632 uint8_t rej_cause;
633
634 enum vlr_lu_type type;
635 bool lu_by_tmsi;
636 char imsi[16];
637 uint32_t tmsi;
638 struct osmo_location_area_id old_lai;
639 struct osmo_location_area_id new_lai;
640 bool authentication_required;
641 enum vlr_ciph ciphering_required;
642 bool is_r99;
643 bool is_utran;
644 bool assign_tmsi;
645};
646
647
648/* Determine if given location area is served by this VLR */
649static bool lai_in_this_vlr(struct vlr_instance *vlr,
650 const struct osmo_location_area_id *lai)
651{
652 /* TODO: VLR needs to keep a locally configued list of LAIs */
653 return true;
654}
655
656/* Determine if authentication is required */
657static bool is_auth_required(struct lu_fsm_priv *lfp)
658{
659 /* The cases where the authentication procedure should be used
660 * are defined in 3GPP TS 33.102 */
661 /* For now we use a default value passed in to vlr_lu_fsm(). */
662 return lfp->authentication_required
663 || (lfp->ciphering_required != VLR_CIPH_NONE);
664}
665
666/* Determine if ciphering is required */
667static bool is_ciph_required(struct lu_fsm_priv *lfp)
668{
669 return lfp->ciphering_required != VLR_CIPH_NONE;
670}
671
672/* Determine if a HLR Update is required */
673static bool hlr_update_needed(struct vlr_subscr *vsub)
674{
675 /* TODO: properly decide this, rather than always assuming we
676 * need to update the HLR. */
677 return true;
678}
679
680static void lu_fsm_dispatch_result(struct osmo_fsm_inst *fi,
681 uint32_t prev_state)
682{
683 struct lu_fsm_priv *lfp = fi->priv;
684 if (!fi->proc.parent) {
685 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
686 return;
687 }
688 osmo_fsm_inst_dispatch(fi->proc.parent,
689 (lfp->result == VLR_FSM_RESULT_SUCCESS)
690 ? lfp->parent_event_success
691 : lfp->parent_event_failure,
692 lfp->parent_event_data);
693}
694
695static void _lu_fsm_done(struct osmo_fsm_inst *fi,
696 enum vlr_fsm_result result)
697{
698 struct lu_fsm_priv *lfp = fi->priv;
699 lfp->result = result;
700 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_DONE, 0, 0);
701}
702
703static void lu_fsm_success(struct osmo_fsm_inst *fi)
704{
705 _lu_fsm_done(fi, VLR_FSM_RESULT_SUCCESS);
706}
707
708static void lu_fsm_failure(struct osmo_fsm_inst *fi, uint8_t rej_cause)
709{
710 struct lu_fsm_priv *lfp = fi->priv;
711 if (rej_cause)
712 lfp->vlr->ops.tx_lu_rej(lfp->msc_conn_ref, rej_cause);
713 _lu_fsm_done(fi, VLR_FSM_RESULT_FAILURE);
714}
715
716static void vlr_loc_upd_start_lu_compl_fsm(struct osmo_fsm_inst *fi)
717{
718 struct lu_fsm_priv *lfp = fi->priv;
719 lfp->lu_compl_vlr_fsm =
720 lu_compl_vlr_proc_alloc(fi, lfp->vsub, lfp->msc_conn_ref,
721 VLR_ULA_E_LU_COMPL_SUCCESS,
722 VLR_ULA_E_LU_COMPL_FAILURE,
723 lfp->assign_tmsi);
724
725 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, LU_COMPL_VLR_E_START, NULL);
726}
727
728static void lu_fsm_discard_lu_compl_fsm(struct osmo_fsm_inst *fi)
729{
730 struct lu_fsm_priv *lfp = fi->priv;
731 if (!lfp->lu_compl_vlr_fsm)
732 return;
733 osmo_fsm_inst_term(lfp->lu_compl_vlr_fsm, OSMO_FSM_TERM_PARENT, NULL);
734}
735
736/* 4.1.2.1 Node 4 */
737static void vlr_loc_upd_node_4(struct osmo_fsm_inst *fi)
738{
739 struct lu_fsm_priv *lfp = fi->priv;
740 struct vlr_subscr *vsub = lfp->vsub;
741 bool hlr_unknown = false;
742
743 LOGPFSM(fi, "%s()\n", __func__);
744
745 if (hlr_unknown) {
746 /* FIXME: Delete subscriber record */
747 /* LU REJ: Roaming not allowed */
748 lu_fsm_failure(fi, GSM48_REJECT_ROAMING_NOT_ALLOWED);
749 } else {
750 /* Update_HLR_VLR */
751 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_UPD,
752 LU_TIMEOUT_LONG, 0);
753 lfp->upd_hlr_vlr_fsm =
754 upd_hlr_vlr_proc_start(fi, vsub, VLR_ULA_E_UPD_HLR_COMPL);
755 }
756}
757
758/* 4.1.2.1 Node B */
759static void vlr_loc_upd_node_b(struct osmo_fsm_inst *fi)
760{
761 LOGPFSM(fi, "%s()\n", __func__);
762
Neels Hofmeyr29dfc912017-07-18 15:38:39 +0200763 /* OsmoHLR does not support PgA, neither stores the IMEISV, so we have no need to update the HLR
764 * with either. TODO: depend on actual HLR configuration. See 3GPP TS 23.012 Release 14, process
765 * Update_Location_Area_VLR (ULA_VLR2). */
Harald Weltea183a6e2016-06-17 00:06:42 +0200766 if (0) { /* IMEISV or PgA to send */
767 vlr_loc_upd_node_4(fi);
768 } else {
769 /* Location_Update_Completion */
770 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
771 LU_TIMEOUT_LONG, 0);
772 vlr_loc_upd_start_lu_compl_fsm(fi);
773 }
774}
775
776/* Non-standard: after Ciphering Mode Complete (or no ciph required) */
777static void vlr_loc_upd_post_ciph(struct osmo_fsm_inst *fi)
778{
779 struct lu_fsm_priv *lfp = fi->priv;
780 struct vlr_subscr *vsub = lfp->vsub;
781
782 LOGPFSM(fi, "%s()\n", __func__);
783
784 OSMO_ASSERT(vsub);
785
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200786 if (lfp->is_utran) {
787 int rc;
788 rc = lfp->vlr->ops.tx_common_id(lfp->msc_conn_ref);
789 if (rc)
790 LOGPFSML(fi, LOGL_ERROR,
791 "Error while sending Common ID (%d)\n", rc);
792 }
793
Harald Weltea183a6e2016-06-17 00:06:42 +0200794 vsub->conf_by_radio_contact_ind = true;
795 /* Update LAI */
796 vsub->cgi.lai = lfp->new_lai;
797 vsub->dormant_ind = false;
798 vsub->cancel_loc_rx = false;
799 if (hlr_update_needed(vsub)) {
800 vlr_loc_upd_node_4(fi);
801 } else {
802 /* TODO: ADD Support */
803 /* TODO: Node A: PgA Support */
804 vlr_loc_upd_node_b(fi);
805 }
806}
807
808/* 4.1.2.1 after Authentication successful (or no auth rqd) */
809static void vlr_loc_upd_post_auth(struct osmo_fsm_inst *fi)
810{
811 struct lu_fsm_priv *lfp = fi->priv;
812 struct vlr_subscr *vsub = lfp->vsub;
813
814 LOGPFSM(fi, "%s()\n", __func__);
815
816 OSMO_ASSERT(vsub);
817
818 if (!is_ciph_required(lfp)) {
819 vlr_loc_upd_post_ciph(fi);
820 return;
821 }
822
823 if (vlr_set_ciph_mode(vsub->vlr, fi, lfp->msc_conn_ref,
824 lfp->ciphering_required,
Neels Hofmeyr2d503d02017-07-18 15:39:27 +0200825 vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
Harald Weltea183a6e2016-06-17 00:06:42 +0200826 LOGPFSML(fi, LOGL_ERROR,
827 "Failed to send Ciphering Mode Command\n");
828 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
829 return;
830 }
831
832 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_CIPH, LU_TIMEOUT_LONG, 0);
833}
834
835static void vlr_loc_upd_node1(struct osmo_fsm_inst *fi)
836{
837 struct lu_fsm_priv *lfp = fi->priv;
838 struct vlr_subscr *vsub = lfp->vsub;
839
840 LOGPFSM(fi, "%s()\n", __func__);
841
842 OSMO_ASSERT(vsub);
843
844 if (is_auth_required(lfp)) {
845 /* Authenticate_VLR */
846 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH,
847 LU_TIMEOUT_LONG, 0);
848 vsub->auth_fsm = auth_fsm_start(lfp->vsub, fi->log_level,
849 fi, VLR_ULA_E_AUTH_RES,
850 lfp->is_r99,
851 lfp->is_utran);
852 } else {
853 /* no need for authentication */
854 vlr_loc_upd_post_auth(fi);
855 }
856}
857
858static void vlr_loc_upd_want_imsi(struct osmo_fsm_inst *fi)
859{
860 struct lu_fsm_priv *lfp = fi->priv;
861 struct vlr_instance *vlr = lfp->vlr;
862
863 LOGPFSM(fi, "%s()\n", __func__);
864
865 OSMO_ASSERT(lfp->vsub);
866
867 /* Obtain_IMSI_VLR */
868 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI,
869 vlr_timer(vlr, 3270), 3270);
870 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI);
871 /* will continue at vlr_loc_upd_node1() once IMSI arrives */
872}
873
874static int assoc_lfp_with_sub(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
875{
876 struct lu_fsm_priv *lfp = fi->priv;
877 struct vlr_instance *vlr = lfp->vlr;
878
879 if (vsub->lu_fsm) {
880 LOGPFSML(fi, LOGL_ERROR,
881 "A Location Updating process is already pending for"
882 " this subscriber. Aborting.\n");
883 /* Also get rid of the other pending LU attempt? */
884 /*lu_fsm_failure(vsub->lu_fsm, GSM48_REJECT_CONGESTION);*/
885 lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
886 return -EINVAL;
887 }
888 vsub->lu_fsm = fi;
889 vsub->msc_conn_ref = lfp->msc_conn_ref;
890 /* FIXME: send new LAC to HLR? */
891 vsub->lac = lfp->new_lai.lac;
892 lfp->vsub = vsub;
893 /* Tell MSC to associate this subscriber with the given
894 * connection */
895 vlr->ops.subscr_assoc(lfp->msc_conn_ref, lfp->vsub);
896 return 0;
897}
898
899static const char *lai_name(struct osmo_location_area_id *lai)
900{
901 static char buf[64];
902 snprintf(buf, sizeof(buf),"MCC:%u, MNC:%u, LAC:%u",
903 lai->plmn.mcc, lai->plmn.mnc, lai->lac);
904 return buf;
905}
906
Neels Hofmeyr2d503d02017-07-18 15:39:27 +0200907static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi)
908{
909 struct lu_fsm_priv *lfp = fi->priv;
910 struct vlr_instance *vlr = lfp->vlr;
911 struct vlr_subscr *vsub = NULL;
912
913 if (!lfp->imsi[0]) {
914 /* TMSI was used */
915 lfp->lu_by_tmsi = true;
916 /* TMSI clash: if a different subscriber already has this TMSI,
917 * we will find that other subscriber in the VLR. So the IMSIs
918 * would mismatch, but we don't know about it. Theoretically,
919 * an authentication process would thwart any attempt to use
920 * someone else's TMSI.
921 * TODO: Otherwise we can ask for the IMSI and verify that it
922 * matches the IMSI on record. */
923 vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, NULL);
924
925 if (!vsub) {
926 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
927 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
928 return -1;
929 }
930
931 vsub->sub_dataconf_by_hlr_ind = false;
932 if (assoc_lfp_with_sub(fi, vsub)) {
933 vlr_subscr_put(vsub);
934 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
935 }
936 vlr_subscr_put(vsub);
937 } else {
938 /* IMSI was used */
939 vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, NULL);
940
941 if (!vsub) {
942 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
943 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
944 vlr_subscr_put(vsub);
945 return -1;
946 }
947
948 vsub->sub_dataconf_by_hlr_ind = false;
949 if (assoc_lfp_with_sub(fi, vsub)) {
950 vlr_subscr_put(vsub);
951 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
952 }
953 vlr_subscr_put(vsub);
954 }
955 return 0;
956}
957
Harald Weltea183a6e2016-06-17 00:06:42 +0200958/* 4.1.2.1: Subscriber (via MSC/SGSN) requests location update */
959static void _start_lu_main(struct osmo_fsm_inst *fi)
960{
961 struct lu_fsm_priv *lfp = fi->priv;
962 struct vlr_instance *vlr = lfp->vlr;
Harald Weltea183a6e2016-06-17 00:06:42 +0200963
964 /* TODO: PUESBINE related handling */
965
966 /* Is previous LAI in this VLR? */
967 if (!lai_in_this_vlr(vlr, &lfp->old_lai)) {
968#if 0
969 /* FIXME: check previous VLR, (3) */
970 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_PVLR,
971 LU_TIMEOUT_LONG, 0);
972 return;
973#endif
974 LOGPFSML(fi, LOGL_NOTICE, "LAI change from %s,"
975 " but checking previous VLR not implemented\n",
976 lai_name(&lfp->old_lai));
977 }
978
Neels Hofmeyr2d503d02017-07-18 15:39:27 +0200979 /* If this is a TMSI based LU, we may not have the IMSI. Make sure that
980 * we know the IMSI, either on record, or request it. */
981 if (!lfp->vsub->imsi[0])
982 vlr_loc_upd_want_imsi(fi);
983 else
Harald Weltea183a6e2016-06-17 00:06:42 +0200984 vlr_loc_upd_node1(fi);
Harald Weltea183a6e2016-06-17 00:06:42 +0200985}
986
Harald Weltea183a6e2016-06-17 00:06:42 +0200987static void lu_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event,
988 void *data)
989{
990 struct lu_fsm_priv *lfp = fi->priv;
991 struct vlr_instance *vlr = lfp->vlr;
992
993 OSMO_ASSERT(event == VLR_ULA_E_UPDATE_LA);
994
Neels Hofmeyr2d503d02017-07-18 15:39:27 +0200995 if (_lu_fsm_associate_vsub(fi))
996 return; /* error. FSM already terminated. */
997
998 OSMO_ASSERT(lfp->vsub);
999
1000 /* See 3GPP TS 23.012, procedure Retrieve_IMEISV_If_Required */
1001 if ((!vlr->cfg.retrieve_imeisv_early)
1002 || (lfp->type == VLR_LU_TYPE_PERIODIC && lfp->vsub->imeisv[0])) {
Harald Weltea183a6e2016-06-17 00:06:42 +02001003 /* R_IMEISV_IR1 passed */
1004 _start_lu_main(fi);
1005 } else {
1006 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMEISV);
1007 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV,
1008 vlr_timer(vlr, 3270), 3270);
1009 }
1010}
1011
1012static void lu_fsm_wait_imeisv(struct osmo_fsm_inst *fi, uint32_t event,
1013 void *data)
1014{
1015 switch (event) {
1016 case VLR_ULA_E_ID_IMEISV:
Neels Hofmeyr2d503d02017-07-18 15:39:27 +02001017 /* IMEISV was copied in vlr_subscr_rx_id_resp(), and that's
1018 * where we received this event from. */
Harald Weltea183a6e2016-06-17 00:06:42 +02001019 _start_lu_main(fi);
1020 break;
1021 default:
1022 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1023 osmo_fsm_event_name(fi->fsm, event));
1024 break;
1025 }
1026}
1027
1028/* Wait for response from Send_Identification to PVLR */
1029static void lu_fsm_wait_pvlr(struct osmo_fsm_inst *fi, uint32_t event,
1030 void *data)
1031{
1032 switch (event) {
1033 case VLR_ULA_E_SEND_ID_ACK:
1034 vlr_loc_upd_node1(fi);
1035 break;
1036 case VLR_ULA_E_SEND_ID_NACK:
1037 vlr_loc_upd_want_imsi(fi);
1038 break;
1039 default:
1040 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1041 osmo_fsm_event_name(fi->fsm, event));
1042 break;
1043 }
1044}
1045
1046/* Wait for result of Authenticate_VLR procedure */
1047static void lu_fsm_wait_auth(struct osmo_fsm_inst *fi, uint32_t event,
1048 void *data)
1049{
1050 struct lu_fsm_priv *lfp = fi->priv;
1051 enum vlr_auth_fsm_result *res = data;
1052 uint8_t rej_cause = 0;
1053
1054 OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES);
1055
1056 lfp->upd_hlr_vlr_fsm = NULL;
1057
1058 if (res) {
1059 switch (*res) {
1060 case VLR_AUTH_RES_PASSED:
1061 /* Result == Pass */
1062 vlr_loc_upd_post_auth(fi);
1063 return;
1064 case VLR_AUTH_RES_ABORTED:
1065 /* go to Idle with no response */
1066 rej_cause = 0;
1067 break;
1068 case VLR_AUTH_RES_UNKNOWN_SUBSCR:
1069 /* FIXME: delete subscribe record */
1070 rej_cause = GSM48_REJECT_IMSI_UNKNOWN_IN_HLR;
1071 break;
1072 case VLR_AUTH_RES_AUTH_FAILED:
1073 /* cause = illegal subscriber */
1074 rej_cause = GSM48_REJECT_ILLEGAL_MS;
1075 break;
1076 case VLR_AUTH_RES_PROC_ERR:
1077 /* cause = system failure */
1078 rej_cause = GSM48_REJECT_NETWORK_FAILURE;
1079 break;
1080 default:
1081 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1082 osmo_fsm_event_name(fi->fsm, event));
1083 break;
1084 }
1085 } else
1086 rej_cause = GSM48_REJECT_NETWORK_FAILURE;
1087
1088 lu_fsm_failure(fi, rej_cause);
1089}
1090
1091static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event,
1092 void *data)
1093{
1094 struct lu_fsm_priv *lfp = fi->priv;
1095 struct vlr_subscr *vsub = lfp->vsub;
1096 struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
1097
1098 OSMO_ASSERT(event == VLR_ULA_E_CIPH_RES);
1099
1100 if (!data)
1101 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
1102 else
1103 res = *(struct vlr_ciph_result*)data;
1104
1105 switch (res.cause) {
1106 case VLR_CIPH_COMPL:
1107 break;
1108 case VLR_CIPH_REJECT:
1109 LOGPFSM(fi, "ciphering rejected\n");
1110 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1111 return;
1112 default:
1113 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
1114 res.cause);
1115 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1116 return;
1117 }
1118
1119 if (res.imeisv) {
1120 LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
1121 vlr_subscr_set_imeisv(vsub, res.imeisv);
1122 }
1123 vlr_loc_upd_post_ciph(fi);
1124}
1125
1126static void lu_fsm_wait_imsi(struct osmo_fsm_inst *fi, uint32_t event,
1127 void *data)
1128{
1129 struct lu_fsm_priv *lfp = fi->priv;
1130 struct vlr_subscr *vsub = lfp->vsub;
1131 char *mi_string = data;
1132
1133 switch (event) {
1134 case VLR_ULA_E_ID_IMSI:
1135 vlr_subscr_set_imsi(vsub, mi_string);
1136 vlr_loc_upd_node1(fi);
1137 break;
1138 default:
1139 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1140 osmo_fsm_event_name(fi->fsm, event));
1141 break;
1142 }
1143}
1144
1145/* At the end of Update_HLR_VLR */
1146static void lu_fsm_wait_hlr_ul_res(struct osmo_fsm_inst *fi, uint32_t event,
1147 void *data)
1148{
1149 struct lu_fsm_priv *lfp = fi->priv;
1150
1151 switch (event) {
1152 case VLR_ULA_E_HLR_LU_RES:
1153 /* pass-through this event to Update_HLR_VLR */
1154 if (data == NULL)
1155 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_ACK, NULL);
1156 else
1157 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_NACK, data);
1158 break;
1159 case VLR_ULA_E_UPD_HLR_COMPL:
1160 if (data == NULL) {
1161 /* successful case */
1162 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
1163 LU_TIMEOUT_LONG, 0);
1164 vlr_loc_upd_start_lu_compl_fsm(fi);
1165 /* continue in MSC ?!? */
1166 } else {
1167 /* unsuccessful case */
1168 enum gsm48_gmm_cause cause =
1169 *(enum gsm48_gmm_cause *)data;
Neels Hofmeyr29dfc912017-07-18 15:38:39 +02001170 /* Ignoring standalone mode for now. */
Harald Weltea183a6e2016-06-17 00:06:42 +02001171 if (0 /* procedure_error && vlr->cfg.standalone_mode */) {
1172 osmo_fsm_inst_state_chg(fi,
1173 VLR_ULA_S_WAIT_LU_COMPL_STANDALONE,
1174 LU_TIMEOUT_LONG, 0);
1175 vlr_loc_upd_start_lu_compl_fsm(fi);
1176 } else {
1177 lu_fsm_failure(fi, cause);
1178 }
1179 }
1180 break;
1181 default:
1182 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1183 osmo_fsm_event_name(fi->fsm, event));
1184 break;
1185 }
1186}
1187
1188/* Wait for end of Location_Update_Completion_VLR */
1189static void lu_fsm_wait_lu_compl(struct osmo_fsm_inst *fi, uint32_t event,
1190 void *data)
1191{
1192 struct lu_fsm_priv *lfp = fi->priv;
1193 uint8_t cause;
1194
1195 switch (event) {
1196 case VLR_ULA_E_NEW_TMSI_ACK:
1197 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1198 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1199 break;
1200 case VLR_ULA_E_ID_IMEI:
1201 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1202 LU_COMPL_VLR_E_IMEI_CHECK_ACK, NULL);
1203 break;
1204 case VLR_ULA_E_LU_COMPL_SUCCESS:
1205 lu_fsm_discard_lu_compl_fsm(fi);
1206
1207 /* Update Register */
1208 /* TODO: Set_Notification_Type 23.078 */
1209 /* TODO: Notify_gsmSCF 23.078 */
1210 /* TODO: Authenticated Radio Contact Established -> ARC */
1211 lu_fsm_success(fi);
1212 break;
1213 case VLR_ULA_E_LU_COMPL_FAILURE:
1214 cause = GSM48_REJECT_NETWORK_FAILURE;
1215 if (data)
1216 cause = *(uint8_t*)data;
1217 lu_fsm_discard_lu_compl_fsm(fi);
1218 lu_fsm_failure(fi, cause);
1219 break;
1220 default:
1221 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1222 osmo_fsm_event_name(fi->fsm, event));
1223 break;
1224 }
1225}
1226
1227/* Wait for end of Location_Update_Completion_VLR (standalone case) */
1228static void lu_fsm_wait_lu_compl_standalone(struct osmo_fsm_inst *fi,
1229 uint32_t event, void *data)
1230{
1231 struct lu_fsm_priv *lfp = fi->priv;
1232 struct vlr_subscr *vsub = lfp->vsub;
1233 uint8_t cause;
1234
1235 switch (event) {
1236 case VLR_ULA_E_NEW_TMSI_ACK:
1237 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1238 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1239 break;
1240 case VLR_ULA_E_LU_COMPL_SUCCESS:
1241 lu_fsm_discard_lu_compl_fsm(fi);
1242 vsub->sub_dataconf_by_hlr_ind = false;
1243 lu_fsm_success(fi);
1244 break;
1245 case VLR_ULA_E_LU_COMPL_FAILURE:
1246 vsub->sub_dataconf_by_hlr_ind = false;
1247 cause = GSM48_REJECT_NETWORK_FAILURE;
1248 if (data)
1249 cause = *(uint8_t*)data;
1250 lu_fsm_discard_lu_compl_fsm(fi);
1251 lu_fsm_failure(fi, cause);
1252 break;
1253 default:
1254 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1255 osmo_fsm_event_name(fi->fsm, event));
1256 break;
1257 }
1258}
1259
1260static const struct osmo_fsm_state vlr_lu_fsm_states[] = {
1261 [VLR_ULA_S_IDLE] = {
1262 .in_event_mask = S(VLR_ULA_E_UPDATE_LA),
1263 .out_state_mask = S(VLR_ULA_S_WAIT_IMEISV) |
1264 S(VLR_ULA_S_WAIT_PVLR) |
1265 S(VLR_ULA_S_WAIT_IMSI) |
1266 S(VLR_ULA_S_WAIT_AUTH) |
1267 S(VLR_ULA_S_WAIT_HLR_UPD) |
1268 S(VLR_ULA_S_DONE),
1269 .name = OSMO_STRINGIFY(VLR_ULA_S_IDLE),
1270 .action = lu_fsm_idle,
1271 },
1272 [VLR_ULA_S_WAIT_IMEISV] = {
1273 .in_event_mask = S(VLR_ULA_E_ID_IMEISV),
1274 .out_state_mask = S(VLR_ULA_S_WAIT_PVLR) |
1275 S(VLR_ULA_S_WAIT_IMSI) |
Neels Hofmeyr2d503d02017-07-18 15:39:27 +02001276 S(VLR_ULA_S_WAIT_AUTH) |
1277 S(VLR_ULA_S_WAIT_HLR_UPD) |
Harald Weltea183a6e2016-06-17 00:06:42 +02001278 S(VLR_ULA_S_DONE),
1279 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMEISV),
1280 .action = lu_fsm_wait_imeisv,
1281 },
1282 [VLR_ULA_S_WAIT_PVLR] = {
1283 .in_event_mask = S(VLR_ULA_E_SEND_ID_ACK) |
1284 S(VLR_ULA_E_SEND_ID_NACK),
1285 .out_state_mask = S(VLR_ULA_S_WAIT_IMSI) |
1286 S(VLR_ULA_S_WAIT_AUTH) |
1287 S(VLR_ULA_S_DONE),
1288 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_PVLR),
1289 .action = lu_fsm_wait_pvlr,
1290 },
1291 [VLR_ULA_S_WAIT_AUTH] = {
1292 .in_event_mask = S(VLR_ULA_E_AUTH_RES),
1293 .out_state_mask = S(VLR_ULA_S_WAIT_CIPH) |
1294 S(VLR_ULA_S_WAIT_LU_COMPL) |
1295 S(VLR_ULA_S_WAIT_HLR_UPD) |
1296 S(VLR_ULA_S_DONE),
1297 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_AUTH),
1298 .action = lu_fsm_wait_auth,
1299 },
1300 [VLR_ULA_S_WAIT_CIPH] = {
1301 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_CIPH),
1302 .in_event_mask = S(VLR_ULA_E_CIPH_RES),
1303 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1304 S(VLR_ULA_S_WAIT_HLR_UPD) |
1305 S(VLR_ULA_S_DONE),
1306 .action = lu_fsm_wait_ciph,
1307 },
1308 [VLR_ULA_S_WAIT_IMSI] = {
1309 .in_event_mask = S(VLR_ULA_E_ID_IMSI),
1310 .out_state_mask = S(VLR_ULA_S_WAIT_AUTH) |
1311 S(VLR_ULA_S_WAIT_HLR_UPD) |
1312 S(VLR_ULA_S_DONE),
1313 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMSI),
1314 .action = lu_fsm_wait_imsi,
1315 },
1316 [VLR_ULA_S_WAIT_HLR_UPD] = {
1317 .in_event_mask = S(VLR_ULA_E_HLR_LU_RES) |
1318 S(VLR_ULA_E_UPD_HLR_COMPL),
1319 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1320 S(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE) |
1321 S(VLR_ULA_S_DONE),
1322 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_HLR_UPD),
1323 .action = lu_fsm_wait_hlr_ul_res,
1324 },
1325 [VLR_ULA_S_WAIT_LU_COMPL] = {
1326 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1327 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1328 S(VLR_ULA_E_NEW_TMSI_ACK) |
1329 S(VLR_ULA_E_ID_IMEI) |
1330 S(VLR_ULA_E_ID_IMEISV),
1331 .out_state_mask = S(VLR_ULA_S_DONE),
1332 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL),
1333 .action = lu_fsm_wait_lu_compl,
1334 },
1335 [VLR_ULA_S_WAIT_LU_COMPL_STANDALONE] = {
1336 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1337 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1338 S(VLR_ULA_E_NEW_TMSI_ACK),
1339 .out_state_mask = S(VLR_ULA_S_DONE),
1340 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE),
1341 .action = lu_fsm_wait_lu_compl_standalone,
1342 },
1343 [VLR_ULA_S_DONE] = {
1344 .name = OSMO_STRINGIFY(VLR_ULA_S_DONE),
1345 .onenter = lu_fsm_dispatch_result,
1346 },
1347};
1348
1349static void fsm_lu_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
1350{
1351 struct lu_fsm_priv *lfp = fi->priv;
1352 struct vlr_subscr *vsub = lfp->vsub;
1353
1354 LOGPFSM(fi, "fsm_lu_cleanup called with cause %s\n",
1355 osmo_fsm_term_cause_name(cause));
1356 if (vsub && vsub->lu_fsm == fi)
1357 vsub->lu_fsm = NULL;
1358}
1359
1360static struct osmo_fsm vlr_lu_fsm = {
1361 .name = "vlr_lu_fsm",
1362 .states = vlr_lu_fsm_states,
1363 .num_states = ARRAY_SIZE(vlr_lu_fsm_states),
1364 .allstate_event_mask = 0,
1365 .allstate_action = NULL,
1366 .log_subsys = DVLR,
1367 .event_names = fsm_lu_event_names,
1368 .cleanup = fsm_lu_cleanup,
1369};
1370
1371struct osmo_fsm_inst *
1372vlr_loc_update(struct osmo_fsm_inst *parent,
1373 uint32_t parent_event_success,
1374 uint32_t parent_event_failure,
1375 void *parent_event_data,
1376 struct vlr_instance *vlr, void *msc_conn_ref,
1377 enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
1378 const struct osmo_location_area_id *old_lai,
1379 const struct osmo_location_area_id *new_lai,
1380 bool authentication_required,
1381 enum vlr_ciph ciphering_required,
1382 bool is_r99, bool is_utran,
1383 bool assign_tmsi)
1384{
1385 struct osmo_fsm_inst *fi;
1386 struct lu_fsm_priv *lfp;
1387
1388 fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure);
1389 if (!fi)
1390 return NULL;
1391
1392 lfp = talloc_zero(fi, struct lu_fsm_priv);
1393 lfp->vlr = vlr;
1394 lfp->msc_conn_ref = msc_conn_ref;
1395 lfp->tmsi = tmsi;
1396 lfp->type = type;
1397 lfp->old_lai = *old_lai;
1398 lfp->new_lai = *new_lai;
1399 lfp->lu_by_tmsi = true;
1400 lfp->parent_event_success = parent_event_success;
1401 lfp->parent_event_failure = parent_event_failure;
1402 lfp->parent_event_data = parent_event_data;
1403 lfp->authentication_required = authentication_required;
1404 lfp->ciphering_required = ciphering_required;
1405 lfp->is_r99 = is_r99;
1406 lfp->is_utran = is_utran;
1407 lfp->assign_tmsi = assign_tmsi;
1408 if (imsi) {
1409 strncpy(lfp->imsi, imsi, sizeof(lfp->imsi)-1);
1410 lfp->imsi[sizeof(lfp->imsi)-1] = '\0';
1411 lfp->lu_by_tmsi = false;
1412 }
1413 fi->priv = lfp;
1414
1415 LOGPFSM(fi, "rev=%s net=%s%s%s\n",
1416 is_r99 ? "R99" : "GSM",
1417 is_utran ? "UTRAN" : "GERAN",
1418 (authentication_required || ciphering_required)?
1419 " Auth" : " (no Auth)",
1420 (authentication_required || ciphering_required)?
1421 (ciphering_required? "+Ciph" : " (no Ciph)")
1422 : "");
1423
Neels Hofmeyra1756f32016-05-20 21:59:55 +02001424 if (is_utran && !authentication_required)
1425 LOGPFSML(fi, LOGL_ERROR,
1426 "Authentication off on UTRAN network. Good luck.\n");
1427
Harald Weltea183a6e2016-06-17 00:06:42 +02001428 osmo_fsm_inst_dispatch(fi, VLR_ULA_E_UPDATE_LA, NULL);
1429
1430 return fi;
1431}
1432
1433/* Gracefully terminate an FSM created by vlr_loc_update() in case of external
1434 * timeout (i.e. from MSC). */
1435void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi)
1436{
1437 if (!fi || fi->state == VLR_ULA_S_DONE)
1438 return;
1439 LOGPFSM(fi, "Connection timed out\n");
1440 lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
1441}
1442
1443void vlr_lu_fsm_init(void)
1444{
1445 osmo_fsm_register(&vlr_lu_fsm);
1446 osmo_fsm_register(&upd_hlr_vlr_fsm);
1447 osmo_fsm_register(&sub_pres_vlr_fsm);
1448 osmo_fsm_register(&lu_compl_vlr_fsm);
1449}