diff --git a/lib/diameter/gy/message.c b/lib/diameter/gy/message.c index 698d799e0..ae45110a9 100644 --- a/lib/diameter/gy/message.c +++ b/lib/diameter/gy/message.c @@ -56,6 +56,9 @@ struct dict_object *ogs_diam_gy_ggsn_address = NULL; struct dict_object *ogs_diam_gy_3gpp_nsapi = NULL; struct dict_object *ogs_diam_gy_3gpp_selection_mode = NULL; struct dict_object *ogs_diam_gy_3gpp_charging_characteristics = NULL; +struct dict_object *ogs_diam_gy_user_equipment_info = NULL; +struct dict_object *ogs_diam_gy_user_equipment_info_type = NULL; +struct dict_object *ogs_diam_gy_user_equipment_info_value = NULL; struct dict_object *ogs_diam_gy_feature_list_id = NULL; struct dict_object *ogs_diam_gy_feature_list = NULL; @@ -120,6 +123,9 @@ int ogs_diam_gy_init(void) CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-NSAPI", &ogs_diam_gy_3gpp_nsapi); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-Selection-Mode", &ogs_diam_gy_3gpp_selection_mode); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-Charging-Characteristics", &ogs_diam_gy_3gpp_charging_characteristics); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "User-Equipment-Info", &ogs_diam_gy_user_equipment_info); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "User-Equipment-Info-Type", &ogs_diam_gy_user_equipment_info_type); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "User-Equipment-Info-Value", &ogs_diam_gy_user_equipment_info_value); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List-ID", &ogs_diam_gy_feature_list_id); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List", &ogs_diam_gy_feature_list); diff --git a/lib/diameter/gy/message.h b/lib/diameter/gy/message.h index 1d2e107b6..75a289e44 100644 --- a/lib/diameter/gy/message.h +++ b/lib/diameter/gy/message.h @@ -107,6 +107,9 @@ extern struct dict_object *ogs_diam_gy_ggsn_address; extern struct dict_object *ogs_diam_gy_3gpp_nsapi; extern struct dict_object *ogs_diam_gy_3gpp_selection_mode; extern struct dict_object *ogs_diam_gy_3gpp_charging_characteristics; +extern struct dict_object *ogs_diam_gy_user_equipment_info; +extern struct dict_object *ogs_diam_gy_user_equipment_info_type; +extern struct dict_object *ogs_diam_gy_user_equipment_info_value; extern struct dict_object *ogs_diam_gy_feature_list_id; extern struct dict_object *ogs_diam_gy_feature_list; extern struct dict_object *ogs_diam_gy_qos_information; diff --git a/src/smf/context.h b/src/smf/context.h index eabd28619..0903fbf5a 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -114,6 +114,11 @@ typedef struct smf_ue_s { int msisdn_len; char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; + /* IMEI */ + uint8_t imeisv[OGS_MAX_IMEISV_LEN]; + int imeisv_len; + char imeisv_bcd[OGS_MAX_IMEISV_BCD_LEN+1]; + ogs_list_t sess_list; } smf_ue_t; diff --git a/src/smf/gn-handler.c b/src/smf/gn-handler.c index 1fea05fbb..94cbf4d0b 100644 --- a/src/smf/gn-handler.c +++ b/src/smf/gn-handler.c @@ -218,6 +218,15 @@ uint8_t smf_gn_handle_create_pdp_context_request( OGS_TLV_STORE_DATA(&sess->gtp.ue_timezone, &req->ms_time_zone); } + /* Set IMEI(SV) */ + if (req->imei.presence && req->imei.len > 0) { + smf_ue->imeisv_len = req->imei.len; + memcpy(smf_ue->imeisv, + (uint8_t*)req->imei.data, smf_ue->imeisv_len); + ogs_buffer_to_bcd( + smf_ue->imeisv, smf_ue->imeisv_len, smf_ue->imeisv_bcd); + } + /* UE IP Address */ eua = req->end_user_address.data; ogs_assert(eua); diff --git a/src/smf/gy-path.c b/src/smf/gy-path.c index f96b2ae4d..1faa9f824 100644 --- a/src/smf/gy-path.c +++ b/src/smf/gy-path.c @@ -262,7 +262,7 @@ static void fill_service_information_ccr(smf_sess_t *sess, int ret; union avp_value val; struct avp *avp; - struct avp *avpch1, *avpch2; + struct avp *avpch1, *avpch2, *avpch3; struct sockaddr_in sin; struct sockaddr_in6 sin6; char buf[OGS_PLMNIDSTRLEN]; @@ -504,6 +504,35 @@ static void fill_service_information_ccr(smf_sess_t *sess, } } + if (sess->smf_ue->imeisv_len > 0) { + /* User-Equipment-Info, 3GPP TS 32.299 7.1.17 */ + ret = fd_msg_avp_new(ogs_diam_gy_user_equipment_info, 0, &avpch2); + + /* User-Equipment-Info-Type 0 (IMEI) */ + ret = fd_msg_avp_new(ogs_diam_gy_user_equipment_info_type, 0, &avpch3); + ogs_assert(ret == 0); + val.i32 = 0; + ret = fd_msg_avp_setvalue(avpch3, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3); + ogs_assert(ret == 0); + + /* User-Equipment-Info-Val */ + ret = fd_msg_avp_new(ogs_diam_gy_user_equipment_info_value, 0, &avpch3); + ogs_assert(ret == 0); + digit = '0'; + val.os.data = (uint8_t*)&sess->smf_ue->imeisv_bcd[0]; + val.os.len = 16; + ret = fd_msg_avp_setvalue(avpch3, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3); + ogs_assert(ret == 0); + + /* User-Equipment-Info AVP add to PS-Information: */ + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + /* PS-Information AVP add to req: */ ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index de89a4f25..70b83b1bf 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -354,6 +354,15 @@ uint8_t smf_s5c_handle_create_session_request( smf_ue->msisdn_len, smf_ue->msisdn_bcd); } + /* Set IMEI(SV) */ + if (req->me_identity.presence && req->me_identity.len > 0) { + smf_ue->imeisv_len = req->me_identity.len; + memcpy(smf_ue->imeisv, + (uint8_t*)req->me_identity.data, smf_ue->imeisv_len); + ogs_buffer_to_bcd( + smf_ue->imeisv, smf_ue->imeisv_len, smf_ue->imeisv_bcd); + } + return OGS_GTP2_CAUSE_REQUEST_ACCEPTED; }