aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOliver Smith <osmith@sysmocom.de>2018-12-14 17:37:38 +0100
committerosmith <osmith@sysmocom.de>2019-01-16 10:42:56 +0000
commit7d05309e3ac7a843933e9b5aaac5cf8f1fb53e5c (patch)
treeb6cbe77c1bb359bef09e82dbedeb0ef58948ff36 /src
parentc065ca3171a8b2e9b2da6e05c07d4599fe5202f8 (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')
-rw-r--r--src/libvlr/vlr.c49
-rw-r--r--src/libvlr/vlr_core.h1
-rw-r--r--src/libvlr/vlr_lu_fsm.c14
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,