mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-23 07:41:57 +00:00
[NRF] Implemented PLMN list update handling in nrf_nnrf_handle_nf_update (#3566)
- Added functionality to parse and validate the plmnList JSON array during a PATCH request. - Updated the nf_instance structure with new PLMN data from the request. - Ensured robust error handling for invalid PLMN entries and excessive PLMN counts. - Responded with appropriate HTTP status codes for success and error scenarios.
This commit is contained in:
@@ -1205,6 +1205,35 @@ void ogs_sbi_free_plmn_list(OpenAPI_list_t *PlmnList)
|
||||
OpenAPI_list_free(PlmnList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares an ogs_plmn_id_t structure with an OpenAPI_plmn_id_t structure.
|
||||
*
|
||||
* @param plmn_list The PLMN-ID in ogs_plmn_id_t format.
|
||||
* @param PlmnList The PLMN-ID in OpenAPI_plmn_id_t format.
|
||||
* @return true if the PLMN-IDs are equal; otherwise, false.
|
||||
*/
|
||||
bool ogs_sbi_compare_plmn_list(
|
||||
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId)
|
||||
{
|
||||
ogs_plmn_id_t temp_plmn_id;
|
||||
|
||||
ogs_assert(plmn_id);
|
||||
ogs_assert(PlmnId);
|
||||
ogs_assert(PlmnId->mcc);
|
||||
ogs_assert(PlmnId->mnc);
|
||||
|
||||
/* Convert OpenAPI_plmn_id_t to ogs_plmn_id_t */
|
||||
ogs_sbi_parse_plmn_id(&temp_plmn_id, PlmnId);
|
||||
|
||||
/* Compare MCC and MNC values */
|
||||
if (ogs_plmn_id_mcc(plmn_id) == ogs_plmn_id_mcc(&temp_plmn_id) &&
|
||||
ogs_plmn_id_mnc(plmn_id) == ogs_plmn_id_mnc(&temp_plmn_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id)
|
||||
{
|
||||
OpenAPI_plmn_id_nid_t *PlmnIdNid = NULL;
|
||||
|
@@ -98,6 +98,8 @@ OpenAPI_list_t *ogs_sbi_build_plmn_list(
|
||||
int ogs_sbi_parse_plmn_list(
|
||||
ogs_plmn_id_t *plmn_list, OpenAPI_list_t *PlmnList);
|
||||
void ogs_sbi_free_plmn_list(OpenAPI_list_t *PlmnList);
|
||||
bool ogs_sbi_compare_plmn_list(
|
||||
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId);
|
||||
|
||||
OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id);
|
||||
bool ogs_sbi_parse_plmn_id_nid(
|
||||
|
@@ -150,6 +150,7 @@ extern "C" {
|
||||
|
||||
#define OGS_SBI_PATCH_PATH_NF_STATUS "/nfStatus"
|
||||
#define OGS_SBI_PATCH_PATH_LOAD "/load"
|
||||
#define OGS_SBI_PATCH_PATH_PLMN_LIST "/plmnList"
|
||||
#define OGS_SBI_PATCH_PATH_VALIDITY_TIME "/validityTime"
|
||||
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -25,6 +25,15 @@ static int discover_handler(
|
||||
static void handle_nf_discover_search_result(
|
||||
OpenAPI_search_result_t *SearchResult);
|
||||
|
||||
/**
|
||||
* Handles NF registration in NRF. Validates the PLMN-ID against configured
|
||||
* serving PLMN-IDs and registers the NF instance if valid.
|
||||
*
|
||||
* @param nf_instance The NF instance being registered.
|
||||
* @param stream The SBI stream for communication.
|
||||
* @param recvmsg The received SBI message.
|
||||
* @return true if registration is successful; otherwise, false.
|
||||
*/
|
||||
bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance,
|
||||
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
|
||||
{
|
||||
@@ -33,6 +42,10 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance,
|
||||
|
||||
OpenAPI_nf_profile_t *NFProfile = NULL;
|
||||
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
bool plmn_valid = false;
|
||||
int i;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(stream);
|
||||
ogs_assert(recvmsg);
|
||||
@@ -73,6 +86,41 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Validate the PLMN-ID against configured serving PLMN-IDs */
|
||||
if (NFProfile->plmn_list) {
|
||||
/* Set PLMN status to invalid */
|
||||
plmn_valid = false;
|
||||
|
||||
if (ogs_local_conf()->num_of_serving_plmn_id > 0 && NFProfile->plmn_list) {
|
||||
OpenAPI_list_for_each(NFProfile->plmn_list, node) {
|
||||
OpenAPI_plmn_id_t *PlmnId = node->data;
|
||||
if (PlmnId == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < ogs_local_conf()->num_of_serving_plmn_id; i++) {
|
||||
if (ogs_sbi_compare_plmn_list(
|
||||
&ogs_local_conf()->serving_plmn_id[i],
|
||||
PlmnId) == true) {
|
||||
plmn_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (plmn_valid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reject the registration if PLMN-ID is invalid */
|
||||
if (!plmn_valid) {
|
||||
ogs_error("PLMN-ID in NFProfile is not allowed");
|
||||
ogs_assert(true == ogs_sbi_server_send_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg,
|
||||
"PLMN-ID not allowed", NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_nnrf_nfm_handle_nf_profile(nf_instance, NFProfile);
|
||||
|
||||
ogs_sbi_client_associate(nf_instance);
|
||||
@@ -146,7 +194,6 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance,
|
||||
if (ogs_local_conf()->num_of_serving_plmn_id &&
|
||||
NFProfile->plmn_list == NULL) {
|
||||
OpenAPI_list_t *PlmnIdList = NULL;
|
||||
int i;
|
||||
|
||||
PlmnIdList = OpenAPI_list_create();
|
||||
ogs_assert(PlmnIdList);
|
||||
@@ -208,6 +255,10 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance,
|
||||
ogs_assert(stream);
|
||||
ogs_assert(recvmsg);
|
||||
|
||||
cJSON *plmn_array = NULL, *plmn_item = NULL;
|
||||
bool plmn_valid = false;
|
||||
int i;
|
||||
|
||||
SWITCH(recvmsg->h.method)
|
||||
CASE(OGS_SBI_HTTP_METHOD_PUT)
|
||||
return nrf_nnrf_handle_nf_register(
|
||||
@@ -224,14 +275,14 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Iterate through the PatchItemList */
|
||||
OpenAPI_list_for_each(PatchItemList, node) {
|
||||
OpenAPI_patch_item_t *patch_item = node->data;
|
||||
if (!patch_item) {
|
||||
ogs_error("No PatchItem");
|
||||
ogs_assert(true ==
|
||||
ogs_sbi_server_send_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
recvmsg, "No PatchItem", NULL, NULL));
|
||||
ogs_assert(true == ogs_sbi_server_send_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg,
|
||||
"No PatchItem", NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -246,6 +297,102 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance,
|
||||
break;
|
||||
CASE(OGS_SBI_PATCH_PATH_LOAD)
|
||||
break;
|
||||
CASE(OGS_SBI_PATCH_PATH_PLMN_LIST)
|
||||
/* Ensure the value is not null and is a valid JSON array */
|
||||
if (patch_item->value && patch_item->value->json) {
|
||||
/* Set PLMN status to invalid */
|
||||
plmn_valid = false;
|
||||
|
||||
plmn_array = patch_item->value->json;
|
||||
if (!cJSON_IsArray(plmn_array)) {
|
||||
ogs_error("Value for /plmnList is not a JSON array");
|
||||
ogs_assert(true == ogs_sbi_server_send_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg,
|
||||
"Invalid value for /plmnList", NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear existing PLMN data in nf_instance */
|
||||
memset(nf_instance->plmn_id, 0,
|
||||
sizeof(nf_instance->plmn_id));
|
||||
nf_instance->num_of_plmn_id = 0;
|
||||
|
||||
/* Iterate through the JSON array of PLMN IDs */
|
||||
cJSON_ArrayForEach(plmn_item, plmn_array) {
|
||||
OpenAPI_plmn_id_t plmn_id;
|
||||
memset(&plmn_id, 0, sizeof(plmn_id));
|
||||
|
||||
if (nf_instance->num_of_plmn_id >=
|
||||
OGS_ARRAY_SIZE(nf_instance->plmn_id)) {
|
||||
ogs_error("Exceeded maximum number of PLMN IDs");
|
||||
ogs_assert(true == ogs_sbi_server_send_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
recvmsg,
|
||||
"Too many PLMN IDs", NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Parse the PLMN item */
|
||||
plmn_id.mcc = cJSON_GetObjectItem(plmn_item, "mcc")
|
||||
? cJSON_GetStringValue(
|
||||
cJSON_GetObjectItem(
|
||||
plmn_item, "mcc"))
|
||||
: NULL;
|
||||
plmn_id.mnc = cJSON_GetObjectItem(plmn_item, "mnc")
|
||||
? cJSON_GetStringValue(
|
||||
cJSON_GetObjectItem(
|
||||
plmn_item, "mnc"))
|
||||
: NULL;
|
||||
|
||||
if (!plmn_id.mcc || !plmn_id.mnc) {
|
||||
ogs_error(
|
||||
"Invalid PLMN item in /plmnList update");
|
||||
ogs_assert(true ==
|
||||
ogs_sbi_server_send_error(
|
||||
stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
recvmsg,
|
||||
"Invalid PLMN item", NULL,
|
||||
NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert OpenAPI_plmn_id_t to ogs_plmn_id_t
|
||||
* and store in nf_instance
|
||||
*/
|
||||
ogs_sbi_parse_plmn_id(
|
||||
&nf_instance->
|
||||
plmn_id[nf_instance->num_of_plmn_id],
|
||||
&plmn_id);
|
||||
nf_instance->num_of_plmn_id++;
|
||||
|
||||
/* Compare with the serving PLMN list */
|
||||
for (i = 0;
|
||||
i < ogs_local_conf()->num_of_serving_plmn_id;
|
||||
i++) {
|
||||
if (ogs_sbi_compare_plmn_list(
|
||||
&ogs_local_conf()->serving_plmn_id[i],
|
||||
&plmn_id) == true) {
|
||||
plmn_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (plmn_valid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reject the update if PLMN-ID is invalid */
|
||||
if (!plmn_valid) {
|
||||
ogs_error("PLMN-ID in NFProfile update is not allowed");
|
||||
ogs_assert(true == ogs_sbi_server_send_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg,
|
||||
"PLMN-ID not allowed", NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
DEFAULT
|
||||
ogs_error("Unknown PatchItem.Path [%s]", patch_item->path);
|
||||
END
|
||||
|
Reference in New Issue
Block a user