blob: 3b40285241f9994aa34efc5ac494b5c48012eaf3 [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
Neels Hofmeyr1035d902018-12-28 21:22:32 +010075static int assoc_par_with_subscr(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
Harald Welteb8b85a12016-06-17 00:06:42 +020076{
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 */
Neels Hofmeyr1035d902018-12-28 21:22:32 +010084 return vlr->ops.subscr_assoc(par->msc_conn_ref, par->vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +020085}
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;
Neels Hofmeyr1035d902018-12-28 21:22:32 +0100374 if (assoc_par_with_subscr(fi, vsub) != 0)
375 proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE);
376 else
377 proc_arq_vlr_fn_post_imsi(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200378 vlr_subscr_put(vsub);
379 return;
380 }
381 /* No VSUB could be resolved. What now? */
382
383 if (!par->by_tmsi) {
384 /* We couldn't find a subscriber even by IMSI,
385 * Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200386 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200387 return;
388 } else {
389 /* TMSI was included, are we permitted to use it? */
390 if (vlr->cfg.parq_retrieve_imsi) {
391 /* Obtain_IMSI_VLR */
392 osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_OBTAIN_IMSI,
393 vlr_timer(vlr, 3270), 3270);
394 return;
395 } else {
396 /* Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200397 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200398 return;
399 }
400 }
401}
402
403/* ID REQ(IMSI) has returned */
404static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi,
405 uint32_t event, void *data)
406{
407 struct proc_arq_priv *par = fi->priv;
408 struct vlr_instance *vlr = par->vlr;
409 struct vlr_subscr *vsub;
410
411 OSMO_ASSERT(event == PR_ARQ_E_ID_IMSI);
412
413 vsub = vlr_subscr_find_by_imsi(vlr, par->imsi);
414 if (!vsub) {
415 /* Set User Error: Unidentified Subscriber */
Philipp Maier6f4752e2018-05-15 15:23:59 +0200416 proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welteb8b85a12016-06-17 00:06:42 +0200417 return;
418 }
Neels Hofmeyr1035d902018-12-28 21:22:32 +0100419 if (assoc_par_with_subscr(fi, vsub))
420 proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE);
421 else
422 proc_arq_vlr_fn_post_imsi(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200423 vlr_subscr_put(vsub);
424}
425
426/* Authenticate_VLR has completed */
427static void proc_arq_vlr_fn_w_auth(struct osmo_fsm_inst *fi,
428 uint32_t event, void *data)
429{
Neels Hofmeyr15809592018-04-06 02:57:51 +0200430 enum gsm48_reject_value *cause = data;
Harald Welteb8b85a12016-06-17 00:06:42 +0200431
432 OSMO_ASSERT(event == PR_ARQ_E_AUTH_RES);
433
Neels Hofmeyr15809592018-04-06 02:57:51 +0200434 if (!cause || *cause) {
435 proc_arq_fsm_done(fi, cause? *cause : GSM48_REJECT_NETWORK_FAILURE);
Harald Welteb8b85a12016-06-17 00:06:42 +0200436 return;
Harald Welteb8b85a12016-06-17 00:06:42 +0200437 }
438
Neels Hofmeyr15809592018-04-06 02:57:51 +0200439 /* Node 2 */
440 _proc_arq_vlr_node2(fi);
Harald Welteb8b85a12016-06-17 00:06:42 +0200441}
442
443static void proc_arq_vlr_fn_w_ciph(struct osmo_fsm_inst *fi,
444 uint32_t event, void *data)
445{
446 struct proc_arq_priv *par = fi->priv;
447 struct vlr_subscr *vsub = par->vsub;
448 struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
449
450 OSMO_ASSERT(event == PR_ARQ_E_CIPH_RES);
451
452 if (!data)
453 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
454 else
455 res = *(struct vlr_ciph_result*)data;
456
457 switch (res.cause) {
458 case VLR_CIPH_COMPL:
459 break;
460 case VLR_CIPH_REJECT:
461 LOGPFSM(fi, "ciphering rejected\n");
Neels Hofmeyr15809592018-04-06 02:57:51 +0200462 proc_arq_fsm_done(fi, GSM48_REJECT_ILLEGAL_MS);
Harald Welteb8b85a12016-06-17 00:06:42 +0200463 return;
464 default:
465 LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
466 res.cause);
Neels Hofmeyr15809592018-04-06 02:57:51 +0200467 proc_arq_fsm_done(fi, GSM48_REJECT_ILLEGAL_MS);
Harald Welteb8b85a12016-06-17 00:06:42 +0200468 return;
469 }
470
471
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +0100472 if (*res.imeisv) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200473 LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
474 vlr_subscr_set_imeisv(vsub, res.imeisv);
475 }
476 _proc_arq_vlr_node2_post_ciph(fi);
477}
478
479/* Update_Location_Child_VLR has completed */
480static void proc_arq_vlr_fn_w_upd_loc(struct osmo_fsm_inst *fi,
481 uint32_t event, void *data)
482{
483 OSMO_ASSERT(event == PR_ARQ_E_UPD_LOC_RES);
484
485 _proc_arq_vlr_node2_post_vlr(fi);
486}
487
488/* Subscriber_Present_VLR has completed */
489static void proc_arq_vlr_fn_w_pres(struct osmo_fsm_inst *fi,
490 uint32_t event, void *data)
491{
492 OSMO_ASSERT(event == PR_ARQ_E_PRES_RES);
493
494 _proc_arq_vlr_post_pres(fi);
495}
496
497static void proc_arq_vlr_fn_w_trace(struct osmo_fsm_inst *fi,
498 uint32_t event, void *data)
499{
500 OSMO_ASSERT(event == PR_ARQ_E_TRACE_RES);
501
502 _proc_arq_vlr_post_trace(fi);
503}
504
505/* we have received the ID RESPONSE (IMEI) */
506static void proc_arq_vlr_fn_w_imei(struct osmo_fsm_inst *fi,
507 uint32_t event, void *data)
508{
509 OSMO_ASSERT(event == PR_ARQ_E_IMEI_RES);
510
511 _proc_arq_vlr_post_imei(fi);
512}
513
514/* MSC tells us that MS has acknowleded TMSI re-allocation */
515static void proc_arq_vlr_fn_w_tmsi(struct osmo_fsm_inst *fi,
516 uint32_t event, void *data)
517{
518 OSMO_ASSERT(event == PR_ARQ_E_TMSI_ACK);
519
520 /* FIXME: check confirmation? unfreeze? */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200521 proc_arq_fsm_done(fi, 0);
Harald Welteb8b85a12016-06-17 00:06:42 +0200522}
523
524static const struct osmo_fsm_state proc_arq_vlr_states[] = {
525 [PR_ARQ_S_INIT] = {
526 .name = OSMO_STRINGIFY(PR_ARQ_S_INIT),
527 .in_event_mask = S(PR_ARQ_E_START),
528 .out_state_mask = S(PR_ARQ_S_DONE) |
529 S(PR_ARQ_S_WAIT_OBTAIN_IMSI) |
530 S(PR_ARQ_S_WAIT_AUTH) |
531 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
532 S(PR_ARQ_S_WAIT_SUB_PRES) |
533 S(PR_ARQ_S_WAIT_TRACE_SUB) |
534 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
535 S(PR_ARQ_S_WAIT_TMSI_ACK),
536 .action = proc_arq_vlr_fn_init,
537 },
538 [PR_ARQ_S_WAIT_OBTAIN_IMSI] = {
539 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_OBTAIN_IMSI),
540 .in_event_mask = S(PR_ARQ_E_ID_IMSI),
541 .out_state_mask = S(PR_ARQ_S_DONE) |
542 S(PR_ARQ_S_WAIT_AUTH) |
543 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
544 S(PR_ARQ_S_WAIT_SUB_PRES) |
545 S(PR_ARQ_S_WAIT_TRACE_SUB) |
546 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
547 S(PR_ARQ_S_WAIT_TMSI_ACK),
548 .action = proc_arq_vlr_fn_w_obt_imsi,
549 },
550 [PR_ARQ_S_WAIT_AUTH] = {
551 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_AUTH),
552 .in_event_mask = S(PR_ARQ_E_AUTH_RES),
553 .out_state_mask = S(PR_ARQ_S_DONE) |
554 S(PR_ARQ_S_WAIT_CIPH) |
555 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
556 S(PR_ARQ_S_WAIT_SUB_PRES) |
557 S(PR_ARQ_S_WAIT_TRACE_SUB) |
558 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
559 S(PR_ARQ_S_WAIT_TMSI_ACK),
560 .action = proc_arq_vlr_fn_w_auth,
561 },
562 [PR_ARQ_S_WAIT_CIPH] = {
563 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CIPH),
564 .in_event_mask = S(PR_ARQ_E_CIPH_RES),
565 .out_state_mask = S(PR_ARQ_S_DONE) |
566 S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
567 S(PR_ARQ_S_WAIT_SUB_PRES) |
568 S(PR_ARQ_S_WAIT_TRACE_SUB) |
569 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
570 S(PR_ARQ_S_WAIT_TMSI_ACK),
571 .action = proc_arq_vlr_fn_w_ciph,
572 },
573 [PR_ARQ_S_WAIT_UPD_LOC_CHILD] = {
574 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_UPD_LOC_CHILD),
575 .in_event_mask = S(PR_ARQ_E_UPD_LOC_RES),
576 .out_state_mask = S(PR_ARQ_S_DONE) |
577 S(PR_ARQ_S_WAIT_SUB_PRES) |
578 S(PR_ARQ_S_WAIT_TRACE_SUB) |
579 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
580 S(PR_ARQ_S_WAIT_TMSI_ACK),
581 .action = proc_arq_vlr_fn_w_upd_loc,
582 },
583 [PR_ARQ_S_WAIT_SUB_PRES] = {
584 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_SUB_PRES),
585 .in_event_mask = S(PR_ARQ_E_PRES_RES),
586 .out_state_mask = S(PR_ARQ_S_DONE) |
587 S(PR_ARQ_S_WAIT_TRACE_SUB) |
588 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
589 S(PR_ARQ_S_WAIT_TMSI_ACK),
590 .action = proc_arq_vlr_fn_w_pres,
591 },
592 [PR_ARQ_S_WAIT_TRACE_SUB] = {
593 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TRACE_SUB),
594 .in_event_mask = S(PR_ARQ_E_TRACE_RES),
595 .out_state_mask = S(PR_ARQ_S_DONE) |
596 S(PR_ARQ_S_WAIT_CHECK_IMEI) |
597 S(PR_ARQ_S_WAIT_TMSI_ACK),
598 .action = proc_arq_vlr_fn_w_trace,
599 },
600 [PR_ARQ_S_WAIT_CHECK_IMEI] = {
601 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CHECK_IMEI),
602 .in_event_mask = S(PR_ARQ_E_IMEI_RES),
603 .out_state_mask = S(PR_ARQ_S_DONE) |
604 S(PR_ARQ_S_WAIT_TMSI_ACK),
605 .action = proc_arq_vlr_fn_w_imei,
606 },
607 [PR_ARQ_S_WAIT_TMSI_ACK] = {
608 .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TMSI_ACK),
609 .in_event_mask = S(PR_ARQ_E_TMSI_ACK),
610 .out_state_mask = S(PR_ARQ_S_DONE),
611 .action = proc_arq_vlr_fn_w_tmsi,
612 },
613 [PR_ARQ_S_DONE] = {
614 .name = OSMO_STRINGIFY(PR_ARQ_S_DONE),
615 .onenter = proc_arq_vlr_dispatch_result,
616 },
617};
618
619static struct osmo_fsm proc_arq_vlr_fsm = {
620 .name = "Process_Access_Request_VLR",
621 .states = proc_arq_vlr_states,
622 .num_states = ARRAY_SIZE(proc_arq_vlr_states),
623 .allstate_event_mask = 0,
624 .allstate_action = NULL,
625 .log_subsys = DVLR,
626 .event_names = proc_arq_vlr_event_names,
627 .cleanup = proc_arq_vlr_cleanup,
628};
629
630void
631vlr_proc_acc_req(struct osmo_fsm_inst *parent,
632 uint32_t parent_event_success,
633 uint32_t parent_event_failure,
634 void *parent_event_data,
635 struct vlr_instance *vlr, void *msc_conn_ref,
636 enum vlr_parq_type type, const uint8_t *mi_lv,
637 const struct osmo_location_area_id *lai,
638 bool authentication_required,
Harald Welte71c51df2017-12-23 18:51:48 +0100639 bool ciphering_required,
Harald Welteb8b85a12016-06-17 00:06:42 +0200640 bool is_r99, bool is_utran)
641{
642 struct osmo_fsm_inst *fi;
643 struct proc_arq_priv *par;
644 char mi_string[GSM48_MI_SIZE];
645 uint8_t mi_type;
646
647 fi = osmo_fsm_inst_alloc_child(&proc_arq_vlr_fsm, parent,
648 parent_event_failure);
649 if (!fi)
650 return;
651
652 par = talloc_zero(fi, struct proc_arq_priv);
653 fi->priv = par;
654 par->vlr = vlr;
655 par->msc_conn_ref = msc_conn_ref;
656 par->type = type;
657 par->lai = *lai;
658 par->parent_event_success = parent_event_success;
659 par->parent_event_failure = parent_event_failure;
660 par->parent_event_data = parent_event_data;
661 par->authentication_required = authentication_required;
662 par->ciphering_required = ciphering_required;
663 par->is_r99 = is_r99;
664 par->is_utran = is_utran;
665
666 LOGPFSM(fi, "rev=%s net=%s%s%s\n",
667 is_r99 ? "R99" : "GSM",
668 is_utran ? "UTRAN" : "GERAN",
669 (authentication_required || ciphering_required)?
670 " Auth" : " (no Auth)",
671 (authentication_required || ciphering_required)?
672 (ciphering_required? "+Ciph" : " (no Ciph)")
673 : "");
674
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200675 if (is_utran && !authentication_required)
676 LOGPFSML(fi, LOGL_ERROR,
677 "Authentication off on UTRAN network. Good luck.\n");
678
Harald Welteb8b85a12016-06-17 00:06:42 +0200679 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, mi_lv[0]);
680 mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
681 switch (mi_type) {
682 case GSM_MI_TYPE_IMSI:
Neels Hofmeyrfa391ee2018-07-26 20:15:51 +0200683 osmo_strlcpy(par->imsi, mi_string, sizeof(par->imsi));
Harald Welteb8b85a12016-06-17 00:06:42 +0200684 par->by_tmsi = false;
685 break;
686 case GSM_MI_TYPE_TMSI:
687 par->by_tmsi = true;
688 par->tmsi = osmo_load32be(mi_lv+2);
689 break;
690 case GSM_MI_TYPE_IMEI:
691 /* TODO: IMEI (emergency call) */
692 default:
Philipp Maier6f4752e2018-05-15 15:23:59 +0200693 proc_arq_fsm_done(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
Harald Welteb8b85a12016-06-17 00:06:42 +0200694 return;
695 }
696
697 osmo_fsm_inst_dispatch(fi, PR_ARQ_E_START, NULL);
698}
699
700/* Gracefully terminate an FSM created by vlr_proc_acc_req() in case of
701 * external timeout (i.e. from MSC). */
Neels Hofmeyr15809592018-04-06 02:57:51 +0200702void vlr_parq_cancel(struct osmo_fsm_inst *fi,
703 enum osmo_fsm_term_cause fsm_cause,
704 enum gsm48_reject_value gsm48_cause)
Harald Welteb8b85a12016-06-17 00:06:42 +0200705{
706 if (!fi || fi->state == PR_ARQ_S_DONE)
707 return;
Neels Hofmeyr15809592018-04-06 02:57:51 +0200708 LOGPFSM(fi, "Cancel: %s\n", osmo_fsm_term_cause_name(fsm_cause));
709 proc_arq_fsm_done(fi, gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200710}
711
712
713#if 0
714/***********************************************************************
715 * Update_Location_Child_VLR, TS 29.002 Chapter 25.4.4
716 ***********************************************************************/
717
718enum upd_loc_child_vlr_state {
719 ULC_S_IDLE,
720 ULC_S_WAIT_HLR_RESP,
721 ULC_S_DONE,
722};
723
724enum upd_loc_child_vlr_event {
725 ULC_E_START,
726};
727
728static const struct value_string upd_loc_child_vlr_event_names[] = {
729 { ULC_E_START, "START" },
730 { 0, NULL }
731};
732
733static void upd_loc_child_f_idle(struct osmo_fsm_inst *fi, uint32_t event,
734 void *data)
735{
736 OSMO_ASSERT(event == ULC_E_START);
737
738 /* send update location */
739}
740
741static void upd_loc_child_f_w_hlr(struct osmo_fsm_inst *fi, uint32_t event,
742 void *data)
743{
744}
745
746static const struct osmo_fsm_state upd_loc_child_vlr_states[] = {
747 [ULC_S_IDLE] = {
748 .in_event_mask = ,
749 .out_state_mask = S(ULC_S_WAIT_HLR_RESP) |
750 S(ULC_S_DONE),
751 .name = "IDLE",
752 .action = upd_loc_child_f_idle,
753 },
754 [ULC_S_WAIT_HLR_RESP] = {
755 .in_event_mask = ,
756 .out_state_mask = S(ULC_S_DONE),
757 .name = "WAIT-HLR-RESP",
758 .action = upd_loc_child_f_w_hlr,
759 },
760 [ULC_S_DONE] = {
761 .name = "DONE",
762 },
763};
764
765static struct osmo_fsm upd_loc_child_vlr_fsm = {
766 .name = "Update_Location_Child_VLR",
767 .states = upd_loc_child_vlr_states,
768 .num_states = ARRAY_SIZE(upd_loc_child_vlr_states),
769 .log_subsys = DVLR,
770 .event_names = upd_loc_child_vlr_event_names,
771};
772#endif
773
774void vlr_parq_fsm_init(void)
775{
776 //osmo_fsm_register(&upd_loc_child_vlr_fsm);
777 osmo_fsm_register(&proc_arq_vlr_fsm);
778}