diff options
author | Oliver Smith <osmith@sysmocom.de> | 2018-12-14 17:37:38 +0100 |
---|---|---|
committer | osmith <osmith@sysmocom.de> | 2019-01-16 10:42:56 +0000 |
commit | 7d05309e3ac7a843933e9b5aaac5cf8f1fb53e5c (patch) | |
tree | b6cbe77c1bb359bef09e82dbedeb0ef58948ff36 /src/libvlr | |
parent | c065ca3171a8b2e9b2da6e05c07d4599fe5202f8 (diff) |
VLR: send CHECK-IMEI to EIR/HLR
When check-imei-req is enabled in the VTY config, do not accept IMEIs
sent by the ME directly anymore. Send the IMEI to the EIR/HLR and wait
for its ACK or NACK.
OsmoHLR also accepts all IMEIs at this point, but this allows to
optionally store the IMEI in the HLR DB.
Depends: Ib240474b0c3c603ba840cf26babb38a44dfc9364 (osmo-hlr)
Related: OS#3733
Change-Id: Ife868ed71c36cdd02638072abebf61fc949080a7
Diffstat (limited to 'src/libvlr')
-rw-r--r-- | src/libvlr/vlr.c | 49 | ||||
-rw-r--r-- | src/libvlr/vlr_core.h | 1 | ||||
-rw-r--r-- | src/libvlr/vlr_lu_fsm.c | 14 |
3 files changed, 63 insertions, 1 deletions
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index 887602c10..451c5217d 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -657,6 +657,28 @@ int vlr_subscr_req_sai(struct vlr_subscr *vsub, return vlr_subscr_tx_gsup_message(vsub, &gsup_msg); } +/* Initiate Check_IMEI_VLR Procedure (23.018 Chapter 7.1.2.9) */ +int vlr_subscr_tx_req_check_imei(const struct vlr_subscr *vsub) +{ + struct osmo_gsup_message gsup_msg = {0}; + uint8_t imei_enc[GSM23003_IMEI_NUM_DIGITS+2]; /* +2: IE header */ + int len; + + /* Encode IMEI */ + len = gsm48_encode_bcd_number(imei_enc, sizeof(imei_enc), 0, vsub->imei); + if (len < 1) { + LOGVSUBP(LOGL_ERROR, vsub, "Error: cannot encode IMEI '%s'\n", vsub->imei); + return -ENOSPC; + } + gsup_msg.imei_enc = imei_enc; + gsup_msg.imei_enc_len = len; + + /* Send CHECK_IMEI_REQUEST */ + gsup_msg.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST; + OSMO_STRLCPY_ARRAY(gsup_msg.imsi, vsub->imsi); + return vlr_tx_gsup_message(vsub->vlr, &gsup_msg); +} + /* Tell HLR that authentication failure occurred */ int vlr_subscr_tx_auth_fail_rep(const struct vlr_subscr *vsub) { @@ -991,6 +1013,29 @@ static int vlr_subscr_handle_cancel_req(struct vlr_subscr *vsub, return rc; } +/* Handle Check_IMEI_VLR result and error from HLR */ +static int vlr_subscr_handle_check_imei(struct vlr_subscr *vsub, const struct osmo_gsup_message *gsup) +{ + if (!vsub->lu_fsm) { + LOGVSUBP(LOGL_ERROR, vsub, "Rx %s without LU in progress\n", + osmo_gsup_message_type_name(gsup->message_type)); + return -ENODEV; + } + + if (gsup->message_type == OSMO_GSUP_MSGT_CHECK_IMEI_RESULT) { + if (gsup->imei_result == OSMO_GSUP_IMEI_RESULT_ACK) + osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_HLR_IMEI_ACK, NULL); + else + osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_HLR_IMEI_NACK, NULL); + } else { + LOGVSUBP(LOGL_ERROR, vsub, "Check_IMEI_VLR failed; gmm_cause: %s\n", + get_value_string(gsm48_gmm_cause_names, gsup->cause)); + osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_HLR_IMEI_NACK, NULL); + } + + return 0; +} + /* Incoming handler for GSUP from HLR. * Keep this function non-static for direct invocation by unit tests. */ int vlr_gsupc_read_cb(struct osmo_gsup_client *gsupc, struct msgb *msg) @@ -1060,6 +1105,10 @@ int vlr_gsupc_read_cb(struct osmo_gsup_client *gsupc, struct msgb *msg) gsup.message_type); rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; break; + case OSMO_GSUP_MSGT_CHECK_IMEI_ERROR: + case OSMO_GSUP_MSGT_CHECK_IMEI_RESULT: + rc = vlr_subscr_handle_check_imei(vsub, &gsup); + break; default: /* Forward message towards MSC */ rc = vlr->ops.forward_gsup_msg(vsub, &gsup); diff --git a/src/libvlr/vlr_core.h b/src/libvlr/vlr_core.h index c249dffd0..41b880011 100644 --- a/src/libvlr/vlr_core.h +++ b/src/libvlr/vlr_core.h @@ -7,5 +7,6 @@ struct osmo_gsup_message; int vlr_subscr_req_lu(struct vlr_subscr *vsub) __attribute__((warn_unused_result)); int vlr_subscr_req_sai(struct vlr_subscr *vsub, const uint8_t *auts, const uint8_t *auts_rand) __attribute__((warn_unused_result)); +int vlr_subscr_tx_req_check_imei(const struct vlr_subscr *vsub); void vlr_subscr_update_tuples(struct vlr_subscr *vsub, const struct osmo_gsup_message *gsup); diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index 8640d2b14..a97e97ada 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -653,6 +653,8 @@ static const struct value_string fsm_lu_event_names[] = { OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI), OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI), OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEISV), + OSMO_VALUE_STRING(VLR_ULA_E_HLR_IMEI_ACK), + OSMO_VALUE_STRING(VLR_ULA_E_HLR_IMEI_NACK), OSMO_VALUE_STRING(VLR_ULA_E_HLR_LU_RES), OSMO_VALUE_STRING(VLR_ULA_E_UPD_HLR_COMPL), OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_SUCCESS), @@ -1229,9 +1231,17 @@ static void lu_fsm_wait_lu_compl(struct osmo_fsm_inst *fi, uint32_t event, LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL); break; case VLR_ULA_E_ID_IMEI: + /* Got the IMEI from ME, now send it to HLR */ + vlr_subscr_tx_req_check_imei(lfp->vsub); + break; + case VLR_ULA_E_HLR_IMEI_ACK: osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, LU_COMPL_VLR_E_IMEI_CHECK_ACK, NULL); break; + case VLR_ULA_E_HLR_IMEI_NACK: + osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, + LU_COMPL_VLR_E_IMEI_CHECK_NACK, NULL); + break; case VLR_ULA_E_LU_COMPL_SUCCESS: lu_fsm_discard_lu_compl_fsm(fi); @@ -1362,7 +1372,9 @@ static const struct osmo_fsm_state vlr_lu_fsm_states[] = { S(VLR_ULA_E_LU_COMPL_FAILURE) | S(VLR_ULA_E_NEW_TMSI_ACK) | S(VLR_ULA_E_ID_IMEI) | - S(VLR_ULA_E_ID_IMEISV), + S(VLR_ULA_E_ID_IMEISV) | + S(VLR_ULA_E_HLR_IMEI_ACK) | + S(VLR_ULA_E_HLR_IMEI_NACK), .out_state_mask = S(VLR_ULA_S_DONE), .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL), .action = lu_fsm_wait_lu_compl, |