Add IMEISV Request

This commit is contained in:
Sukchan Lee 2019-11-18 19:34:28 +09:00
parent f3ccd71db0
commit 552305afe2
16 changed files with 187 additions and 24 deletions

View File

@ -40,6 +40,8 @@ extern "C" {
#define OGS_MAX_IMSI_LEN \
OGS_BCD_TO_BUFFER_LEN(OGS_MAX_IMSI_BCD_LEN)
#define OGS_MAX_IMEISV_BCD_LEN 16
#define OGS_MAX_NUM_OF_HOSTNAME 16
#define OGS_MAX_APN_LEN 100
#define OGS_MAX_PCO_LEN 251

View File

@ -68,6 +68,10 @@ struct dict_object *ogs_diam_s6a_priority_level = NULL;
struct dict_object *ogs_diam_s6a_pre_emption_capability = NULL;
struct dict_object *ogs_diam_s6a_pre_emption_vulnerability = NULL;
struct dict_object *ogs_diam_s6a_terminal_information = NULL;
struct dict_object *ogs_diam_s6a_imei = NULL;
struct dict_object *ogs_diam_s6a_software_version = NULL;
extern int ogs_dict_s6a_entry(char *conffile);
int ogs_diam_s6a_init(void)
@ -127,5 +131,9 @@ int ogs_diam_s6a_init(void)
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Access-Restriction-Data", &ogs_diam_s6a_access_restriction_data);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscribed-Periodic-RAU-TAU-Timer", &ogs_diam_s6a_subscribed_rau_tau_timer);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Terminal-Information", &ogs_diam_s6a_terminal_information);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "IMEI", &ogs_diam_s6a_imei);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Software-Version", &ogs_diam_s6a_software_version);
return 0;
}

View File

