blob: b4bb27f6f39396ac6405ef342eb6522ff27573ec [file] [log] [blame]
Harald Welteb8b85a12016-06-17 00:06:42 +02001#pragma once
2
3#include <stdint.h>
4#include <osmocom/core/linuxlist.h>
5#include <osmocom/core/fsm.h>
6#include <osmocom/core/logging.h>
7#include <osmocom/gsm/protocol/gsm_23_003.h>
8#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
9#include <osmocom/gsm/gsm23003.h>
Neels Hofmeyrcf309132017-12-14 03:57:31 +010010#include <osmocom/gsm/gsm0808.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020011#include <osmocom/msc/gsm_data.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020012// for GSM_NAME_LENGTH
Neels Hofmeyr90843962017-09-04 15:04:35 +020013#include <osmocom/msc/gsm_subscriber.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020014
Maxa263bb22017-12-27 13:23:44 +010015#define LOGGSUPP(level, gsup, fmt, args...) \
16 LOGP(DVLR, level, "GSUP(%s) " fmt, (gsup)->imsi, ## args)
17
18#define LOGVSUBP(level, vsub, fmt, args...) \
19 LOGP(DVLR, level, "SUBSCR(%s) " fmt, vlr_subscr_name(vsub), ## args)
20
Harald Welte2483f1b2016-06-19 18:06:02 +020021struct log_target;
22
Harald Welteb8b85a12016-06-17 00:06:42 +020023/* from 3s to 10s */
24#define GSM_29002_TIMER_S 10
25/* from 15s to 30s */
26#define GSM_29002_TIMER_M 30
27/* from 1min to 10min */
28#define GSM_29002_TIMER_ML (10*60)
29/* from 28h to 38h */
30#define GSM_29002_TIMER_L (32*60*60)
31
Harald Welteb8b85a12016-06-17 00:06:42 +020032/* VLR subscriber authentication state */
33enum vlr_subscr_auth_state {
34 /* subscriber needs to be autenticated */
35 VLR_SUB_AS_NEEDS_AUTH,
36 /* waiting for AuthInfo from HLR/AUC */
37 VLR_SUB_AS_NEEDS_AUTH_WAIT_AI,
38 /* waiting for response from subscriber */
39 VLR_SUB_AS_WAIT_RESP,
40 /* successfully authenticated */
41 VLR_SUB_AS_AUTHENTICATED,
42 /* subscriber needs re-sync */
43 VLR_SUB_AS_NEEDS_RESYNC,
44 /* waiting for AuthInfo with ReSync */
45 VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC,
46 /* waiting for response from subscr, resync case */
47 VLR_SUB_AS_WAIT_RESP_RESYNC,
48 /* waiting for IMSI from subscriber */
49 VLR_SUB_AS_WAIT_ID_IMSI,
50 /* authentication has failed */
51 VLR_SUB_AS_AUTH_FAILED,
52};
53
54enum vlr_lu_event {
55 VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */
56 VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */
57 VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */
58 VLR_ULA_E_AUTH_RES, /* Result of auth procedure */
59 VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */
60 VLR_ULA_E_ID_IMSI, /* IMSI recieved from MS */
61 VLR_ULA_E_ID_IMEI, /* IMEI received from MS */
62 VLR_ULA_E_ID_IMEISV, /* IMEISV received from MS */
63 VLR_ULA_E_HLR_LU_RES, /* HLR UpdateLocation result */
64 VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */
65 VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */
66 VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */
67 VLR_ULA_E_NEW_TMSI_ACK, /* TMSI Reallocation Complete */
68};
69
70enum vlr_ciph_result_cause {
71 VLR_CIPH_REJECT, /* ? */
72 VLR_CIPH_COMPL,
73};
74
75struct vlr_ciph_result {
76 enum vlr_ciph_result_cause cause;
77 const char *imeisv;
78};
79
80enum vlr_subscr_security_context {
81 VLR_SEC_CTX_NONE,
82 VLR_SEC_CTX_GSM,
83 VLR_SEC_CTX_UMTS,
84};
85
86enum vlr_lu_type {
87 VLR_LU_TYPE_PERIODIC,
88 VLR_LU_TYPE_IMSI_ATTACH,
89 VLR_LU_TYPE_REGULAR,
90};
91
92#define OSMO_LBUF_DECL(name, xlen) \
93 struct { \
94 uint8_t buf[xlen]; \
95 size_t len; \
96 } name
97
98struct sgsn_mm_ctx;
99struct vlr_instance;
100
101/* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or
102 * SGSN (PS), particularly while interacting with the HLR via GSUP */
103struct vlr_subscr {
104 struct llist_head list;
105 struct vlr_instance *vlr;
106
107 /* TODO either populate from HLR or drop this completely? */
108 long long unsigned int id;
109
110 /* Data from HLR */ /* 3GPP TS 23.008 */
111 /* Always use vlr_subscr_set_imsi() to write to imsi[] */
112 char imsi[GSM23003_IMSI_MAX_DIGITS+1]; /* 2.1.1.1 */
113 char msisdn[GSM_EXTENSION_LENGTH+1]; /* 2.1.2 */
114 char name[GSM_NAME_LENGTH+1]; /* proprietary */
115 OSMO_LBUF_DECL(hlr, 16); /* 2.4.7 */
116 uint32_t periodic_lu_timer; /* 2.4.24 */
117 uint32_t age_indicator; /* 2.17.1 */
118
119 /* Authentication Data */
120 struct gsm_auth_tuple auth_tuples[5]; /* 2.3.1-2.3.4 */
121 struct gsm_auth_tuple *last_tuple;
122 enum vlr_subscr_security_context sec_ctx;
123
124 /* Data local to VLR is below */
125 uint32_t tmsi; /* 2.1.4 */
126 /* Newly allocated TMSI that was not yet acked by MS */
127 uint32_t tmsi_new;
128
129 /* some redundancy in information below? */
130 struct osmo_cell_global_id cgi; /* 2.4.16 */
131 uint16_t lac; /* 2.4.2 */
132
133 char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.2.3 */
134 char imei[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.1.9 */
135 bool imsi_detached_flag; /* 2.7.1 */
136 bool conf_by_radio_contact_ind; /* 2.7.4.1 */
137 bool sub_dataconf_by_hlr_ind; /* 2.7.4.2 */
138 bool loc_conf_in_hlr_ind; /* 2.7.4.3 */
139 bool dormant_ind; /* 2.7.8 */
140 bool cancel_loc_rx; /* 2.7.8A */
141 bool ms_not_reachable_flag; /* 2.10.2 (MNRF) */
142 bool la_allowed;
143
144 int use_count;
Harald Welteb8b85a12016-06-17 00:06:42 +0200145
146 struct osmo_fsm_inst *lu_fsm;
147 struct osmo_fsm_inst *auth_fsm;
148 struct osmo_fsm_inst *proc_arq_fsm;
149
150 bool lu_complete;
151
152 void *msc_conn_ref;
153
154 /* PS (SGSN) specific parts */
155 struct {
156 struct llist_head pdp_list;
157 uint8_t rac;
158 uint8_t sac;
159 struct gprs_mm_ctx *mmctx;
160 } ps;
161 /* CS (NITB/CSCN) specific parts */
162 struct {
163 /* pending requests */
164 bool is_paging;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100165 struct osmo_timer_list paging_response_timer;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200166 /* list of struct subscr_request */
Harald Welteb8b85a12016-06-17 00:06:42 +0200167 struct llist_head requests;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200168 uint8_t lac;
169 enum ran_type attached_via_ran;
Harald Welteb8b85a12016-06-17 00:06:42 +0200170 } cs;
171};
172
173enum vlr_proc_arq_result;
174
175enum vlr_ciph {
176 VLR_CIPH_NONE, /*< A5/0, no encryption */
177 VLR_CIPH_A5_1, /*< A5/1, encryption */
178 VLR_CIPH_A5_2, /*< A5/2, deprecated export-grade encryption */
179 VLR_CIPH_A5_3, /*< A5/3, 'new secure' encryption */
180};
181
Neels Hofmeyrcf309132017-12-14 03:57:31 +0100182static inline uint8_t vlr_ciph_to_gsm0808_alg_id(enum vlr_ciph ciph)
183{
184 switch (ciph) {
185 default:
186 case VLR_CIPH_NONE:
187 return GSM0808_ALG_ID_A5_0;
188 case VLR_CIPH_A5_1:
189 return GSM0808_ALG_ID_A5_1;
190 case VLR_CIPH_A5_2:
191 return GSM0808_ALG_ID_A5_2;
192 case VLR_CIPH_A5_3:
193 return GSM0808_ALG_ID_A5_3;
194 }
195}
196
Harald Welteb8b85a12016-06-17 00:06:42 +0200197struct vlr_ops {
198 /* encode + transmit an AUTH REQ towards the MS.
199 * \param[in] at auth tuple providing rand, key_seq and autn.
200 * \param[in] send_autn True to send AUTN, for r99 UMTS auth.
201 */
202 int (*tx_auth_req)(void *msc_conn_ref, struct gsm_auth_tuple *at,
203 bool send_autn);
204 /* encode + transmit an AUTH REJECT towards the MS */
205 int (*tx_auth_rej)(void *msc_conn_ref);
206
207 /* encode + transmit an IDENTITY REQUEST towards the MS */
208 int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type);
209
210 int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi);
211 int (*tx_lu_rej)(void *msc_conn_ref, uint8_t cause);
212 int (*tx_cm_serv_acc)(void *msc_conn_ref);
213 int (*tx_cm_serv_rej)(void *msc_conn_ref, enum vlr_proc_arq_result result);
214
215 int (*set_ciph_mode)(void *msc_conn_ref, enum vlr_ciph ciph_mode,
Neels Hofmeyr2ef2da52017-12-18 01:23:42 +0100216 bool umts_aka, bool retrieve_imeisv);
Harald Welteb8b85a12016-06-17 00:06:42 +0200217
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200218 /* UTRAN: send Common Id (when auth+ciph are complete) */
219 int (*tx_common_id)(void *msc_conn_ref);
220
221
Harald Welteb8b85a12016-06-17 00:06:42 +0200222 /* notify MSC/SGSN that the subscriber data in VLR has been updated */
223 void (*subscr_update)(struct vlr_subscr *vsub);
224 /* notify MSC/SGSN that the given subscriber has been associated
225 * with this msc_conn_ref */
226 void (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub);
227};
228
229enum vlr_timer {
230 VLR_T_3250,
231 VLR_T_3260,
232 VLR_T_3270,
233 _NUM_VLR_TIMERS
234};
235
236/* An instance of the VLR codebase */
237struct vlr_instance {
238 struct llist_head subscribers;
239 struct llist_head operations;
240 struct gsup_client *gsup_client;
241 struct vlr_ops ops;
242 struct {
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200243 bool retrieve_imeisv_early;
244 bool retrieve_imeisv_ciphered;
Harald Welteb8b85a12016-06-17 00:06:42 +0200245 bool assign_tmsi;
246 bool check_imei_rqd;
Neels Hofmeyr33f53412017-10-29 02:11:18 +0100247 int auth_tuple_max_reuse_count;
Harald Welteb8b85a12016-06-17 00:06:42 +0200248 bool auth_reuse_old_sets_on_error;
249 bool parq_retrieve_imsi;
250 bool is_ps;
251 uint32_t timer[_NUM_VLR_TIMERS];
252 } cfg;
253 /* A free-form pointer for use by the caller */
254 void *user_ctx;
255};
256
257extern const struct value_string vlr_ciph_names[];
258static inline const char *vlr_ciph_name(enum vlr_ciph val)
259{
260 return get_value_string(vlr_ciph_names, val);
261}
262
263/* Location Updating request */
264struct osmo_fsm_inst *
265vlr_loc_update(struct osmo_fsm_inst *parent,
266 uint32_t parent_event_success,
267 uint32_t parent_event_failure,
268 void *parent_event_data,
269 struct vlr_instance *vlr, void *msc_conn_ref,
270 enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
271 const struct osmo_location_area_id *old_lai,
272 const struct osmo_location_area_id *new_lai,
273 bool authentication_required,
274 enum vlr_ciph ciphering_required,
275 bool is_r99, bool is_utran,
276 bool assign_tmsi);
277
278void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi);
279
280/* tell the VLR that the subscriber connection is gone */
281int vlr_subscr_disconnected(struct vlr_subscr *vsub);
282
283int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const uint8_t *mi, size_t mi_len);
284int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran,
285 const uint8_t *res, uint8_t res_len);
286int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts);
287int vlr_subscr_tx_auth_fail_rep(struct vlr_subscr *vsub);
288void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, struct vlr_ciph_result *res);
289int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub);
290int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub);
291void vlr_subscr_conn_timeout(struct vlr_subscr *vsub);
292
293struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops);
294int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr,
295 const char *gsup_server_addr_str, uint16_t gsup_server_port);
296
297/* internal use only */
298
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100299void sub_pres_vlr_fsm_start(struct osmo_fsm_inst **fsm,
300 struct osmo_fsm_inst *parent,
301 struct vlr_subscr *vsub,
302 uint32_t term_event);
Harald Welteb8b85a12016-06-17 00:06:42 +0200303struct osmo_fsm_inst *
304upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
305 struct vlr_subscr *vsub,
306 uint32_t parent_event);
307
308struct osmo_fsm_inst *
309lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent,
310 struct vlr_subscr *vsub,
311 void *msc_conn_ref,
312 uint32_t parent_event_success,
313 uint32_t parent_event_failure);
314
315
316const char *vlr_subscr_name(struct vlr_subscr *vsub);
317const char *vlr_subscr_msisdn_or_name(struct vlr_subscr *vsub);
318
319#define vlr_subscr_find_by_imsi(vlr, imsi) \
320 _vlr_subscr_find_by_imsi(vlr, imsi, __BASE_FILE__, __LINE__)
321#define vlr_subscr_find_or_create_by_imsi(vlr, imsi, created) \
322 _vlr_subscr_find_or_create_by_imsi(vlr, imsi, created, \
323 __BASE_FILE__, __LINE__)
324
325#define vlr_subscr_find_by_tmsi(vlr, tmsi) \
326 _vlr_subscr_find_by_tmsi(vlr, tmsi, __BASE_FILE__, __LINE__)
327#define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created) \
328 _vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created, \
329 __BASE_FILE__, __LINE__)
330
331#define vlr_subscr_find_by_msisdn(vlr, msisdn) \
332 _vlr_subscr_find_by_msisdn(vlr, msisdn, __BASE_FILE__, __LINE__)
333
334struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr,
335 const char *imsi,
336 const char *file, int line);
337struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr,
338 const char *imsi,
339 bool *created,
340 const char *file,
341 int line);
342
343struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr,
344 uint32_t tmsi,
345 const char *file, int line);
346struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr,
347 uint32_t tmsi,
348 bool *created,
349 const char *file,
350 int line);
351
352struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr,
353 const char *msisdn,
354 const char *file, int line);
355
356#define vlr_subscr_get(sub) _vlr_subscr_get(sub, __BASE_FILE__, __LINE__)
357#define vlr_subscr_put(sub) _vlr_subscr_put(sub, __BASE_FILE__, __LINE__)
358struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line);
359struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line);
360
361struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr);
362void vlr_subscr_free(struct vlr_subscr *vsub);
363int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub);
364
365void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi);
366void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei);
367void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv);
368void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn);
369
370bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi);
371bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi);
372bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn);
373bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei);
374
375uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer);
376
377int vlr_subscr_changed(struct vlr_subscr *vsub);
378int vlr_subscr_purge(struct vlr_subscr *vsub);
379void vlr_subscr_cancel(struct vlr_subscr *vsub, enum gsm48_gmm_cause cause);
380
381
382/* Process Acccess Request FSM */
383
384enum vlr_proc_arq_result {
385 VLR_PR_ARQ_RES_NONE,
386 VLR_PR_ARQ_RES_SYSTEM_FAILURE,
387 VLR_PR_ARQ_RES_ILLEGAL_SUBSCR,
388 VLR_PR_ARQ_RES_UNIDENT_SUBSCR,
389 VLR_PR_ARQ_RES_ROAMING_NOTALLOWED,
390 VLR_PR_ARQ_RES_ILLEGAL_EQUIP,
391 VLR_PR_ARQ_RES_UNKNOWN_ERROR,
392 VLR_PR_ARQ_RES_TIMEOUT,
393 VLR_PR_ARQ_RES_PASSED,
394};
395
396extern const struct value_string vlr_proc_arq_result_names[];
397static inline const char *vlr_proc_arq_result_name(enum vlr_proc_arq_result res)
398{
399 return get_value_string(vlr_proc_arq_result_names, res);
400}
401
402enum proc_arq_vlr_event {
403 PR_ARQ_E_START,
404 PR_ARQ_E_ID_IMSI,
405 PR_ARQ_E_AUTH_RES,
406 PR_ARQ_E_CIPH_RES,
407 PR_ARQ_E_UPD_LOC_RES,
408 PR_ARQ_E_TRACE_RES,
409 PR_ARQ_E_IMEI_RES,
410 PR_ARQ_E_PRES_RES,
411 PR_ARQ_E_TMSI_ACK,
412};
413
414enum vlr_parq_type {
415 VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */
416 VLR_PR_ARQ_T_CM_SERV_REQ,
417 VLR_PR_ARQ_T_PAGING_RESP,
418 /* FIXME: differentiate between services of 24.008 10.5.3.3 */
419};
420
421/* Process Access Request (CM SERV REQ / PAGING RESP) */
422void
423vlr_proc_acc_req(struct osmo_fsm_inst *parent,
424 uint32_t parent_event_success,
425 uint32_t parent_event_failure,
426 void *parent_event_data,
427 struct vlr_instance *vlr, void *msc_conn_ref,
428 enum vlr_parq_type type, const uint8_t *mi_lv,
429 const struct osmo_location_area_id *lai,
430 bool authentication_required,
431 enum vlr_ciph ciphering_required,
432 bool is_r99, bool is_utran);
433
434void vlr_parq_conn_timeout(struct osmo_fsm_inst *fi);
435
436void vlr_parq_fsm_init(void);
437
438int vlr_set_ciph_mode(struct vlr_instance *vlr,
439 struct osmo_fsm_inst *fi,
440 void *msc_conn_ref,
441 enum vlr_ciph ciph_mode,
Neels Hofmeyr2ef2da52017-12-18 01:23:42 +0100442 bool umts_aka,
Harald Welteb8b85a12016-06-17 00:06:42 +0200443 bool retrieve_imeisv);
444
Neels Hofmeyre3d72d72017-12-18 02:06:44 +0100445bool vlr_use_umts_aka(struct osmo_auth_vector *vec, bool is_r99);
446
Harald Welteb8b85a12016-06-17 00:06:42 +0200447void log_set_filter_vlr_subscr(struct log_target *target,
448 struct vlr_subscr *vlr_subscr);