Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 1 | #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> |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 7 | #include <osmocom/core/use_count.h> |
Harald Welte | 123261e | 2022-05-15 11:43:35 +0200 | [diff] [blame] | 8 | #include <osmocom/core/stat_item.h> |
| 9 | #include <osmocom/core/rate_ctr.h> |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 10 | #include <osmocom/gsm/protocol/gsm_23_003.h> |
| 11 | #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> |
| 12 | #include <osmocom/gsm/gsm23003.h> |
Neels Hofmeyr | cf30913 | 2017-12-14 03:57:31 +0100 | [diff] [blame] | 13 | #include <osmocom/gsm/gsm0808.h> |
Vadim Yanitskiy | 8a0e258 | 2018-06-14 03:54:33 +0700 | [diff] [blame] | 14 | #include <osmocom/gsm/gsup.h> |
Stefan Sperling | afa030d | 2018-12-06 12:06:59 +0100 | [diff] [blame] | 15 | #include <osmocom/gsm/ipa.h> |
Neels Hofmeyr | a8945ce | 2018-11-30 00:44:32 +0100 | [diff] [blame] | 16 | #include <osmocom/msc/ran_conn.h> |
Neels Hofmeyr | 7b61ffe | 2018-11-30 02:46:53 +0100 | [diff] [blame] | 17 | #include <osmocom/msc/msc_common.h> |
Harald Welte | 1ea6baf | 2018-07-31 19:40:52 +0200 | [diff] [blame] | 18 | #include <osmocom/gsupclient/gsup_client.h> |
Harald Welte | 0df904d | 2018-12-03 11:00:04 +0100 | [diff] [blame] | 19 | #include <osmocom/msc/vlr_sgs.h> |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 20 | |
Max | a263bb2 | 2017-12-27 13:23:44 +0100 | [diff] [blame] | 21 | #define LOGGSUPP(level, gsup, fmt, args...) \ |
| 22 | LOGP(DVLR, level, "GSUP(%s) " fmt, (gsup)->imsi, ## args) |
| 23 | |
| 24 | #define LOGVSUBP(level, vsub, fmt, args...) \ |
| 25 | LOGP(DVLR, level, "SUBSCR(%s) " fmt, vlr_subscr_name(vsub), ## args) |
| 26 | |
Harald Welte | 2483f1b | 2016-06-19 18:06:02 +0200 | [diff] [blame] | 27 | struct log_target; |
Neels Hofmeyr | 46d526a | 2020-05-29 03:27:50 +0200 | [diff] [blame] | 28 | struct osmo_mobile_identity; |
Harald Welte | 2483f1b | 2016-06-19 18:06:02 +0200 | [diff] [blame] | 29 | |
Stefan Sperling | defc3c8 | 2018-05-15 14:48:04 +0200 | [diff] [blame] | 30 | #define VLR_SUBSCRIBER_NO_EXPIRATION 0 |
| 31 | #define VLR_SUBSCRIBER_LU_EXPIRATION_INTERVAL 60 /* in seconds */ |
| 32 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 33 | #define VSUB_USE_ATTACHED "attached" |
| 34 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 35 | /* from 3s to 10s */ |
| 36 | #define GSM_29002_TIMER_S 10 |
| 37 | /* from 15s to 30s */ |
| 38 | #define GSM_29002_TIMER_M 30 |
| 39 | /* from 1min to 10min */ |
| 40 | #define GSM_29002_TIMER_ML (10*60) |
| 41 | /* from 28h to 38h */ |
| 42 | #define GSM_29002_TIMER_L (32*60*60) |
| 43 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 44 | /* VLR subscriber authentication state */ |
| 45 | enum vlr_subscr_auth_state { |
Martin Hauke | 3f07dac | 2019-11-14 17:49:08 +0100 | [diff] [blame] | 46 | /* subscriber needs to be authenticated */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 47 | VLR_SUB_AS_NEEDS_AUTH, |
| 48 | /* waiting for AuthInfo from HLR/AUC */ |
| 49 | VLR_SUB_AS_NEEDS_AUTH_WAIT_AI, |
| 50 | /* waiting for response from subscriber */ |
| 51 | VLR_SUB_AS_WAIT_RESP, |
| 52 | /* successfully authenticated */ |
| 53 | VLR_SUB_AS_AUTHENTICATED, |
| 54 | /* subscriber needs re-sync */ |
| 55 | VLR_SUB_AS_NEEDS_RESYNC, |
| 56 | /* waiting for AuthInfo with ReSync */ |
| 57 | VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC, |
| 58 | /* waiting for response from subscr, resync case */ |
| 59 | VLR_SUB_AS_WAIT_RESP_RESYNC, |
| 60 | /* waiting for IMSI from subscriber */ |
| 61 | VLR_SUB_AS_WAIT_ID_IMSI, |
| 62 | /* authentication has failed */ |
| 63 | VLR_SUB_AS_AUTH_FAILED, |
| 64 | }; |
| 65 | |
| 66 | enum vlr_lu_event { |
| 67 | VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */ |
| 68 | VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */ |
| 69 | VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */ |
Neels Hofmeyr | 3189f39 | 2022-10-26 18:11:58 +0200 | [diff] [blame] | 70 | VLR_ULA_E_AUTH_SUCCESS, /* Successful result of auth procedure */ |
Neels Hofmeyr | 1cb18a2 | 2022-10-11 00:18:04 +0200 | [diff] [blame] | 71 | VLR_ULA_E_AUTH_NO_INFO, /* HLR returned SAI NACK, possibly continue without auth */ |
Neels Hofmeyr | 923b664 | 2022-09-28 00:15:45 +0200 | [diff] [blame] | 72 | VLR_ULA_E_AUTH_FAILURE, /* Auth procedure failed */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 73 | VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */ |
Martin Hauke | 3f07dac | 2019-11-14 17:49:08 +0100 | [diff] [blame] | 74 | VLR_ULA_E_ID_IMSI, /* IMSI received from MS */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 75 | VLR_ULA_E_ID_IMEI, /* IMEI received from MS */ |
| 76 | VLR_ULA_E_ID_IMEISV, /* IMEISV received from MS */ |
Oliver Smith | 7d05309 | 2018-12-14 17:37:38 +0100 | [diff] [blame] | 77 | VLR_ULA_E_HLR_IMEI_ACK, /* Check_IMEI_VLR result from HLR */ |
| 78 | VLR_ULA_E_HLR_IMEI_NACK,/* Check_IMEI_VLR result from HLR */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 79 | VLR_ULA_E_HLR_LU_RES, /* HLR UpdateLocation result */ |
| 80 | VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */ |
| 81 | VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */ |
| 82 | VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */ |
| 83 | VLR_ULA_E_NEW_TMSI_ACK, /* TMSI Reallocation Complete */ |
| 84 | }; |
| 85 | |
| 86 | enum vlr_ciph_result_cause { |
| 87 | VLR_CIPH_REJECT, /* ? */ |
| 88 | VLR_CIPH_COMPL, |
| 89 | }; |
| 90 | |
Neels Hofmeyr | 8b6e536 | 2018-11-30 02:57:33 +0100 | [diff] [blame] | 91 | struct vlr_auth_tuple { |
| 92 | int use_count; |
| 93 | int key_seq; |
| 94 | struct osmo_auth_vector vec; |
| 95 | }; |
| 96 | #define VLR_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */ |
| 97 | |
| 98 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 99 | enum vlr_subscr_security_context { |
| 100 | VLR_SEC_CTX_NONE, |
| 101 | VLR_SEC_CTX_GSM, |
| 102 | VLR_SEC_CTX_UMTS, |
| 103 | }; |
| 104 | |
| 105 | enum vlr_lu_type { |
| 106 | VLR_LU_TYPE_PERIODIC, |
| 107 | VLR_LU_TYPE_IMSI_ATTACH, |
| 108 | VLR_LU_TYPE_REGULAR, |
| 109 | }; |
| 110 | |
| 111 | #define OSMO_LBUF_DECL(name, xlen) \ |
| 112 | struct { \ |
| 113 | uint8_t buf[xlen]; \ |
| 114 | size_t len; \ |
| 115 | } name |
| 116 | |
| 117 | struct sgsn_mm_ctx; |
| 118 | struct vlr_instance; |
| 119 | |
Neels Hofmeyr | 7b61ffe | 2018-11-30 02:46:53 +0100 | [diff] [blame] | 120 | #define VLR_NAME_LENGTH 160 |
Neels Hofmeyr | 7b61ffe | 2018-11-30 02:46:53 +0100 | [diff] [blame] | 121 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 122 | /* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or |
| 123 | * SGSN (PS), particularly while interacting with the HLR via GSUP */ |
| 124 | struct vlr_subscr { |
| 125 | struct llist_head list; |
| 126 | struct vlr_instance *vlr; |
| 127 | |
| 128 | /* TODO either populate from HLR or drop this completely? */ |
| 129 | long long unsigned int id; |
| 130 | |
| 131 | /* Data from HLR */ /* 3GPP TS 23.008 */ |
| 132 | /* Always use vlr_subscr_set_imsi() to write to imsi[] */ |
| 133 | char imsi[GSM23003_IMSI_MAX_DIGITS+1]; /* 2.1.1.1 */ |
Vadim Yanitskiy | 8b0737f | 2019-05-25 19:27:17 +0700 | [diff] [blame] | 134 | char msisdn[GSM23003_MSISDN_MAX_DIGITS+1]; /* 2.1.2 */ |
Neels Hofmeyr | 7b61ffe | 2018-11-30 02:46:53 +0100 | [diff] [blame] | 135 | char name[VLR_NAME_LENGTH+1]; /* proprietary */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 136 | OSMO_LBUF_DECL(hlr, 16); /* 2.4.7 */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 137 | uint32_t age_indicator; /* 2.17.1 */ |
| 138 | |
| 139 | /* Authentication Data */ |
Neels Hofmeyr | 8b6e536 | 2018-11-30 02:57:33 +0100 | [diff] [blame] | 140 | struct vlr_auth_tuple auth_tuples[5]; /* 2.3.1-2.3.4 */ |
| 141 | struct vlr_auth_tuple *last_tuple; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 142 | enum vlr_subscr_security_context sec_ctx; |
| 143 | |
| 144 | /* Data local to VLR is below */ |
| 145 | uint32_t tmsi; /* 2.1.4 */ |
| 146 | /* Newly allocated TMSI that was not yet acked by MS */ |
| 147 | uint32_t tmsi_new; |
| 148 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 149 | struct osmo_cell_global_id cgi; /* 2.4.16 */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 150 | |
| 151 | char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.2.3 */ |
Oliver Smith | d103705 | 2019-05-02 13:39:26 +0200 | [diff] [blame] | 152 | char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1]; /* 2.1.9 */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 153 | bool imsi_detached_flag; /* 2.7.1 */ |
| 154 | bool conf_by_radio_contact_ind; /* 2.7.4.1 */ |
| 155 | bool sub_dataconf_by_hlr_ind; /* 2.7.4.2 */ |
| 156 | bool loc_conf_in_hlr_ind; /* 2.7.4.3 */ |
| 157 | bool dormant_ind; /* 2.7.8 */ |
| 158 | bool cancel_loc_rx; /* 2.7.8A */ |
| 159 | bool ms_not_reachable_flag; /* 2.10.2 (MNRF) */ |
| 160 | bool la_allowed; |
| 161 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 162 | struct osmo_use_count use_count; |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 163 | struct osmo_use_count_entry use_count_buf[8]; |
| 164 | int32_t max_total_use_count; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 165 | |
| 166 | struct osmo_fsm_inst *lu_fsm; |
| 167 | struct osmo_fsm_inst *auth_fsm; |
| 168 | struct osmo_fsm_inst *proc_arq_fsm; |
Harald Welte | 0df904d | 2018-12-03 11:00:04 +0100 | [diff] [blame] | 169 | struct osmo_fsm_inst *sgs_fsm; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 170 | |
| 171 | bool lu_complete; |
Stefan Sperling | defc3c8 | 2018-05-15 14:48:04 +0200 | [diff] [blame] | 172 | time_t expire_lu; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 173 | |
| 174 | void *msc_conn_ref; |
| 175 | |
| 176 | /* PS (SGSN) specific parts */ |
| 177 | struct { |
| 178 | struct llist_head pdp_list; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 179 | } ps; |
| 180 | /* CS (NITB/CSCN) specific parts */ |
| 181 | struct { |
| 182 | /* pending requests */ |
| 183 | bool is_paging; |
Neels Hofmeyr | 2ff5bcd | 2017-12-15 03:02:27 +0100 | [diff] [blame] | 184 | struct osmo_timer_list paging_response_timer; |
Neels Hofmeyr | 84da6b1 | 2016-05-20 21:59:55 +0200 | [diff] [blame] | 185 | /* list of struct subscr_request */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 186 | struct llist_head requests; |
Neels Hofmeyr | 84da6b1 | 2016-05-20 21:59:55 +0200 | [diff] [blame] | 187 | uint8_t lac; |
Neels Hofmeyr | 7814a83 | 2018-12-26 00:40:18 +0100 | [diff] [blame] | 188 | enum osmo_rat_type attached_via_ran; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 189 | } cs; |
Harald Welte | 0df904d | 2018-12-03 11:00:04 +0100 | [diff] [blame] | 190 | /* SGs (MME) specific parts */ |
| 191 | struct { |
| 192 | struct vlr_sgs_cfg cfg; |
| 193 | char mme_name[SGS_MME_NAME_LEN + 1]; |
| 194 | struct osmo_location_area_id lai; |
| 195 | vlr_sgs_lu_response_cb_t response_cb; |
| 196 | vlr_sgs_lu_paging_cb_t paging_cb; |
| 197 | vlr_sgs_lu_mminfo_cb_t mminfo_cb; |
| 198 | enum sgsap_service_ind paging_serv_ind; |
| 199 | struct osmo_timer_list Ts5; |
Pau Espin Pedrol | 6710670 | 2021-04-27 18:20:15 +0200 | [diff] [blame] | 200 | bool last_eutran_plmn_present; |
| 201 | struct osmo_plmn_id last_eutran_plmn; |
Harald Welte | 0df904d | 2018-12-03 11:00:04 +0100 | [diff] [blame] | 202 | } sgs; |
Neels Hofmeyr | 986fe7e | 2018-09-13 03:05:52 +0200 | [diff] [blame] | 203 | |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 204 | struct osmo_gsm48_classmark classmark; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 205 | }; |
| 206 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 207 | enum vlr_ciph { |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 208 | VLR_CIPH_NONE = 0, /*< A5/0, no encryption */ |
| 209 | VLR_CIPH_A5_1 = 1, /*< A5/1, encryption */ |
| 210 | VLR_CIPH_A5_2 = 2, /*< A5/2, deprecated export-grade encryption */ |
| 211 | VLR_CIPH_A5_3 = 3, /*< A5/3, 'new secure' encryption */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 212 | }; |
| 213 | |
Neels Hofmeyr | cf30913 | 2017-12-14 03:57:31 +0100 | [diff] [blame] | 214 | static inline uint8_t vlr_ciph_to_gsm0808_alg_id(enum vlr_ciph ciph) |
| 215 | { |
| 216 | switch (ciph) { |
Neels Hofmeyr | cf30913 | 2017-12-14 03:57:31 +0100 | [diff] [blame] | 217 | case VLR_CIPH_NONE: |
| 218 | return GSM0808_ALG_ID_A5_0; |
| 219 | case VLR_CIPH_A5_1: |
| 220 | return GSM0808_ALG_ID_A5_1; |
| 221 | case VLR_CIPH_A5_2: |
| 222 | return GSM0808_ALG_ID_A5_2; |
| 223 | case VLR_CIPH_A5_3: |
| 224 | return GSM0808_ALG_ID_A5_3; |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 225 | default: |
| 226 | return GSM0808_ALG_ID_A5_7; |
Neels Hofmeyr | cf30913 | 2017-12-14 03:57:31 +0100 | [diff] [blame] | 227 | } |
| 228 | } |
| 229 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 230 | struct vlr_ops { |
| 231 | /* encode + transmit an AUTH REQ towards the MS. |
| 232 | * \param[in] at auth tuple providing rand, key_seq and autn. |
| 233 | * \param[in] send_autn True to send AUTN, for r99 UMTS auth. |
| 234 | */ |
Neels Hofmeyr | 8b6e536 | 2018-11-30 02:57:33 +0100 | [diff] [blame] | 235 | int (*tx_auth_req)(void *msc_conn_ref, struct vlr_auth_tuple *at, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 236 | bool send_autn); |
| 237 | /* encode + transmit an AUTH REJECT towards the MS */ |
| 238 | int (*tx_auth_rej)(void *msc_conn_ref); |
| 239 | |
| 240 | /* encode + transmit an IDENTITY REQUEST towards the MS */ |
| 241 | int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type); |
| 242 | |
| 243 | int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi); |
Neels Hofmeyr | 1580959 | 2018-04-06 02:57:51 +0200 | [diff] [blame] | 244 | int (*tx_lu_rej)(void *msc_conn_ref, enum gsm48_reject_value cause); |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 245 | int (*tx_cm_serv_acc)(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type); |
| 246 | int (*tx_cm_serv_rej)(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type, |
| 247 | enum gsm48_reject_value cause); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 248 | |
Harald Welte | 71c51df | 2017-12-23 18:51:48 +0100 | [diff] [blame] | 249 | int (*set_ciph_mode)(void *msc_conn_ref, bool umts_aka, bool retrieve_imeisv); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 250 | |
Neels Hofmeyr | 84da6b1 | 2016-05-20 21:59:55 +0200 | [diff] [blame] | 251 | int (*tx_common_id)(void *msc_conn_ref); |
| 252 | |
Stefan Sperling | 3a74128 | 2018-03-13 21:11:49 +0100 | [diff] [blame] | 253 | int (*tx_mm_info)(void *msc_conn_ref); |
Neels Hofmeyr | 84da6b1 | 2016-05-20 21:59:55 +0200 | [diff] [blame] | 254 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 255 | /* notify MSC/SGSN that the subscriber data in VLR has been updated */ |
| 256 | void (*subscr_update)(struct vlr_subscr *vsub); |
| 257 | /* notify MSC/SGSN that the given subscriber has been associated |
| 258 | * with this msc_conn_ref */ |
Neels Hofmeyr | 1035d90 | 2018-12-28 21:22:32 +0100 | [diff] [blame] | 259 | int (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 260 | }; |
| 261 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 262 | /* An instance of the VLR codebase */ |
| 263 | struct vlr_instance { |
| 264 | struct llist_head subscribers; |
| 265 | struct llist_head operations; |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 266 | struct gsup_client_mux *gcm; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 267 | struct vlr_ops ops; |
Stefan Sperling | defc3c8 | 2018-05-15 14:48:04 +0200 | [diff] [blame] | 268 | struct osmo_timer_list lu_expire_timer; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 269 | struct { |
Neels Hofmeyr | 54a706c | 2017-07-18 15:39:27 +0200 | [diff] [blame] | 270 | bool retrieve_imeisv_early; |
| 271 | bool retrieve_imeisv_ciphered; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 272 | bool assign_tmsi; |
| 273 | bool check_imei_rqd; |
Neels Hofmeyr | 33f5341 | 2017-10-29 02:11:18 +0100 | [diff] [blame] | 274 | int auth_tuple_max_reuse_count; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 275 | bool auth_reuse_old_sets_on_error; |
| 276 | bool parq_retrieve_imsi; |
| 277 | bool is_ps; |
Neels Hofmeyr | 9aac5c2 | 2020-05-27 00:04:26 +0200 | [diff] [blame] | 278 | uint8_t nri_bitlen; |
| 279 | struct osmo_nri_ranges *nri_ranges; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 280 | } cfg; |
Harald Welte | 123261e | 2022-05-15 11:43:35 +0200 | [diff] [blame] | 281 | struct osmo_stat_item_group *statg; |
| 282 | struct rate_ctr_group *ctrg; |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 283 | /* A free-form pointer for use by the caller */ |
| 284 | void *user_ctx; |
| 285 | }; |
| 286 | |
| 287 | extern const struct value_string vlr_ciph_names[]; |
| 288 | static inline const char *vlr_ciph_name(enum vlr_ciph val) |
| 289 | { |
| 290 | return get_value_string(vlr_ciph_names, val); |
| 291 | } |
| 292 | |
| 293 | /* Location Updating request */ |
| 294 | struct osmo_fsm_inst * |
| 295 | vlr_loc_update(struct osmo_fsm_inst *parent, |
| 296 | uint32_t parent_event_success, |
| 297 | uint32_t parent_event_failure, |
| 298 | void *parent_event_data, |
| 299 | struct vlr_instance *vlr, void *msc_conn_ref, |
| 300 | enum vlr_lu_type type, uint32_t tmsi, const char *imsi, |
| 301 | const struct osmo_location_area_id *old_lai, |
| 302 | const struct osmo_location_area_id *new_lai, |
| 303 | bool authentication_required, |
Neels Hofmeyr | d99a607 | 2022-10-10 23:34:48 +0200 | [diff] [blame] | 304 | bool is_ciphering_to_be_attempted, |
Neels Hofmeyr | 2ea7264 | 2022-10-10 23:35:47 +0200 | [diff] [blame] | 305 | bool is_ciphering_required, |
Sylvain Munaut | da9f37e | 2019-03-14 11:02:36 +0100 | [diff] [blame] | 306 | uint8_t key_seq, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 307 | bool is_r99, bool is_utran, |
| 308 | bool assign_tmsi); |
| 309 | |
Neels Hofmeyr | 1580959 | 2018-04-06 02:57:51 +0200 | [diff] [blame] | 310 | void vlr_loc_update_cancel(struct osmo_fsm_inst *fi, |
| 311 | enum osmo_fsm_term_cause fsm_cause, |
| 312 | uint8_t gsm48_cause); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 313 | |
Neels Hofmeyr | c036b79 | 2018-11-29 22:37:51 +0100 | [diff] [blame] | 314 | /* tell the VLR that the RAN connection is gone */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 315 | int vlr_subscr_disconnected(struct vlr_subscr *vsub); |
Max | dcc193d | 2017-12-27 19:34:15 +0100 | [diff] [blame] | 316 | bool vlr_subscr_expire(struct vlr_subscr *vsub); |
Neels Hofmeyr | 46d526a | 2020-05-29 03:27:50 +0200 | [diff] [blame] | 317 | int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const struct osmo_mobile_identity *mi); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 318 | int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran, |
| 319 | const uint8_t *res, uint8_t res_len); |
| 320 | int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts); |
Max | 770fbd2 | 2018-01-24 12:48:33 +0100 | [diff] [blame] | 321 | int vlr_subscr_tx_auth_fail_rep(const struct vlr_subscr *vsub) __attribute__((warn_unused_result)); |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 322 | void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, enum vlr_ciph_result_cause result); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 323 | int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub); |
| 324 | int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 325 | |
| 326 | struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops); |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 327 | int vlr_start(struct vlr_instance *vlr, struct gsup_client_mux *gcm); |
| 328 | int vlr_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 329 | |
| 330 | /* internal use only */ |
| 331 | |
Neels Hofmeyr | 1a5bcd5 | 2017-11-18 22:19:55 +0100 | [diff] [blame] | 332 | void sub_pres_vlr_fsm_start(struct osmo_fsm_inst **fsm, |
| 333 | struct osmo_fsm_inst *parent, |
| 334 | struct vlr_subscr *vsub, |
| 335 | uint32_t term_event); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 336 | struct osmo_fsm_inst * |
| 337 | upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent, |
| 338 | struct vlr_subscr *vsub, |
| 339 | uint32_t parent_event); |
| 340 | |
| 341 | struct osmo_fsm_inst * |
| 342 | lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent, |
| 343 | struct vlr_subscr *vsub, |
| 344 | void *msc_conn_ref, |
| 345 | uint32_t parent_event_success, |
| 346 | uint32_t parent_event_failure); |
| 347 | |
| 348 | |
Oliver Smith | 5598aae | 2019-01-08 11:47:21 +0100 | [diff] [blame] | 349 | const char *vlr_subscr_name(const struct vlr_subscr *vsub); |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 350 | const char *vlr_subscr_short_name(const struct vlr_subscr *vsub, unsigned int maxlen); |
Oliver Smith | 5598aae | 2019-01-08 11:47:21 +0100 | [diff] [blame] | 351 | const char *vlr_subscr_msisdn_or_name(const struct vlr_subscr *vsub); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 352 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 353 | #define vlr_subscr_find_by_imsi(vlr, imsi, USE) \ |
| 354 | _vlr_subscr_find_by_imsi(vlr, imsi, USE, __FILE__, __LINE__) |
| 355 | #define vlr_subscr_find_or_create_by_imsi(vlr, imsi, USE, created) \ |
| 356 | _vlr_subscr_find_or_create_by_imsi(vlr, imsi, USE, created, \ |
Neels Hofmeyr | c36e61e | 2018-08-20 12:41:36 +0200 | [diff] [blame] | 357 | __FILE__, __LINE__) |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 358 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 359 | #define vlr_subscr_find_by_tmsi(vlr, tmsi, USE) \ |
| 360 | _vlr_subscr_find_by_tmsi(vlr, tmsi, USE, __FILE__, __LINE__) |
| 361 | #define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, USE, created) \ |
| 362 | _vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, USE, created, \ |
Neels Hofmeyr | c36e61e | 2018-08-20 12:41:36 +0200 | [diff] [blame] | 363 | __FILE__, __LINE__) |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 364 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 365 | #define vlr_subscr_find_by_msisdn(vlr, msisdn, USE) \ |
| 366 | _vlr_subscr_find_by_msisdn(vlr, msisdn, USE, __FILE__, __LINE__) |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 367 | |
Neels Hofmeyr | 5bdba0d | 2021-07-27 03:46:18 +0200 | [diff] [blame] | 368 | #define vlr_subscr_find_by_mi(vlr, mi, USE) \ |
| 369 | _vlr_subscr_find_by_mi(vlr, mi, USE, __FILE__, __LINE__) |
| 370 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 371 | struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr, |
| 372 | const char *imsi, |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 373 | const char *use, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 374 | const char *file, int line); |
| 375 | struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr, |
| 376 | const char *imsi, |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 377 | const char *use, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 378 | bool *created, |
| 379 | const char *file, |
| 380 | int line); |
| 381 | |
| 382 | struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr, |
| 383 | uint32_t tmsi, |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 384 | const char *use, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 385 | const char *file, int line); |
| 386 | struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr, |
| 387 | uint32_t tmsi, |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 388 | const char *use, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 389 | bool *created, |
| 390 | const char *file, |
| 391 | int line); |
| 392 | |
| 393 | struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr, |
| 394 | const char *msisdn, |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 395 | const char *use, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 396 | const char *file, int line); |
| 397 | |
Neels Hofmeyr | 5bdba0d | 2021-07-27 03:46:18 +0200 | [diff] [blame] | 398 | struct vlr_subscr *_vlr_subscr_find_by_mi(struct vlr_instance *vlr, |
| 399 | const struct osmo_mobile_identity *mi, |
| 400 | const char *use, |
| 401 | const char *file, int line); |
| 402 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 403 | #define vlr_subscr_get(VSUB, USE) vlr_subscr_get_src(VSUB, USE, __FILE__, __LINE__) |
| 404 | #define vlr_subscr_put(VSUB, USE) vlr_subscr_put_src(VSUB, USE, __FILE__, __LINE__) |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 405 | |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 406 | #define vlr_subscr_get_src(VSUB, USE, SRCFILE, SRCLINE) \ |
Neels Hofmeyr | 08aae21 | 2019-04-23 15:09:04 +0200 | [diff] [blame] | 407 | OSMO_ASSERT((VSUB) && _osmo_use_count_get_put(&(VSUB)->use_count, USE, 1, SRCFILE, SRCLINE) == 0) |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 408 | #define vlr_subscr_put_src(VSUB, USE, SRCFILE, SRCLINE) \ |
Neels Hofmeyr | 08aae21 | 2019-04-23 15:09:04 +0200 | [diff] [blame] | 409 | OSMO_ASSERT((VSUB) && _osmo_use_count_get_put(&(VSUB)->use_count, USE, -1, SRCFILE, SRCLINE) == 0) |
Neels Hofmeyr | 7c5346c | 2019-02-19 02:36:35 +0100 | [diff] [blame] | 410 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 411 | void vlr_subscr_free(struct vlr_subscr *vsub); |
| 412 | int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub); |
| 413 | |
| 414 | void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi); |
| 415 | void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei); |
| 416 | void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv); |
| 417 | void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn); |
Pau Espin Pedrol | 6710670 | 2021-04-27 18:20:15 +0200 | [diff] [blame] | 418 | void vlr_subscr_set_last_used_eutran_plmn_id(struct vlr_subscr *vsub, |
| 419 | const struct osmo_plmn_id *last_eutran_plmn); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 420 | |
| 421 | bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi); |
| 422 | bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi); |
| 423 | bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn); |
| 424 | bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei); |
| 425 | |
| 426 | uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer); |
| 427 | |
| 428 | int vlr_subscr_changed(struct vlr_subscr *vsub); |
Max | 770fbd2 | 2018-01-24 12:48:33 +0100 | [diff] [blame] | 429 | int vlr_subscr_purge(struct vlr_subscr *vsub) __attribute__((warn_unused_result)); |
Neels Hofmeyr | 1580959 | 2018-04-06 02:57:51 +0200 | [diff] [blame] | 430 | void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub, |
| 431 | enum osmo_fsm_term_cause fsm_cause, |
| 432 | uint8_t gsm48_cause); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 433 | |
Stefan Sperling | defc3c8 | 2018-05-15 14:48:04 +0200 | [diff] [blame] | 434 | void vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 435 | |
Martin Hauke | 3f07dac | 2019-11-14 17:49:08 +0100 | [diff] [blame] | 436 | /* Process Access Request FSM */ |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 437 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 438 | enum proc_arq_vlr_event { |
| 439 | PR_ARQ_E_START, |
| 440 | PR_ARQ_E_ID_IMSI, |
| 441 | PR_ARQ_E_AUTH_RES, |
Neels Hofmeyr | 1cb18a2 | 2022-10-11 00:18:04 +0200 | [diff] [blame] | 442 | PR_ARQ_E_AUTH_NO_INFO, |
Neels Hofmeyr | 923b664 | 2022-09-28 00:15:45 +0200 | [diff] [blame] | 443 | PR_ARQ_E_AUTH_FAILURE, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 444 | PR_ARQ_E_CIPH_RES, |
| 445 | PR_ARQ_E_UPD_LOC_RES, |
| 446 | PR_ARQ_E_TRACE_RES, |
| 447 | PR_ARQ_E_IMEI_RES, |
| 448 | PR_ARQ_E_PRES_RES, |
| 449 | PR_ARQ_E_TMSI_ACK, |
| 450 | }; |
| 451 | |
| 452 | enum vlr_parq_type { |
| 453 | VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */ |
| 454 | VLR_PR_ARQ_T_CM_SERV_REQ, |
| 455 | VLR_PR_ARQ_T_PAGING_RESP, |
Neels Hofmeyr | ae98b97 | 2021-07-27 03:46:49 +0200 | [diff] [blame] | 456 | VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 457 | /* FIXME: differentiate between services of 24.008 10.5.3.3 */ |
| 458 | }; |
| 459 | |
| 460 | /* Process Access Request (CM SERV REQ / PAGING RESP) */ |
| 461 | void |
| 462 | vlr_proc_acc_req(struct osmo_fsm_inst *parent, |
| 463 | uint32_t parent_event_success, |
| 464 | uint32_t parent_event_failure, |
| 465 | void *parent_event_data, |
| 466 | struct vlr_instance *vlr, void *msc_conn_ref, |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 467 | enum vlr_parq_type type, enum osmo_cm_service_type cm_service_type, |
Neels Hofmeyr | 46d526a | 2020-05-29 03:27:50 +0200 | [diff] [blame] | 468 | const struct osmo_mobile_identity *mi, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 469 | const struct osmo_location_area_id *lai, |
| 470 | bool authentication_required, |
Neels Hofmeyr | d99a607 | 2022-10-10 23:34:48 +0200 | [diff] [blame] | 471 | bool is_ciphering_to_be_attempted, |
Neels Hofmeyr | 2ea7264 | 2022-10-10 23:35:47 +0200 | [diff] [blame] | 472 | bool is_ciphering_required, |
Sylvain Munaut | da9f37e | 2019-03-14 11:02:36 +0100 | [diff] [blame] | 473 | uint8_t key_seq, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 474 | bool is_r99, bool is_utran); |
| 475 | |
Neels Hofmeyr | 1580959 | 2018-04-06 02:57:51 +0200 | [diff] [blame] | 476 | void vlr_parq_cancel(struct osmo_fsm_inst *fi, |
| 477 | enum osmo_fsm_term_cause fsm_cause, |
| 478 | enum gsm48_reject_value gsm48_cause); |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 479 | |
| 480 | void vlr_parq_fsm_init(void); |
| 481 | |
| 482 | int vlr_set_ciph_mode(struct vlr_instance *vlr, |
| 483 | struct osmo_fsm_inst *fi, |
| 484 | void *msc_conn_ref, |
Neels Hofmeyr | 2ef2da5 | 2017-12-18 01:23:42 +0100 | [diff] [blame] | 485 | bool umts_aka, |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 486 | bool retrieve_imeisv); |
| 487 | |
Neels Hofmeyr | e3d72d7 | 2017-12-18 02:06:44 +0100 | [diff] [blame] | 488 | bool vlr_use_umts_aka(struct osmo_auth_vector *vec, bool is_r99); |
| 489 | |
Harald Welte | b8b85a1 | 2016-06-17 00:06:42 +0200 | [diff] [blame] | 490 | void log_set_filter_vlr_subscr(struct log_target *target, |
| 491 | struct vlr_subscr *vlr_subscr); |
Alexander Couzens | 7312b15 | 2019-08-19 15:30:12 +0200 | [diff] [blame] | 492 | |
| 493 | void vlr_gmm_cause_to_mm_cause(enum gsm48_gmm_cause gmm_cause, |
| 494 | enum gsm48_reject_value *gsm48_rej_p); |