@ -108,6 +108,10 @@ extern struct dict_object *ogs_diam_s6a_priority_level;
extern struct dict_object *ogs_diam_s6a_pre_emption_capability;
extern struct dict_object *ogs_diam_s6a_pre_emption_vulnerability;
extern struct dict_object *ogs_diam_s6a_terminal_information;
extern struct dict_object *ogs_diam_s6a_imei;
extern struct dict_object *ogs_diam_s6a_software_version;
typedef struct ogs_diam_e_utran_vector_s {
uint8_t xres[OGS_MAX_RES_LEN];
uint8_t xres_len;

View File

@ -44,7 +44,7 @@ void ogs_nas_imsi_to_bcd(
if (!imsi->odd_even) { /* if bcd length is even */
if (bcd[bcd_len] != 0xf)
ogs_warn("Spec warning : bcd[%d] = 0x%x", bcd_len, bcd[bcd_len]);
(bcd_len)--;
(bcd_len)--;
}
bcd[bcd_len] = 0;
@ -72,8 +72,41 @@ void ogs_nas_imsi_to_buffer(
*buf_len = imsi_len;
if (!imsi->odd_even) { /* if imsi length is even */
(*buf_len)--;
(*buf_len)--;
if ((buf[*buf_len] & 0xf) != 0xf)
ogs_warn("Spec warning : buf[%d] = 0x%x", *buf_len, buf[*buf_len]);
}
}
void ogs_nas_imeisv_to_bcd(
ogs_nas_mobile_identity_imeisv_t *imeisv, uint8_t imeisv_len, char *bcd)
{
int bcd_len;
bcd[0] = '0' + imeisv->digit1;
bcd[1] = '0' + imeisv->digit2;
bcd[2] = '0' + imeisv->digit3;
bcd[3] = '0' + imeisv->digit4;
bcd[4] = '0' + imeisv->digit5;
bcd[5] = '0' + imeisv->digit6;
bcd[6] = '0' + imeisv->digit7;
bcd[7] = '0' + imeisv->digit8;
bcd[8] = '0' + imeisv->digit9;
bcd[9] = '0' + imeisv->digit10;
bcd[10] = '0' + imeisv->digit11;
bcd[11] = '0' + imeisv->digit12;
bcd[12] = '0' + imeisv->digit13;
bcd[13] = '0' + imeisv->digit14;
bcd[14] = '0' + imeisv->digit15;
bcd[15] = '0' + imeisv->digit16;
bcd[16] = '0' + imeisv->digit17;
bcd_len = imeisv_len * 2 - 1;
if (!imeisv->odd_even) { /* if bcd length is even */
if (bcd[bcd_len] != 0xf)
ogs_warn("Spec warning : bcd[%d] = 0x%x", bcd_len, bcd[bcd_len]);
(bcd_len)--;
}
bcd[bcd_len] = 0;
}

View File

@ -37,6 +37,9 @@ void ogs_nas_imsi_to_buffer(
void ogs_nas_imsi_to_bcd(
ogs_nas_mobile_identity_imsi_t *imsi, uint8_t imsi_len, char *bcd);
void ogs_nas_imeisv_to_bcd(
ogs_nas_mobile_identity_imeisv_t *imeisv, uint8_t imeisv_len, char *bcd);
#ifdef __cplusplus
}
#endif

View File

@ -172,12 +172,35 @@ ED5(uint8_t spare:2;,
uint8_t mbms_session_identity;
} __attribute__ ((packed)) ogs_nas_mobile_identity_tmgi_t;
typedef struct ogs_nas_mobile_identity_imeisv_s {
ED3(uint8_t digit1:4;,
uint8_t odd_even:1;,
uint8_t type:3;)
ED2(uint8_t digit3:4;,
uint8_t digit2:4;)
ED2(uint8_t digit5:4;,
uint8_t digit4:4;)
ED2(uint8_t digit7:4;,
uint8_t digit6:4;)
ED2(uint8_t digit9:4;,
uint8_t digit8:4;)
ED2(uint8_t digit11:4;,
uint8_t digit10:4;)
ED2(uint8_t digit13:4;,
uint8_t digit12:4;)
ED2(uint8_t digit15:4;,
uint8_t digit14:4;)
ED2(uint8_t digit17:4;,
uint8_t digit16:4;)
} __attribute__ ((packed)) ogs_nas_mobile_identity_imeisv_t;
typedef struct ogs_nas_mobile_identity_s {
uint8_t length;
union {
ogs_nas_mobile_identity_imsi_t imsi;
ogs_nas_mobile_identity_tmsi_t tmsi;
ogs_nas_mobile_identity_tmgi_t tmgi;
ogs_nas_mobile_identity_imeisv_t imeisv;
};
} ogs_nas_mobile_identity_t;
@ -586,8 +609,11 @@ ED2(uint8_t spare:5;,
* See subclause 10.5.5.10 in 3GPP TS 24.008 [13].
* O TV 1 */
typedef struct ogs_nas_imeisv_request_s {
#define OGS_NAS_IMEISV_TYPE 0xc
ED3(uint8_t type:4;,
uint8_t spare:1;,
#define OGS_NAS_IMEISV_NOT_REQUESTED 0
#define OGS_NAS_IMEISV_REQUESTED 1
uint8_t imeisv_request_value:3;)
} __attribute__ ((packed)) ogs_nas_imeisv_request_t;

View File

@ -151,7 +151,7 @@ int emm_build_attach_reject(
attach_reject->emm_cause = emm_cause;
if (esmbuf) {
attach_reject->presencemask |=
attach_reject->presencemask |=
OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT;
attach_reject->esm_message_container.buffer = esmbuf->data;
attach_reject->esm_message_container.length = esmbuf->len;
@ -248,6 +248,8 @@ int emm_build_security_mode_command(
&security_mode_command->nas_key_set_identifier;
ogs_nas_ue_security_capability_t *replayed_ue_security_capabilities =
&security_mode_command->replayed_ue_security_capabilities;
ogs_nas_imeisv_request_t *imeisv_request =
&security_mode_command->imeisv_request;
ogs_assert(mme_ue);
@ -305,6 +307,12 @@ int emm_build_security_mode_command(
replayed_ue_security_capabilities->gea);
ogs_debug(" Selected[Integrity:0x%x Encrypt:0x%x]",
mme_ue->selected_int_algorithm, mme_ue->selected_enc_algorithm);
security_mode_command->presencemask |=
OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT;
imeisv_request->type = OGS_NAS_IMEISV_TYPE;
imeisv_request->imeisv_request_value = OGS_NAS_IMEISV_REQUESTED;
if (mme_ue->selected_int_algorithm == OGS_NAS_SECURITY_ALGORITHMS_EIA0) {
ogs_fatal("Encrypt[0x%x] can be skipped with EEA0, "
"but Integrity[0x%x] cannot be bypassed with EIA0",
@ -313,7 +321,6 @@ int emm_build_security_mode_command(
return OGS_ERROR;
}
mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm,
mme_ue->kasme, mme_ue->knas_int);
mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_ue->selected_enc_algorithm,
@ -371,13 +378,13 @@ int emm_build_tau_accept(ogs_pkbuf_t **emmbuf, mme_ue_t *mme_ue)
tau_accept->eps_update_result.result = mme_ue->nas_eps.update.update_type;
/* Set T3412 */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT ;
tau_accept->t3412_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
tau_accept->t3412_value.value = 9;
/* Set TAI */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT;
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
@ -395,7 +402,7 @@ int emm_build_tau_accept(ogs_pkbuf_t **emmbuf, mme_ue_t *mme_ue)
&mme_self()->served_tai[served_tai_index].list2);
/* Set EPS bearer context status */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT;
tau_accept->eps_bearer_context_status.length = 2;
sess = mme_sess_first(mme_ue);
@ -424,20 +431,20 @@ int emm_build_tau_accept(ogs_pkbuf_t **emmbuf, mme_ue_t *mme_ue)
#if 0 /* Need not to include T3402 */
/* Set T3402 */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT;
tau_accept->t3402_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM;
tau_accept->t3402_value.value = 12;
#endif
/* Set T3423 */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT;
tau_accept->t3423_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
tau_accept->t3423_value.value = 9;
/* Set EPS network feature support */
tau_accept->presencemask |=
tau_accept->presencemask |=
OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT;
tau_accept->eps_network_feature_support.length = 1;
tau_accept->eps_network_feature_support.ims_vops = 1;

View File

@ -152,8 +152,10 @@ int emm_handle_attach_request(
switch (eps_mobile_identity->imsi.type) {
case OGS_NAS_EPS_MOBILE_IDENTITY_IMSI:
ogs_assert(sizeof(ogs_nas_mobile_identity_imsi_t) ==
eps_mobile_identity->length);
memcpy(&mme_ue->nas_mobile_identity_imsi,
&eps_mobile_identity->imsi, sizeof(ogs_nas_mobile_identity_imsi_t));
&eps_mobile_identity->imsi, eps_mobile_identity->length);
ogs_nas_imsi_to_bcd(
&eps_mobile_identity->imsi, eps_mobile_identity->length,
imsi_bcd);
@ -297,8 +299,10 @@ int emm_handle_identity_response(
if (mobile_identity->imsi.type == OGS_NAS_IDENTITY_TYPE_2_IMSI) {
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
ogs_assert(sizeof(ogs_nas_mobile_identity_imsi_t) ==
mobile_identity->length);
memcpy(&mme_ue->nas_mobile_identity_imsi,
&mobile_identity->imsi, sizeof(ogs_nas_mobile_identity_imsi_t));
&mobile_identity->imsi, mobile_identity->length);
ogs_nas_imsi_to_bcd(
&mobile_identity->imsi, mobile_identity->length, imsi_bcd);
mme_ue_set_imsi(mme_ue, imsi_bcd);
@ -615,3 +619,31 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue,
return OGS_OK;
}
int emm_handle_security_mode_complete(mme_ue_t *mme_ue,
ogs_nas_security_mode_complete_t *security_mode_complete)
{
ogs_nas_mobile_identity_t *imeisv = &security_mode_complete->imeisv;
ogs_assert(mme_ue);
if (security_mode_complete->presencemask &
OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT) {
switch (imeisv->imeisv.type) {
case OGS_NAS_MOBILE_IDENTITY_IMEISV:
memcpy(&mme_ue->nas_mobile_identity_imeisv,
&imeisv->imeisv, imeisv->length);
ogs_nas_imeisv_to_bcd(&imeisv->imeisv, imeisv->length,
mme_ue->imeisv_bcd);
mme_ue->imeisv_presence = true;
break;
default:
ogs_warn("Invalid IMEISV Type[%d]", imeisv->imeisv.type);
break;
}
}
return OGS_OK;
}

View File

@ -46,6 +46,9 @@ int emm_handle_tau_request(
int emm_handle_extended_service_request(mme_ue_t *mme_ue,
ogs_nas_extended_service_request_t *extended_service_request);
int emm_handle_security_mode_complete(mme_ue_t *mme_ue,
ogs_nas_security_mode_complete_t *security_mode_complete);
#ifdef __cplusplus
}
#endif

View File

@ -708,6 +708,14 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
break;
}
rv = emm_handle_security_mode_complete(
mme_ue, &message->emm.security_mode_complete);
if (rv != OGS_OK) {
ogs_error("emm_handle_security_mode_complete() failed");
OGS_FSM_TRAN(s, emm_state_exception);
return;
}
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
mme_ue->kenb);
mme_kdf_nh(mme_ue->kasme, mme_ue->kenb, mme_ue->nh);

View File

@ -305,6 +305,10 @@ struct mme_ue_s {
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
ogs_nas_mobile_identity_imsi_t nas_mobile_identity_imsi;
bool imeisv_presence;
char imeisv_bcd[OGS_MAX_IMEISV_BCD_LEN+1];
ogs_nas_mobile_identity_imeisv_t nas_mobile_identity_imeisv;
mme_m_tmsi_t *m_tmsi;
mme_p_tmsi_t p_tmsi;
ogs_nas_guti_t guti;

View File

@ -433,7 +433,7 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
int ret;
struct msg *req = NULL;
struct avp *avp;
struct avp *avp, *avpch;
union avp_value val;
struct sess_state *sess_data = NULL, *svg;
struct session *session = NULL;
@ -492,6 +492,33 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Set the Terminal-Information AVP */
if (mme_ue->imeisv_presence) {
ret = fd_msg_avp_new(ogs_diam_s6a_terminal_information, 0, &avp);
ogs_assert(ret == 0);
ret = fd_msg_avp_new(ogs_diam_s6a_imei, 0, &avpch);
ogs_assert(ret == 0);
val.os.data = (uint8_t *)mme_ue->imeisv_bcd;
val.os.len = 14;
ret = fd_msg_avp_setvalue(avpch, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
ogs_assert(ret == 0);
ret = fd_msg_avp_new(ogs_diam_s6a_software_version, 0, &avpch);
ogs_assert(ret == 0);
val.os.data = (uint8_t *)mme_ue->imeisv_bcd+14;
val.os.len = 2;
ret = fd_msg_avp_setvalue(avpch, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
}
/* Set the RAT-Type */
ret = fd_msg_avp_new(ogs_diam_s6a_rat_type, 0, &avp);
ogs_assert(ret == 0);

View File

@ -775,8 +775,10 @@ int tests1ap_build_security_mode_complete(ogs_pkbuf_t **pkbuf, int i)
"",
/* 18 */
"000d403200000500 0000020001000800 020001001a000908 470ba943dd00075e"
"006440080009f107 0019b01000434006 0009f1070007",
"000d403d00000500 0000020001000800 020001001a001413 471647b75200075e"
"2309337522002954 3118f40064400800 09f1070019b01000 4340060009f10700"
"07",
"000d403400000500 00000200f8000800 048003e993001a00 090847592cf09600"
"075e006440080027 f412000640200043 40060027f4123039",
"",
@ -813,7 +815,7 @@ int tests1ap_build_security_mode_complete(ogs_pkbuf_t **pkbuf, int i)
0,
0,
54,
65,
56,
0,

View File

@ -41,8 +41,9 @@ static void test1_func(abts_case *tc, void *data)
"000b403800000300 0000020001000800 020001001a002524 075200aa266700bc"
"2887354e9f87368d 5d0ae710ab857af5 5f1a8000d71e5537 4ee176e9";
const char *_security_mode_command =
"000b402400000300 0000020001000800 020001001a001110 378ccbca6000075d"
"010005f0f0c04070";
"000b4025"
"0000030000000200 0100080002000100 1a001211379be42b 4200075d010005f0"
"f0c04070c1";
const char *_esm_information_request =
"000b401d00000300 0000020001000800 020001001a000a09 27d1237969010234"
"d9";

View File

@ -38,8 +38,9 @@ static void test1_func(abts_case *tc, void *data)
"000b403b00000300 000005c001a00102 000800020018001a 002524075200906d"
"231ff57ef278c719 1d170303deb610d0 7c4defa47480001f 2b5350926bdb3a";
const char *_security_mode_command =
"000b402400000300 000005c001a00102 000800020018001a 000e0d37c966d549"
"00075d010002e0e0";
"000b4025"
"00000300000005c0 01a0010200080002 0018001a000f0e37 62522c0900075d01"
"0002e0e0c1";
const char *_esm_information_request =
"000b402000000300 000005c001a00102 000800020018001a 000a0927846a01a8"
"010201d9";

View File

@ -42,8 +42,9 @@ static void attach_test1(abts_case *tc, void *data)
"000b403b00000300 000005c00100009d 000800020001001a 0025240752002008"
"0c3818183b522614 162c07601d0d10f1 1b89a2a8de8000ad 0ccf7f55e8b20d";
const char *_security_mode_command =
"000b402700000300 000005c00100009d 000800020001001a 00111037f933b5d5"
"00075d010005e060 c04070";
"000b4028"
"00000300000005c0 0100009d00080002 0001001a00121137 f497722900075d01"
"0005e060c04070c1";
const char *_esm_information_request =
"000b402000000300 000005c00100009d 000800020001001a 000a092779012320"
"010221d9";
@ -760,8 +761,9 @@ static void attach_test3(abts_case *tc, void *data)
"403b000003000000 05c0020000c80008 00020002001a0025 2407520042200639"
"1c0021554d444928 4a1a062e10e543cb 257f1f800021f4f9 2d522a5b87";
const char *_security_mode_command =
"000b402400000300 000005c0020000c8 000800020002001a 000e0d37a3761a13"
"00075d010002f0f0";
"000b4025"
"00000300000005c0 020000c800080002 0002001a000f0e37 c48c93b000075d01"
"0002f0f0c1";
const char *_esm_information_request =
"000b"