blob: a97e97adaa4b21918e84e8ff268ebaec5dc3e9fb [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
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +010071static inline struct vlr_subscr *upd_hlr_vlr_fi_priv(struct osmo_fsm_inst *fi);
72
Harald Welteb8b85a12016-06-17 00:06:42 +020073static void upd_hlr_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
74 void *data)
75{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +010076 struct vlr_subscr *vsub = upd_hlr_vlr_fi_priv(fi);
Max770fbd22018-01-24 12:48:33 +010077 int rc;
Harald Welteb8b85a12016-06-17 00:06:42 +020078
79 OSMO_ASSERT(event == UPD_HLR_VLR_E_START);
80
81 /* Send UpdateLocation to HLR */
Philipp Maier6038ad42018-11-13 13:55:09 +010082 rc = vlr_subscr_req_lu(vsub);
Max770fbd22018-01-24 12:48:33 +010083 if (rc < 0)
84 LOGPFSML(fi, LOGL_ERROR, "Failed to send UpdateLocation to HLR\n");
Harald Welteb8b85a12016-06-17 00:06:42 +020085 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_WAIT_FOR_DATA,
86 LU_TIMEOUT_LONG, 0);
87}
88
89static void upd_hlr_vlr_fsm_wait_data(struct osmo_fsm_inst *fi, uint32_t event,
90 void *data)
91{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +010092 struct vlr_subscr *vsub = upd_hlr_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +020093
94 switch (event) {
95 case UPD_HLR_VLR_E_INS_SUB_DATA:
96 /* FIXME: Insert_Subscr_Data_VLR */
97 break;
98 case UPD_HLR_VLR_E_ACT_TRACE_MODE:
99 /* TODO: Activate_Tracing_VLR */
100 break;
101 case UPD_HLR_VLR_E_FW_CHECK_SS_IND:
102 /* TODO: Forward Check SS Ind to MSC */
103 break;
104 case UPD_HLR_VLR_E_UPD_LOC_ACK:
105 /* Inside Update_HLR_VLR after UpdateLocationAck */
106 vsub->sub_dataconf_by_hlr_ind = true;
107 vsub->loc_conf_in_hlr_ind = true;
108 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
109 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
110 break;
111 case UPD_HLR_VLR_E_UPD_LOC_NACK:
112 /* Inside Update_HLR_VLR after UpdateLocationNack */
113 /* TODO: Check_User_Error_In_Serving_Network_Entity */
114 vsub->sub_dataconf_by_hlr_ind = false;
115 vsub->loc_conf_in_hlr_ind = false;
116 osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
117 /* Data is a pointer to a gsm48_gmm_cause which we
118 * simply pass through */
119 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, data);
120 break;
121 }
122}
123
124static const struct osmo_fsm_state upd_hlr_vlr_states[] = {
125 [UPD_HLR_VLR_S_INIT] = {
126 .in_event_mask = S(UPD_HLR_VLR_E_START),
127 .out_state_mask = S(UPD_HLR_VLR_S_WAIT_FOR_DATA),
128 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_INIT),
129 .action = upd_hlr_vlr_fsm_init,
130 },
131 [UPD_HLR_VLR_S_WAIT_FOR_DATA] = {
132 .in_event_mask = S(UPD_HLR_VLR_E_INS_SUB_DATA) |
133 S(UPD_HLR_VLR_E_ACT_TRACE_MODE) |
134 S(UPD_HLR_VLR_E_FW_CHECK_SS_IND) |
135 S(UPD_HLR_VLR_E_UPD_LOC_ACK) |
136 S(UPD_HLR_VLR_E_UPD_LOC_NACK),
137 .out_state_mask = S(UPD_HLR_VLR_S_DONE),
138 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_WAIT_FOR_DATA),
139 .action = upd_hlr_vlr_fsm_wait_data,
140 },
141 [UPD_HLR_VLR_S_DONE] = {
142 .name = OSMO_STRINGIFY(UPD_HLR_VLR_S_DONE),
143 },
144};
145
146static struct osmo_fsm upd_hlr_vlr_fsm = {
147 .name = "upd_hlr_vlr_fsm",
148 .states = upd_hlr_vlr_states,
149 .num_states = ARRAY_SIZE(upd_hlr_vlr_states),
150 .allstate_event_mask = 0,
151 .allstate_action = NULL,
152 .log_subsys = DVLR,
153 .event_names = upd_hlr_vlr_event_names,
154};
155
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100156static inline struct vlr_subscr *upd_hlr_vlr_fi_priv(struct osmo_fsm_inst *fi)
157{
158 OSMO_ASSERT(fi->fsm == &upd_hlr_vlr_fsm);
159 return (struct vlr_subscr*)fi->priv;
160}
161
Harald Welteb8b85a12016-06-17 00:06:42 +0200162struct osmo_fsm_inst *
163upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
164 struct vlr_subscr *vsub,
165 uint32_t parent_event)
166{
167 struct osmo_fsm_inst *fi;
168
169 fi = osmo_fsm_inst_alloc_child(&upd_hlr_vlr_fsm, parent,
170 parent_event);
171 if (!fi)
172 return NULL;
173
174 fi->priv = vsub;
175 osmo_fsm_inst_dispatch(fi, UPD_HLR_VLR_E_START, NULL);
176
177 return fi;
178}
179
180
181/***********************************************************************
182 * Subscriber_Present_VLR, TS 29.002 Chapter 25.10.1
183 ***********************************************************************/
184
185enum sub_pres_vlr_state {
186 SUB_PRES_VLR_S_INIT,
187 SUB_PRES_VLR_S_WAIT_FOR_HLR,
188 SUB_PRES_VLR_S_DONE,
189};
190
191enum sub_pres_vlr_event {
192 SUB_PRES_VLR_E_START,
193 SUB_PRES_VLR_E_READY_SM_CNF,
194 SUB_PRES_VLR_E_READY_SM_ERR,
195};
196
197static const struct value_string sub_pres_vlr_event_names[] = {
198 OSMO_VALUE_STRING(SUB_PRES_VLR_E_START),
199 OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_CNF),
200 OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_ERR),
201 { 0, NULL }
202};
203
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100204static inline struct vlr_subscr *sub_pres_vlr_fi_priv(struct osmo_fsm_inst *fi);
205
Harald Welteb8b85a12016-06-17 00:06:42 +0200206static void sub_pres_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
207 void *data)
208{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100209 struct vlr_subscr *vsub = sub_pres_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200210 OSMO_ASSERT(event == SUB_PRES_VLR_E_START);
211
212 if (!vsub->ms_not_reachable_flag) {
213 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
214 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
215 return;
216 }
217 /* FIXME: Send READY_FOR_SM via GSUP */
218 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_WAIT_FOR_HLR,
219 LU_TIMEOUT_LONG, 0);
220}
221
222static void sub_pres_vlr_fsm_wait_hlr(struct osmo_fsm_inst *fi, uint32_t event,
223 void *data)
224{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100225 struct vlr_subscr *vsub = sub_pres_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200226
227 switch (event) {
228 case SUB_PRES_VLR_E_READY_SM_CNF:
229 vsub->ms_not_reachable_flag = false;
230 break;
231 case SUB_PRES_VLR_E_READY_SM_ERR:
232 break;
233 }
234 osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
235 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
236}
237
238static const struct osmo_fsm_state sub_pres_vlr_states[] = {
239 [SUB_PRES_VLR_S_INIT] = {
240 .in_event_mask = S(SUB_PRES_VLR_E_START),
241 .out_state_mask = S(SUB_PRES_VLR_S_WAIT_FOR_HLR) |
242 S(SUB_PRES_VLR_S_DONE),
243 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_INIT),
244 .action = sub_pres_vlr_fsm_init,
245 },
246 [SUB_PRES_VLR_S_WAIT_FOR_HLR] = {
247 .in_event_mask = S(SUB_PRES_VLR_E_READY_SM_CNF) |
248 S(SUB_PRES_VLR_E_READY_SM_ERR),
249 .out_state_mask = S(SUB_PRES_VLR_S_DONE),
250 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_WAIT_FOR_HLR),
251 .action = sub_pres_vlr_fsm_wait_hlr,
252 },
253 [SUB_PRES_VLR_S_DONE] = {
254 .name = OSMO_STRINGIFY(SUB_PRES_VLR_S_DONE),
255 },
256};
257
258static struct osmo_fsm sub_pres_vlr_fsm = {
259 .name = "sub_pres_vlr_fsm",
260 .states = sub_pres_vlr_states,
261 .num_states = ARRAY_SIZE(sub_pres_vlr_states),
262 .allstate_event_mask = 0,
263 .allstate_action = NULL,
264 .log_subsys = DVLR,
265 .event_names = sub_pres_vlr_event_names,
266};
267
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100268static inline struct vlr_subscr *sub_pres_vlr_fi_priv(struct osmo_fsm_inst *fi)
269{
270 OSMO_ASSERT(fi->fsm == &sub_pres_vlr_fsm);
271 return (struct vlr_subscr*)fi->priv;
272}
273
Neels Hofmeyr5f1ac6d2018-12-11 01:59:25 +0100274/* THIS IS CURRENTLY DEAD CODE, SINCE WE NEVER SET vsub->ms_not_reachable_flag = true.
275 *
276 * Note that the start event is dispatched right away, so in case the FSM immediately concludes from that
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100277 * event, the created FSM struct may no longer be valid as it already deallocated again, and it may
278 * furthermore already have invoked the parent FSM instance's deallocation as well. Hence, instead of
279 * returning, store the created FSM instance address in *fi_p before dispatching the event. It is thus
280 * possible to store the instance's pointer in a parent FSM instance without running danger of using
281 * already freed memory. */
282void sub_pres_vlr_fsm_start(struct osmo_fsm_inst **fi_p,
283 struct osmo_fsm_inst *parent,
284 struct vlr_subscr *vsub,
285 uint32_t term_event)
Harald Welteb8b85a12016-06-17 00:06:42 +0200286{
287 struct osmo_fsm_inst *fi;
288
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100289 OSMO_ASSERT(fi_p);
290
Harald Welteb8b85a12016-06-17 00:06:42 +0200291 fi = osmo_fsm_inst_alloc_child(&sub_pres_vlr_fsm, parent,
292 term_event);
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100293 *fi_p = fi;
Harald Welteb8b85a12016-06-17 00:06:42 +0200294 if (!fi)
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100295 return;
Harald Welteb8b85a12016-06-17 00:06:42 +0200296
297 fi->priv = vsub;
298 osmo_fsm_inst_dispatch(fi, SUB_PRES_VLR_E_START, NULL);
Harald Welteb8b85a12016-06-17 00:06:42 +0200299}
300
301/***********************************************************************
302 * Location_Update_Completion_VLR, TS 23.012 Chapter 4.1.2.3
303 ***********************************************************************/
304
305enum lu_compl_vlr_state {
306 LU_COMPL_VLR_S_INIT,
307 LU_COMPL_VLR_S_WAIT_SUB_PRES,
308 LU_COMPL_VLR_S_WAIT_IMEI,
309 LU_COMPL_VLR_S_WAIT_IMEI_TMSI,
310 LU_COMPL_VLR_S_WAIT_TMSI_CNF,
311 LU_COMPL_VLR_S_DONE,
312};
313
314enum lu_compl_vlr_event {
315 LU_COMPL_VLR_E_START,
316 LU_COMPL_VLR_E_SUB_PRES_COMPL,
317 LU_COMPL_VLR_E_IMEI_CHECK_ACK,
318 LU_COMPL_VLR_E_IMEI_CHECK_NACK,
319 LU_COMPL_VLR_E_NEW_TMSI_ACK,
320};
321
322static const struct value_string lu_compl_vlr_event_names[] = {
323 OSMO_VALUE_STRING(LU_COMPL_VLR_E_START),
324 OSMO_VALUE_STRING(LU_COMPL_VLR_E_SUB_PRES_COMPL),
325 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_ACK),
326 OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
327 OSMO_VALUE_STRING(LU_COMPL_VLR_E_NEW_TMSI_ACK),
328 { 0, NULL }
329};
330
331struct lu_compl_vlr_priv {
332 struct vlr_subscr *vsub;
333 void *msc_conn_ref;
334 struct osmo_fsm_inst *sub_pres_vlr_fsm;
335 uint32_t parent_event_success;
336 uint32_t parent_event_failure;
337 void *parent_event_data;
338 enum vlr_fsm_result result;
339 uint8_t cause;
340 bool assign_tmsi;
341};
342
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100343static inline struct lu_compl_vlr_priv *lu_compl_vlr_fi_priv(struct osmo_fsm_inst *fi);
344
Harald Welteb8b85a12016-06-17 00:06:42 +0200345static void _vlr_lu_compl_fsm_done(struct osmo_fsm_inst *fi,
346 enum vlr_fsm_result result,
347 uint8_t cause)
348{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100349 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200350 lcvp->result = result;
351 lcvp->cause = cause;
352 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_DONE, 0, 0);
353}
354
355static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi)
356{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100357 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200358 struct vlr_subscr *vsub = lcvp->vsub;
359 if (!vsub->lu_complete) {
360 vsub->lu_complete = true;
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200361 /* Balanced by vlr_subscr_expire() */
Harald Welteb8b85a12016-06-17 00:06:42 +0200362 vlr_subscr_get(vsub);
363 }
364 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0);
365}
366
367static void vlr_lu_compl_fsm_failure(struct osmo_fsm_inst *fi, uint8_t cause)
368{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100369 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200370 lcvp->vsub->vlr->ops.tx_lu_rej(lcvp->msc_conn_ref, cause);
371 _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_FAILURE, cause);
372}
373
374static void vlr_lu_compl_fsm_dispatch_result(struct osmo_fsm_inst *fi,
375 uint32_t prev_state)
376{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100377 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200378 if (!fi->proc.parent) {
379 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
380 return;
381 }
382 osmo_fsm_inst_dispatch(fi->proc.parent,
383 (lcvp->result == VLR_FSM_RESULT_SUCCESS)
384 ? lcvp->parent_event_success
385 : lcvp->parent_event_failure,
386 &lcvp->cause);
387}
388
389static void lu_compl_vlr_init(struct osmo_fsm_inst *fi, uint32_t event,
390 void *data)
391{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100392 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200393 struct vlr_subscr *vsub = lcvp->vsub;
394 struct vlr_instance *vlr;
395 OSMO_ASSERT(vsub);
396 vlr = vsub->vlr;
397 OSMO_ASSERT(vlr);
398
399 OSMO_ASSERT(event == LU_COMPL_VLR_E_START);
400
401 /* TODO: National Roaming restrictions? */
402 /* TODO: Roaming restriction due to unsupported feature in subscriber
403 * data? */
404 /* TODO: Regional subscription restriction? */
405 /* TODO: Administrative restriction of subscribres' access feature? */
406 /* TODO: AccessRestrictuionData parameter available? */
407 /* TODO: AccessRestrictionData permits RAT? */
408 /* Node 1 */
409 /* TODO: Autonomous CSG supported in VPLMN and allowed by HPLMN? */
410 /* TODO: Hybrid Cel / CSG Cell */
411 /* Node 2 */
412 vsub->la_allowed = true;
413 vsub->imsi_detached_flag = false;
414 /* Start Subscriber_Present_VLR Procedure */
415 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_SUB_PRES,
416 LU_TIMEOUT_LONG, 0);
417
Neels Hofmeyraa14bac2018-12-11 01:56:11 +0100418 /* If ms_not_reachable_flag == false, the sub_pres_vlr_fsm will anyway terminate straight away and dispatch
419 * LU_COMPL_VLR_E_SUB_PRES_COMPL to this fi, so we might as well skip that dance here and save some logging. */
420 if (vsub->ms_not_reachable_flag)
421 sub_pres_vlr_fsm_start(&lcvp->sub_pres_vlr_fsm, fi, vsub, LU_COMPL_VLR_E_SUB_PRES_COMPL);
422 else
423 osmo_fsm_inst_dispatch(fi, LU_COMPL_VLR_E_SUB_PRES_COMPL, NULL);
Harald Welteb8b85a12016-06-17 00:06:42 +0200424}
425
426static void lu_compl_vlr_new_tmsi(struct osmo_fsm_inst *fi)
427{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100428 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200429 struct vlr_subscr *vsub = lcvp->vsub;
430 struct vlr_instance *vlr = vsub->vlr;
431
432 LOGPFSM(fi, "%s()\n", __func__);
433
434 if (vlr_subscr_alloc_tmsi(vsub)) {
435 vlr_lu_compl_fsm_failure(fi,
436 GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
437 return;
438 }
439
440 osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF,
441 vlr_timer(vlr, 3250), 3250);
442
443 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new);
444}
445
446/* After completion of Subscriber_Present_VLR */
447static void lu_compl_vlr_wait_subscr_pres(struct osmo_fsm_inst *fi,
448 uint32_t event,
449 void *data)
450{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100451 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200452 struct vlr_subscr *vsub = lcvp->vsub;
453 struct vlr_instance *vlr = vsub->vlr;
454
455 OSMO_ASSERT(event == LU_COMPL_VLR_E_SUB_PRES_COMPL);
456
457 lcvp->sub_pres_vlr_fsm = NULL;
458
459 /* TODO: Trace_Subscriber_Activity_VLR */
460
461 if (vlr->cfg.check_imei_rqd) {
462 /* Check IMEI VLR */
463 osmo_fsm_inst_state_chg(fi,
464 lcvp->assign_tmsi ?
465 LU_COMPL_VLR_S_WAIT_IMEI_TMSI
466 : LU_COMPL_VLR_S_WAIT_IMEI,
467 vlr_timer(vlr, 3270), 3270);
468 vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI);
469 return;
470 }
471
472 /* Do we need to allocate a TMSI? */
473 if (lcvp->assign_tmsi) {
474 lu_compl_vlr_new_tmsi(fi);
475 return;
476 }
477
478 /* Location Updating Accept */
479 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
480 vlr_lu_compl_fsm_success(fi);
481}
482
483/* Waiting for completion of CHECK_IMEI_VLR */
484static void lu_compl_vlr_wait_imei(struct osmo_fsm_inst *fi, uint32_t event,
485 void *data)
486{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100487 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200488 struct vlr_subscr *vsub = lcvp->vsub;
489 struct vlr_instance *vlr = vsub->vlr;
490
491 switch (event) {
492 case LU_COMPL_VLR_E_IMEI_CHECK_ACK:
493 if (!vsub->imei[0]) {
494 /* Abort: Do nothing */
495 vlr_lu_compl_fsm_failure(fi,
496 GSM48_REJECT_PROTOCOL_ERROR);
497 return;
498 }
499 /* Pass */
500 break;
501
502 case LU_COMPL_VLR_E_IMEI_CHECK_NACK:
503 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_ILLEGAL_ME);
504 /* FIXME: IMEI Check Fail to VLR Application (Detach IMSI VLR) */
505 return;
506 }
507
508 /* IMEI is available. Allocate TMSI if needed. */
509 if (lcvp->assign_tmsi) {
510 if (fi->state != LU_COMPL_VLR_S_WAIT_IMEI_TMSI)
511 LOGPFSML(fi, LOGL_ERROR,
512 "TMSI required, expected to be in state"
513 " LU_COMPL_VLR_S_WAIT_IMEI_TMSI,"
514 " am in %s instead\n",
515 osmo_fsm_state_name(fi->fsm, fi->state));
516 /* Logged an error, continue anyway. */
517
518 lu_compl_vlr_new_tmsi(fi);
519
520 /* Wait for TMSI ack */
521 return;
522 }
523
524 /* No TMSI needed, accept now. */
525 vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
526 vlr_lu_compl_fsm_success(fi);
527}
528
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100529static inline struct lu_compl_vlr_priv *lu_compl_vlr_fi_priv(struct osmo_fsm_inst *fi);
530
Harald Welteb8b85a12016-06-17 00:06:42 +0200531/* Waiting for TMSI confirmation */
532static void lu_compl_vlr_wait_tmsi(struct osmo_fsm_inst *fi, uint32_t event,
533 void *data)
534{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100535 struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200536 struct vlr_subscr *vsub = lcvp->vsub;
537
538 OSMO_ASSERT(event == LU_COMPL_VLR_E_NEW_TMSI_ACK);
539
540 if (!vsub || vsub->tmsi_new == GSM_RESERVED_TMSI) {
541 LOGPFSML(fi, LOGL_ERROR, "TMSI Realloc Compl implies that"
542 " the subscriber has a new TMSI allocated, but"
543 " the new TMSI is unset.\n");
544 vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
545 return;
546 }
547
548 vsub->tmsi = vsub->tmsi_new;
549 vsub->tmsi_new = GSM_RESERVED_TMSI;
Neels Hofmeyr361e5712019-01-03 02:32:14 +0100550 vsub->vlr->ops.subscr_update(vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +0200551
552 vlr_lu_compl_fsm_success(fi);
553}
554
555static const struct osmo_fsm_state lu_compl_vlr_states[] = {
556 [LU_COMPL_VLR_S_INIT] = {
557 .in_event_mask = S(LU_COMPL_VLR_E_START),
558 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
Neels Hofmeyrd50f8982018-12-11 02:24:57 +0100559 S(LU_COMPL_VLR_S_WAIT_SUB_PRES),
Harald Welteb8b85a12016-06-17 00:06:42 +0200560 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_INIT),
561 .action = lu_compl_vlr_init,
562 },
563 [LU_COMPL_VLR_S_WAIT_SUB_PRES] = {
564 .in_event_mask = S(LU_COMPL_VLR_E_SUB_PRES_COMPL),
565 .out_state_mask = S(LU_COMPL_VLR_S_WAIT_IMEI) |
566 S(LU_COMPL_VLR_S_WAIT_IMEI_TMSI) |
567 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF) |
568 S(LU_COMPL_VLR_S_DONE),
569 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_SUB_PRES),
570 .action = lu_compl_vlr_wait_subscr_pres,
571 },
572 [LU_COMPL_VLR_S_WAIT_IMEI] = {
573 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
574 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
575 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
576 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI),
577 .action = lu_compl_vlr_wait_imei,
578 },
579 [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = {
580 .in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
581 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
582 .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
583 S(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
584 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI_TMSI),
585 .action = lu_compl_vlr_wait_imei,
586 },
587 [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = {
588 .in_event_mask = S(LU_COMPL_VLR_E_NEW_TMSI_ACK),
589 .out_state_mask = S(LU_COMPL_VLR_S_DONE),
590 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
591 .action = lu_compl_vlr_wait_tmsi,
592 },
593 [LU_COMPL_VLR_S_DONE] = {
594 .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_DONE),
595 .onenter = vlr_lu_compl_fsm_dispatch_result,
596 },
597};
598
599static struct osmo_fsm lu_compl_vlr_fsm = {
600 .name = "lu_compl_vlr_fsm",
601 .states = lu_compl_vlr_states,
602 .num_states = ARRAY_SIZE(lu_compl_vlr_states),
603 .allstate_event_mask = 0,
604 .allstate_action = NULL,
605 .log_subsys = DVLR,
606 .event_names = lu_compl_vlr_event_names,
607};
608
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100609static inline struct lu_compl_vlr_priv *lu_compl_vlr_fi_priv(struct osmo_fsm_inst *fi)
610{
611 OSMO_ASSERT(fi->fsm == &lu_compl_vlr_fsm);
612 return (struct lu_compl_vlr_priv*)fi->priv;
613}
614
Harald Welteb8b85a12016-06-17 00:06:42 +0200615struct osmo_fsm_inst *
616lu_compl_vlr_proc_alloc(struct osmo_fsm_inst *parent,
617 struct vlr_subscr *vsub,
618 void *msc_conn_ref,
619 uint32_t parent_event_success,
620 uint32_t parent_event_failure,
621 bool assign_tmsi)
622{
623 struct osmo_fsm_inst *fi;
624 struct lu_compl_vlr_priv *lcvp;
625
626 fi = osmo_fsm_inst_alloc_child(&lu_compl_vlr_fsm, parent,
627 parent_event_failure);
628 if (!fi)
629 return NULL;
630
631 lcvp = talloc_zero(fi, struct lu_compl_vlr_priv);
632 lcvp->vsub = vsub;
633 lcvp->msc_conn_ref = msc_conn_ref;
634 lcvp->parent_event_success = parent_event_success;
635 lcvp->parent_event_failure = parent_event_failure;
636 lcvp->assign_tmsi = assign_tmsi;
637 fi->priv = lcvp;
638
639 return fi;
640}
641
642
643/***********************************************************************
644 * Update_Location_Area_VLR, TS 23.012 Chapter 4.1.2.1
645 ***********************************************************************/
646
647static const struct value_string fsm_lu_event_names[] = {
648 OSMO_VALUE_STRING(VLR_ULA_E_UPDATE_LA),
649 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK),
650 OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK),
651 OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES),
652 OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES),
653 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI),
654 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI),
655 OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEISV),
Oliver Smith7d053092018-12-14 17:37:38 +0100656 OSMO_VALUE_STRING(VLR_ULA_E_HLR_IMEI_ACK),
657 OSMO_VALUE_STRING(VLR_ULA_E_HLR_IMEI_NACK),
Harald Welteb8b85a12016-06-17 00:06:42 +0200658 OSMO_VALUE_STRING(VLR_ULA_E_HLR_LU_RES),
659 OSMO_VALUE_STRING(VLR_ULA_E_UPD_HLR_COMPL),
660 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_SUCCESS),
661 OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_FAILURE),
662 OSMO_VALUE_STRING(VLR_ULA_E_NEW_TMSI_ACK),
663 { 0, NULL }
664};
665
666struct lu_fsm_priv {
667 struct vlr_instance *vlr;
668 struct vlr_subscr *vsub;
669 void *msc_conn_ref;
670 struct osmo_fsm_inst *upd_hlr_vlr_fsm;
671 struct osmo_fsm_inst *lu_compl_vlr_fsm;
672 uint32_t parent_event_success;
673 uint32_t parent_event_failure;
674 void *parent_event_data;
675 enum vlr_fsm_result result;
676 uint8_t rej_cause;
677
678 enum vlr_lu_type type;
679 bool lu_by_tmsi;
680 char imsi[16];
681 uint32_t tmsi;
682 struct osmo_location_area_id old_lai;
683 struct osmo_location_area_id new_lai;
684 bool authentication_required;
Harald Welte71c51df2017-12-23 18:51:48 +0100685 bool ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +0200686 bool is_r99;
687 bool is_utran;
688 bool assign_tmsi;
689};
690
691
692/* Determine if given location area is served by this VLR */
693static bool lai_in_this_vlr(struct vlr_instance *vlr,
694 const struct osmo_location_area_id *lai)
695{
696 /* TODO: VLR needs to keep a locally configued list of LAIs */
697 return true;
698}
699
700/* Determine if authentication is required */
701static bool is_auth_required(struct lu_fsm_priv *lfp)
702{
703 /* The cases where the authentication procedure should be used
704 * are defined in 3GPP TS 33.102 */
705 /* For now we use a default value passed in to vlr_lu_fsm(). */
Harald Welte71c51df2017-12-23 18:51:48 +0100706 return lfp->authentication_required || lfp->ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +0200707}
708
709/* Determine if ciphering is required */
710static bool is_ciph_required(struct lu_fsm_priv *lfp)
711{
Harald Welte71c51df2017-12-23 18:51:48 +0100712 return lfp->ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +0200713}
714
715/* Determine if a HLR Update is required */
716static bool hlr_update_needed(struct vlr_subscr *vsub)
717{
718 /* TODO: properly decide this, rather than always assuming we
719 * need to update the HLR. */
720 return true;
721}
722
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100723static inline struct lu_fsm_priv *lu_fsm_fi_priv(struct osmo_fsm_inst *fi);
724
Harald Welteb8b85a12016-06-17 00:06:42 +0200725static void lu_fsm_dispatch_result(struct osmo_fsm_inst *fi,
726 uint32_t prev_state)
727{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100728 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200729 if (!fi->proc.parent) {
730 LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
731 return;
732 }
733 osmo_fsm_inst_dispatch(fi->proc.parent,
734 (lfp->result == VLR_FSM_RESULT_SUCCESS)
735 ? lfp->parent_event_success
736 : lfp->parent_event_failure,
737 lfp->parent_event_data);
738}
739
740static void _lu_fsm_done(struct osmo_fsm_inst *fi,
741 enum vlr_fsm_result result)
742{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100743 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200744 lfp->result = result;
745 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_DONE, 0, 0);
746}
747
748static void lu_fsm_success(struct osmo_fsm_inst *fi)
749{
750 _lu_fsm_done(fi, VLR_FSM_RESULT_SUCCESS);
751}
752
Neels Hofmeyr15809592018-04-06 02:57:51 +0200753static void lu_fsm_failure(struct osmo_fsm_inst *fi, enum gsm48_reject_value rej_cause)
Harald Welteb8b85a12016-06-17 00:06:42 +0200754{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100755 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Neels Hofmeyr15809592018-04-06 02:57:51 +0200756 lfp->vlr->ops.tx_lu_rej(lfp->msc_conn_ref, rej_cause ? : GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200757 _lu_fsm_done(fi, VLR_FSM_RESULT_FAILURE);
758}
759
760static void vlr_loc_upd_start_lu_compl_fsm(struct osmo_fsm_inst *fi)
761{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100762 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200763 lfp->lu_compl_vlr_fsm =
764 lu_compl_vlr_proc_alloc(fi, lfp->vsub, lfp->msc_conn_ref,
765 VLR_ULA_E_LU_COMPL_SUCCESS,
766 VLR_ULA_E_LU_COMPL_FAILURE,
767 lfp->assign_tmsi);
768
769 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, LU_COMPL_VLR_E_START, NULL);
770}
771
772static void lu_fsm_discard_lu_compl_fsm(struct osmo_fsm_inst *fi)
773{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100774 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200775 if (!lfp->lu_compl_vlr_fsm)
776 return;
777 osmo_fsm_inst_term(lfp->lu_compl_vlr_fsm, OSMO_FSM_TERM_PARENT, NULL);
778}
779
780/* 4.1.2.1 Node 4 */
781static void vlr_loc_upd_node_4(struct osmo_fsm_inst *fi)
782{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100783 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200784 struct vlr_subscr *vsub = lfp->vsub;
785 bool hlr_unknown = false;
786
787 LOGPFSM(fi, "%s()\n", __func__);
788
789 if (hlr_unknown) {
790 /* FIXME: Delete subscriber record */
791 /* LU REJ: Roaming not allowed */
792 lu_fsm_failure(fi, GSM48_REJECT_ROAMING_NOT_ALLOWED);
793 } else {
794 /* Update_HLR_VLR */
795 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_UPD,
796 LU_TIMEOUT_LONG, 0);
797 lfp->upd_hlr_vlr_fsm =
798 upd_hlr_vlr_proc_start(fi, vsub, VLR_ULA_E_UPD_HLR_COMPL);
799 }
800}
801
802/* 4.1.2.1 Node B */
803static void vlr_loc_upd_node_b(struct osmo_fsm_inst *fi)
804{
805 LOGPFSM(fi, "%s()\n", __func__);
806
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200807 /* OsmoHLR does not support PgA, neither stores the IMEISV, so we have no need to update the HLR
808 * with either. TODO: depend on actual HLR configuration. See 3GPP TS 23.012 Release 14, process
809 * Update_Location_Area_VLR (ULA_VLR2). */
Harald Welteb8b85a12016-06-17 00:06:42 +0200810 if (0) { /* IMEISV or PgA to send */
811 vlr_loc_upd_node_4(fi);
812 } else {
813 /* Location_Update_Completion */
814 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
815 LU_TIMEOUT_LONG, 0);
816 vlr_loc_upd_start_lu_compl_fsm(fi);
817 }
818}
819
820/* Non-standard: after Ciphering Mode Complete (or no ciph required) */
821static void vlr_loc_upd_post_ciph(struct osmo_fsm_inst *fi)
822{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100823 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200824 struct vlr_subscr *vsub = lfp->vsub;
825
826 LOGPFSM(fi, "%s()\n", __func__);
827
828 OSMO_ASSERT(vsub);
829
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200830 if (lfp->is_utran) {
831 int rc;
832 rc = lfp->vlr->ops.tx_common_id(lfp->msc_conn_ref);
833 if (rc)
834 LOGPFSML(fi, LOGL_ERROR,
835 "Error while sending Common ID (%d)\n", rc);
836 }
837
Harald Welteb8b85a12016-06-17 00:06:42 +0200838 vsub->conf_by_radio_contact_ind = true;
839 /* Update LAI */
840 vsub->cgi.lai = lfp->new_lai;
841 vsub->dormant_ind = false;
842 vsub->cancel_loc_rx = false;
843 if (hlr_update_needed(vsub)) {
844 vlr_loc_upd_node_4(fi);
845 } else {
846 /* TODO: ADD Support */
847 /* TODO: Node A: PgA Support */
848 vlr_loc_upd_node_b(fi);
849 }
850}
851
852/* 4.1.2.1 after Authentication successful (or no auth rqd) */
853static void vlr_loc_upd_post_auth(struct osmo_fsm_inst *fi)
854{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100855 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200856 struct vlr_subscr *vsub = lfp->vsub;
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100857 bool umts_aka;
Harald Welteb8b85a12016-06-17 00:06:42 +0200858
859 LOGPFSM(fi, "%s()\n", __func__);
860
861 OSMO_ASSERT(vsub);
862
863 if (!is_ciph_required(lfp)) {
864 vlr_loc_upd_post_ciph(fi);
865 return;
866 }
867
Neels Hofmeyr2ef2da52017-12-18 01:23:42 +0100868 if (!vsub->last_tuple) {
869 LOGPFSML(fi, LOGL_ERROR, "No auth tuple available\n");
Neels Hofmeyrd2278ec2018-03-02 02:44:05 +0100870 lu_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
Neels Hofmeyr2ef2da52017-12-18 01:23:42 +0100871 return;
872 }
873
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100874 switch (vsub->sec_ctx) {
875 case VLR_SEC_CTX_GSM:
876 umts_aka = false;
877 break;
878 case VLR_SEC_CTX_UMTS:
879 umts_aka = true;
880 break;
881 default:
882 LOGPFSML(fi, LOGL_ERROR, "Cannot start ciphering, security context is not established\n");
883 lu_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
884 return;
885 }
886
Harald Welteb8b85a12016-06-17 00:06:42 +0200887 if (vlr_set_ciph_mode(vsub->vlr, fi, lfp->msc_conn_ref,
888 lfp->ciphering_required,
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100889 umts_aka,
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200890 vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200891 LOGPFSML(fi, LOGL_ERROR,
892 "Failed to send Ciphering Mode Command\n");
Neels Hofmeyrd2278ec2018-03-02 02:44:05 +0100893 lu_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200894 return;
895 }
896
897 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_CIPH, LU_TIMEOUT_LONG, 0);
898}
899
900static void vlr_loc_upd_node1(struct osmo_fsm_inst *fi)
901{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100902 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200903 struct vlr_subscr *vsub = lfp->vsub;
904
905 LOGPFSM(fi, "%s()\n", __func__);
906
907 OSMO_ASSERT(vsub);
908
909 if (is_auth_required(lfp)) {
910 /* Authenticate_VLR */
911 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH,
912 LU_TIMEOUT_LONG, 0);
913 vsub->auth_fsm = auth_fsm_start(lfp->vsub, fi->log_level,
914 fi, VLR_ULA_E_AUTH_RES,
915 lfp->is_r99,
916 lfp->is_utran);
917 } else {
918 /* no need for authentication */
919 vlr_loc_upd_post_auth(fi);
920 }
921}
922
923static void vlr_loc_upd_want_imsi(struct osmo_fsm_inst *fi)
924{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100925 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200926 struct vlr_instance *vlr = lfp->vlr;
927
928 LOGPFSM(fi, "%s()\n", __func__);
929
930 OSMO_ASSERT(lfp->vsub);
931
932 /* Obtain_IMSI_VLR */
933 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI,
934 vlr_timer(vlr, 3270), 3270);
935 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI);
936 /* will continue at vlr_loc_upd_node1() once IMSI arrives */
937}
938
939static int assoc_lfp_with_sub(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
940{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100941 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200942 struct vlr_instance *vlr = lfp->vlr;
943
944 if (vsub->lu_fsm) {
945 LOGPFSML(fi, LOGL_ERROR,
946 "A Location Updating process is already pending for"
947 " this subscriber. Aborting.\n");
948 /* Also get rid of the other pending LU attempt? */
949 /*lu_fsm_failure(vsub->lu_fsm, GSM48_REJECT_CONGESTION);*/
950 lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
951 return -EINVAL;
952 }
953 vsub->lu_fsm = fi;
954 vsub->msc_conn_ref = lfp->msc_conn_ref;
955 /* FIXME: send new LAC to HLR? */
Max7d41d872018-12-19 11:48:33 +0100956 vsub->cgi.lai.lac = lfp->new_lai.lac;
Harald Welteb8b85a12016-06-17 00:06:42 +0200957 lfp->vsub = vsub;
958 /* Tell MSC to associate this subscriber with the given
959 * connection */
Neels Hofmeyr1035d902018-12-28 21:22:32 +0100960 if (vlr->ops.subscr_assoc(lfp->msc_conn_ref, lfp->vsub))
961 lu_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200962 return 0;
963}
964
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200965static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi)
966{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +0100967 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200968 struct vlr_instance *vlr = lfp->vlr;
969 struct vlr_subscr *vsub = NULL;
970
971 if (!lfp->imsi[0]) {
972 /* TMSI was used */
973 lfp->lu_by_tmsi = true;
974 /* TMSI clash: if a different subscriber already has this TMSI,
975 * we will find that other subscriber in the VLR. So the IMSIs
976 * would mismatch, but we don't know about it. Theoretically,
977 * an authentication process would thwart any attempt to use
978 * someone else's TMSI.
979 * TODO: Otherwise we can ask for the IMSI and verify that it
980 * matches the IMSI on record. */
981 vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, NULL);
982
983 if (!vsub) {
984 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
985 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
986 return -1;
987 }
988
989 vsub->sub_dataconf_by_hlr_ind = false;
990 if (assoc_lfp_with_sub(fi, vsub)) {
991 vlr_subscr_put(vsub);
992 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
993 }
994 vlr_subscr_put(vsub);
995 } else {
996 /* IMSI was used */
997 vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, NULL);
998
999 if (!vsub) {
1000 LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
1001 lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
1002 vlr_subscr_put(vsub);
1003 return -1;
1004 }
1005
1006 vsub->sub_dataconf_by_hlr_ind = false;
1007 if (assoc_lfp_with_sub(fi, vsub)) {
1008 vlr_subscr_put(vsub);
1009 return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
1010 }
1011 vlr_subscr_put(vsub);
1012 }
1013 return 0;
1014}
1015
Harald Welteb8b85a12016-06-17 00:06:42 +02001016/* 4.1.2.1: Subscriber (via MSC/SGSN) requests location update */
1017static void _start_lu_main(struct osmo_fsm_inst *fi)
1018{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001019 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001020 struct vlr_instance *vlr = lfp->vlr;
Harald Welteb8b85a12016-06-17 00:06:42 +02001021
1022 /* TODO: PUESBINE related handling */
1023
1024 /* Is previous LAI in this VLR? */
1025 if (!lai_in_this_vlr(vlr, &lfp->old_lai)) {
1026#if 0
1027 /* FIXME: check previous VLR, (3) */
1028 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_PVLR,
1029 LU_TIMEOUT_LONG, 0);
1030 return;
1031#endif
1032 LOGPFSML(fi, LOGL_NOTICE, "LAI change from %s,"
1033 " but checking previous VLR not implemented\n",
Neels Hofmeyr379d5792018-02-22 04:04:54 +01001034 osmo_lai_name(&lfp->old_lai));
Harald Welteb8b85a12016-06-17 00:06:42 +02001035 }
1036
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001037 /* If this is a TMSI based LU, we may not have the IMSI. Make sure that
1038 * we know the IMSI, either on record, or request it. */
1039 if (!lfp->vsub->imsi[0])
1040 vlr_loc_upd_want_imsi(fi);
1041 else
Harald Welteb8b85a12016-06-17 00:06:42 +02001042 vlr_loc_upd_node1(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001043}
1044
Harald Welteb8b85a12016-06-17 00:06:42 +02001045static void lu_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event,
1046 void *data)
1047{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001048 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001049 struct vlr_instance *vlr = lfp->vlr;
1050
1051 OSMO_ASSERT(event == VLR_ULA_E_UPDATE_LA);
1052
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001053 if (_lu_fsm_associate_vsub(fi))
1054 return; /* error. FSM already terminated. */
1055
1056 OSMO_ASSERT(lfp->vsub);
1057
1058 /* See 3GPP TS 23.012, procedure Retrieve_IMEISV_If_Required */
1059 if ((!vlr->cfg.retrieve_imeisv_early)
1060 || (lfp->type == VLR_LU_TYPE_PERIODIC && lfp->vsub->imeisv[0])) {
Harald Welteb8b85a12016-06-17 00:06:42 +02001061 /* R_IMEISV_IR1 passed */
1062 _start_lu_main(fi);
1063 } else {
1064 vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMEISV);
1065 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV,
1066 vlr_timer(vlr, 3270), 3270);
1067 }
1068}
1069
1070static void lu_fsm_wait_imeisv(struct osmo_fsm_inst *fi, uint32_t event,
1071 void *data)
1072{
1073 switch (event) {
1074 case VLR_ULA_E_ID_IMEISV:
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001075 /* IMEISV was copied in vlr_subscr_rx_id_resp(), and that's
1076 * where we received this event from. */
Harald Welteb8b85a12016-06-17 00:06:42 +02001077 _start_lu_main(fi);
1078 break;
1079 default:
1080 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1081 osmo_fsm_event_name(fi->fsm, event));
1082 break;
1083 }
1084}
1085
1086/* Wait for response from Send_Identification to PVLR */
1087static void lu_fsm_wait_pvlr(struct osmo_fsm_inst *fi, uint32_t event,
1088 void *data)
1089{
1090 switch (event) {
1091 case VLR_ULA_E_SEND_ID_ACK:
1092 vlr_loc_upd_node1(fi);
1093 break;
1094 case VLR_ULA_E_SEND_ID_NACK:
1095 vlr_loc_upd_want_imsi(fi);
1096 break;
1097 default:
1098 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1099 osmo_fsm_event_name(fi->fsm, event));
1100 break;
1101 }
1102}
1103
1104/* Wait for result of Authenticate_VLR procedure */
1105static void lu_fsm_wait_auth(struct osmo_fsm_inst *fi, uint32_t event,
1106 void *data)
1107{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001108 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Neels Hofmeyr15809592018-04-06 02:57:51 +02001109 enum gsm48_reject_value *res = data;
Harald Welteb8b85a12016-06-17 00:06:42 +02001110
1111 OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES);
1112
1113 lfp->upd_hlr_vlr_fsm = NULL;
1114
Neels Hofmeyr15809592018-04-06 02:57:51 +02001115 if (!res || *res) {
1116 lu_fsm_failure(fi, res? *res : GSM48_REJECT_NETWORK_FAILURE);
1117 return;
1118 }
Harald Welteb8b85a12016-06-17 00:06:42 +02001119
Neels Hofmeyr15809592018-04-06 02:57:51 +02001120 /* Result == Pass */
1121 vlr_loc_upd_post_auth(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001122}
1123
1124static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event,
1125 void *data)
1126{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001127 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001128 struct vlr_subscr *vsub = lfp->vsub;
1129 struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
1130
1131 OSMO_ASSERT(event == VLR_ULA_E_CIPH_RES);
1132
1133 if (!data)
1134 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
1135 else
1136 res = *(struct vlr_ciph_result*)data;
1137
1138 switch (res.cause) {
1139 case VLR_CIPH_COMPL:
1140 break;
1141 case VLR_CIPH_REJECT:
1142 LOGPFSM(fi, "ciphering rejected\n");
1143 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1144 return;
1145 default:
1146 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
1147 res.cause);
1148 lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
1149 return;
1150 }
1151
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +01001152 if (*res.imeisv) {
Harald Welteb8b85a12016-06-17 00:06:42 +02001153 LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
1154 vlr_subscr_set_imeisv(vsub, res.imeisv);
1155 }
1156 vlr_loc_upd_post_ciph(fi);
1157}
1158
1159static void lu_fsm_wait_imsi(struct osmo_fsm_inst *fi, uint32_t event,
1160 void *data)
1161{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001162 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001163 struct vlr_subscr *vsub = lfp->vsub;
1164 char *mi_string = data;
1165
1166 switch (event) {
1167 case VLR_ULA_E_ID_IMSI:
1168 vlr_subscr_set_imsi(vsub, mi_string);
1169 vlr_loc_upd_node1(fi);
1170 break;
1171 default:
1172 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1173 osmo_fsm_event_name(fi->fsm, event));
1174 break;
1175 }
1176}
1177
1178/* At the end of Update_HLR_VLR */
1179static void lu_fsm_wait_hlr_ul_res(struct osmo_fsm_inst *fi, uint32_t event,
1180 void *data)
1181{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001182 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001183
1184 switch (event) {
1185 case VLR_ULA_E_HLR_LU_RES:
1186 /* pass-through this event to Update_HLR_VLR */
1187 if (data == NULL)
1188 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_ACK, NULL);
1189 else
1190 osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_NACK, data);
1191 break;
1192 case VLR_ULA_E_UPD_HLR_COMPL:
1193 if (data == NULL) {
1194 /* successful case */
1195 osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
1196 LU_TIMEOUT_LONG, 0);
1197 vlr_loc_upd_start_lu_compl_fsm(fi);
1198 /* continue in MSC ?!? */
1199 } else {
1200 /* unsuccessful case */
Neels Hofmeyrdd2aeba2018-10-30 19:47:01 +01001201 enum gsm48_reject_value cause =
1202 *(enum gsm48_reject_value *)data;
Neels Hofmeyref9126c2017-07-18 15:38:39 +02001203 /* Ignoring standalone mode for now. */
Harald Welteb8b85a12016-06-17 00:06:42 +02001204 if (0 /* procedure_error && vlr->cfg.standalone_mode */) {
1205 osmo_fsm_inst_state_chg(fi,
1206 VLR_ULA_S_WAIT_LU_COMPL_STANDALONE,
1207 LU_TIMEOUT_LONG, 0);
1208 vlr_loc_upd_start_lu_compl_fsm(fi);
1209 } else {
1210 lu_fsm_failure(fi, cause);
1211 }
1212 }
1213 break;
1214 default:
1215 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1216 osmo_fsm_event_name(fi->fsm, event));
1217 break;
1218 }
1219}
1220
1221/* Wait for end of Location_Update_Completion_VLR */
1222static void lu_fsm_wait_lu_compl(struct osmo_fsm_inst *fi, uint32_t event,
1223 void *data)
1224{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001225 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001226 uint8_t cause;
1227
1228 switch (event) {
1229 case VLR_ULA_E_NEW_TMSI_ACK:
1230 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1231 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1232 break;
1233 case VLR_ULA_E_ID_IMEI:
Oliver Smith7d053092018-12-14 17:37:38 +01001234 /* Got the IMEI from ME, now send it to HLR */
1235 vlr_subscr_tx_req_check_imei(lfp->vsub);
1236 break;
1237 case VLR_ULA_E_HLR_IMEI_ACK:
Harald Welteb8b85a12016-06-17 00:06:42 +02001238 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1239 LU_COMPL_VLR_E_IMEI_CHECK_ACK, NULL);
1240 break;
Oliver Smith7d053092018-12-14 17:37:38 +01001241 case VLR_ULA_E_HLR_IMEI_NACK:
1242 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1243 LU_COMPL_VLR_E_IMEI_CHECK_NACK, NULL);
1244 break;
Harald Welteb8b85a12016-06-17 00:06:42 +02001245 case VLR_ULA_E_LU_COMPL_SUCCESS:
1246 lu_fsm_discard_lu_compl_fsm(fi);
1247
1248 /* Update Register */
1249 /* TODO: Set_Notification_Type 23.078 */
1250 /* TODO: Notify_gsmSCF 23.078 */
1251 /* TODO: Authenticated Radio Contact Established -> ARC */
Stefan Sperling3a741282018-03-13 21:11:49 +01001252
1253 if (lfp->type == VLR_LU_TYPE_IMSI_ATTACH)
1254 lfp->vlr->ops.tx_mm_info(lfp->msc_conn_ref);
1255
Harald Welteb8b85a12016-06-17 00:06:42 +02001256 lu_fsm_success(fi);
1257 break;
1258 case VLR_ULA_E_LU_COMPL_FAILURE:
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
1272/* Wait for end of Location_Update_Completion_VLR (standalone case) */
1273static void lu_fsm_wait_lu_compl_standalone(struct osmo_fsm_inst *fi,
1274 uint32_t event, void *data)
1275{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001276 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001277 struct vlr_subscr *vsub = lfp->vsub;
1278 uint8_t cause;
1279
1280 switch (event) {
1281 case VLR_ULA_E_NEW_TMSI_ACK:
1282 osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
1283 LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
1284 break;
1285 case VLR_ULA_E_LU_COMPL_SUCCESS:
1286 lu_fsm_discard_lu_compl_fsm(fi);
1287 vsub->sub_dataconf_by_hlr_ind = false;
1288 lu_fsm_success(fi);
1289 break;
1290 case VLR_ULA_E_LU_COMPL_FAILURE:
1291 vsub->sub_dataconf_by_hlr_ind = false;
1292 cause = GSM48_REJECT_NETWORK_FAILURE;
1293 if (data)
1294 cause = *(uint8_t*)data;
1295 lu_fsm_discard_lu_compl_fsm(fi);
1296 lu_fsm_failure(fi, cause);
1297 break;
1298 default:
1299 LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
1300 osmo_fsm_event_name(fi->fsm, event));
1301 break;
1302 }
1303}
1304
1305static const struct osmo_fsm_state vlr_lu_fsm_states[] = {
1306 [VLR_ULA_S_IDLE] = {
1307 .in_event_mask = S(VLR_ULA_E_UPDATE_LA),
1308 .out_state_mask = S(VLR_ULA_S_WAIT_IMEISV) |
1309 S(VLR_ULA_S_WAIT_PVLR) |
1310 S(VLR_ULA_S_WAIT_IMSI) |
1311 S(VLR_ULA_S_WAIT_AUTH) |
1312 S(VLR_ULA_S_WAIT_HLR_UPD) |
1313 S(VLR_ULA_S_DONE),
1314 .name = OSMO_STRINGIFY(VLR_ULA_S_IDLE),
1315 .action = lu_fsm_idle,
1316 },
1317 [VLR_ULA_S_WAIT_IMEISV] = {
1318 .in_event_mask = S(VLR_ULA_E_ID_IMEISV),
1319 .out_state_mask = S(VLR_ULA_S_WAIT_PVLR) |
1320 S(VLR_ULA_S_WAIT_IMSI) |
Neels Hofmeyr54a706c2017-07-18 15:39:27 +02001321 S(VLR_ULA_S_WAIT_AUTH) |
1322 S(VLR_ULA_S_WAIT_HLR_UPD) |
Harald Welteb8b85a12016-06-17 00:06:42 +02001323 S(VLR_ULA_S_DONE),
1324 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMEISV),
1325 .action = lu_fsm_wait_imeisv,
1326 },
1327 [VLR_ULA_S_WAIT_PVLR] = {
1328 .in_event_mask = S(VLR_ULA_E_SEND_ID_ACK) |
1329 S(VLR_ULA_E_SEND_ID_NACK),
1330 .out_state_mask = S(VLR_ULA_S_WAIT_IMSI) |
1331 S(VLR_ULA_S_WAIT_AUTH) |
1332 S(VLR_ULA_S_DONE),
1333 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_PVLR),
1334 .action = lu_fsm_wait_pvlr,
1335 },
1336 [VLR_ULA_S_WAIT_AUTH] = {
1337 .in_event_mask = S(VLR_ULA_E_AUTH_RES),
1338 .out_state_mask = S(VLR_ULA_S_WAIT_CIPH) |
1339 S(VLR_ULA_S_WAIT_LU_COMPL) |
1340 S(VLR_ULA_S_WAIT_HLR_UPD) |
1341 S(VLR_ULA_S_DONE),
1342 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_AUTH),
1343 .action = lu_fsm_wait_auth,
1344 },
1345 [VLR_ULA_S_WAIT_CIPH] = {
1346 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_CIPH),
1347 .in_event_mask = S(VLR_ULA_E_CIPH_RES),
1348 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1349 S(VLR_ULA_S_WAIT_HLR_UPD) |
1350 S(VLR_ULA_S_DONE),
1351 .action = lu_fsm_wait_ciph,
1352 },
1353 [VLR_ULA_S_WAIT_IMSI] = {
1354 .in_event_mask = S(VLR_ULA_E_ID_IMSI),
1355 .out_state_mask = S(VLR_ULA_S_WAIT_AUTH) |
1356 S(VLR_ULA_S_WAIT_HLR_UPD) |
1357 S(VLR_ULA_S_DONE),
1358 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMSI),
1359 .action = lu_fsm_wait_imsi,
1360 },
1361 [VLR_ULA_S_WAIT_HLR_UPD] = {
1362 .in_event_mask = S(VLR_ULA_E_HLR_LU_RES) |
1363 S(VLR_ULA_E_UPD_HLR_COMPL),
1364 .out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
1365 S(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE) |
1366 S(VLR_ULA_S_DONE),
1367 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_HLR_UPD),
1368 .action = lu_fsm_wait_hlr_ul_res,
1369 },
1370 [VLR_ULA_S_WAIT_LU_COMPL] = {
1371 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1372 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1373 S(VLR_ULA_E_NEW_TMSI_ACK) |
1374 S(VLR_ULA_E_ID_IMEI) |
Oliver Smith7d053092018-12-14 17:37:38 +01001375 S(VLR_ULA_E_ID_IMEISV) |
1376 S(VLR_ULA_E_HLR_IMEI_ACK) |
1377 S(VLR_ULA_E_HLR_IMEI_NACK),
Harald Welteb8b85a12016-06-17 00:06:42 +02001378 .out_state_mask = S(VLR_ULA_S_DONE),
1379 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL),
1380 .action = lu_fsm_wait_lu_compl,
1381 },
1382 [VLR_ULA_S_WAIT_LU_COMPL_STANDALONE] = {
1383 .in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
1384 S(VLR_ULA_E_LU_COMPL_FAILURE) |
1385 S(VLR_ULA_E_NEW_TMSI_ACK),
1386 .out_state_mask = S(VLR_ULA_S_DONE),
1387 .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE),
1388 .action = lu_fsm_wait_lu_compl_standalone,
1389 },
1390 [VLR_ULA_S_DONE] = {
1391 .name = OSMO_STRINGIFY(VLR_ULA_S_DONE),
1392 .onenter = lu_fsm_dispatch_result,
1393 },
1394};
1395
1396static void fsm_lu_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
1397{
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001398 struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +02001399 struct vlr_subscr *vsub = lfp->vsub;
1400
1401 LOGPFSM(fi, "fsm_lu_cleanup called with cause %s\n",
1402 osmo_fsm_term_cause_name(cause));
1403 if (vsub && vsub->lu_fsm == fi)
1404 vsub->lu_fsm = NULL;
1405}
1406
1407static struct osmo_fsm vlr_lu_fsm = {
1408 .name = "vlr_lu_fsm",
1409 .states = vlr_lu_fsm_states,
1410 .num_states = ARRAY_SIZE(vlr_lu_fsm_states),
1411 .allstate_event_mask = 0,
1412 .allstate_action = NULL,
1413 .log_subsys = DVLR,
1414 .event_names = fsm_lu_event_names,
1415 .cleanup = fsm_lu_cleanup,
1416};
1417
Neels Hofmeyrc5e0ace2018-03-02 03:12:22 +01001418static inline struct lu_fsm_priv *lu_fsm_fi_priv(struct osmo_fsm_inst *fi)
1419{
1420 OSMO_ASSERT(fi->fsm == &vlr_lu_fsm);
1421 return (struct lu_fsm_priv*)fi->priv;
1422}
1423
Harald Welteb8b85a12016-06-17 00:06:42 +02001424struct osmo_fsm_inst *
1425vlr_loc_update(struct osmo_fsm_inst *parent,
1426 uint32_t parent_event_success,
1427 uint32_t parent_event_failure,
1428 void *parent_event_data,
1429 struct vlr_instance *vlr, void *msc_conn_ref,
1430 enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
1431 const struct osmo_location_area_id *old_lai,
1432 const struct osmo_location_area_id *new_lai,
1433 bool authentication_required,
Harald Welte71c51df2017-12-23 18:51:48 +01001434 bool ciphering_required,
Harald Welteb8b85a12016-06-17 00:06:42 +02001435 bool is_r99, bool is_utran,
1436 bool assign_tmsi)
1437{
1438 struct osmo_fsm_inst *fi;
1439 struct lu_fsm_priv *lfp;
1440
1441 fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure);
1442 if (!fi)
1443 return NULL;
1444
1445 lfp = talloc_zero(fi, struct lu_fsm_priv);
1446 lfp->vlr = vlr;
1447 lfp->msc_conn_ref = msc_conn_ref;
1448 lfp->tmsi = tmsi;
1449 lfp->type = type;
1450 lfp->old_lai = *old_lai;
1451 lfp->new_lai = *new_lai;
1452 lfp->lu_by_tmsi = true;
1453 lfp->parent_event_success = parent_event_success;
1454 lfp->parent_event_failure = parent_event_failure;
1455 lfp->parent_event_data = parent_event_data;
1456 lfp->authentication_required = authentication_required;
1457 lfp->ciphering_required = ciphering_required;
1458 lfp->is_r99 = is_r99;
1459 lfp->is_utran = is_utran;
1460 lfp->assign_tmsi = assign_tmsi;
1461 if (imsi) {
1462 strncpy(lfp->imsi, imsi, sizeof(lfp->imsi)-1);
1463 lfp->imsi[sizeof(lfp->imsi)-1] = '\0';
1464 lfp->lu_by_tmsi = false;
1465 }
1466 fi->priv = lfp;
1467
1468 LOGPFSM(fi, "rev=%s net=%s%s%s\n",
1469 is_r99 ? "R99" : "GSM",
1470 is_utran ? "UTRAN" : "GERAN",
1471 (authentication_required || ciphering_required)?
1472 " Auth" : " (no Auth)",
1473 (authentication_required || ciphering_required)?
1474 (ciphering_required? "+Ciph" : " (no Ciph)")
1475 : "");
1476
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001477 if (is_utran && !authentication_required)
1478 LOGPFSML(fi, LOGL_ERROR,
1479 "Authentication off on UTRAN network. Good luck.\n");
1480
Harald Welteb8b85a12016-06-17 00:06:42 +02001481 osmo_fsm_inst_dispatch(fi, VLR_ULA_E_UPDATE_LA, NULL);
1482
1483 return fi;
1484}
1485
Neels Hofmeyr15809592018-04-06 02:57:51 +02001486void vlr_loc_update_cancel(struct osmo_fsm_inst *fi,
1487 enum osmo_fsm_term_cause fsm_cause,
1488 uint8_t gsm48_cause)
Harald Welteb8b85a12016-06-17 00:06:42 +02001489{
Neels Hofmeyr15809592018-04-06 02:57:51 +02001490 struct lu_fsm_priv *lfp;
1491
1492 OSMO_ASSERT(fi);
1493 OSMO_ASSERT(fi->fsm == &vlr_lu_fsm);
1494
1495 lfp = fi->priv;
1496 lfp->rej_cause = gsm48_cause;
1497
1498 if (fi->state != VLR_ULA_S_DONE)
1499 lu_fsm_failure(fi, gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +02001500}
1501
1502void vlr_lu_fsm_init(void)
1503{
1504 osmo_fsm_register(&vlr_lu_fsm);
1505 osmo_fsm_register(&upd_hlr_vlr_fsm);
1506 osmo_fsm_register(&sub_pres_vlr_fsm);
1507 osmo_fsm_register(&lu_compl_vlr_fsm);
1508}