diff --git a/src/hss/hss-context.c b/src/hss/hss-context.c index 550377826..1f3a25354 100644 --- a/src/hss/hss-context.c +++ b/src/hss/hss-context.c @@ -759,6 +759,28 @@ ogs_plmn_id_t *hss_cx_get_visited_plmn_id(char *public_identity) return visited_plmn_id; } +char *hss_cx_get_user_name(char *public_identity) +{ + hss_impi_t *impi = NULL; + hss_impu_t *impu = NULL; + + char *user_name = NULL; + + ogs_thread_mutex_lock(&self.cx_lock); + + impu = impu_find_by_id(public_identity); + if (impu) { + impi = impu->impi; + ogs_assert(impi); + + user_name = impi->id; + } + + ogs_thread_mutex_unlock(&self.cx_lock); + + return user_name; +} + char *hss_cx_get_server_name(char *public_identity) { char *server_name = NULL; diff --git a/src/hss/hss-context.h b/src/hss/hss-context.h index fc12857ec..0382bf694 100644 --- a/src/hss/hss-context.h +++ b/src/hss/hss-context.h @@ -79,6 +79,7 @@ void hss_cx_set_imsi_bcd(char *user_name, char *imsi_bcd); char *hss_cx_get_imsi_bcd(char *public_identity); ogs_plmn_id_t *hss_cx_get_visited_plmn_id(char *public_identity); +char *hss_cx_get_user_name(char *public_identity); char *hss_cx_get_server_name(char *public_identity); void hss_cx_set_server_name( diff --git a/src/hss/hss-cx-path.c b/src/hss/hss-cx-path.c index 6a51bdc03..e8ac6dbe1 100644 --- a/src/hss/hss-cx-path.c +++ b/src/hss/hss-cx-path.c @@ -232,6 +232,8 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, uint8_t mac_s[OGS_MAC_S_LEN]; + bool matched = false; + ogs_assert(msg); ogs_debug("Multimedia-Auth-Request"); @@ -273,7 +275,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, ogs_assert(server_name); /* Check if IMPI(User-Name) + IMPU(Public-Identity) is associated */ - bool matched = hss_cx_identity_is_associated(user_name, public_identity); + matched = hss_cx_identity_is_associated(user_name, public_identity); if (!matched) { ogs_error("User-Name[%s] Public-Identity[%s] is not assocated", user_name, public_identity); @@ -593,6 +595,8 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, struct msg *ans, *qry; + bool matched = false; + struct avp *user_name_avp = NULL; struct avp *avpch = NULL; struct avp_hdr *hdr; union avp_value val; @@ -617,16 +621,6 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ans = *msg; - /* Get User-Name AVP (Mandatory) */ - ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp); - ogs_assert(ret == 0); - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - - user_name = ogs_strndup( - (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); - ogs_assert(user_name); - /* Get Public-Identity AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp); ogs_assert(ret == 0); @@ -647,13 +641,36 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(server_name); - /* Check if IMPI(User-Name) + IMPU(Public-Identity) is associated */ - bool matched = hss_cx_identity_is_associated(user_name, public_identity); - if (!matched) { - ogs_error("User-Name[%s] Public-Identity[%s] is not assocated", - user_name, public_identity); - result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH; - goto out; + /* Get User-Name AVP */ + ret = fd_msg_search_avp(qry, ogs_diam_user_name, &user_name_avp); + ogs_assert(ret == 0); + if (user_name_avp) { + ret = fd_msg_avp_hdr(user_name_avp, &hdr); + ogs_assert(ret == 0); + + user_name = ogs_strndup( + (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); + ogs_assert(user_name); + + /* Check if IMPI(User-Name) + IMPU(Public-Identity) is associated */ + matched = hss_cx_identity_is_associated(user_name, public_identity); + if (!matched) { + ogs_error("User-Name[%s] Public-Identity[%s] is not assocated", + user_name, public_identity); + result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH; + goto out; + } + } else { + user_name = hss_cx_get_user_name(public_identity); + if (!user_name) { + ogs_error("Cannot find User-Name for Public-Identity[%s]", + public_identity); + result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN; + goto out; + } + + user_name = ogs_strdup(user_name); + ogs_assert(user_name); } /* Check if IMSI */ @@ -704,62 +721,75 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); ogs_assert(ret == 0); - /* Set the User-Name AVP */ - ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)user_name; - val.os.len = strlen(user_name); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Get User-Data-Already-Available AVP (Mandatory) */ - ret = fd_msg_search_avp(qry, ogs_diam_cx_user_data_already_available, &avp); - ogs_assert(ret == 0); - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - - if (hdr->avp_value->i32 == OGS_DIAM_CX_USER_DATA_ALREADY_AVAILABLE) { - /* Nothing to do */ - } else { - /* Set the User-Data AVP */ - user_data = hss_cx_download_user_data( - user_name, visited_plmn_id, &ims_data); - ogs_assert(user_data); - - ret = fd_msg_avp_new(ogs_diam_cx_user_data, 0, &avp); + if (user_name_avp) { + /* Set the User-Name AVP */ + ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp); ogs_assert(ret == 0); - val.os.data = (uint8_t *)user_data; - val.os.len = strlen(user_data); + val.os.data = (uint8_t *)user_name; + val.os.len = strlen(user_name); ret = fd_msg_avp_setvalue(avp, &val); ogs_assert(ret == 0); ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); + } - /* Set the Charging-Information AVP */ - ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp); + /* Get Server-Assignment-Type AVP (Mandatory) */ + ret = fd_msg_search_avp(qry, + ogs_diam_cx_server_assignment_type, &avp); + ogs_assert(ret == 0); + ret = fd_msg_avp_hdr(avp, &hdr); + ogs_assert(ret == 0); + if (hdr->avp_value->i32 == OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION || + hdr->avp_value->i32 == OGS_DIAM_CX_SERVER_ASSIGNMENT_RE_REGISTRATION) { + + /* Get User-Data-Already-Available AVP (Mandatory) */ + ret = fd_msg_search_avp( + qry, ogs_diam_cx_user_data_already_available, &avp); + ogs_assert(ret == 0); + ret = fd_msg_avp_hdr(avp, &hdr); ogs_assert(ret == 0); - /* Set the Charging-Information AVP */ - ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp); - ogs_assert(ret == 0); + if (hdr->avp_value->i32 == OGS_DIAM_CX_USER_DATA_ALREADY_AVAILABLE) { + /* Nothing to do */ + } else { + /* Set the User-Data AVP */ + user_data = hss_cx_download_user_data( + user_name, visited_plmn_id, &ims_data); + ogs_assert(user_data); - /* Set the Primary-Charging-Collection-Function-Name AVP */ - ret = fd_msg_avp_new( - ogs_diam_cx_primary_charging_collection_function_name, 0, - &avpch); - ogs_assert(ret == 0); + ret = fd_msg_avp_new(ogs_diam_cx_user_data, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (uint8_t *)user_data; + val.os.len = strlen(user_data); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Charging-Information AVP */ + ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp); + ogs_assert(ret == 0); + + /* Set the Charging-Information AVP */ + ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp); + ogs_assert(ret == 0); + + /* Set the Primary-Charging-Collection-Function-Name AVP */ + ret = fd_msg_avp_new( + ogs_diam_cx_primary_charging_collection_function_name, 0, + &avpch); + ogs_assert(ret == 0); #define PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME "pcrf" - val.os.data = (uint8_t *)PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME; - val.os.len = strlen(PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME); - 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); + val.os.data = (uint8_t *)PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME; + val.os.len = strlen(PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME); + 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(ans, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + } } /* Send the answer */ diff --git a/tests/volte/diameter-cx-path.c b/tests/volte/diameter-cx-path.c index 4bb51d8b9..b0ccaead7 100644 --- a/tests/volte/diameter-cx-path.c +++ b/tests/volte/diameter-cx-path.c @@ -32,6 +32,8 @@ struct sess_state { bool resync; + int server_assignment_type; + struct timespec ts; /* Time of sending the message */ }; @@ -623,6 +625,8 @@ static void test_cx_maa_cb(void *data, struct msg **msg) *msg = NULL; if (sess_data->resync == true) { + sess_data->server_assignment_type = + OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION; test_cx_send_sar(sess_data); } else { sess_data->resync = true; @@ -706,15 +710,18 @@ static void test_cx_send_sar(struct sess_state *sess_data) ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); - /* Set the User-Name AVP */ - ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)sess_data->user_name; - val.os.len = strlen(sess_data->user_name); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); + if (sess_data->server_assignment_type == + OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION) { + /* Set the User-Name AVP */ + ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (uint8_t *)sess_data->user_name; + val.os.len = strlen(sess_data->user_name); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + } /* Set the Public-Identity AVP */ ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp); @@ -739,7 +746,7 @@ static void test_cx_send_sar(struct sess_state *sess_data) /* Set the Server-Assignment-Type AVP */ ret = fd_msg_avp_new(ogs_diam_cx_server_assignment_type, 0, &avp); ogs_assert(ret == 0); - val.i32 = OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION; + val.i32 = sess_data->server_assignment_type; ret = fd_msg_avp_setvalue(avp, &val); ogs_assert(ret == 0); ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); @@ -885,7 +892,11 @@ static void test_cx_saa_cb(void *data, struct msg **msg) ogs_assert(ret == 0); *msg = NULL; - test_cx_send_lir(sess_data); + if (sess_data->server_assignment_type == + OGS_DIAM_CX_SERVER_ASSIGNMENT_UNREGISTERED_USER) + state_cleanup(sess_data, NULL, NULL); + else + test_cx_send_lir(sess_data); return; } @@ -1110,7 +1121,9 @@ static void test_cx_lia_cb(void *data, struct msg **msg) ogs_assert(ret == 0); *msg = NULL; - state_cleanup(sess_data, NULL, NULL); + sess_data->server_assignment_type = + OGS_DIAM_CX_SERVER_ASSIGNMENT_UNREGISTERED_USER; + test_cx_send_sar(sess_data); return; }