blob: 3a0760d84a7631604214e2ce6814107c68351611 [file] [log] [blame]
Harald Welteb8b85a12016-06-17 00:06:42 +02001/* Osmocom Visitor Location Register (VLR): Access Request 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>
Max43b01b02017-09-15 11:22:30 +020024#include <osmocom/gsm/gsm48.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020025#include <osmocom/msc/vlr.h>
26#include <osmocom/msc/debug.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020027
28#include "vlr_core.h"
29#include "vlr_auth_fsm.h"
30#include "vlr_lu_fsm.h"
31#include "vlr_access_req_fsm.h"
32
33#define S(x) (1 << (x))
34
35/***********************************************************************
36 * Process_Access_Request_VLR, TS 29.002 Chapter 25.4.2
37 ***********************************************************************/
38
Harald Welteb8b85a12016-06-17 00:06:42 +020039static const struct value_string proc_arq_vlr_event_names[] = {
40 OSMO_VALUE_STRING(PR_ARQ_E_START),
41 OSMO_VALUE_STRING(PR_ARQ_E_ID_IMSI),
42 OSMO_VALUE_STRING(PR_ARQ_E_AUTH_RES),
43 OSMO_VALUE_STRING(PR_ARQ_E_CIPH_RES),
44 OSMO_VALUE_STRING(PR_ARQ_E_UPD_LOC_RES),
45 OSMO_VALUE_STRING(PR_ARQ_E_TRACE_RES),
46 OSMO_VALUE_STRING(PR_ARQ_E_IMEI_RES),
47 OSMO_VALUE_STRING(PR_ARQ_E_PRES_RES),
48 OSMO_VALUE_STRING(PR_ARQ_E_TMSI_ACK),
49 { 0, NULL }
50};
51
52struct proc_arq_priv {
53 struct vlr_instance *vlr;
54 struct vlr_subscr *vsub;
55 void *msc_conn_ref;
56 struct osmo_fsm_inst *ul_child_fsm;
57 struct osmo_fsm_inst *sub_pres_vlr_fsm;
58 uint32_t parent_event_success;
59 uint32_t parent_event_failure;
60 void *parent_event_data;
61
62 enum vlr_parq_type type;
Neels Hofmeyr15809592018-04-06 02:57:51 +020063 enum gsm48_reject_value result; /*< 0 on success */
Harald Welteb8b85a12016-06-17 00:06:42 +020064 bool by_tmsi;
65 char imsi[16];
66 uint32_t tmsi;
67 struct osmo_location_area_id lai;
68 bool authentication_required;
Harald Welte71c51df2017-12-23 18:51:48 +010069 bool ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +020070 bool is_r99;
71 bool is_utran;
72 bool implicitly_accepted_parq_by_ciphering_cmd;
73};
74
75static void assoc_par_with_subscr(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
76{
77 struct proc_arq_priv *par = fi->priv;
78 struct vlr_instance *vlr = par->vlr;
79
80 vsub->msc_conn_ref = par->msc_conn_ref;
81 par->vsub = vsub;
82 /* Tell MSC to associate this subscriber with the given
83 * connection */
84 vlr->ops.subscr_assoc(par->msc_conn_ref, par->vsub);
85}
86
Neels Hofmeyr15809592018-04-06 02:57:51 +020087static const char *vlr_proc_arq_result_name(const struct osmo_fsm_inst *fi)
88{
89 struct proc_arq_priv *par = fi->priv;
90 return par->result? gsm48_reject_value_name(par->result) : "PASSED";
91}
92
Harald Welteb8b85a12016-06-17 00:06:42 +020093#define proc_arq_fsm_done(fi, res) _proc_arq_fsm_done(fi, res, __FILE__, __LINE__)
94static void _proc_arq_fsm_done(struct osmo_fsm_inst *fi,
Neels Hofmeyr15809592018-04-06 02:57:51 +020095 enum gsm48_reject_value gsm48_rej,
Harald Welteb8b85a12016-06-17 00:06:42 +020096 const char *file, int line)
97{
98 struct proc_arq_priv *par = fi->priv;
Neels Hofmeyr15809592018-04-06 02:57:51 +020099 par->result = gsm48_rej;
100 LOGPFSMSRC(fi, file, line, "proc_arq_fsm_done(%s)\n", vlr_proc_arq_result_name(fi));
Harald Welteb8b85a12016-06-17 00:06:42 +0200101 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_DONE, 0, 0);
102}
103
104static void proc_arq_vlr_dispatch_result(struct osmo_fsm_inst *fi,
105 uint32_t prev_state)
106{
107 struct proc_arq_priv *par = fi->priv;
108 bool success;
109 int rc;
Neels Hofmeyr15809592018-04-06 02:57:51 +0200110 LOGPFSM(fi, "Process Access Request result: %s\n", vlr_proc_arq_result_name(fi));
Harald Welteb8b85a12016-06-17 00:06:42 +0200111
Neels Hofmeyr15809592018-04-06 02:57:51 +0200112 success = (par->result == 0);
Harald Welteb8b85a12016-06-17 00:06:42 +0200113
114 /* It would be logical to first dispatch the success event to the
115 * parent FSM, but that could start actions that send messages to the
116 * MS. Rather send the CM Service Accept message first and then signal
117 * success. Since messages are handled synchronously, the success event
118 * will be processed before we handle new incoming data from the MS. */
119
120 if (par->type == VLR_PR_ARQ_T_CM_SERV_REQ) {
121 if (success
122 && !par->implicitly_accepted_parq_by_ciphering_cmd) {
123 rc = par->vlr->ops.tx_cm_serv_acc(par->msc_conn_ref);
124 if (rc) {
125 LOGPFSML(fi, LOGL_ERROR,
126 "Failed to send CM Service Accept\n");
127 success = false;
128 }
129 }
130 if (!success) {
131 rc = par->vlr->ops.tx_cm_serv_rej(par->msc_conn_ref,
132 par->result);
133 if (rc)
134 LOGPFSML(fi, LOGL_ERROR,
135 "Failed to send CM Service Reject\n");
136 }
137 }
138
139 /* For VLR_PR_ARQ_T_PAGING_RESP, there is nothing to send. The conn_fsm
140 * will start handling pending paging transactions. */
141
142 if (!fi->proc.parent) {
143 LOGPFSML(fi, LOGL_ERROR, "No parent FSM");
144 return;
145 }
146 osmo_fsm_inst_dispatch(fi->proc.parent,
147 success ? par->parent_event_success
148 : par->parent_event_failure,
149 par->parent_event_data);
150}
151
152void proc_arq_vlr_cleanup(struct osmo_fsm_inst *fi,
153 enum osmo_fsm_term_cause cause)
154{
155 struct proc_arq_priv *par = fi->priv;
156 if (par->vsub && par->vsub->proc_arq_fsm == fi)
157 par->vsub->proc_arq_fsm = NULL;
158}
159
160static void _proc_arq_vlr_post_imei(struct osmo_fsm_inst *fi)
161{
162 struct proc_arq_priv *par = fi->priv;
163 struct vlr_subscr *vsub = par->vsub;
164
165 LOGPFSM(fi, "%s()\n", __func__);
166
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200167 /* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
Harald Welteb8b85a12016-06-17 00:06:42 +0200168 /* TODO: Identity := IMSI */
169 if (0 /* TODO: TMSI reallocation at access: vlr->cfg.alloc_tmsi_arq */) {
170 vlr_subscr_alloc_tmsi(vsub);
171 /* TODO: forward TMSI to MS, wait for TMSI
172 * REALLOC COMPLETE */
173 /* TODO: Freeze old TMSI */
174 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_TMSI_ACK, 0, 0);
175 return;
176 }
177
Neels Hofmeyr15809592018-04-06 02:57:51 +0200178 proc_arq_fsm_done(fi, 0);
Harald Welteb8b85a12016-06-17 00:06:42 +0200179}
180
181static void _proc_arq_vlr_post_trace(struct osmo_fsm_inst *fi)
182{
183 struct proc_arq_priv *par = fi->priv;
184 struct vlr_subscr *vsub = par->vsub;
185 struct vlr_instance *vlr = vsub->vlr;
186
187 LOGPFSM(fi, "%s()\n", __func__);
188
189 /* Node 3 */
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200190 /* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
Harald Welteb8b85a12016-06-17 00:06:42 +0200191 if (0 /* IMEI check required */) {
192 /* Chck_IMEI_VLR */
193 vlr->ops.tx_id_req(par->msc_conn_ref, GSM_MI_TYPE_IMEI);
194 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CHECK_IMEI,
195 vlr_timer(vlr, 3270), 3270);
196 } else
197 _proc_arq_vlr_post_imei(fi);
198}
199
200/* After Subscriber_Present_VLR */
201static void _proc_arq_vlr_post_pres(struct osmo_fsm_inst *fi)
202{
203 LOGPFSM(fi, "%s()\n", __func__);
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200204 /* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
Harald Welteb8b85a12016-06-17 00:06:42 +0200205 if (0 /* TODO: tracing required */) {
206 /* TODO: Trace_Subscriber_Activity_VLR */
207 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_TRACE_SUB, 0, 0);
208 }
209 _proc_arq_vlr_post_trace(fi);
210}
211
212/* After Update_Location_Child_VLR */
213static void _proc_arq_vlr_node2_post_vlr(struct osmo_fsm_inst *fi)
214{
215 struct proc_arq_priv *par = fi->priv;
216 struct vlr_subscr *vsub = par->vsub;
217
218 LOGPFSM(fi, "%s()\n", __func__);
219
220 if (!vsub->sub_dataconf_by_hlr_ind) {
221 /* Set User Error: Unidentified Subscriber */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200222 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200223 return;
224 }
Neels Hofmeyref9126c2017-07-18 15:38:39 +0200225 /* We don't feature location area specific blocking (yet). */
Harald Welteb8b85a12016-06-17 00:06:42 +0200226 if (0 /* roaming not allowed in LA */) {
227 /* Set User Error: Roaming not allowed in this LA */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200228 proc_arq_fsm_done(fi, GSM48_REJECT_ROAMING_NOT_ALLOWED);
Harald Welteb8b85a12016-06-17 00:06:42 +0200229 return;
230 }
231 vsub->imsi_detached_flag = false;
232 if (vsub->ms_not_reachable_flag) {
233 /* Start Subscriber_Present_VLR */
234 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_SUB_PRES, 0, 0);
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100235 sub_pres_vlr_fsm_start(&par->sub_pres_vlr_fsm, fi, vsub, PR_ARQ_E_PRES_RES);
Harald Welteb8b85a12016-06-17 00:06:42 +0200236 return;
237 }
238 _proc_arq_vlr_post_pres(fi);
239}
240
241static void _proc_arq_vlr_node2_post_ciph(struct osmo_fsm_inst *fi)
242{
243 struct proc_arq_priv *par = fi->priv;
244 struct vlr_subscr *vsub = par->vsub;
245
246 LOGPFSM(fi, "%s()\n", __func__);
247
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200248 if (par->is_utran) {
249 int rc;
250 rc = par->vlr->ops.tx_common_id(par->msc_conn_ref);
251 if (rc)
252 LOGPFSML(fi, LOGL_ERROR,
253 "Error while sending Common ID (%d)\n", rc);
254 }
255
Harald Welteb8b85a12016-06-17 00:06:42 +0200256 vsub->conf_by_radio_contact_ind = true;
257 if (vsub->loc_conf_in_hlr_ind == false) {
258 /* start Update_Location_Child_VLR. WE use
259 * Update_HLR_VLR instead, the differences appear
260 * insignificant for now. */
261 par->ul_child_fsm = upd_hlr_vlr_proc_start(fi, vsub,
262 PR_ARQ_E_UPD_LOC_RES);
263 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_UPD_LOC_CHILD, 0, 0);
264 return;
265 }
266 _proc_arq_vlr_node2_post_vlr(fi);
267}
268
269static bool is_ciph_required(struct proc_arq_priv *par)
270{
Harald Welte71c51df2017-12-23 18:51:48 +0100271 return par->ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +0200272}
273
274static void _proc_arq_vlr_node2(struct osmo_fsm_inst *fi)
275{
276 struct proc_arq_priv *par = fi->priv;
277 struct vlr_subscr *vsub = par->vsub;
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100278 bool umts_aka;
Harald Welteb8b85a12016-06-17 00:06:42 +0200279
280 LOGPFSM(fi, "%s()\n", __func__);
281
282 if (!is_ciph_required(par)) {
283 _proc_arq_vlr_node2_post_ciph(fi);
284 return;
285 }
286
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100287 switch (vsub->sec_ctx) {
288 case VLR_SEC_CTX_GSM:
289 umts_aka = false;
290 break;
291 case VLR_SEC_CTX_UMTS:
292 umts_aka = true;
293 break;
294 default:
295 LOGPFSML(fi, LOGL_ERROR, "Cannot start ciphering, security context is not established\n");
Neels Hofmeyr15809592018-04-06 02:57:51 +0200296 proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE);
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100297 return;
298 }
299
Harald Welteb8b85a12016-06-17 00:06:42 +0200300 if (vlr_set_ciph_mode(vsub->vlr, fi, par->msc_conn_ref,
301 par->ciphering_required,
Neels Hofmeyr7795a192018-03-10 00:26:36 +0100302 umts_aka,
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200303 vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200304 LOGPFSML(fi, LOGL_ERROR,
305 "Failed to send Ciphering Mode Command\n");
Neels Hofmeyr15809592018-04-06 02:57:51 +0200306 proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200307 return;
308 }
309
310 par->implicitly_accepted_parq_by_ciphering_cmd = true;
311 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CIPH, 0, 0);
312}
313
314static bool is_auth_required(struct proc_arq_priv *par)
315{
316 /* The cases where the authentication procedure should be used
317 * are defined in 3GPP TS 33.102 */
318 /* For now we use a default value passed in to vlr_lu_fsm(). */
Harald Welte71c51df2017-12-23 18:51:48 +0100319 return par->authentication_required || par->ciphering_required;
Harald Welteb8b85a12016-06-17 00:06:42 +0200320}
321
322/* after the IMSI is known */
323static void proc_arq_vlr_fn_post_imsi(struct osmo_fsm_inst *fi)
324{
325 struct proc_arq_priv *par = fi->priv;
326 struct vlr_subscr *vsub = par->vsub;
327
328 LOGPFSM(fi, "%s()\n", __func__);
329
330 OSMO_ASSERT(vsub);
331
332 /* TODO: Identity IMEI -> System Failure */
333 if (is_auth_required(par)) {
334 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_AUTH,
335 0, 0);
336 vsub->auth_fsm = auth_fsm_start(vsub, fi->log_level, fi,
337 PR_ARQ_E_AUTH_RES,
338 par->is_r99,
339 par->is_utran);
340 } else {
341 _proc_arq_vlr_node2(fi);
342 }
343}
344
345static void proc_arq_vlr_fn_init(struct osmo_fsm_inst *fi,
346 uint32_t event, void *data)
347{
348 struct proc_arq_priv *par = fi->priv;
349 struct vlr_instance *vlr = par->vlr;
350 struct vlr_subscr *vsub = NULL;
351
352 OSMO_ASSERT(event == PR_ARQ_E_START);
353
354 /* Obtain_Identity_VLR */
355 if (!par->by_tmsi) {
356 /* IMSI was included */
357 vsub = vlr_subscr_find_by_imsi(par->vlr, par->imsi);
358 } else {
359 /* TMSI was included */
360 vsub = vlr_subscr_find_by_tmsi(par->vlr, par->tmsi);
361 }
362 if (vsub) {
Harald Welte2483f1b2016-06-19 18:06:02 +0200363 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +0200364 if (vsub->proc_arq_fsm && fi != vsub->proc_arq_fsm) {
365 LOGPFSML(fi, LOGL_ERROR,
366 "Another proc_arq_fsm is already"
367 " associated with subscr %s,"
368 " terminating the other FSM.\n",
369 vlr_subscr_name(vsub));
370 proc_arq_fsm_done(vsub->proc_arq_fsm,
Neels Hofmeyr15809592018-04-06 02:57:51 +0200371 GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200372 }
373 vsub->proc_arq_fsm = fi;
374 assoc_par_with_subscr(fi, vsub);
375 proc_arq_vlr_fn_post_imsi(fi);
376 vlr_subscr_put(vsub);
377 return;
378 }
379 /* No VSUB could be resolved. What now? */
380
381 if (!par->by_tmsi) {
382 /* We couldn't find a subscriber even by IMSI,
383 * Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200384 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200385 return;
386 } else {
387 /* TMSI was included, are we permitted to use it? */
388 if (vlr->cfg.parq_retrieve_imsi) {
389 /* Obtain_IMSI_VLR */
390 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_OBTAIN_IMSI,
391 vlr_timer(vlr, 3270), 3270);
392 return;
393 } else {
394 /* Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200395 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200396 return;
397 }
398 }
399}
400
401/* ID REQ(IMSI) has returned */
402static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi,
403 uint32_t event, void *data)
404{
405 struct proc_arq_priv *par = fi->priv;
406 struct vlr_instance *vlr = par->vlr;
407 struct vlr_subscr *vsub;
408
409 OSMO_ASSERT(event == PR_ARQ_E_ID_IMSI);
410
411 vsub = vlr_subscr_find_by_imsi(vlr, par->imsi);
412 if (!vsub) {
413 /* Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200414 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200415 return;
416 }
417 assoc_par_with_subscr(fi, vsub);
418 proc_arq_vlr_fn_post_imsi(fi);
419 vlr_subscr_put(vsub);
420}
421
422/* Authenticate_VLR has completed */
423static void proc_arq_vlr_fn_w_auth(struct osmo_fsm_inst *fi,
424 uint32_t event, void *data)
425{
Neels Hofmeyr15809592018-04-06 02:57:51 +0200426 enum gsm48_reject_value *cause = data;
Harald Welteb8b85a12016-06-17 00:06:42 +0200427
428 OSMO_ASSERT(event == PR_ARQ_E_AUTH_RES);
429
Neels Hofmeyr15809592018-04-06 02:57:51 +0200430 if (!cause || *cause) {
431 proc_arq_fsm_done(fi, cause? *cause : GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200432 return;
Harald Welteb8b85a12016-06-17 00:06:42 +0200433 }
434
Neels Hofmeyr15809592018-04-06 02:57:51 +0200435 /* Node 2 */
436 _proc_arq_vlr_node2(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200437}
438
439static void proc_arq_vlr_fn_w_ciph(struct osmo_fsm_inst *fi,
440 uint32_t event, void *data)
441{
442 struct proc_arq_priv *par = fi->priv;
443 struct vlr_subscr *vsub = par->vsub;
444 struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
445
446 OSMO_ASSERT(event == PR_ARQ_E_CIPH_RES);
447
448 if (!data)
449 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
450 else
451 res = *(struct vlr_ciph_result*)data;
452
453 switch (res.cause) {
454 case VLR_CIPH_COMPL:
455 break;
456 case VLR_CIPH_REJECT:
457 LOGPFSM(fi, "ciphering rejected\n");
Neels Hofmeyr15809592018-04-06 02:57:51 +0200458 proc_arq_fsm_done(fi, GSM48_REJECT_ILLEGAL_MS);
Harald Welteb8b85a12016-06-17 00:06:42 +0200459 return;
460 default:
461 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
462 res.cause);
Neels Hofmeyr15809592018-04-06 02:57:51 +0200463 proc_arq_fsm_done(fi, GSM48_REJECT_ILLEGAL_MS);
Harald Welteb8b85a12016-06-17 00:06:42 +0200464 return;
465 }
466
467
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +0100468 if (*res.imeisv) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200469 LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
470 vlr_subscr_set_imeisv(vsub, res.imeisv);
471 }
472 _proc_arq_vlr_node2_post_ciph(fi);
473}
474
475/* Update_Location_Child_VLR has completed */
476static void proc_arq_vlr_fn_w_upd_loc(struct osmo_fsm_inst *fi,
477 uint32_t event, void *data)
478{
479 OSMO_ASSERT(event == PR_ARQ_E_UPD_LOC_RES);
480
481 _proc_arq_vlr_node2_post_vlr(fi);
482}
483
484/* Subscriber_Present_VLR has completed */
485static void proc_arq_vlr_fn_w_pres(struct osmo_fsm_inst *fi,
486 uint32_t event, void *data)
487{
488 OSMO_ASSERT(event == PR_ARQ_E_PRES_RES);
489
490 _proc_arq_vlr_post_pres(fi);
491}
492
493static void proc_arq_vlr_fn_w_trace(struct osmo_fsm_inst *fi,
494 uint32_t event, void *data)
495{
496 OSMO_ASSERT(event == PR_ARQ_E_TRACE_RES);
497
498 _proc_arq_vlr_post_trace(fi);
499}
500
501/* we have received the ID RESPONSE (IMEI) */
502static void proc_arq_vlr_fn_w_imei(struct osmo_fsm_inst *fi,
503 uint32_t event, void *data)
504{
505 OSMO_ASSERT(event == PR_ARQ_E_IMEI_RES);
506
507 _proc_arq_vlr_post_imei(fi);
508}
509
510/* MSC tells us that MS has acknowleded TMSI re-allocation */
511static void proc_arq_vlr_fn_w_tmsi(struct osmo_fsm_inst *fi,
512 uint32_t event, void *data)
513{
514 OSMO_ASSERT(event == PR_ARQ_E_TMSI_ACK);
515
516 /* FIXME: check confirmation? unfreeze? */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200517 proc_arq_fsm_done(fi, 0);
Harald Welteb8b85a12016-06-17 00:06:42 +0200518}
519
520static const struct osmo_fsm_state proc_arq_vlr_states[] = {
521 [PR_ARQ_S_INIT] = {
522 .name = OSMO_STRINGIFY(PR_ARQ_S_INIT),
523 .in_event_mask = S(PR_ARQ_E_START),
524 .out_state_mask = S(PR_ARQ_S_DONE) |
525 S(PR_ARQ_S_WAIT_OBTAIN_IMSI) |
526 S(PR_ARQ_S_WAIT_AUTH) |
527 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
528 S(PR_ARQ_S_WAIT_SUB_PRES) |
529 S(PR_ARQ_S_WAIT_TRACE_SUB) |
530 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
531 S(PR_ARQ_S_WAIT_TMSI_ACK),
532 .action = proc_arq_vlr_fn_init,
533 },
534 [PR_ARQ_S_WAIT_OBTAIN_IMSI] = {
535 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_OBTAIN_IMSI),
536 .in_event_mask = S(PR_ARQ_E_ID_IMSI),
537 .out_state_mask = S(PR_ARQ_S_DONE) |
538 S(PR_ARQ_S_WAIT_AUTH) |
539 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
540 S(PR_ARQ_S_WAIT_SUB_PRES) |
541 S(PR_ARQ_S_WAIT_TRACE_SUB) |
542 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
543 S(PR_ARQ_S_WAIT_TMSI_ACK),
544 .action = proc_arq_vlr_fn_w_obt_imsi,
545 },
546 [PR_ARQ_S_WAIT_AUTH] = {
547 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_AUTH),
548 .in_event_mask = S(PR_ARQ_E_AUTH_RES),
549 .out_state_mask = S(PR_ARQ_S_DONE) |
550 S(PR_ARQ_S_WAIT_CIPH) |
551 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
552 S(PR_ARQ_S_WAIT_SUB_PRES) |
553 S(PR_ARQ_S_WAIT_TRACE_SUB) |
554 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
555 S(PR_ARQ_S_WAIT_TMSI_ACK),
556 .action = proc_arq_vlr_fn_w_auth,
557 },
558 [PR_ARQ_S_WAIT_CIPH] = {
559 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CIPH),
560 .in_event_mask = S(PR_ARQ_E_CIPH_RES),
561 .out_state_mask = S(PR_ARQ_S_DONE) |
562 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
563 S(PR_ARQ_S_WAIT_SUB_PRES) |
564 S(PR_ARQ_S_WAIT_TRACE_SUB) |
565 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
566 S(PR_ARQ_S_WAIT_TMSI_ACK),
567 .action = proc_arq_vlr_fn_w_ciph,
568 },
569 [PR_ARQ_S_WAIT_UPD_LOC_CHILD] = {
570 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_UPD_LOC_CHILD),
571 .in_event_mask = S(PR_ARQ_E_UPD_LOC_RES),
572 .out_state_mask = S(PR_ARQ_S_DONE) |
573 S(PR_ARQ_S_WAIT_SUB_PRES) |
574 S(PR_ARQ_S_WAIT_TRACE_SUB) |
575 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
576 S(PR_ARQ_S_WAIT_TMSI_ACK),
577 .action = proc_arq_vlr_fn_w_upd_loc,
578 },
579 [PR_ARQ_S_WAIT_SUB_PRES] = {
580 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_SUB_PRES),
581 .in_event_mask = S(PR_ARQ_E_PRES_RES),
582 .out_state_mask = S(PR_ARQ_S_DONE) |
583 S(PR_ARQ_S_WAIT_TRACE_SUB) |
584 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
585 S(PR_ARQ_S_WAIT_TMSI_ACK),
586 .action = proc_arq_vlr_fn_w_pres,
587 },
588 [PR_ARQ_S_WAIT_TRACE_SUB] = {
589 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TRACE_SUB),
590 .in_event_mask = S(PR_ARQ_E_TRACE_RES),
591 .out_state_mask = S(PR_ARQ_S_DONE) |
592 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
593 S(PR_ARQ_S_WAIT_TMSI_ACK),
594 .action = proc_arq_vlr_fn_w_trace,
595 },
596 [PR_ARQ_S_WAIT_CHECK_IMEI] = {
597 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CHECK_IMEI),
598 .in_event_mask = S(PR_ARQ_E_IMEI_RES),
599 .out_state_mask = S(PR_ARQ_S_DONE) |
600 S(PR_ARQ_S_WAIT_TMSI_ACK),
601 .action = proc_arq_vlr_fn_w_imei,
602 },
603 [PR_ARQ_S_WAIT_TMSI_ACK] = {
604 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TMSI_ACK),
605 .in_event_mask = S(PR_ARQ_E_TMSI_ACK),
606 .out_state_mask = S(PR_ARQ_S_DONE),
607 .action = proc_arq_vlr_fn_w_tmsi,
608 },
609 [PR_ARQ_S_DONE] = {
610 .name = OSMO_STRINGIFY(PR_ARQ_S_DONE),
611 .onenter = proc_arq_vlr_dispatch_result,
612 },
613};
614
615static struct osmo_fsm proc_arq_vlr_fsm = {
616 .name = "Process_Access_Request_VLR",
617 .states = proc_arq_vlr_states,
618 .num_states = ARRAY_SIZE(proc_arq_vlr_states),
619 .allstate_event_mask = 0,
620 .allstate_action = NULL,
621 .log_subsys = DVLR,
622 .event_names = proc_arq_vlr_event_names,
623 .cleanup = proc_arq_vlr_cleanup,
624};
625
626void
627vlr_proc_acc_req(struct osmo_fsm_inst *parent,
628 uint32_t parent_event_success,
629 uint32_t parent_event_failure,
630 void *parent_event_data,
631 struct vlr_instance *vlr, void *msc_conn_ref,
632 enum vlr_parq_type type, const uint8_t *mi_lv,
633 const struct osmo_location_area_id *lai,
634 bool authentication_required,
Harald Welte71c51df2017-12-23 18:51:48 +0100635 bool ciphering_required,
Harald Welteb8b85a12016-06-17 00:06:42 +0200636 bool is_r99, bool is_utran)
637{
638 struct osmo_fsm_inst *fi;
639 struct proc_arq_priv *par;
640 char mi_string[GSM48_MI_SIZE];
641 uint8_t mi_type;
642
643 fi = osmo_fsm_inst_alloc_child(&proc_arq_vlr_fsm, parent,
644 parent_event_failure);
645 if (!fi)
646 return;
647
648 par = talloc_zero(fi, struct proc_arq_priv);
649 fi->priv = par;
650 par->vlr = vlr;
651 par->msc_conn_ref = msc_conn_ref;
652 par->type = type;
653 par->lai = *lai;
654 par->parent_event_success = parent_event_success;
655 par->parent_event_failure = parent_event_failure;
656 par->parent_event_data = parent_event_data;
657 par->authentication_required = authentication_required;
658 par->ciphering_required = ciphering_required;
659 par->is_r99 = is_r99;
660 par->is_utran = is_utran;
661
662 LOGPFSM(fi, "rev=%s net=%s%s%s\n",
663 is_r99 ? "R99" : "GSM",
664 is_utran ? "UTRAN" : "GERAN",
665 (authentication_required || ciphering_required)?
666 " Auth" : " (no Auth)",
667 (authentication_required || ciphering_required)?
668 (ciphering_required? "+Ciph" : " (no Ciph)")
669 : "");
670
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200671 if (is_utran && !authentication_required)
672 LOGPFSML(fi, LOGL_ERROR,
673 "Authentication off on UTRAN network. Good luck.\n");
674
Harald Welteb8b85a12016-06-17 00:06:42 +0200675 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, mi_lv[0]);
676 mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
677 switch (mi_type) {
678 case GSM_MI_TYPE_IMSI:
Neels Hofmeyrfa391ee2018-07-26 20:15:51 +0200679 osmo_strlcpy(par->imsi, mi_string, sizeof(par->imsi));
Harald Welteb8b85a12016-06-17 00:06:42 +0200680 par->by_tmsi = false;
681 break;
682 case GSM_MI_TYPE_TMSI:
683 par->by_tmsi = true;
684 par->tmsi = osmo_load32be(mi_lv+2);
685 break;
686 case GSM_MI_TYPE_IMEI:
687 /* TODO: IMEI (emergency call) */
688 default:
Philipp Maier6f4752e2018-05-15 15:23:59 +0200689 proc_arq_fsm_done(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
Harald Welteb8b85a12016-06-17 00:06:42 +0200690 return;
691 }
692
693 osmo_fsm_inst_dispatch(fi, PR_ARQ_E_START, NULL);
694}
695
696/* Gracefully terminate an FSM created by vlr_proc_acc_req() in case of
697 * external timeout (i.e. from MSC). */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200698void vlr_parq_cancel(struct osmo_fsm_inst *fi,
699 enum osmo_fsm_term_cause fsm_cause,
700 enum gsm48_reject_value gsm48_cause)
Harald Welteb8b85a12016-06-17 00:06:42 +0200701{
702 if (!fi || fi->state == PR_ARQ_S_DONE)
703 return;
Neels Hofmeyr15809592018-04-06 02:57:51 +0200704 LOGPFSM(fi, "Cancel: %s\n", osmo_fsm_term_cause_name(fsm_cause));
705 proc_arq_fsm_done(fi, gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200706}
707
708
709#if 0
710/***********************************************************************
711 * Update_Location_Child_VLR, TS 29.002 Chapter 25.4.4
712 ***********************************************************************/
713
714enum upd_loc_child_vlr_state {
715 ULC_S_IDLE,
716 ULC_S_WAIT_HLR_RESP,
717 ULC_S_DONE,
718};
719
720enum upd_loc_child_vlr_event {
721 ULC_E_START,
722};
723
724static const struct value_string upd_loc_child_vlr_event_names[] = {
725 { ULC_E_START, "START" },
726 { 0, NULL }
727};
728
729static void upd_loc_child_f_idle(struct osmo_fsm_inst *fi, uint32_t event,
730 void *data)
731{
732 OSMO_ASSERT(event == ULC_E_START);
733
734 /* send update location */
735}
736
737static void upd_loc_child_f_w_hlr(struct osmo_fsm_inst *fi, uint32_t event,
738 void *data)
739{
740}
741
742static const struct osmo_fsm_state upd_loc_child_vlr_states[] = {
743 [ULC_S_IDLE] = {
744 .in_event_mask = ,
745 .out_state_mask = S(ULC_S_WAIT_HLR_RESP) |
746 S(ULC_S_DONE),
747 .name = "IDLE",
748 .action = upd_loc_child_f_idle,
749 },
750 [ULC_S_WAIT_HLR_RESP] = {
751 .in_event_mask = ,
752 .out_state_mask = S(ULC_S_DONE),
753 .name = "WAIT-HLR-RESP",
754 .action = upd_loc_child_f_w_hlr,
755 },
756 [ULC_S_DONE] = {
757 .name = "DONE",
758 },
759};
760
761static struct osmo_fsm upd_loc_child_vlr_fsm = {
762 .name = "Update_Location_Child_VLR",
763 .states = upd_loc_child_vlr_states,
764 .num_states = ARRAY_SIZE(upd_loc_child_vlr_states),
765 .log_subsys = DVLR,
766 .event_names = upd_loc_child_vlr_event_names,
767};
768#endif
769
770void vlr_parq_fsm_init(void)
771{
772 //osmo_fsm_register(&upd_loc_child_vlr_fsm);
773 osmo_fsm_register(&proc_arq_vlr_fsm);
774}