diff --git a/lib/sbi/message.c b/lib/sbi/message.c index d00674bca..d3f408e62 100644 --- a/lib/sbi/message.c +++ b/lib/sbi/message.c @@ -66,6 +66,8 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message) /* Query parameters */ for (i = 0; i < message->param.num_of_fields; i++) ogs_free(message->param.fields[i]); + for (i = 0; i < message->param.num_of_dataset_names; i++) + ogs_free(message->param.dataset_names[i]); /* JSON Data */ if (message->NFProfile) @@ -113,6 +115,8 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message) message->Amf3GppAccessRegistrationModification); if (message->SmfRegistration) OpenAPI_smf_registration_free(message->SmfRegistration); + if (message->ProvisionedDataSets) + OpenAPI_provisioned_data_sets_free(message->ProvisionedDataSets); if (message->Nssai) OpenAPI_nssai_free(message->Nssai); if (message->AccessAndMobilitySubscriptionData) @@ -761,6 +765,25 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message) } } + if (message->param.num_of_dataset_names) { + char *dataset_names; + + dataset_names = ogs_strdup(message->param.dataset_names[0]); + if (!dataset_names) { + ogs_error("ogs_strdup() failed"); + return NULL; + } + + for (i = 1; i < message->param.num_of_dataset_names; i++) + dataset_names = ogs_mstrcatf( + dataset_names, ",%s", message->param.dataset_names[i]); + + if (dataset_names) { + ogs_sbi_header_set(request->http.params, + OGS_SBI_PARAM_DATASET_NAMES, dataset_names); + ogs_free(dataset_names); + } + } if (message->param.ipv4addr) { ogs_sbi_header_set(request->http.params, OGS_SBI_PARAM_IPV4ADDR, message->param.ipv4addr); @@ -1172,6 +1195,34 @@ int ogs_sbi_parse_request( } } + ogs_free(v); + } else if (!strcmp(ogs_hash_this_key(hi), + OGS_SBI_PARAM_DATASET_NAMES)) { + char *_v = ogs_hash_this_val(hi), *v = NULL; + char *token = NULL; + char *saveptr = NULL; + + v = ogs_strdup(_v); + ogs_assert(v); + + token = ogs_strtok_r(v, ",", &saveptr); + while (token != NULL) { + if (message->param.num_of_fields < + OGS_SBI_MAX_NUM_OF_DATASETNAMES) { + message->param.dataset_names + [message->param.num_of_dataset_names] = + ogs_strdup(token); + ogs_assert(message->param.dataset_names + [message->param.num_of_dataset_names]); + message->param.num_of_dataset_names++; + token = ogs_strtok_r(NULL, ",", &saveptr); + } else { + ogs_error("Datasetnames in query exceeds " + "MAX_NUM_OF_DATASETNAMES"); + break; + } + } + ogs_free(v); } else if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_PARAM_IPV4ADDR)) { message->param.ipv4addr = ogs_hash_this_val(hi); @@ -1480,6 +1531,10 @@ static char *build_json(ogs_sbi_message_t *message) } else if (message->SmfRegistration) { item = OpenAPI_smf_registration_convertToJSON(message->SmfRegistration); ogs_assert(item); + } else if (message->ProvisionedDataSets) { + item = OpenAPI_provisioned_data_sets_convertToJSON( + message->ProvisionedDataSets); + ogs_assert(item); } else if (message->Nssai) { item = OpenAPI_nssai_convertToJSON(message->Nssai); ogs_assert(item); @@ -2182,6 +2237,20 @@ static int parse_json(ogs_sbi_message_t *message, DEFAULT SWITCH(message->h.resource.component[3]) CASE(OGS_SBI_RESOURCE_NAME_PROVISIONED_DATA) + if (!message->h.resource.component[4]) { + if (message->res_status < 300) { + message->ProvisionedDataSets = + OpenAPI_provisioned_data_sets_parseFromJSON(item); + if (!message->ProvisionedDataSets) { + rv = OGS_ERROR; + ogs_error("JSON parse error"); + } + } else { + ogs_error("HTTP ERROR Status : %d", + message->res_status); + } + break; + } SWITCH(message->h.resource.component[4]) CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) if (message->res_status < 300) { diff --git a/lib/sbi/message.h b/lib/sbi/message.h index 83fd1ec09..cd1b46ee8 100644 --- a/lib/sbi/message.h +++ b/lib/sbi/message.h @@ -354,6 +354,7 @@ extern "C" { #define OGS_SBI_PARAM_SLICE_INFO_REQUEST_FOR_PDU_SESSION \ "slice-info-request-for-pdu-session" #define OGS_SBI_PARAM_FIELDS "fields" +#define OGS_SBI_PARAM_DATASET_NAMES "dataset-names" #define OGS_SBI_PARAM_IPV4ADDR "ipv4Addr" #define OGS_SBI_PARAM_IPV6PREFIX "ipv6Prefix" #define OGS_SBI_PARAM_HOME_PLMN_ID "home-plmn-id" @@ -369,6 +370,11 @@ extern "C" { #define OGS_SBI_PARAM_FIELDS_NSSAI "nssai" #define OGS_SBI_MAX_NUM_OF_FIELDS 8 +#define OGS_SBI_PARAM_DATASET_NAME_AM "AM" +#define OGS_SBI_PARAM_DATASET_NAME_SMF_SEL "SMF_SEL" +#define OGS_SBI_PARAM_DATASET_NAME_SM "SM" +#define OGS_SBI_MAX_NUM_OF_DATASETNAMES 8 + #define OGS_SBI_CONTENT_JSON_TYPE \ OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE #define OGS_SBI_CONTENT_PROBLEM_TYPE \ @@ -509,6 +515,8 @@ typedef struct ogs_sbi_message_s { char *dnn; int num_of_fields; char *fields[OGS_SBI_MAX_NUM_OF_FIELDS]; + int num_of_dataset_names; + char *dataset_names[OGS_SBI_MAX_NUM_OF_DATASETNAMES]; /* Shared memory */ bool plmn_id_presence; @@ -552,6 +560,7 @@ typedef struct ogs_sbi_message_s { OpenAPI_amf3_gpp_access_registration_t *Amf3GppAccessRegistration; OpenAPI_amf3_gpp_access_registration_modification_t *Amf3GppAccessRegistrationModification; + OpenAPI_provisioned_data_sets_t *ProvisionedDataSets; OpenAPI_nssai_t *Nssai; OpenAPI_access_and_mobility_subscription_data_t *AccessAndMobilitySubscriptionData; diff --git a/lib/sbi/ogs-sbi.h b/lib/sbi/ogs-sbi.h index bb06b52d1..2477e58ab 100644 --- a/lib/sbi/ogs-sbi.h +++ b/lib/sbi/ogs-sbi.h @@ -100,6 +100,7 @@ #include "model/ue_reg_status_update_req_data.h" #include "model/ue_reg_status_update_rsp_data.h" #include "model/status_notification.h" +#include "model/provisioned_data_sets.h" #include "custom/links.h" diff --git a/lib/sbi/openapi/model/sm_subs_data.c b/lib/sbi/openapi/model/sm_subs_data.c index 9fc7a6b6c..16e8653dd 100644 --- a/lib/sbi/openapi/model/sm_subs_data.c +++ b/lib/sbi/openapi/model/sm_subs_data.c @@ -5,15 +5,15 @@ #include "sm_subs_data.h" OpenAPI_sm_subs_data_t *OpenAPI_sm_subs_data_create( - OpenAPI_list_t *shared_sm_subs_data_ids, - OpenAPI_list_t *individual_sm_subs_data + OpenAPI_list_t *session_management_subscription_data_list, + OpenAPI_extended_sm_subs_data_t *extended_sm_subs_data ) { OpenAPI_sm_subs_data_t *sm_subs_data_local_var = ogs_malloc(sizeof(OpenAPI_sm_subs_data_t)); ogs_assert(sm_subs_data_local_var); - sm_subs_data_local_var->shared_sm_subs_data_ids = shared_sm_subs_data_ids; - sm_subs_data_local_var->individual_sm_subs_data = individual_sm_subs_data; + sm_subs_data_local_var->session_management_subscription_data_list = session_management_subscription_data_list; + sm_subs_data_local_var->extended_sm_subs_data = extended_sm_subs_data; return sm_subs_data_local_var; } @@ -25,19 +25,16 @@ void OpenAPI_sm_subs_data_free(OpenAPI_sm_subs_data_t *sm_subs_data) if (NULL == sm_subs_data) { return; } - if (sm_subs_data->shared_sm_subs_data_ids) { - OpenAPI_list_for_each(sm_subs_data->shared_sm_subs_data_ids, node) { - ogs_free(node->data); - } - OpenAPI_list_free(sm_subs_data->shared_sm_subs_data_ids); - sm_subs_data->shared_sm_subs_data_ids = NULL; - } - if (sm_subs_data->individual_sm_subs_data) { - OpenAPI_list_for_each(sm_subs_data->individual_sm_subs_data, node) { + if (sm_subs_data->session_management_subscription_data_list) { + OpenAPI_list_for_each(sm_subs_data->session_management_subscription_data_list, node) { OpenAPI_session_management_subscription_data_free(node->data); } - OpenAPI_list_free(sm_subs_data->individual_sm_subs_data); - sm_subs_data->individual_sm_subs_data = NULL; + OpenAPI_list_free(sm_subs_data->session_management_subscription_data_list); + sm_subs_data->session_management_subscription_data_list = NULL; + } + if (sm_subs_data->extended_sm_subs_data) { + OpenAPI_extended_sm_subs_data_free(sm_subs_data->extended_sm_subs_data); + sm_subs_data->extended_sm_subs_data = NULL; } ogs_free(sm_subs_data); } @@ -53,35 +50,32 @@ cJSON *OpenAPI_sm_subs_data_convertToJSON(OpenAPI_sm_subs_data_t *sm_subs_data) } item = cJSON_CreateObject(); - if (!sm_subs_data->shared_sm_subs_data_ids) { - ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [shared_sm_subs_data_ids]"); - return NULL; - } - cJSON *shared_sm_subs_data_idsList = cJSON_AddArrayToObject(item, "sharedSmSubsDataIds"); - if (shared_sm_subs_data_idsList == NULL) { - ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [shared_sm_subs_data_ids]"); + if (sm_subs_data->session_management_subscription_data_list) { + cJSON *session_management_subscription_data_listList = cJSON_AddArrayToObject(item, "SessionManagementSubscriptionDataList"); + if (session_management_subscription_data_listList == NULL) { + ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [session_management_subscription_data_list]"); goto end; } - OpenAPI_list_for_each(sm_subs_data->shared_sm_subs_data_ids, node) { - if (cJSON_AddStringToObject(shared_sm_subs_data_idsList, "", (char*)node->data) == NULL) { - ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [shared_sm_subs_data_ids]"); - goto end; - } - } - - if (sm_subs_data->individual_sm_subs_data) { - cJSON *individual_sm_subs_dataList = cJSON_AddArrayToObject(item, "individualSmSubsData"); - if (individual_sm_subs_dataList == NULL) { - ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [individual_sm_subs_data]"); - goto end; - } - OpenAPI_list_for_each(sm_subs_data->individual_sm_subs_data, node) { + OpenAPI_list_for_each(sm_subs_data->session_management_subscription_data_list, node) { cJSON *itemLocal = OpenAPI_session_management_subscription_data_convertToJSON(node->data); if (itemLocal == NULL) { - ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [individual_sm_subs_data]"); + ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [session_management_subscription_data_list]"); goto end; } - cJSON_AddItemToArray(individual_sm_subs_dataList, itemLocal); + cJSON_AddItemToArray(session_management_subscription_data_listList, itemLocal); + } + } + + if (sm_subs_data->extended_sm_subs_data) { + cJSON *extended_sm_subs_data_local_JSON = OpenAPI_extended_sm_subs_data_convertToJSON(sm_subs_data->extended_sm_subs_data); + if (extended_sm_subs_data_local_JSON == NULL) { + ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [extended_sm_subs_data]"); + goto end; + } + cJSON_AddItemToObject(item, "ExtendedSmSubsData", extended_sm_subs_data_local_JSON); + if (item->child == NULL) { + ogs_error("OpenAPI_sm_subs_data_convertToJSON() failed [extended_sm_subs_data]"); + goto end; } } @@ -93,77 +87,60 @@ OpenAPI_sm_subs_data_t *OpenAPI_sm_subs_data_parseFromJSON(cJSON *sm_subs_dataJS { OpenAPI_sm_subs_data_t *sm_subs_data_local_var = NULL; OpenAPI_lnode_t *node = NULL; - cJSON *shared_sm_subs_data_ids = NULL; - OpenAPI_list_t *shared_sm_subs_data_idsList = NULL; - cJSON *individual_sm_subs_data = NULL; - OpenAPI_list_t *individual_sm_subs_dataList = NULL; - shared_sm_subs_data_ids = cJSON_GetObjectItemCaseSensitive(sm_subs_dataJSON, "sharedSmSubsDataIds"); - if (!shared_sm_subs_data_ids) { - ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [shared_sm_subs_data_ids]"); + cJSON *session_management_subscription_data_list = NULL; + OpenAPI_list_t *session_management_subscription_data_listList = NULL; + cJSON *extended_sm_subs_data = NULL; + OpenAPI_extended_sm_subs_data_t *extended_sm_subs_data_local_nonprim = NULL; + session_management_subscription_data_list = cJSON_GetObjectItemCaseSensitive(sm_subs_dataJSON, "SessionManagementSubscriptionDataList"); + if (session_management_subscription_data_list) { + cJSON *session_management_subscription_data_list_local = NULL; + if (!cJSON_IsArray(session_management_subscription_data_list)) { + ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [session_management_subscription_data_list]"); + goto end; + } + + session_management_subscription_data_listList = OpenAPI_list_create(); + + cJSON_ArrayForEach(session_management_subscription_data_list_local, session_management_subscription_data_list) { + if (!cJSON_IsObject(session_management_subscription_data_list_local)) { + ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [session_management_subscription_data_list]"); + goto end; + } + OpenAPI_session_management_subscription_data_t *session_management_subscription_data_listItem = OpenAPI_session_management_subscription_data_parseFromJSON(session_management_subscription_data_list_local); + if (!session_management_subscription_data_listItem) { + ogs_error("No session_management_subscription_data_listItem"); + goto end; + } + OpenAPI_list_add(session_management_subscription_data_listList, session_management_subscription_data_listItem); + } + } + + extended_sm_subs_data = cJSON_GetObjectItemCaseSensitive(sm_subs_dataJSON, "ExtendedSmSubsData"); + if (extended_sm_subs_data) { + extended_sm_subs_data_local_nonprim = OpenAPI_extended_sm_subs_data_parseFromJSON(extended_sm_subs_data); + if (!extended_sm_subs_data_local_nonprim) { + ogs_error("OpenAPI_extended_sm_subs_data_parseFromJSON failed [extended_sm_subs_data]"); goto end; } - cJSON *shared_sm_subs_data_ids_local = NULL; - if (!cJSON_IsArray(shared_sm_subs_data_ids)) { - ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [shared_sm_subs_data_ids]"); - goto end; - } - - shared_sm_subs_data_idsList = OpenAPI_list_create(); - - cJSON_ArrayForEach(shared_sm_subs_data_ids_local, shared_sm_subs_data_ids) { - double *localDouble = NULL; - int *localInt = NULL; - if (!cJSON_IsString(shared_sm_subs_data_ids_local)) { - ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [shared_sm_subs_data_ids]"); - goto end; - } - OpenAPI_list_add(shared_sm_subs_data_idsList, ogs_strdup(shared_sm_subs_data_ids_local->valuestring)); - } - - individual_sm_subs_data = cJSON_GetObjectItemCaseSensitive(sm_subs_dataJSON, "individualSmSubsData"); - if (individual_sm_subs_data) { - cJSON *individual_sm_subs_data_local = NULL; - if (!cJSON_IsArray(individual_sm_subs_data)) { - ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [individual_sm_subs_data]"); - goto end; - } - - individual_sm_subs_dataList = OpenAPI_list_create(); - - cJSON_ArrayForEach(individual_sm_subs_data_local, individual_sm_subs_data) { - if (!cJSON_IsObject(individual_sm_subs_data_local)) { - ogs_error("OpenAPI_sm_subs_data_parseFromJSON() failed [individual_sm_subs_data]"); - goto end; - } - OpenAPI_session_management_subscription_data_t *individual_sm_subs_dataItem = OpenAPI_session_management_subscription_data_parseFromJSON(individual_sm_subs_data_local); - if (!individual_sm_subs_dataItem) { - ogs_error("No individual_sm_subs_dataItem"); - goto end; - } - OpenAPI_list_add(individual_sm_subs_dataList, individual_sm_subs_dataItem); - } } sm_subs_data_local_var = OpenAPI_sm_subs_data_create ( - shared_sm_subs_data_idsList, - individual_sm_subs_data ? individual_sm_subs_dataList : NULL + session_management_subscription_data_list ? session_management_subscription_data_listList : NULL, + extended_sm_subs_data ? extended_sm_subs_data_local_nonprim : NULL ); return sm_subs_data_local_var; end: - if (shared_sm_subs_data_idsList) { - OpenAPI_list_for_each(shared_sm_subs_data_idsList, node) { - ogs_free(node->data); - } - OpenAPI_list_free(shared_sm_subs_data_idsList); - shared_sm_subs_data_idsList = NULL; - } - if (individual_sm_subs_dataList) { - OpenAPI_list_for_each(individual_sm_subs_dataList, node) { + if (session_management_subscription_data_listList) { + OpenAPI_list_for_each(session_management_subscription_data_listList, node) { OpenAPI_session_management_subscription_data_free(node->data); } - OpenAPI_list_free(individual_sm_subs_dataList); - individual_sm_subs_dataList = NULL; + OpenAPI_list_free(session_management_subscription_data_listList); + session_management_subscription_data_listList = NULL; + } + if (extended_sm_subs_data_local_nonprim) { + OpenAPI_extended_sm_subs_data_free(extended_sm_subs_data_local_nonprim); + extended_sm_subs_data_local_nonprim = NULL; } return NULL; } diff --git a/lib/sbi/openapi/model/sm_subs_data.h b/lib/sbi/openapi/model/sm_subs_data.h index caae88556..ebc000634 100644 --- a/lib/sbi/openapi/model/sm_subs_data.h +++ b/lib/sbi/openapi/model/sm_subs_data.h @@ -21,13 +21,13 @@ extern "C" { typedef struct OpenAPI_sm_subs_data_s OpenAPI_sm_subs_data_t; typedef struct OpenAPI_sm_subs_data_s { - OpenAPI_list_t *shared_sm_subs_data_ids; - OpenAPI_list_t *individual_sm_subs_data; + OpenAPI_list_t *session_management_subscription_data_list; + struct OpenAPI_extended_sm_subs_data_s *extended_sm_subs_data; } OpenAPI_sm_subs_data_t; OpenAPI_sm_subs_data_t *OpenAPI_sm_subs_data_create( - OpenAPI_list_t *shared_sm_subs_data_ids, - OpenAPI_list_t *individual_sm_subs_data + OpenAPI_list_t *session_management_subscription_data_list, + OpenAPI_extended_sm_subs_data_t *extended_sm_subs_data ); void OpenAPI_sm_subs_data_free(OpenAPI_sm_subs_data_t *sm_subs_data); OpenAPI_sm_subs_data_t *OpenAPI_sm_subs_data_parseFromJSON(cJSON *sm_subs_dataJSON); diff --git a/lib/sbi/support/r17-20230301-openapitools-6.4.0/modified/TS29503_Nudm_SDM.yaml b/lib/sbi/support/r17-20230301-openapitools-6.4.0/modified/TS29503_Nudm_SDM.yaml index a6777f4ad..fb291ce3b 100644 --- a/lib/sbi/support/r17-20230301-openapitools-6.4.0/modified/TS29503_Nudm_SDM.yaml +++ b/lib/sbi/support/r17-20230301-openapitools-6.4.0/modified/TS29503_Nudm_SDM.yaml @@ -3351,12 +3351,15 @@ components: $ref: 'TS29571_CommonData.yaml#/components/schemas/Gpsi' SmSubsData: - oneOf: - - type: array + type: object + properties: + SessionManagementSubscriptionDataList: + type: array items: $ref: '#/components/schemas/SessionManagementSubscriptionData' - minItems: 1 - - $ref: '#/components/schemas/ExtendedSmSubsData' + minItems: 1 + ExtendedSmSubsData: + $ref: '#/components/schemas/ExtendedSmSubsData' ExtendedSmSubsData: description: Contains identifiers of shared Session Management Subscription Data and optionally individual Session Management Subscription Data. diff --git a/src/udm/nudr-build.c b/src/udm/nudr-build.c index 2549ee5de..cc053fa46 100644 --- a/src/udm/nudr-build.c +++ b/src/udm/nudr-build.c @@ -221,7 +221,15 @@ ogs_sbi_request_t *udm_nudr_dr_build_query_subscription_provisioned( (char *)ogs_plmn_id_to_string(&udm_ue->guami.plmn_id, buf); sendmsg.h.resource.component[3] = (char *)OGS_SBI_RESOURCE_NAME_PROVISIONED_DATA; - sendmsg.h.resource.component[4] = recvmsg->h.resource.component[1]; + if (recvmsg->h.resource.component[1]) { + sendmsg.h.resource.component[4] = recvmsg->h.resource.component[1]; + } else if (recvmsg->param.num_of_dataset_names) { + int i; + for (i = 0; i < recvmsg->param.num_of_dataset_names; i++) { + sendmsg.param.dataset_names[i] = recvmsg->param.dataset_names[i]; + sendmsg.param.num_of_dataset_names++; + } + } SWITCH(recvmsg->h.resource.component[1]) CASE(OGS_SBI_RESOURCE_NAME_SM_DATA) diff --git a/src/udm/nudr-handler.c b/src/udm/nudr-handler.c index 035f614ef..f8a576a36 100644 --- a/src/udm/nudr-handler.c +++ b/src/udm/nudr-handler.c @@ -622,6 +622,37 @@ bool udm_nudr_dr_handle_subscription_provisioned( ogs_assert(recvmsg); + if (state == UDM_SBI_UE_PROVISIONED_DATASETS) { + OpenAPI_provisioned_data_sets_t *ProvisionedDataSets; + + ProvisionedDataSets = recvmsg->ProvisionedDataSets; + if (!ProvisionedDataSets) { + ogs_error("[%s] No ProvisionedDataSets", + udm_ue->supi); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "No ProvisionedDataSets", + udm_ue->supi, NULL)); + return false; + } + + memset(&sendmsg, 0, sizeof(sendmsg)); + + sendmsg.ProvisionedDataSets = + OpenAPI_provisioned_data_sets_copy( + sendmsg.ProvisionedDataSets, + recvmsg->ProvisionedDataSets); + + response = ogs_sbi_build_response(&sendmsg, recvmsg->res_status); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + + OpenAPI_provisioned_data_sets_free(sendmsg.ProvisionedDataSets); + + return true; + } + SWITCH(recvmsg->h.resource.component[4]) CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) OpenAPI_access_and_mobility_subscription_data_t diff --git a/src/udm/sbi-path.h b/src/udm/sbi-path.h index 32c2268ee..2f3a1b9f0 100644 --- a/src/udm/sbi-path.h +++ b/src/udm/sbi-path.h @@ -34,6 +34,7 @@ bool udm_sbi_send_request( #define UDM_SBI_NO_STATE 0 #define UDM_SBI_UE_PROVISIONED_NSSAI_ONLY 1 +#define UDM_SBI_UE_PROVISIONED_DATASETS 2 int udm_ue_sbi_discover_and_send( ogs_sbi_service_type_e service_type, diff --git a/src/udm/udm-sm.c b/src/udm/udm-sm.c index 49b3ca9a4..47cd8b924 100644 --- a/src/udm/udm-sm.c +++ b/src/udm/udm-sm.c @@ -153,24 +153,26 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e) break; } - if (!message.h.resource.component[1]) { - ogs_error("Invalid resource name [%s]", message.h.method); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - &message, "Invalid resource name", message.h.method, - NULL)); - break; - } - - SWITCH(message.h.resource.component[1]) - CASE(OGS_SBI_RESOURCE_NAME_AUTH_EVENTS) - if (message.h.resource.component[2]) { - udm_ue = udm_ue_find_by_ctx_id( - message.h.resource.component[2]); + if (!message.param.num_of_dataset_names) { + if (!message.h.resource.component[1]) { + ogs_error("Invalid resource name [%s]", message.h.method); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, + &message, "Invalid resource name", message.h.method, + NULL)); + break; } - DEFAULT - END + + SWITCH(message.h.resource.component[1]) + CASE(OGS_SBI_RESOURCE_NAME_AUTH_EVENTS) + if (message.h.resource.component[2]) { + udm_ue = udm_ue_find_by_ctx_id( + message.h.resource.component[2]); + } + DEFAULT + END + } if (!udm_ue) { udm_ue = udm_ue_find_by_suci_or_supi( diff --git a/src/udm/ue-sm.c b/src/udm/ue-sm.c index 54e196e7b..d2734b31a 100644 --- a/src/udm/ue-sm.c +++ b/src/udm/ue-sm.c @@ -189,6 +189,17 @@ void udm_ue_state_operational(ogs_fsm_t *s, udm_event_t *e) CASE(OGS_SBI_SERVICE_NAME_NUDM_SDM) SWITCH(message->h.method) CASE(OGS_SBI_HTTP_METHOD_GET) + if (message->param.num_of_dataset_names && + !message->h.resource.component[1]) { + r = udm_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDR_DR, NULL, + udm_nudr_dr_build_query_subscription_provisioned, + udm_ue, stream, UDM_SBI_UE_PROVISIONED_DATASETS, + message); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + break; + } SWITCH(message->h.resource.component[1]) CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) CASE(OGS_SBI_RESOURCE_NAME_SMF_SELECT_DATA) diff --git a/src/udr/nudr-handler.c b/src/udr/nudr-handler.c index ee58291b4..6e26f810f 100644 --- a/src/udr/nudr-handler.c +++ b/src/udr/nudr-handler.c @@ -425,17 +425,61 @@ bool udr_nudr_dr_handle_subscription_provisioned( int rv, status = 0; char *strerror = NULL; + bool processAmData = false; + bool processSmfSel = false; + bool processSmData = false; + bool returnProvisionedData = false; + ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; ogs_subscription_data_t subscription_data; ogs_slice_data_t *slice_data = NULL; + OpenAPI_access_and_mobility_subscription_data_t + AccessAndMobilitySubscriptionData; + OpenAPI_list_t *SessionManagementSubscriptionDataList = NULL; + OpenAPI_session_management_subscription_data_t + *SessionManagementSubscriptionData = NULL; + OpenAPI_smf_selection_subscription_data_t SmfSelectionSubscriptionData; + + OpenAPI_list_t *GpsiList = NULL; + OpenAPI_ambr_rm_t SubscribedUeAmbr; + OpenAPI_list_t *DefaultSingleNssaiList = NULL; + OpenAPI_list_t *SingleNssaiList = NULL; + OpenAPI_nssai_t NSSAI; + OpenAPI_snssai_t *Snssai = NULL; + + OpenAPI_list_t *SubscribedSnssaiInfoList = NULL; + OpenAPI_map_t *SubscribedSnssaiInfoMap = NULL; + OpenAPI_snssai_info_t *SubscribedSnssaiInfo = NULL; + OpenAPI_list_t *DnnInfoList = NULL; + OpenAPI_dnn_info_t *DnnInfo = NULL; + + OpenAPI_snssai_t *singleNSSAI = NULL; + OpenAPI_list_t *dnnConfigurationList = NULL; + OpenAPI_map_t *dnnConfigurationMap = NULL; + OpenAPI_dnn_configuration_t *dnnConfiguration = NULL; + OpenAPI_pdu_session_types_t *pduSessionTypeList = NULL; + OpenAPI_ssc_modes_t *sscModeList = NULL; + OpenAPI_subscribed_default_qos_t *_5gQoSProfile = NULL; + OpenAPI_ambr_t *sessionAmbr = NULL; + OpenAPI_list_t *staticIpAddress = NULL; + OpenAPI_ip_address_t *ipAddress = NULL; + OpenAPI_list_t *FrameRouteList = NULL; + OpenAPI_sm_subs_data_t smSubsData; + char *supi = NULL; ogs_assert(stream); ogs_assert(recvmsg); + memset(&AccessAndMobilitySubscriptionData, 0, + sizeof(AccessAndMobilitySubscriptionData)); + memset(&SubscribedUeAmbr, 0, sizeof(SubscribedUeAmbr)); + memset(&NSSAI, 0, sizeof(NSSAI)); memset(&subscription_data, 0, sizeof(ogs_subscription_data_t)); + memset(&SmfSelectionSubscriptionData, 0, + sizeof(SmfSelectionSubscriptionData)); supi = recvmsg->h.resource.component[1]; if (!supi) { @@ -464,31 +508,64 @@ bool udr_nudr_dr_handle_subscription_provisioned( goto cleanup; } - SWITCH(recvmsg->h.resource.component[4]) - CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) + if (recvmsg->h.resource.component[4]) { + SWITCH(recvmsg->h.resource.component[4]) + CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) + processAmData = true; + break; + CASE(OGS_SBI_RESOURCE_NAME_SMF_SELECTION_SUBSCRIPTION_DATA) + processSmfSel = true; + break; + CASE(OGS_SBI_RESOURCE_NAME_SM_DATA) + processSmData = true; + break; + DEFAULT + strerror = ogs_msprintf("Invalid resource name [%s]", + recvmsg->h.resource.component[4]); + status = OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED; + goto cleanup; + END + } else { + returnProvisionedData = true; + if (recvmsg->param.num_of_dataset_names) { + int i, validParams = false; + for (i = 0; i < recvmsg->param.num_of_dataset_names; i++) { + SWITCH(recvmsg->param.dataset_names[i]) + CASE(OGS_SBI_PARAM_DATASET_NAME_AM) + processAmData = true; + validParams = true; + break; + CASE(OGS_SBI_PARAM_DATASET_NAME_SMF_SEL) + processSmfSel = true; + validParams = true; + break; + CASE(OGS_SBI_PARAM_DATASET_NAME_SM) + processSmData = true; + validParams = true; + break; + DEFAULT + ogs_error("Unexpected dataset-name! [%s]", + recvmsg->param.dataset_names[i]); + END + } + if (!validParams) { + strerror = ogs_msprintf("No valid dataset-names"); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + } else { + processAmData = true; + processSmfSel = true; + processSmData = true; + } + } + + if (processAmData) { int i; bool processGpsi = false; bool processUeAmbr = false; bool processNssai = false; - OpenAPI_access_and_mobility_subscription_data_t - AccessAndMobilitySubscriptionData; - OpenAPI_list_t *GpsiList = NULL; - OpenAPI_ambr_rm_t SubscribedUeAmbr; - - OpenAPI_nssai_t NSSAI; - OpenAPI_list_t *DefaultSingleNssaiList = NULL; - OpenAPI_list_t *SingleNssaiList = NULL; - OpenAPI_snssai_t *Snssai = NULL; - - OpenAPI_lnode_t *node = NULL; - - memset(&AccessAndMobilitySubscriptionData, 0, - sizeof(AccessAndMobilitySubscriptionData)); - - memset(&SubscribedUeAmbr, 0, sizeof(SubscribedUeAmbr)); - memset(&NSSAI, 0, sizeof(NSSAI)); - /* Apply filtering based on fields query parameter */ if (recvmsg->param.num_of_fields) { for (i = 0; i < recvmsg->param.num_of_fields; i++) { @@ -588,61 +665,19 @@ bool udr_nudr_dr_handle_subscription_provisioned( AccessAndMobilitySubscriptionData.nssai = &NSSAI; } - memset(&sendmsg, 0, sizeof(sendmsg)); - sendmsg.AccessAndMobilitySubscriptionData = - &AccessAndMobilitySubscriptionData; + if (!returnProvisionedData) { + memset(&sendmsg, 0, sizeof(sendmsg)); + sendmsg.AccessAndMobilitySubscriptionData = + &AccessAndMobilitySubscriptionData; - response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); - ogs_assert(response); - ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - - OpenAPI_list_for_each(GpsiList, node) { - if (node->data) ogs_free(node->data); + response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); } - OpenAPI_list_free(GpsiList); - - if (SubscribedUeAmbr.uplink) - ogs_free(SubscribedUeAmbr.uplink); - if (SubscribedUeAmbr.downlink) - ogs_free(SubscribedUeAmbr.downlink); - - OpenAPI_list_for_each(DefaultSingleNssaiList, node) { - OpenAPI_snssai_t *Snssai = node->data; - if (Snssai) { - if (Snssai->sd) - ogs_free(Snssai->sd); - ogs_free(Snssai); - } - } - OpenAPI_list_free(DefaultSingleNssaiList); - OpenAPI_list_for_each(SingleNssaiList, node) { - OpenAPI_snssai_t *Snssai = node->data; - if (Snssai) { - if (Snssai->sd) - ogs_free(Snssai->sd); - ogs_free(Snssai); - } - } - OpenAPI_list_free(SingleNssaiList); - break; - - CASE(OGS_SBI_RESOURCE_NAME_SMF_SELECTION_SUBSCRIPTION_DATA) + } + if (processSmfSel) { int i, j; - OpenAPI_smf_selection_subscription_data_t SmfSelectionSubscriptionData; - - OpenAPI_list_t *SubscribedSnssaiInfoList = NULL; - OpenAPI_map_t *SubscribedSnssaiInfoMap = NULL; - OpenAPI_snssai_info_t *SubscribedSnssaiInfo = NULL; - - OpenAPI_list_t *DnnInfoList = NULL; - OpenAPI_dnn_info_t *DnnInfo = NULL; - - OpenAPI_lnode_t *node = NULL, *node2 = NULL; - - memset(&SmfSelectionSubscriptionData, 0, - sizeof(SmfSelectionSubscriptionData)); - SubscribedSnssaiInfoList = OpenAPI_list_create(); ogs_assert(SubscribedSnssaiInfoList); @@ -712,12 +747,362 @@ bool udr_nudr_dr_handle_subscription_provisioned( else OpenAPI_list_free(SubscribedSnssaiInfoList); + if (!returnProvisionedData) { + memset(&sendmsg, 0, sizeof(sendmsg)); + sendmsg.SmfSelectionSubscriptionData = + &SmfSelectionSubscriptionData; + + response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + } + } + if (processSmData) { + int i, j; + + if (recvmsg->param.single_nssai_presence && !returnProvisionedData) { + slice_data = ogs_slice_find_by_s_nssai( + subscription_data.slice, subscription_data.num_of_slice, + &recvmsg->param.s_nssai); + + if (!slice_data) { + strerror = ogs_msprintf("[%s] Cannot find S_NSSAI" + "[SST:%d SD:0x%x]", + supi, + recvmsg->param.s_nssai.sst, + recvmsg->param.s_nssai.sd.v); + status = OGS_SBI_HTTP_STATUS_NOT_FOUND; + goto cleanup; + } + } + + /* According to 29.503 6.1.3.8.3.1 + * sm-data can be filtered by singleNssai or dnn query params. + * If there is no filtering, then all NSSAIs and all DNNs are returned. + */ + + SessionManagementSubscriptionDataList = OpenAPI_list_create(); + ogs_assert(SessionManagementSubscriptionDataList); + + ogs_assert(subscription_data.num_of_slice); + + for (j = 0; j < subscription_data.num_of_slice; j++) { + slice_data = &subscription_data.slice[j]; + + if (!slice_data) { + continue; + } + + if (recvmsg->param.single_nssai_presence + && !returnProvisionedData) { + if (slice_data->s_nssai.sst != recvmsg->param.s_nssai.sst || + slice_data->s_nssai.sd.v != + recvmsg->param.s_nssai.sd.v) { + continue; + } + } + + singleNSSAI = ogs_calloc(1, sizeof(*singleNSSAI)); + ogs_assert(singleNSSAI); + + dnnConfigurationList = ogs_calloc(1, sizeof(*dnnConfigurationList)); + ogs_assert(dnnConfigurationList); + + singleNSSAI->sst = slice_data->s_nssai.sst; + singleNSSAI->sd = ogs_s_nssai_sd_to_string(slice_data->s_nssai.sd); + + for (i = 0; i < slice_data->num_of_session; i++) { + ogs_session_t *session = NULL; + + if (i >= OGS_MAX_NUM_OF_SESS) { + ogs_warn("Ignore max session count overflow [%d>=%d]", + slice_data->num_of_session, OGS_MAX_NUM_OF_SESS); + break; + } + + session = &slice_data->session[i]; + ogs_assert(session); + ogs_assert(session->name); + + if (recvmsg->param.dnn && + ogs_strcasecmp(recvmsg->param.dnn, session->name) != 0 && + !returnProvisionedData) + continue; + + if (!session->qos.index) { + ogs_error("No 5QI"); + continue; + } + if (!session->qos.arp.priority_level) { + ogs_error("No Priority Level"); + continue; + } + + if (!session->ambr.uplink && !session->ambr.downlink) { + ogs_error("No Session-AMBR"); + continue; + } + + dnnConfiguration = ogs_calloc(1, sizeof(*dnnConfiguration)); + ogs_assert(dnnConfiguration); + + pduSessionTypeList = ogs_calloc(1, sizeof(*pduSessionTypeList)); + ogs_assert(pduSessionTypeList); + pduSessionTypeList->default_session_type = + session->session_type; + + pduSessionTypeList->allowed_session_types = + OpenAPI_list_create(); + ogs_assert(pduSessionTypeList->allowed_session_types); + switch (pduSessionTypeList->default_session_type) { + case OpenAPI_pdu_session_type_IPV4: + OpenAPI_list_add(pduSessionTypeList->allowed_session_types, + (void *)OpenAPI_pdu_session_type_IPV4); + break; + case OpenAPI_pdu_session_type_IPV6: + OpenAPI_list_add(pduSessionTypeList->allowed_session_types, + (void *)OpenAPI_pdu_session_type_IPV6); + break; + case OpenAPI_pdu_session_type_IPV4V6: + OpenAPI_list_add(pduSessionTypeList->allowed_session_types, + (void *)OpenAPI_pdu_session_type_IPV4); + OpenAPI_list_add(pduSessionTypeList->allowed_session_types, + (void *)OpenAPI_pdu_session_type_IPV6); + OpenAPI_list_add(pduSessionTypeList->allowed_session_types, + (void *)OpenAPI_pdu_session_type_IPV4V6); + break; + default: + ogs_fatal("Unsupported PDN_TYPE[%d]", + pduSessionTypeList->default_session_type); + ogs_assert_if_reached(); + } + + dnnConfiguration->pdu_session_types = pduSessionTypeList; + + sscModeList = ogs_calloc(1, sizeof(*sscModeList)); + ogs_assert(sscModeList); + sscModeList->default_ssc_mode = OpenAPI_ssc_mode_SSC_MODE_1; + + sscModeList->allowed_ssc_modes = OpenAPI_list_create(); + ogs_assert(sscModeList->allowed_ssc_modes); + OpenAPI_list_add(sscModeList->allowed_ssc_modes, + (void *)OpenAPI_ssc_mode_SSC_MODE_1); + OpenAPI_list_add(sscModeList->allowed_ssc_modes, + (void *)OpenAPI_ssc_mode_SSC_MODE_2); + OpenAPI_list_add(sscModeList->allowed_ssc_modes, + (void *)OpenAPI_ssc_mode_SSC_MODE_3); + + dnnConfiguration->ssc_modes = sscModeList; + + _5gQoSProfile = ogs_calloc(1, sizeof(*_5gQoSProfile)); + ogs_assert(_5gQoSProfile); + _5gQoSProfile->_5qi = session->qos.index; + _5gQoSProfile->is_priority_level = true; + _5gQoSProfile->priority_level = session->qos.arp.priority_level; + _5gQoSProfile->arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); + ogs_assert(_5gQoSProfile->arp); + _5gQoSProfile->arp->priority_level = + session->qos.arp.priority_level; + if (session->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_ENABLED) + _5gQoSProfile->arp->preempt_cap = + OpenAPI_preemption_capability_MAY_PREEMPT; + else if (session->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_DISABLED) + _5gQoSProfile->arp->preempt_cap = + OpenAPI_preemption_capability_NOT_PREEMPT; + ogs_assert(_5gQoSProfile->arp->preempt_cap); + + if (session->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_ENABLED) + _5gQoSProfile->arp->preempt_vuln = + OpenAPI_preemption_vulnerability_PREEMPTABLE; + else if (session->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_DISABLED) + _5gQoSProfile->arp->preempt_vuln = + OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; + ogs_assert(_5gQoSProfile->arp->preempt_vuln); + + dnnConfiguration->_5g_qos_profile = _5gQoSProfile; + + ogs_assert(session->ambr.uplink || session->ambr.downlink); + sessionAmbr = ogs_calloc(1, sizeof(*sessionAmbr)); + ogs_assert(sessionAmbr); + sessionAmbr->uplink = ogs_sbi_bitrate_to_string( + session->ambr.uplink, OGS_SBI_BITRATE_KBPS); + sessionAmbr->downlink = ogs_sbi_bitrate_to_string( + session->ambr.downlink, OGS_SBI_BITRATE_KBPS); + + dnnConfiguration->session_ambr = sessionAmbr; + + staticIpAddress = OpenAPI_list_create(); + ogs_assert(staticIpAddress); + + if (session->ue_ip.ipv4 || session->ue_ip.ipv6) { + ipAddress = ogs_calloc(1, sizeof(*ipAddress)); + ogs_assert(ipAddress); + + if (session->ue_ip.ipv4) { + ipAddress->ipv4_addr = + ogs_ipv4_to_string(session->ue_ip.addr); + ogs_assert(ipAddress->ipv4_addr); + } + if (session->ue_ip.ipv6) { + ipAddress->ipv6_addr = + ogs_ipv6addr_to_string(session->ue_ip.addr6); + ogs_assert(ipAddress->ipv6_addr); + } + + if (ipAddress->ipv4_addr || ipAddress->ipv6_addr) + OpenAPI_list_add(staticIpAddress, ipAddress); + else + ogs_free(ipAddress); + } + + if (staticIpAddress->count) + dnnConfiguration->static_ip_address = staticIpAddress; + else + OpenAPI_list_free(staticIpAddress); + + dnnConfigurationMap = OpenAPI_map_create( + session->name, dnnConfiguration); + ogs_assert(dnnConfigurationMap); + OpenAPI_list_add(dnnConfigurationList, dnnConfigurationMap); + + if (session->ipv4_framed_routes) { + int i; + FrameRouteList = OpenAPI_list_create(); + + for (i = 0; i < OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI; i++) { + const char *route = session->ipv4_framed_routes[i]; + if (!route) break; + OpenAPI_list_add(FrameRouteList, + OpenAPI_frame_route_info_create( + ogs_strdup(route), NULL)); + } + dnnConfiguration->ipv4_frame_route_list = FrameRouteList; + } + + if (session->ipv6_framed_routes) { + int i; + FrameRouteList = OpenAPI_list_create(); + + for (i = 0; i < OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI; i++) { + const char *route = session->ipv6_framed_routes[i]; + if (!route) break; + OpenAPI_list_add(FrameRouteList, + OpenAPI_frame_route_info_create( + NULL, ogs_strdup(route))); + } + dnnConfiguration->ipv6_frame_route_list = FrameRouteList; + } + } + + if (dnnConfigurationList->count) { + SessionManagementSubscriptionData = ogs_calloc(1, + sizeof(*SessionManagementSubscriptionData)); + ogs_assert(SessionManagementSubscriptionData); + SessionManagementSubscriptionData->single_nssai = singleNSSAI; + SessionManagementSubscriptionData->dnn_configurations = + dnnConfigurationList; + OpenAPI_list_add(SessionManagementSubscriptionDataList, + SessionManagementSubscriptionData); + } else { + if (singleNSSAI->sd) + ogs_free(singleNSSAI->sd); + ogs_free(singleNSSAI); + OpenAPI_list_free(dnnConfigurationList); + } + } + + memset(&smSubsData, 0, sizeof(smSubsData)); + smSubsData.session_management_subscription_data_list = + SessionManagementSubscriptionDataList; + + if (!returnProvisionedData) { + if (!SessionManagementSubscriptionDataList->count) { + OpenAPI_list_free(SessionManagementSubscriptionDataList); + + strerror = ogs_msprintf("[%s] Cannot find S_NSSAI with DNN" + "[SST:%d SD:0x%x, DNN:%s]", + supi, + recvmsg->param.s_nssai.sst, + recvmsg->param.s_nssai.sd.v, + recvmsg->param.dnn); + status = OGS_SBI_HTTP_STATUS_NOT_FOUND; + goto cleanup; + } + memset(&sendmsg, 0, sizeof(sendmsg)); + + sendmsg.SessionManagementSubscriptionDataList = + SessionManagementSubscriptionDataList; + ogs_assert(sendmsg.SessionManagementSubscriptionDataList); + + response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + } + } + + /* Build Provisioned Data Sets */ + if (returnProvisionedData) { + OpenAPI_provisioned_data_sets_t ProvisionedDataSets; + + memset(&ProvisionedDataSets, 0, + sizeof(ProvisionedDataSets)); + + if (processAmData) { + ProvisionedDataSets.am_data = &AccessAndMobilitySubscriptionData; + } + if (processSmfSel) { + ProvisionedDataSets.smf_sel_data = &SmfSelectionSubscriptionData; + } + if (processSmData) { + ProvisionedDataSets.sm_data = &smSubsData; + } memset(&sendmsg, 0, sizeof(sendmsg)); - sendmsg.SmfSelectionSubscriptionData = &SmfSelectionSubscriptionData; + sendmsg.ProvisionedDataSets = &ProvisionedDataSets; response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + } + + /* Free resources used above */ + if (processAmData) { + OpenAPI_lnode_t *node = NULL; + + OpenAPI_list_for_each(GpsiList, node) { + if (node->data) ogs_free(node->data); + } + OpenAPI_list_free(GpsiList); + + if (SubscribedUeAmbr.uplink) + ogs_free(SubscribedUeAmbr.uplink); + if (SubscribedUeAmbr.downlink) + ogs_free(SubscribedUeAmbr.downlink); + + OpenAPI_list_for_each(DefaultSingleNssaiList, node) { + OpenAPI_snssai_t *Snssai = node->data; + if (Snssai) { + if (Snssai->sd) + ogs_free(Snssai->sd); + ogs_free(Snssai); + } + } + OpenAPI_list_free(DefaultSingleNssaiList); + OpenAPI_list_for_each(SingleNssaiList, node) { + OpenAPI_snssai_t *Snssai = node->data; + if (Snssai) { + if (Snssai->sd) + ogs_free(Snssai->sd); + ogs_free(Snssai); + } + } + OpenAPI_list_free(SingleNssaiList); + } + if (processSmfSel) { + OpenAPI_lnode_t *node = NULL, *node2 = NULL; SubscribedSnssaiInfoList = SmfSelectionSubscriptionData.subscribed_snssai_infos; @@ -744,342 +1129,105 @@ bool udr_nudr_dr_handle_subscription_provisioned( } } OpenAPI_list_free(SubscribedSnssaiInfoList); - break; + } + if (processSmData) { + OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; - CASE(OGS_SBI_RESOURCE_NAME_SM_DATA) - int i; - - OpenAPI_session_management_subscription_data_t - SessionManagementSubscriptionData; - OpenAPI_snssai_t singleNSSAI; - OpenAPI_list_t *dnnConfigurationList = NULL; - OpenAPI_map_t *dnnConfigurationMap = NULL; - OpenAPI_dnn_configuration_t *dnnConfiguration = NULL; - OpenAPI_pdu_session_types_t *pduSessionTypeList = NULL; - OpenAPI_ssc_modes_t *sscModeList = NULL; - OpenAPI_subscribed_default_qos_t *_5gQoSProfile = NULL; - OpenAPI_ambr_t *sessionAmbr = NULL; - OpenAPI_list_t *staticIpAddress = NULL; - OpenAPI_ip_address_t *ipAddress = NULL; - OpenAPI_list_t *FrameRouteList = NULL; - OpenAPI_lnode_t *node = NULL, *node2 = NULL; - - if (!recvmsg->param.single_nssai_presence) { - strerror = ogs_msprintf("[%s] No S_NSSAI", supi); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - }; - - ogs_assert(subscription_data.num_of_slice); - slice_data = ogs_slice_find_by_s_nssai( - subscription_data.slice, subscription_data.num_of_slice, - &recvmsg->param.s_nssai); - - if (!slice_data) { - strerror = ogs_msprintf("[%s] Cannot find S_NSSAI[SST:%d SD:0x%x]", - supi, - recvmsg->param.s_nssai.sst, - recvmsg->param.s_nssai.sd.v); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - } - - singleNSSAI.sst = slice_data->s_nssai.sst; - singleNSSAI.sd = ogs_s_nssai_sd_to_string(slice_data->s_nssai.sd); - - dnnConfigurationList = OpenAPI_list_create(); - - for (i = 0; i < slice_data->num_of_session; i++) { - ogs_session_t *session = NULL; - - if (i >= OGS_MAX_NUM_OF_SESS) { - ogs_warn("Ignore max session count overflow [%d>=%d]", - slice_data->num_of_session, OGS_MAX_NUM_OF_SESS); - break; + OpenAPI_list_for_each(SessionManagementSubscriptionDataList, node) { + SessionManagementSubscriptionData = node->data; + if (SessionManagementSubscriptionData->single_nssai) { + singleNSSAI = SessionManagementSubscriptionData->single_nssai; + if (singleNSSAI->sd) + ogs_free(singleNSSAI->sd); + ogs_free(singleNSSAI); } - session = &slice_data->session[i]; - ogs_assert(session); - ogs_assert(session->name); - - if (recvmsg->param.dnn && - ogs_strcasecmp(recvmsg->param.dnn, session->name) != 0) - continue; - - if (!session->qos.index) { - ogs_error("No 5QI"); - continue; - } - if (!session->qos.arp.priority_level) { - ogs_error("No Priority Level"); - continue; - } - - if (!session->ambr.uplink && !session->ambr.downlink) { - ogs_error("No Session-AMBR"); - continue; - } - - dnnConfiguration = ogs_calloc(1, sizeof(*dnnConfiguration)); - ogs_assert(dnnConfiguration); - - pduSessionTypeList = ogs_calloc(1, sizeof(*pduSessionTypeList)); - ogs_assert(pduSessionTypeList); - pduSessionTypeList->default_session_type = session->session_type; - - pduSessionTypeList->allowed_session_types = OpenAPI_list_create(); - ogs_assert(pduSessionTypeList->allowed_session_types); - switch (pduSessionTypeList->default_session_type) { - case OpenAPI_pdu_session_type_IPV4: - OpenAPI_list_add(pduSessionTypeList->allowed_session_types, - (void *)OpenAPI_pdu_session_type_IPV4); - break; - case OpenAPI_pdu_session_type_IPV6: - OpenAPI_list_add(pduSessionTypeList->allowed_session_types, - (void *)OpenAPI_pdu_session_type_IPV6); - break; - case OpenAPI_pdu_session_type_IPV4V6: - OpenAPI_list_add(pduSessionTypeList->allowed_session_types, - (void *)OpenAPI_pdu_session_type_IPV4); - OpenAPI_list_add(pduSessionTypeList->allowed_session_types, - (void *)OpenAPI_pdu_session_type_IPV6); - OpenAPI_list_add(pduSessionTypeList->allowed_session_types, - (void *)OpenAPI_pdu_session_type_IPV4V6); - break; - default: - ogs_fatal("Unsupported PDN_TYPE[%d]", - pduSessionTypeList->default_session_type); - ogs_assert_if_reached(); - } - - dnnConfiguration->pdu_session_types = pduSessionTypeList; - - sscModeList = ogs_calloc(1, sizeof(*sscModeList)); - ogs_assert(sscModeList); - sscModeList->default_ssc_mode = OpenAPI_ssc_mode_SSC_MODE_1; - - sscModeList->allowed_ssc_modes = OpenAPI_list_create(); - ogs_assert(sscModeList->allowed_ssc_modes); - OpenAPI_list_add(sscModeList->allowed_ssc_modes, - (void *)OpenAPI_ssc_mode_SSC_MODE_1); - OpenAPI_list_add(sscModeList->allowed_ssc_modes, - (void *)OpenAPI_ssc_mode_SSC_MODE_2); - OpenAPI_list_add(sscModeList->allowed_ssc_modes, - (void *)OpenAPI_ssc_mode_SSC_MODE_3); - - dnnConfiguration->ssc_modes = sscModeList; - - _5gQoSProfile = ogs_calloc(1, sizeof(*_5gQoSProfile)); - ogs_assert(_5gQoSProfile); - _5gQoSProfile->_5qi = session->qos.index; - _5gQoSProfile->is_priority_level = true; - _5gQoSProfile->priority_level = session->qos.arp.priority_level; - _5gQoSProfile->arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); - ogs_assert(_5gQoSProfile->arp); - _5gQoSProfile->arp->priority_level = - session->qos.arp.priority_level; - if (session->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_ENABLED) - _5gQoSProfile->arp->preempt_cap = - OpenAPI_preemption_capability_MAY_PREEMPT; - else if (session->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_DISABLED) - _5gQoSProfile->arp->preempt_cap = - OpenAPI_preemption_capability_NOT_PREEMPT; - ogs_assert(_5gQoSProfile->arp->preempt_cap); - - if (session->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_ENABLED) - _5gQoSProfile->arp->preempt_vuln = - OpenAPI_preemption_vulnerability_PREEMPTABLE; - else if (session->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_DISABLED) - _5gQoSProfile->arp->preempt_vuln = - OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; - ogs_assert(_5gQoSProfile->arp->preempt_vuln); - - dnnConfiguration->_5g_qos_profile = _5gQoSProfile; - - ogs_assert(session->ambr.uplink || session->ambr.downlink); - sessionAmbr = ogs_calloc(1, sizeof(*sessionAmbr)); - ogs_assert(sessionAmbr); - sessionAmbr->uplink = ogs_sbi_bitrate_to_string( - session->ambr.uplink, OGS_SBI_BITRATE_KBPS); - sessionAmbr->downlink = ogs_sbi_bitrate_to_string( - session->ambr.downlink, OGS_SBI_BITRATE_KBPS); - - dnnConfiguration->session_ambr = sessionAmbr; - - staticIpAddress = OpenAPI_list_create(); - ogs_assert(staticIpAddress); - - if (session->ue_ip.ipv4 || session->ue_ip.ipv6) { - ipAddress = ogs_calloc(1, sizeof(*ipAddress)); - ogs_assert(ipAddress); - - if (session->ue_ip.ipv4) { - ipAddress->ipv4_addr = - ogs_ipv4_to_string(session->ue_ip.addr); - ogs_assert(ipAddress->ipv4_addr); - } - if (session->ue_ip.ipv6) { - ipAddress->ipv6_addr = - ogs_ipv6addr_to_string(session->ue_ip.addr6); - ogs_assert(ipAddress->ipv6_addr); - } - - if (ipAddress->ipv4_addr || ipAddress->ipv6_addr) - OpenAPI_list_add(staticIpAddress, ipAddress); - else - ogs_free(ipAddress); - } - - if (staticIpAddress->count) - dnnConfiguration->static_ip_address = staticIpAddress; - else - OpenAPI_list_free(staticIpAddress); - - dnnConfigurationMap = OpenAPI_map_create( - session->name, dnnConfiguration); - ogs_assert(dnnConfigurationMap); - OpenAPI_list_add(dnnConfigurationList, dnnConfigurationMap); - - if (session->ipv4_framed_routes) { - int i; - FrameRouteList = OpenAPI_list_create(); - - for (i = 0; i < OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI; i++) { - const char *route = session->ipv4_framed_routes[i]; - if (!route) break; - OpenAPI_list_add(FrameRouteList, - OpenAPI_frame_route_info_create( - ogs_strdup(route), NULL)); - } - dnnConfiguration->ipv4_frame_route_list = FrameRouteList; - } - - if (session->ipv6_framed_routes) { - int i; - FrameRouteList = OpenAPI_list_create(); - - for (i = 0; i < OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI; i++) { - const char *route = session->ipv6_framed_routes[i]; - if (!route) break; - OpenAPI_list_add(FrameRouteList, - OpenAPI_frame_route_info_create( - NULL, ogs_strdup(route))); - } - dnnConfiguration->ipv6_frame_route_list = FrameRouteList; - } - } - - memset(&SessionManagementSubscriptionData, 0, - sizeof(SessionManagementSubscriptionData)); - SessionManagementSubscriptionData.single_nssai = &singleNSSAI; - if (dnnConfigurationList->count) - SessionManagementSubscriptionData.dnn_configurations = - dnnConfigurationList; - - memset(&sendmsg, 0, sizeof(sendmsg)); - - sendmsg.SessionManagementSubscriptionDataList = OpenAPI_list_create(); - ogs_assert(sendmsg.SessionManagementSubscriptionDataList); - - OpenAPI_list_add(sendmsg.SessionManagementSubscriptionDataList, - &SessionManagementSubscriptionData); - - response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); - ogs_assert(response); - ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - - OpenAPI_list_free(sendmsg.SessionManagementSubscriptionDataList); - - if (singleNSSAI.sd) - ogs_free(singleNSSAI.sd); - - OpenAPI_list_for_each(dnnConfigurationList, node) { - dnnConfigurationMap = node->data; - if (dnnConfigurationMap) { - dnnConfiguration = dnnConfigurationMap->value; - if (dnnConfiguration) { - pduSessionTypeList = dnnConfiguration->pdu_session_types; - if (pduSessionTypeList) { - if (pduSessionTypeList->allowed_session_types) - OpenAPI_list_free( - pduSessionTypeList->allowed_session_types); - ogs_free(pduSessionTypeList); - } - sscModeList = dnnConfiguration->ssc_modes;; - if (sscModeList) { - if (sscModeList->allowed_ssc_modes) - OpenAPI_list_free(sscModeList->allowed_ssc_modes); - ogs_free(sscModeList); - } - _5gQoSProfile = dnnConfiguration->_5g_qos_profile; - if (_5gQoSProfile) { - if (_5gQoSProfile->arp) - ogs_free(_5gQoSProfile->arp); - ogs_free(_5gQoSProfile); - } - - sessionAmbr = dnnConfiguration->session_ambr; - if (sessionAmbr) { - if (sessionAmbr->uplink) - ogs_free(sessionAmbr->uplink); - if (sessionAmbr->downlink) - ogs_free(sessionAmbr->downlink); - ogs_free(sessionAmbr); - } - - staticIpAddress = dnnConfiguration->static_ip_address; - if (staticIpAddress) { - OpenAPI_list_for_each(staticIpAddress, node2) { - if (node2->data) { - ipAddress = node2->data; - if (ipAddress) { - if (ipAddress->ipv4_addr) - ogs_free(ipAddress->ipv4_addr); - if (ipAddress->ipv6_addr) - ogs_free(ipAddress->ipv6_addr); - ogs_free(ipAddress); - } + if (SessionManagementSubscriptionData->dnn_configurations) { + dnnConfigurationList = + SessionManagementSubscriptionData->dnn_configurations; + OpenAPI_list_for_each(dnnConfigurationList, node2) { + dnnConfigurationMap = node2->data; + if (dnnConfigurationMap) { + dnnConfiguration = dnnConfigurationMap->value; + if (dnnConfiguration) { + pduSessionTypeList = + dnnConfiguration->pdu_session_types; + if (pduSessionTypeList) { + if (pduSessionTypeList->allowed_session_types) + OpenAPI_list_free( + pduSessionTypeList->allowed_session_types); + ogs_free(pduSessionTypeList); } + sscModeList = dnnConfiguration->ssc_modes;; + if (sscModeList) { + if (sscModeList->allowed_ssc_modes) + OpenAPI_list_free( + sscModeList->allowed_ssc_modes); + ogs_free(sscModeList); + } + _5gQoSProfile = dnnConfiguration->_5g_qos_profile; + if (_5gQoSProfile) { + if (_5gQoSProfile->arp) + ogs_free(_5gQoSProfile->arp); + ogs_free(_5gQoSProfile); + } + + sessionAmbr = dnnConfiguration->session_ambr; + if (sessionAmbr) { + if (sessionAmbr->uplink) + ogs_free(sessionAmbr->uplink); + if (sessionAmbr->downlink) + ogs_free(sessionAmbr->downlink); + ogs_free(sessionAmbr); + } + + staticIpAddress = + dnnConfiguration->static_ip_address; + if (staticIpAddress) { + OpenAPI_list_for_each(staticIpAddress, node3) { + if (node3->data) { + ipAddress = node3->data; + if (ipAddress) { + if (ipAddress->ipv4_addr) + ogs_free(ipAddress->ipv4_addr); + if (ipAddress->ipv6_addr) + ogs_free(ipAddress->ipv6_addr); + ogs_free(ipAddress); + } + } + } + OpenAPI_list_free(staticIpAddress); + } + + FrameRouteList = + dnnConfiguration->ipv4_frame_route_list; + OpenAPI_list_for_each(FrameRouteList, node3) { + OpenAPI_frame_route_info_t *frame = node3->data; + if (frame) + ogs_free(frame); + } + OpenAPI_list_free(FrameRouteList); + + FrameRouteList = + dnnConfiguration->ipv6_frame_route_list; + OpenAPI_list_for_each(FrameRouteList, node3) { + OpenAPI_frame_route_info_t *frame = node3->data; + if (frame) + ogs_free(frame); + } + OpenAPI_list_free(FrameRouteList); + + ogs_free(dnnConfiguration); } - OpenAPI_list_free(staticIpAddress); + ogs_free(dnnConfigurationMap); } - - FrameRouteList = dnnConfiguration->ipv4_frame_route_list; - OpenAPI_list_for_each(FrameRouteList, node2) { - OpenAPI_frame_route_info_t *frame = node2->data; - if (frame) - ogs_free(frame); - } - OpenAPI_list_free(FrameRouteList); - - FrameRouteList = dnnConfiguration->ipv6_frame_route_list; - OpenAPI_list_for_each(FrameRouteList, node2) { - OpenAPI_frame_route_info_t *frame = node2->data; - if (frame) - ogs_free(frame); - } - OpenAPI_list_free(FrameRouteList); - - ogs_free(dnnConfiguration); } - ogs_free(dnnConfigurationMap); + OpenAPI_list_free(dnnConfigurationList); } + ogs_free(SessionManagementSubscriptionData); } - - OpenAPI_list_free(dnnConfigurationList); - - break; - - DEFAULT - strerror = ogs_msprintf("Invalid resource name [%s]", - recvmsg->h.resource.component[3]); - status = OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED; - goto cleanup; - END + OpenAPI_list_free(SessionManagementSubscriptionDataList); + } ogs_subscription_data_free(&subscription_data);